@treeseed/core 0.1.2
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/README.md +145 -0
- package/dist/agents/index.js +5 -0
- package/dist/agents/registry-helper.js +14 -0
- package/dist/agents/registry.js +88 -0
- package/dist/components/DevWatchReload.astro +45 -0
- package/dist/components/SiteTitle.astro +51 -0
- package/dist/components/content/ContentStatusLegend.astro +18 -0
- package/dist/components/content/StatusBadge.astro +11 -0
- package/dist/components/docs/BookFontControls.astro +180 -0
- package/dist/components/docs/DesktopSidebarToggle.astro +88 -0
- package/dist/components/docs/DownloadBook.astro +34 -0
- package/dist/components/docs/Footer.astro +196 -0
- package/dist/components/docs/Header.astro +150 -0
- package/dist/components/docs/PageFrame.astro +260 -0
- package/dist/components/docs/PageSidebar.astro +63 -0
- package/dist/components/docs/PageTitle.astro +39 -0
- package/dist/components/docs/Sidebar.astro +41 -0
- package/dist/components/docs/ThemeSelect.astro +3 -0
- package/dist/components/forms/ContactForm.astro +234 -0
- package/dist/components/forms/FooterSubscribeForm.astro +189 -0
- package/dist/components/site/BookList.astro +27 -0
- package/dist/components/site/CTASection.astro +24 -0
- package/dist/components/site/ChronicleList.astro +33 -0
- package/dist/components/site/Hero.astro +18 -0
- package/dist/components/site/NotesList.astro +18 -0
- package/dist/components/site/PathCard.astro +16 -0
- package/dist/components/site/ProfileList.astro +30 -0
- package/dist/components/site/SectionIntro.astro +9 -0
- package/dist/components/site/StageBanner.astro +8 -0
- package/dist/components/site/TrustCallout.astro +9 -0
- package/dist/components/starlight.js +6 -0
- package/dist/config.js +8 -0
- package/dist/content-config.js +9 -0
- package/dist/content.js +230 -0
- package/dist/contracts.d.ts +130 -0
- package/dist/contracts.js +0 -0
- package/dist/deploy/config.d.ts +4 -0
- package/dist/deploy/config.js +154 -0
- package/dist/deploy/runtime.js +77 -0
- package/dist/env.yaml +322 -0
- package/dist/environment.d.ts +130 -0
- package/dist/environment.js +324 -0
- package/dist/index.js +81 -0
- package/dist/layouts/AuthoredEntryLayout.astro +87 -0
- package/dist/layouts/BookLayout.astro +35 -0
- package/dist/layouts/BridgeLayout.astro +11 -0
- package/dist/layouts/ContentLayout.astro +24 -0
- package/dist/layouts/MainLayout.astro +203 -0
- package/dist/layouts/NoteLayout.astro +26 -0
- package/dist/layouts/ProfileLayout.astro +81 -0
- package/dist/middleware/starlightRouteData.js +45 -0
- package/dist/pages/404.astro +29 -0
- package/dist/pages/[slug].astro +30 -0
- package/dist/pages/agents/[slug].astro +29 -0
- package/dist/pages/agents/index.astro +27 -0
- package/dist/pages/api/form/submit.js +14 -0
- package/dist/pages/books/[slug].astro +19 -0
- package/dist/pages/books/index.astro +28 -0
- package/dist/pages/contact.astro +27 -0
- package/dist/pages/feed.xml.js +34 -0
- package/dist/pages/index.astro +290 -0
- package/dist/pages/notes/[slug].astro +19 -0
- package/dist/pages/notes/index.astro +21 -0
- package/dist/pages/objectives/[slug].astro +31 -0
- package/dist/pages/objectives/index.astro +30 -0
- package/dist/pages/people/[slug].astro +29 -0
- package/dist/pages/people/index.astro +28 -0
- package/dist/pages/questions/[slug].astro +31 -0
- package/dist/pages/questions/index.astro +30 -0
- package/dist/plugin-default.js +4 -0
- package/dist/plugins/builtin/default-plugin.d.ts +21 -0
- package/dist/plugins/builtin/default-plugin.js +32 -0
- package/dist/plugins/constants.d.ts +21 -0
- package/dist/plugins/constants.js +28 -0
- package/dist/plugins/plugin.d.ts +42 -0
- package/dist/plugins/plugin.js +6 -0
- package/dist/plugins/runtime.d.ts +31 -0
- package/dist/plugins/runtime.js +120 -0
- package/dist/scripts/aggregate-book.js +112 -0
- package/dist/scripts/assert-release-tag-version.js +21 -0
- package/dist/scripts/build-dist.js +384 -0
- package/dist/scripts/build-tenant-worker.js +36 -0
- package/dist/scripts/package-tools.js +88 -0
- package/dist/scripts/patch-starlight-content-path.js +172 -0
- package/dist/scripts/paths.js +11 -0
- package/dist/scripts/publish-package.js +20 -0
- package/dist/scripts/release-verify.js +52 -0
- package/dist/scripts/run-fixture-astro-command.js +21 -0
- package/dist/scripts/tenant-astro-command.js +3 -0
- package/dist/scripts/tenant-build.js +16 -0
- package/dist/scripts/tenant-check.js +7 -0
- package/dist/scripts/test-smoke.js +105 -0
- package/dist/server.js +53 -0
- package/dist/site-resources.d.ts +29 -0
- package/dist/site-resources.js +127 -0
- package/dist/site.js +313 -0
- package/dist/styles/global.css +683 -0
- package/dist/styles/prose.css +89 -0
- package/dist/styles/tokens.css +24 -0
- package/dist/tenant/bridge.js +5 -0
- package/dist/tenant/config.d.ts +9 -0
- package/dist/tenant/config.js +124 -0
- package/dist/tenant/runtime-config.js +20 -0
- package/dist/tsconfigs/strict.json +3 -0
- package/dist/types/agents.d.ts +1 -0
- package/dist/types/agents.js +1 -0
- package/dist/types/astro-build.d.js +0 -0
- package/dist/types/cloudflare-sockets.d.js +0 -0
- package/dist/types/cloudflare.d.ts +1 -0
- package/dist/types/cloudflare.js +1 -0
- package/dist/types/forms.js +4 -0
- package/dist/utils/agents/adapters/execution.js +90 -0
- package/dist/utils/agents/adapters/mutations.js +30 -0
- package/dist/utils/agents/adapters/notification.js +16 -0
- package/dist/utils/agents/adapters/repository.js +61 -0
- package/dist/utils/agents/adapters/research.js +25 -0
- package/dist/utils/agents/adapters/verification.js +62 -0
- package/dist/utils/agents/cli-tools.js +5 -0
- package/dist/utils/agents/contracts/messages.d.ts +88 -0
- package/dist/utils/agents/contracts/messages.js +138 -0
- package/dist/utils/agents/contracts/run.d.ts +20 -0
- package/dist/utils/agents/contracts/run.js +0 -0
- package/dist/utils/agents/runtime-types.d.ts +117 -0
- package/dist/utils/agents/runtime-types.js +4 -0
- package/dist/utils/books-data.js +82 -0
- package/dist/utils/content-status.js +38 -0
- package/dist/utils/forms/config.js +87 -0
- package/dist/utils/forms/constants.js +27 -0
- package/dist/utils/forms/contact-submissions-local.js +19 -0
- package/dist/utils/forms/contact-submissions.js +72 -0
- package/dist/utils/forms/crypto.js +64 -0
- package/dist/utils/forms/guard.js +76 -0
- package/dist/utils/forms/http.js +51 -0
- package/dist/utils/forms/provider-core.js +88 -0
- package/dist/utils/forms/routing-core.js +7 -0
- package/dist/utils/forms/routing.js +13 -0
- package/dist/utils/forms/runtime-core.js +17 -0
- package/dist/utils/forms/runtime.js +27 -0
- package/dist/utils/forms/service-core.js +256 -0
- package/dist/utils/forms/service.js +55 -0
- package/dist/utils/forms/session.js +57 -0
- package/dist/utils/forms/smtp-cloudflare.js +107 -0
- package/dist/utils/forms/smtp-node.js +27 -0
- package/dist/utils/forms/smtp.js +10 -0
- package/dist/utils/forms/subscribers-local.js +21 -0
- package/dist/utils/forms/subscribers.js +53 -0
- package/dist/utils/forms/turnstile.js +31 -0
- package/dist/utils/forms/validation.js +58 -0
- package/dist/utils/hub-content.js +28 -0
- package/dist/utils/plugin-runtime.js +158 -0
- package/dist/utils/routes.js +17 -0
- package/dist/utils/seo.js +4 -0
- package/dist/utils/site-config-schema.js +282 -0
- package/dist/utils/site-config.js +122 -0
- package/dist/utils/starlight-nav.js +62 -0
- package/dist/utils/theme.js +49 -0
- package/dist/vendor/starlight/components/AnchorHeading.astro +53 -0
- package/dist/vendor/starlight/components/Banner.astro +23 -0
- package/dist/vendor/starlight/components/ContentNotice.astro +33 -0
- package/dist/vendor/starlight/components/ContentPanel.astro +27 -0
- package/dist/vendor/starlight/components/DraftContentNotice.astro +5 -0
- package/dist/vendor/starlight/components/EditLink.astro +28 -0
- package/dist/vendor/starlight/components/FallbackContentNotice.astro +5 -0
- package/dist/vendor/starlight/components/Footer.astro +61 -0
- package/dist/vendor/starlight/components/Head.astro +5 -0
- package/dist/vendor/starlight/components/Header.astro +94 -0
- package/dist/vendor/starlight/components/Hero.astro +143 -0
- package/dist/vendor/starlight/components/Icons.js +121 -0
- package/dist/vendor/starlight/components/LanguageSelect.astro +57 -0
- package/dist/vendor/starlight/components/LastUpdated.astro +14 -0
- package/dist/vendor/starlight/components/MarkdownContent.astro +5 -0
- package/dist/vendor/starlight/components/MobileMenuFooter.astro +35 -0
- package/dist/vendor/starlight/components/MobileMenuToggle.astro +107 -0
- package/dist/vendor/starlight/components/MobileTableOfContents.astro +151 -0
- package/dist/vendor/starlight/components/Page.astro +126 -0
- package/dist/vendor/starlight/components/PageFrame.astro +97 -0
- package/dist/vendor/starlight/components/PageSidebar.astro +59 -0
- package/dist/vendor/starlight/components/PageTitle.astro +17 -0
- package/dist/vendor/starlight/components/Pagination.astro +79 -0
- package/dist/vendor/starlight/components/Search.astro +488 -0
- package/dist/vendor/starlight/components/Select.astro +99 -0
- package/dist/vendor/starlight/components/Sidebar.astro +15 -0
- package/dist/vendor/starlight/components/SidebarPersistState.js +43 -0
- package/dist/vendor/starlight/components/SidebarPersister.astro +78 -0
- package/dist/vendor/starlight/components/SidebarRestorePoint.astro +12 -0
- package/dist/vendor/starlight/components/SidebarSublist.astro +154 -0
- package/dist/vendor/starlight/components/SiteTitle.astro +59 -0
- package/dist/vendor/starlight/components/SkipLink.astro +26 -0
- package/dist/vendor/starlight/components/SocialIcons.astro +32 -0
- package/dist/vendor/starlight/components/StarlightPage.astro +17 -0
- package/dist/vendor/starlight/components/TableOfContents/TableOfContentsList.astro +79 -0
- package/dist/vendor/starlight/components/TableOfContents/starlight-toc.js +93 -0
- package/dist/vendor/starlight/components/TableOfContents.astro +18 -0
- package/dist/vendor/starlight/components/ThemeProvider.astro +38 -0
- package/dist/vendor/starlight/components/ThemeSelect.astro +73 -0
- package/dist/vendor/starlight/components/TwoColumnContent.astro +54 -0
- package/dist/vendor/starlight/components.js +26 -0
- package/dist/vendor/starlight/constants.js +4 -0
- package/dist/vendor/starlight/expressive-code.d.js +1 -0
- package/dist/vendor/starlight/global.d.js +0 -0
- package/dist/vendor/starlight/i18n.d.js +1 -0
- package/dist/vendor/starlight/index.js +119 -0
- package/dist/vendor/starlight/integrations/asides-error.js +12 -0
- package/dist/vendor/starlight/integrations/asides.js +179 -0
- package/dist/vendor/starlight/integrations/code-rtl-support.js +21 -0
- package/dist/vendor/starlight/integrations/expressive-code/hast.d.js +1 -0
- package/dist/vendor/starlight/integrations/expressive-code/index.js +63 -0
- package/dist/vendor/starlight/integrations/expressive-code/preprocessor.js +92 -0
- package/dist/vendor/starlight/integrations/expressive-code/themes/night-owl-dark.jsonc +1796 -0
- package/dist/vendor/starlight/integrations/expressive-code/themes/night-owl-dark.jsonc.js +1 -0
- package/dist/vendor/starlight/integrations/expressive-code/themes/night-owl-light.jsonc +1695 -0
- package/dist/vendor/starlight/integrations/expressive-code/themes/night-owl-light.jsonc.js +1 -0
- package/dist/vendor/starlight/integrations/expressive-code/theming.js +62 -0
- package/dist/vendor/starlight/integrations/expressive-code/translations.js +29 -0
- package/dist/vendor/starlight/integrations/heading-links.js +61 -0
- package/dist/vendor/starlight/integrations/pagefind.js +43 -0
- package/dist/vendor/starlight/integrations/remark-rehype.js +68 -0
- package/dist/vendor/starlight/integrations/shared/absolutePathToLang.js +15 -0
- package/dist/vendor/starlight/integrations/shared/localeToLang.js +9 -0
- package/dist/vendor/starlight/integrations/shared/slugToLocale.js +10 -0
- package/dist/vendor/starlight/integrations/sitemap.js +20 -0
- package/dist/vendor/starlight/integrations/virtual-user-config.js +110 -0
- package/dist/vendor/starlight/integrations/vite-layer-order.js +42 -0
- package/dist/vendor/starlight/internal.js +6 -0
- package/dist/vendor/starlight/loaders.js +36 -0
- package/dist/vendor/starlight/locals.d.js +0 -0
- package/dist/vendor/starlight/locals.js +30 -0
- package/dist/vendor/starlight/package.json +231 -0
- package/dist/vendor/starlight/package.json.js +248 -0
- package/dist/vendor/starlight/props.js +0 -0
- package/dist/vendor/starlight/route-data.js +6 -0
- package/dist/vendor/starlight/routes/common.astro +23 -0
- package/dist/vendor/starlight/routes/ssr/404.astro +7 -0
- package/dist/vendor/starlight/routes/ssr/index.astro +14 -0
- package/dist/vendor/starlight/routes/static/404.astro +7 -0
- package/dist/vendor/starlight/routes/static/index.astro +12 -0
- package/dist/vendor/starlight/schema.js +102 -0
- package/dist/vendor/starlight/schemas/badge.js +26 -0
- package/dist/vendor/starlight/schemas/components.js +235 -0
- package/dist/vendor/starlight/schemas/expressiveCode.js +12 -0
- package/dist/vendor/starlight/schemas/favicon.js +33 -0
- package/dist/vendor/starlight/schemas/head.js +32 -0
- package/dist/vendor/starlight/schemas/hero.js +57 -0
- package/dist/vendor/starlight/schemas/i18n.js +101 -0
- package/dist/vendor/starlight/schemas/icon.js +7 -0
- package/dist/vendor/starlight/schemas/logo.js +24 -0
- package/dist/vendor/starlight/schemas/pagefind.js +108 -0
- package/dist/vendor/starlight/schemas/prevNextLink.js +14 -0
- package/dist/vendor/starlight/schemas/sidebar.js +80 -0
- package/dist/vendor/starlight/schemas/site-title.js +19 -0
- package/dist/vendor/starlight/schemas/social.js +19 -0
- package/dist/vendor/starlight/schemas/tableOfContents.js +16 -0
- package/dist/vendor/starlight/style/anchor-links.css +131 -0
- package/dist/vendor/starlight/style/asides.css +51 -0
- package/dist/vendor/starlight/style/layers.css +1 -0
- package/dist/vendor/starlight/style/markdown.css +253 -0
- package/dist/vendor/starlight/style/print.css +175 -0
- package/dist/vendor/starlight/style/props.css +188 -0
- package/dist/vendor/starlight/style/reset.css +52 -0
- package/dist/vendor/starlight/style/util.css +63 -0
- package/dist/vendor/starlight/translations/ar.json +30 -0
- package/dist/vendor/starlight/translations/ar.json.js +32 -0
- package/dist/vendor/starlight/translations/ca.json +43 -0
- package/dist/vendor/starlight/translations/ca.json.js +45 -0
- package/dist/vendor/starlight/translations/cs.json +43 -0
- package/dist/vendor/starlight/translations/cs.json.js +45 -0
- package/dist/vendor/starlight/translations/da.json +30 -0
- package/dist/vendor/starlight/translations/da.json.js +32 -0
- package/dist/vendor/starlight/translations/de.json +30 -0
- package/dist/vendor/starlight/translations/de.json.js +32 -0
- package/dist/vendor/starlight/translations/el.json +30 -0
- package/dist/vendor/starlight/translations/el.json.js +32 -0
- package/dist/vendor/starlight/translations/en.json +30 -0
- package/dist/vendor/starlight/translations/en.json.js +32 -0
- package/dist/vendor/starlight/translations/es.json +43 -0
- package/dist/vendor/starlight/translations/es.json.js +45 -0
- package/dist/vendor/starlight/translations/fa.json +30 -0
- package/dist/vendor/starlight/translations/fa.json.js +32 -0
- package/dist/vendor/starlight/translations/fi.json +30 -0
- package/dist/vendor/starlight/translations/fi.json.js +32 -0
- package/dist/vendor/starlight/translations/fr.json +33 -0
- package/dist/vendor/starlight/translations/fr.json.js +35 -0
- package/dist/vendor/starlight/translations/gl.json +43 -0
- package/dist/vendor/starlight/translations/gl.json.js +45 -0
- package/dist/vendor/starlight/translations/he.json +30 -0
- package/dist/vendor/starlight/translations/he.json.js +32 -0
- package/dist/vendor/starlight/translations/hi.json +30 -0
- package/dist/vendor/starlight/translations/hi.json.js +32 -0
- package/dist/vendor/starlight/translations/hu.json +43 -0
- package/dist/vendor/starlight/translations/hu.json.js +45 -0
- package/dist/vendor/starlight/translations/id.json +30 -0
- package/dist/vendor/starlight/translations/id.json.js +32 -0
- package/dist/vendor/starlight/translations/index.js +77 -0
- package/dist/vendor/starlight/translations/it.json +30 -0
- package/dist/vendor/starlight/translations/it.json.js +32 -0
- package/dist/vendor/starlight/translations/ja.json +30 -0
- package/dist/vendor/starlight/translations/ja.json.js +32 -0
- package/dist/vendor/starlight/translations/ko.json +30 -0
- package/dist/vendor/starlight/translations/ko.json.js +32 -0
- package/dist/vendor/starlight/translations/lv.json +30 -0
- package/dist/vendor/starlight/translations/lv.json.js +32 -0
- package/dist/vendor/starlight/translations/nb.json +30 -0
- package/dist/vendor/starlight/translations/nb.json.js +32 -0
- package/dist/vendor/starlight/translations/nl.json +30 -0
- package/dist/vendor/starlight/translations/nl.json.js +32 -0
- package/dist/vendor/starlight/translations/pl.json +33 -0
- package/dist/vendor/starlight/translations/pl.json.js +35 -0
- package/dist/vendor/starlight/translations/pt.json +30 -0
- package/dist/vendor/starlight/translations/pt.json.js +32 -0
- package/dist/vendor/starlight/translations/ro.json +30 -0
- package/dist/vendor/starlight/translations/ro.json.js +32 -0
- package/dist/vendor/starlight/translations/ru.json +33 -0
- package/dist/vendor/starlight/translations/ru.json.js +35 -0
- package/dist/vendor/starlight/translations/sk.json +30 -0
- package/dist/vendor/starlight/translations/sk.json.js +32 -0
- package/dist/vendor/starlight/translations/sv.json +30 -0
- package/dist/vendor/starlight/translations/sv.json.js +32 -0
- package/dist/vendor/starlight/translations/th.json +30 -0
- package/dist/vendor/starlight/translations/th.json.js +32 -0
- package/dist/vendor/starlight/translations/tr.json +30 -0
- package/dist/vendor/starlight/translations/tr.json.js +32 -0
- package/dist/vendor/starlight/translations/uk.json +30 -0
- package/dist/vendor/starlight/translations/uk.json.js +32 -0
- package/dist/vendor/starlight/translations/vi.json +30 -0
- package/dist/vendor/starlight/translations/vi.json.js +32 -0
- package/dist/vendor/starlight/translations/zh-CN.json +30 -0
- package/dist/vendor/starlight/translations/zh-CN.json.js +32 -0
- package/dist/vendor/starlight/translations/zh-TW.json +30 -0
- package/dist/vendor/starlight/translations/zh-TW.json.js +32 -0
- package/dist/vendor/starlight/types.js +0 -0
- package/dist/vendor/starlight/user-components/Aside.astro +40 -0
- package/dist/vendor/starlight/user-components/Badge.astro +148 -0
- package/dist/vendor/starlight/user-components/Card.astro +68 -0
- package/dist/vendor/starlight/user-components/CardGrid.astro +38 -0
- package/dist/vendor/starlight/user-components/FileTree.astro +137 -0
- package/dist/vendor/starlight/user-components/Icon.astro +42 -0
- package/dist/vendor/starlight/user-components/LinkButton.astro +78 -0
- package/dist/vendor/starlight/user-components/LinkCard.astro +78 -0
- package/dist/vendor/starlight/user-components/Steps.astro +90 -0
- package/dist/vendor/starlight/user-components/TabItem.astro +19 -0
- package/dist/vendor/starlight/user-components/Tabs.astro +268 -0
- package/dist/vendor/starlight/user-components/file-tree-icons.js +608 -0
- package/dist/vendor/starlight/user-components/rehype-file-tree.js +160 -0
- package/dist/vendor/starlight/user-components/rehype-steps.js +53 -0
- package/dist/vendor/starlight/user-components/rehype-tabs.js +73 -0
- package/dist/vendor/starlight/utils/base.js +14 -0
- package/dist/vendor/starlight/utils/canonical.js +13 -0
- package/dist/vendor/starlight/utils/collection-fs.js +13 -0
- package/dist/vendor/starlight/utils/collection.js +16 -0
- package/dist/vendor/starlight/utils/createPathFormatter.js +39 -0
- package/dist/vendor/starlight/utils/createTranslationSystem.js +60 -0
- package/dist/vendor/starlight/utils/error-map.js +110 -0
- package/dist/vendor/starlight/utils/format-path.js +9 -0
- package/dist/vendor/starlight/utils/generateToC.js +18 -0
- package/dist/vendor/starlight/utils/git.js +92 -0
- package/dist/vendor/starlight/utils/gitInlined.js +13 -0
- package/dist/vendor/starlight/utils/head.js +156 -0
- package/dist/vendor/starlight/utils/i18n.js +121 -0
- package/dist/vendor/starlight/utils/localizedUrl.js +37 -0
- package/dist/vendor/starlight/utils/navigation.js +320 -0
- package/dist/vendor/starlight/utils/path.js +52 -0
- package/dist/vendor/starlight/utils/plugins.js +355 -0
- package/dist/vendor/starlight/utils/routing/data.js +116 -0
- package/dist/vendor/starlight/utils/routing/index.js +107 -0
- package/dist/vendor/starlight/utils/routing/middleware.js +40 -0
- package/dist/vendor/starlight/utils/routing/types.js +0 -0
- package/dist/vendor/starlight/utils/routing.js +1 -0
- package/dist/vendor/starlight/utils/slugs.js +70 -0
- package/dist/vendor/starlight/utils/starlight-page.js +123 -0
- package/dist/vendor/starlight/utils/translations-fs.js +31 -0
- package/dist/vendor/starlight/utils/translations.js +31 -0
- package/dist/vendor/starlight/utils/types.js +0 -0
- package/dist/vendor/starlight/utils/url.js +5 -0
- package/dist/vendor/starlight/utils/user-config.js +255 -0
- package/dist/vendor/starlight/utils/validateLogoImports.js +22 -0
- package/dist/vendor/starlight/virtual-internal.d.js +0 -0
- package/dist/vendor/starlight/virtual.d.js +0 -0
- package/dist/worker/forms-worker.js +141 -0
- package/package.json +156 -0
- package/style/anchor-links.css +131 -0
- package/templates/github/deploy.workflow.yml +47 -0
- package/tsconfigs/strict.json +3 -0
- package/utils/git.ts +121 -0
- package/utils/gitInlined.ts +20 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { getTreeseedFormsProvider } from "../../deploy/runtime.js";
|
|
2
|
+
import { resolveFormsProvider } from "../plugin-runtime.js";
|
|
3
|
+
import {
|
|
4
|
+
getContactRoutingMap,
|
|
5
|
+
getFormSecret,
|
|
6
|
+
getSmtpConfig,
|
|
7
|
+
getSubscribeRecipients,
|
|
8
|
+
getTurnstileSecret
|
|
9
|
+
} from "./config.js";
|
|
10
|
+
import { resolveFormRuntimeCapabilities } from "./runtime.js";
|
|
11
|
+
import { SITE } from "../site-config.js";
|
|
12
|
+
import { handleFormSubmissionWithConfig, handleTokenRequestWithConfig } from "./service-core.js";
|
|
13
|
+
function getBindings(locals) {
|
|
14
|
+
const runtime = locals.runtime;
|
|
15
|
+
const env = runtime?.env;
|
|
16
|
+
return env ?? null;
|
|
17
|
+
}
|
|
18
|
+
function createAstroRequestContext(context) {
|
|
19
|
+
return {
|
|
20
|
+
request: context.request,
|
|
21
|
+
url: context.url,
|
|
22
|
+
getCookie(name) {
|
|
23
|
+
return context.cookies.get(name)?.value;
|
|
24
|
+
},
|
|
25
|
+
setCookie(cookie) {
|
|
26
|
+
context.cookies.set(cookie.name, cookie.value, cookie.options);
|
|
27
|
+
},
|
|
28
|
+
redirect(location, status) {
|
|
29
|
+
return context.redirect(location, status);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function createAstroFormConfig(context) {
|
|
34
|
+
return {
|
|
35
|
+
runtime: resolveFormRuntimeCapabilities(context.locals),
|
|
36
|
+
bindings: getBindings(context.locals),
|
|
37
|
+
formsProvider: resolveFormsProvider(getTreeseedFormsProvider()),
|
|
38
|
+
formSecret: getFormSecret(),
|
|
39
|
+
turnstileSecret: getTurnstileSecret(),
|
|
40
|
+
contactRouting: getContactRoutingMap(),
|
|
41
|
+
subscribeRecipients: getSubscribeRecipients(),
|
|
42
|
+
smtpConfig: getSmtpConfig(),
|
|
43
|
+
siteUrl: SITE.url
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async function handleTokenRequest(context) {
|
|
47
|
+
return handleTokenRequestWithConfig(createAstroRequestContext(context), createAstroFormConfig(context));
|
|
48
|
+
}
|
|
49
|
+
async function handleFormSubmission(context) {
|
|
50
|
+
return handleFormSubmissionWithConfig(createAstroRequestContext(context), createAstroFormConfig(context));
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
handleFormSubmission,
|
|
54
|
+
handleTokenRequest
|
|
55
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createOpaqueId, signFormToken, verifyFormToken } from "./crypto.js";
|
|
2
|
+
import { FORM_SESSION_COOKIE } from "./constants.js";
|
|
3
|
+
async function issueFormToken(formType, secret) {
|
|
4
|
+
const sessionId = createOpaqueId();
|
|
5
|
+
const nonce = createOpaqueId();
|
|
6
|
+
const issuedAt = Date.now();
|
|
7
|
+
if (!secret) {
|
|
8
|
+
throw new Error("TREESEED_FORM_TOKEN_SECRET is not configured.");
|
|
9
|
+
}
|
|
10
|
+
const formToken = await signFormToken(
|
|
11
|
+
{
|
|
12
|
+
formType,
|
|
13
|
+
sessionId,
|
|
14
|
+
nonce,
|
|
15
|
+
issuedAt
|
|
16
|
+
},
|
|
17
|
+
secret
|
|
18
|
+
);
|
|
19
|
+
return {
|
|
20
|
+
formToken,
|
|
21
|
+
sessionId,
|
|
22
|
+
issuedAt,
|
|
23
|
+
nonce
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async function verifyIssuedToken(formToken, sessionId, formType, secret) {
|
|
27
|
+
if (!secret) {
|
|
28
|
+
return { ok: false, reason: "missing-secret" };
|
|
29
|
+
}
|
|
30
|
+
const result = await verifyFormToken(formToken, secret);
|
|
31
|
+
if (!result.ok) {
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
if (result.payload.sessionId !== sessionId || result.payload.formType !== formType) {
|
|
35
|
+
return { ok: false, reason: "mismatch", payload: result.payload };
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
function createSessionCookie(sessionId, requestUrl) {
|
|
40
|
+
const isSecureRequest = requestUrl?.protocol === "https:";
|
|
41
|
+
return {
|
|
42
|
+
name: FORM_SESSION_COOKIE,
|
|
43
|
+
value: sessionId,
|
|
44
|
+
options: {
|
|
45
|
+
httpOnly: true,
|
|
46
|
+
path: "/",
|
|
47
|
+
sameSite: "lax",
|
|
48
|
+
secure: isSecureRequest,
|
|
49
|
+
maxAge: 60 * 60
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
createSessionCookie,
|
|
55
|
+
issueFormToken,
|
|
56
|
+
verifyIssuedToken
|
|
57
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
async function createSocketContext(port, host) {
|
|
2
|
+
const { connect } = await import("cloudflare:sockets");
|
|
3
|
+
const socket = connect(
|
|
4
|
+
{ hostname: host, port },
|
|
5
|
+
{
|
|
6
|
+
secureTransport: port === 465 ? "on" : "off"
|
|
7
|
+
}
|
|
8
|
+
);
|
|
9
|
+
return {
|
|
10
|
+
socket,
|
|
11
|
+
reader: socket.readable.getReader(),
|
|
12
|
+
writer: socket.writable.getWriter()
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
async function readSmtpResponse(reader) {
|
|
16
|
+
const decoder = new TextDecoder();
|
|
17
|
+
let buffer = "";
|
|
18
|
+
while (true) {
|
|
19
|
+
const { value, done } = await reader.read();
|
|
20
|
+
if (done) break;
|
|
21
|
+
buffer += decoder.decode(value, { stream: true });
|
|
22
|
+
const lines = buffer.split("\r\n").filter(Boolean);
|
|
23
|
+
const lastLine = lines.at(-1);
|
|
24
|
+
if (lastLine && /^\d{3} /.test(lastLine)) {
|
|
25
|
+
return {
|
|
26
|
+
code: Number.parseInt(lastLine.slice(0, 3), 10),
|
|
27
|
+
raw: buffer
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
throw new Error("SMTP connection closed unexpectedly.");
|
|
32
|
+
}
|
|
33
|
+
async function sendCommand(context, command) {
|
|
34
|
+
await context.writer.write(new TextEncoder().encode(`${command}\r
|
|
35
|
+
`));
|
|
36
|
+
return readSmtpResponse(context.reader);
|
|
37
|
+
}
|
|
38
|
+
function normalizeBody(text) {
|
|
39
|
+
return text.replace(/\r?\n/g, "\r\n").split("\r\n").map((line) => line.startsWith(".") ? `.${line}` : line).join("\r\n");
|
|
40
|
+
}
|
|
41
|
+
function toEnvelopeAddress(value) {
|
|
42
|
+
const match = value.match(/<([^>]+)>/);
|
|
43
|
+
return (match?.[1] ?? value).trim();
|
|
44
|
+
}
|
|
45
|
+
function buildMessage({ to, subject, text, replyTo }, from) {
|
|
46
|
+
const headers = [
|
|
47
|
+
`From: ${from}`,
|
|
48
|
+
`To: ${to.join(", ")}`,
|
|
49
|
+
`Subject: ${subject}`,
|
|
50
|
+
"MIME-Version: 1.0",
|
|
51
|
+
"Content-Type: text/plain; charset=UTF-8",
|
|
52
|
+
`Date: ${(/* @__PURE__ */ new Date()).toUTCString()}`
|
|
53
|
+
];
|
|
54
|
+
if (replyTo) {
|
|
55
|
+
headers.push(`Reply-To: ${replyTo}`);
|
|
56
|
+
}
|
|
57
|
+
return `${headers.join("\r\n")}\r
|
|
58
|
+
\r
|
|
59
|
+
${normalizeBody(text)}\r
|
|
60
|
+
.`;
|
|
61
|
+
}
|
|
62
|
+
async function upgradeToTls(context) {
|
|
63
|
+
if (typeof context.socket.startTls !== "function") {
|
|
64
|
+
throw new Error("SMTP socket does not support STARTTLS upgrade.");
|
|
65
|
+
}
|
|
66
|
+
const secureSocket = context.socket.startTls();
|
|
67
|
+
return {
|
|
68
|
+
socket: secureSocket,
|
|
69
|
+
reader: secureSocket.readable.getReader(),
|
|
70
|
+
writer: secureSocket.writable.getWriter()
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function assertResponse(response, acceptedCodes) {
|
|
74
|
+
if (!acceptedCodes.includes(response.code)) {
|
|
75
|
+
throw new Error(`SMTP command failed: ${response.raw}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async function sendEmailWithCloudflareSockets(message, { smtp, siteUrl }) {
|
|
79
|
+
const envelopeFrom = toEnvelopeAddress(smtp.from);
|
|
80
|
+
if (!smtp.host || !smtp.port || !smtp.from || !envelopeFrom) {
|
|
81
|
+
throw new Error("SMTP is not fully configured for Cloudflare-compatible delivery.");
|
|
82
|
+
}
|
|
83
|
+
let context = await createSocketContext(smtp.port, smtp.host);
|
|
84
|
+
assertResponse(await readSmtpResponse(context.reader), [220]);
|
|
85
|
+
assertResponse(await sendCommand(context, `EHLO ${new URL(siteUrl).hostname}`), [250]);
|
|
86
|
+
if (smtp.port === 587) {
|
|
87
|
+
assertResponse(await sendCommand(context, "STARTTLS"), [220]);
|
|
88
|
+
context = await upgradeToTls(context);
|
|
89
|
+
assertResponse(await sendCommand(context, `EHLO ${new URL(siteUrl).hostname}`), [250]);
|
|
90
|
+
}
|
|
91
|
+
if (smtp.username) {
|
|
92
|
+
assertResponse(await sendCommand(context, "AUTH LOGIN"), [334]);
|
|
93
|
+
assertResponse(await sendCommand(context, btoa(smtp.username)), [334]);
|
|
94
|
+
assertResponse(await sendCommand(context, btoa(smtp.password)), [235]);
|
|
95
|
+
}
|
|
96
|
+
assertResponse(await sendCommand(context, `MAIL FROM:<${envelopeFrom}>`), [250]);
|
|
97
|
+
for (const recipient of message.to) {
|
|
98
|
+
assertResponse(await sendCommand(context, `RCPT TO:<${recipient}>`), [250, 251]);
|
|
99
|
+
}
|
|
100
|
+
assertResponse(await sendCommand(context, "DATA"), [354]);
|
|
101
|
+
assertResponse(await sendCommand(context, buildMessage(message, smtp.from)), [250]);
|
|
102
|
+
await sendCommand(context, "QUIT");
|
|
103
|
+
await context.writer.close();
|
|
104
|
+
}
|
|
105
|
+
export {
|
|
106
|
+
sendEmailWithCloudflareSockets
|
|
107
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import nodemailer from "nodemailer";
|
|
2
|
+
import { getSmtpConfig } from "./config.js";
|
|
3
|
+
async function sendEmailWithNode(message) {
|
|
4
|
+
const smtp = getSmtpConfig();
|
|
5
|
+
if (!smtp.host || !smtp.port || !smtp.from) {
|
|
6
|
+
throw new Error("SMTP is not fully configured for local delivery.");
|
|
7
|
+
}
|
|
8
|
+
const transporter = nodemailer.createTransport({
|
|
9
|
+
host: smtp.host,
|
|
10
|
+
port: smtp.port,
|
|
11
|
+
secure: smtp.port === 465,
|
|
12
|
+
auth: smtp.username ? {
|
|
13
|
+
user: smtp.username,
|
|
14
|
+
pass: smtp.password
|
|
15
|
+
} : void 0
|
|
16
|
+
});
|
|
17
|
+
await transporter.sendMail({
|
|
18
|
+
from: smtp.from,
|
|
19
|
+
to: message.to.join(", "),
|
|
20
|
+
subject: message.subject,
|
|
21
|
+
text: message.text,
|
|
22
|
+
replyTo: message.replyTo || smtp.replyTo || void 0
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
sendEmailWithNode
|
|
27
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
async function sendEmail(message, runtime, options) {
|
|
2
|
+
if (runtime.isCloudflareRuntime) {
|
|
3
|
+
const { sendEmailWithCloudflareSockets } = await import("./smtp-cloudflare.js");
|
|
4
|
+
return sendEmailWithCloudflareSockets(message, options);
|
|
5
|
+
}
|
|
6
|
+
throw new Error("Email delivery requires Cloudflare runtime bindings in this docs deployment.");
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
sendEmail
|
|
10
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { hashValue } from "./crypto.js";
|
|
2
|
+
const localSubscribers = globalThis.__treeseedFixtureSubscribers ?? /* @__PURE__ */ new Map();
|
|
3
|
+
globalThis.__treeseedFixtureSubscribers = localSubscribers;
|
|
4
|
+
async function upsertLocalSubscriber(input) {
|
|
5
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
6
|
+
const ipHash = await hashValue(input.ip || "unknown");
|
|
7
|
+
const existing = localSubscribers.get(input.email);
|
|
8
|
+
localSubscribers.set(input.email, {
|
|
9
|
+
email: input.email,
|
|
10
|
+
name: input.name,
|
|
11
|
+
source: input.source,
|
|
12
|
+
status: "active",
|
|
13
|
+
consentAt: now,
|
|
14
|
+
createdAt: existing?.createdAt ?? now,
|
|
15
|
+
updatedAt: now,
|
|
16
|
+
ipHash
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
upsertLocalSubscriber
|
|
21
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { hashValue } from "./crypto.js";
|
|
2
|
+
async function hasRuntimeRecordsTable(db) {
|
|
3
|
+
const row = await db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'runtime_records' LIMIT 1").first();
|
|
4
|
+
return Boolean(row?.name);
|
|
5
|
+
}
|
|
6
|
+
async function upsertSubscriber(db, input) {
|
|
7
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
8
|
+
const ipHash = await hashValue(input.ip || "unknown");
|
|
9
|
+
if (await hasRuntimeRecordsTable(db)) {
|
|
10
|
+
const payloadJson = JSON.stringify({
|
|
11
|
+
email: input.email,
|
|
12
|
+
name: input.name || null,
|
|
13
|
+
source: input.source,
|
|
14
|
+
consentAt: now,
|
|
15
|
+
ipHash
|
|
16
|
+
});
|
|
17
|
+
const metaJson = JSON.stringify({});
|
|
18
|
+
await db.prepare(
|
|
19
|
+
`INSERT INTO runtime_records (
|
|
20
|
+
record_type,
|
|
21
|
+
record_key,
|
|
22
|
+
lookup_key,
|
|
23
|
+
status,
|
|
24
|
+
schema_version,
|
|
25
|
+
created_at,
|
|
26
|
+
updated_at,
|
|
27
|
+
payload_json,
|
|
28
|
+
meta_json
|
|
29
|
+
) VALUES (?, ?, ?, 'active', 1, ?, ?, ?, ?)
|
|
30
|
+
ON CONFLICT(record_type, record_key) DO UPDATE SET
|
|
31
|
+
lookup_key = excluded.lookup_key,
|
|
32
|
+
status = 'active',
|
|
33
|
+
updated_at = excluded.updated_at,
|
|
34
|
+
payload_json = excluded.payload_json,
|
|
35
|
+
meta_json = excluded.meta_json`
|
|
36
|
+
).bind("subscription", input.email, input.email, now, now, payloadJson, metaJson).run();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await db.prepare(
|
|
40
|
+
`INSERT INTO subscriptions (email, name, status, source, consent_at, created_at, updated_at, ip_hash)
|
|
41
|
+
VALUES (?, ?, 'active', ?, ?, ?, ?, ?)
|
|
42
|
+
ON CONFLICT(email) DO UPDATE SET
|
|
43
|
+
name = excluded.name,
|
|
44
|
+
status = 'active',
|
|
45
|
+
source = excluded.source,
|
|
46
|
+
consent_at = excluded.consent_at,
|
|
47
|
+
updated_at = excluded.updated_at,
|
|
48
|
+
ip_hash = excluded.ip_hash`
|
|
49
|
+
).bind(input.email, input.name || null, input.source, now, now, now, ipHash).run();
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
upsertSubscriber
|
|
53
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
async function verifyTurnstileToken(token, remoteIp, expectedAction, runtime, secret) {
|
|
2
|
+
if (runtime.bypassTurnstile || !runtime.turnstileEnabled) {
|
|
3
|
+
return { ok: true, bypassed: true };
|
|
4
|
+
}
|
|
5
|
+
if (!secret || !token) {
|
|
6
|
+
return { ok: false, reason: "missing-config" };
|
|
7
|
+
}
|
|
8
|
+
const form = new FormData();
|
|
9
|
+
form.set("secret", secret);
|
|
10
|
+
form.set("response", token);
|
|
11
|
+
if (remoteIp) {
|
|
12
|
+
form.set("remoteip", remoteIp);
|
|
13
|
+
}
|
|
14
|
+
form.set("idempotency_key", crypto.randomUUID());
|
|
15
|
+
const response = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
|
|
16
|
+
method: "POST",
|
|
17
|
+
body: form
|
|
18
|
+
});
|
|
19
|
+
const result = await response.json();
|
|
20
|
+
if (!result.success || result.action !== expectedAction) {
|
|
21
|
+
return {
|
|
22
|
+
ok: false,
|
|
23
|
+
reason: "verification-failed",
|
|
24
|
+
errors: result["error-codes"] ?? []
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return { ok: true };
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
verifyTurnstileToken
|
|
31
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { CONTACT_TYPES } from "../../types/forms.js";
|
|
2
|
+
function normalizeEmail(value) {
|
|
3
|
+
return typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
4
|
+
}
|
|
5
|
+
function readText(value) {
|
|
6
|
+
return typeof value === "string" ? value.trim() : "";
|
|
7
|
+
}
|
|
8
|
+
function parsePayload(formData) {
|
|
9
|
+
const formType = readText(formData.get("formType"));
|
|
10
|
+
if (formType === "contact") {
|
|
11
|
+
const contactType = readText(formData.get("contactType"));
|
|
12
|
+
if (!CONTACT_TYPES.includes(contactType)) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const payload = {
|
|
16
|
+
formType,
|
|
17
|
+
name: readText(formData.get("name")),
|
|
18
|
+
email: normalizeEmail(formData.get("email")),
|
|
19
|
+
organization: readText(formData.get("organization")),
|
|
20
|
+
contactType,
|
|
21
|
+
subject: readText(formData.get("subject")),
|
|
22
|
+
message: readText(formData.get("message"))
|
|
23
|
+
};
|
|
24
|
+
return payload;
|
|
25
|
+
}
|
|
26
|
+
if (formType === "subscribe") {
|
|
27
|
+
const payload = {
|
|
28
|
+
formType,
|
|
29
|
+
email: normalizeEmail(formData.get("email")),
|
|
30
|
+
name: readText(formData.get("name"))
|
|
31
|
+
};
|
|
32
|
+
return payload;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function validatePayload(payload) {
|
|
37
|
+
if (payload.formType === "contact") {
|
|
38
|
+
if (!payload.name || !payload.email || !payload.subject || !payload.message) {
|
|
39
|
+
return { ok: false, message: "Please complete the required contact fields." };
|
|
40
|
+
}
|
|
41
|
+
if (payload.message.length < 10) {
|
|
42
|
+
return { ok: false, message: "Please share a bit more detail in your message." };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (payload.formType === "subscribe") {
|
|
46
|
+
if (!payload.email) {
|
|
47
|
+
return { ok: false, message: "Please provide your email address." };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(payload.email)) {
|
|
51
|
+
return { ok: false, message: "Please enter a valid email address." };
|
|
52
|
+
}
|
|
53
|
+
return { ok: true };
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
parsePayload,
|
|
57
|
+
validatePayload
|
|
58
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getCollection, getEntries, getEntry } from "astro:content";
|
|
2
|
+
function sortEntriesByDateDescending(entries) {
|
|
3
|
+
return [...entries].sort((left, right) => right.data.date.valueOf() - left.data.date.valueOf());
|
|
4
|
+
}
|
|
5
|
+
async function resolveContributor(reference) {
|
|
6
|
+
return getEntry(reference);
|
|
7
|
+
}
|
|
8
|
+
async function resolveContributorsForEntries(entries) {
|
|
9
|
+
const contributors = await Promise.all(entries.map((entry) => resolveContributor(entry.data.primaryContributor)));
|
|
10
|
+
return new Map(entries.map((entry, index) => [entry.id, contributors[index] ?? null]));
|
|
11
|
+
}
|
|
12
|
+
async function resolveReferences(references) {
|
|
13
|
+
return getEntries(references);
|
|
14
|
+
}
|
|
15
|
+
async function getPublishedQuestions() {
|
|
16
|
+
return sortEntriesByDateDescending(await getCollection("questions", ({ data }) => !data.draft));
|
|
17
|
+
}
|
|
18
|
+
async function getPublishedObjectives() {
|
|
19
|
+
return sortEntriesByDateDescending(await getCollection("objectives", ({ data }) => !data.draft));
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
getPublishedObjectives,
|
|
23
|
+
getPublishedQuestions,
|
|
24
|
+
resolveContributor,
|
|
25
|
+
resolveContributorsForEntries,
|
|
26
|
+
resolveReferences,
|
|
27
|
+
sortEntriesByDateDescending
|
|
28
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { loadTreeseedPluginRuntime } from "../plugins/runtime.js";
|
|
2
|
+
import { BUILTIN_FORMS_PROVIDERS, finalizeFormsProvider } from "./forms/provider-core.js";
|
|
3
|
+
import { StubExecutionAdapter, ManualExecutionAdapter, CopilotExecutionAdapter } from "./agents/adapters/execution.js";
|
|
4
|
+
import { LocalBranchMutationAdapter } from "./agents/adapters/mutations.js";
|
|
5
|
+
import { StubNotificationAdapter } from "./agents/adapters/notification.js";
|
|
6
|
+
import { GitRepositoryInspectionAdapter, StubRepositoryInspectionAdapter } from "./agents/adapters/repository.js";
|
|
7
|
+
import { StubResearchAdapter } from "./agents/adapters/research.js";
|
|
8
|
+
import { LocalVerificationAdapter, StubVerificationAdapter } from "./agents/adapters/verification.js";
|
|
9
|
+
let cachedAgentRuntime = null;
|
|
10
|
+
let cachedFormsRuntime = null;
|
|
11
|
+
function readPluginRecord(pluginEntry, key) {
|
|
12
|
+
const value = pluginEntry.plugin[key];
|
|
13
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
14
|
+
}
|
|
15
|
+
function assertUniqueProvider(registry, id, owner) {
|
|
16
|
+
if (registry.has(id)) {
|
|
17
|
+
throw new Error(`Treeseed plugin runtime found duplicate provider "${id}" from ${owner}.`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function resetTreeseedPluginRuntimeForTests() {
|
|
21
|
+
cachedAgentRuntime = null;
|
|
22
|
+
cachedFormsRuntime = null;
|
|
23
|
+
}
|
|
24
|
+
function resolveFormsProvider(providerId) {
|
|
25
|
+
if (!cachedFormsRuntime) {
|
|
26
|
+
const runtime = loadTreeseedPluginRuntime();
|
|
27
|
+
const providers = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const provider2 of Object.values(BUILTIN_FORMS_PROVIDERS)) {
|
|
29
|
+
providers.set(provider2.id, provider2);
|
|
30
|
+
}
|
|
31
|
+
for (const pluginEntry of runtime.plugins) {
|
|
32
|
+
const contributedProviders = readPluginRecord(pluginEntry, "formsProviders");
|
|
33
|
+
for (const [id, provider2] of Object.entries(contributedProviders)) {
|
|
34
|
+
assertUniqueProvider(providers, id, pluginEntry.package);
|
|
35
|
+
providers.set(id, provider2);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
cachedFormsRuntime = { providers };
|
|
39
|
+
}
|
|
40
|
+
const provider = cachedFormsRuntime.providers.get(providerId);
|
|
41
|
+
if (!provider) {
|
|
42
|
+
throw new Error(`Treeseed forms provider "${providerId}" is not registered.`);
|
|
43
|
+
}
|
|
44
|
+
return finalizeFormsProvider(provider);
|
|
45
|
+
}
|
|
46
|
+
function collectAgentHandlersFromPlugin(pluginEntry, registry) {
|
|
47
|
+
const contributedHandlers = readPluginRecord(pluginEntry, "agentHandlers");
|
|
48
|
+
for (const [id, handler] of Object.entries(contributedHandlers)) {
|
|
49
|
+
assertUniqueProvider(registry, id, pluginEntry.package);
|
|
50
|
+
registry.set(id, handler);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function buildAgentRuntime() {
|
|
54
|
+
const runtime = loadTreeseedPluginRuntime();
|
|
55
|
+
const execution = /* @__PURE__ */ new Map([
|
|
56
|
+
["stub", () => new StubExecutionAdapter()],
|
|
57
|
+
["manual", () => new ManualExecutionAdapter()],
|
|
58
|
+
["copilot", () => new CopilotExecutionAdapter()]
|
|
59
|
+
]);
|
|
60
|
+
const mutation = /* @__PURE__ */ new Map([
|
|
61
|
+
["local_branch", (repoRoot) => new LocalBranchMutationAdapter(repoRoot)]
|
|
62
|
+
]);
|
|
63
|
+
const repository = /* @__PURE__ */ new Map([
|
|
64
|
+
["stub", () => new StubRepositoryInspectionAdapter()],
|
|
65
|
+
["git", () => new GitRepositoryInspectionAdapter()]
|
|
66
|
+
]);
|
|
67
|
+
const verification = /* @__PURE__ */ new Map([
|
|
68
|
+
["stub", () => new StubVerificationAdapter()],
|
|
69
|
+
["local", () => new LocalVerificationAdapter()]
|
|
70
|
+
]);
|
|
71
|
+
const notification = /* @__PURE__ */ new Map([
|
|
72
|
+
["stub", () => new StubNotificationAdapter()]
|
|
73
|
+
]);
|
|
74
|
+
const research = /* @__PURE__ */ new Map([
|
|
75
|
+
["stub", () => new StubResearchAdapter()]
|
|
76
|
+
]);
|
|
77
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
78
|
+
for (const pluginEntry of runtime.plugins) {
|
|
79
|
+
const agentProviders = readPluginRecord(pluginEntry, "agentProviders");
|
|
80
|
+
for (const [id, factory] of Object.entries(agentProviders.execution ?? {})) {
|
|
81
|
+
assertUniqueProvider(execution, id, pluginEntry.package);
|
|
82
|
+
execution.set(id, factory);
|
|
83
|
+
}
|
|
84
|
+
for (const [id, factory] of Object.entries(
|
|
85
|
+
agentProviders.mutation ?? {}
|
|
86
|
+
)) {
|
|
87
|
+
assertUniqueProvider(mutation, id, pluginEntry.package);
|
|
88
|
+
mutation.set(id, factory);
|
|
89
|
+
}
|
|
90
|
+
for (const [id, factory] of Object.entries(
|
|
91
|
+
agentProviders.repository ?? {}
|
|
92
|
+
)) {
|
|
93
|
+
assertUniqueProvider(repository, id, pluginEntry.package);
|
|
94
|
+
repository.set(id, factory);
|
|
95
|
+
}
|
|
96
|
+
for (const [id, factory] of Object.entries(
|
|
97
|
+
agentProviders.verification ?? {}
|
|
98
|
+
)) {
|
|
99
|
+
assertUniqueProvider(verification, id, pluginEntry.package);
|
|
100
|
+
verification.set(id, factory);
|
|
101
|
+
}
|
|
102
|
+
for (const [id, factory] of Object.entries(
|
|
103
|
+
agentProviders.notification ?? {}
|
|
104
|
+
)) {
|
|
105
|
+
assertUniqueProvider(notification, id, pluginEntry.package);
|
|
106
|
+
notification.set(id, factory);
|
|
107
|
+
}
|
|
108
|
+
for (const [id, factory] of Object.entries(
|
|
109
|
+
agentProviders.research ?? {}
|
|
110
|
+
)) {
|
|
111
|
+
assertUniqueProvider(research, id, pluginEntry.package);
|
|
112
|
+
research.set(id, factory);
|
|
113
|
+
}
|
|
114
|
+
collectAgentHandlersFromPlugin(pluginEntry, handlers);
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
providers: {
|
|
118
|
+
execution,
|
|
119
|
+
mutation,
|
|
120
|
+
repository,
|
|
121
|
+
verification,
|
|
122
|
+
notification,
|
|
123
|
+
research
|
|
124
|
+
},
|
|
125
|
+
handlers
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function resolveAgentRuntimeProviders(repoRoot, selections) {
|
|
129
|
+
if (!cachedAgentRuntime) {
|
|
130
|
+
cachedAgentRuntime = buildAgentRuntime();
|
|
131
|
+
}
|
|
132
|
+
const executionFactory = cachedAgentRuntime.providers.execution.get(selections.execution);
|
|
133
|
+
const mutationFactory = cachedAgentRuntime.providers.mutation.get(selections.mutation);
|
|
134
|
+
const repositoryFactory = cachedAgentRuntime.providers.repository.get(selections.repository);
|
|
135
|
+
const verificationFactory = cachedAgentRuntime.providers.verification.get(selections.verification);
|
|
136
|
+
const notificationFactory = cachedAgentRuntime.providers.notification.get(selections.notification);
|
|
137
|
+
const researchFactory = cachedAgentRuntime.providers.research.get(selections.research);
|
|
138
|
+
if (!executionFactory) throw new Error(`Treeseed agent execution provider "${selections.execution}" is not registered.`);
|
|
139
|
+
if (!mutationFactory) throw new Error(`Treeseed agent mutation provider "${selections.mutation}" is not registered.`);
|
|
140
|
+
if (!repositoryFactory) throw new Error(`Treeseed agent repository provider "${selections.repository}" is not registered.`);
|
|
141
|
+
if (!verificationFactory) throw new Error(`Treeseed agent verification provider "${selections.verification}" is not registered.`);
|
|
142
|
+
if (!notificationFactory) throw new Error(`Treeseed agent notification provider "${selections.notification}" is not registered.`);
|
|
143
|
+
if (!researchFactory) throw new Error(`Treeseed agent research provider "${selections.research}" is not registered.`);
|
|
144
|
+
return {
|
|
145
|
+
execution: executionFactory(),
|
|
146
|
+
mutations: mutationFactory(repoRoot),
|
|
147
|
+
repository: repositoryFactory(),
|
|
148
|
+
verification: verificationFactory(),
|
|
149
|
+
notifications: notificationFactory(),
|
|
150
|
+
research: researchFactory(),
|
|
151
|
+
handlers: cachedAgentRuntime.handlers
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
export {
|
|
155
|
+
resetTreeseedPluginRuntimeForTests,
|
|
156
|
+
resolveAgentRuntimeProviders,
|
|
157
|
+
resolveFormsProvider
|
|
158
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SITE_HEADER_MENU } from "./site-config.js";
|
|
2
|
+
const SITE_NAV_GROUPS = SITE_HEADER_MENU;
|
|
3
|
+
function normalizeSitePath(path) {
|
|
4
|
+
return path.endsWith("/") ? path : `${path}/`;
|
|
5
|
+
}
|
|
6
|
+
function isCurrentSitePath(currentPath, href) {
|
|
7
|
+
return normalizeSitePath(currentPath) === normalizeSitePath(href);
|
|
8
|
+
}
|
|
9
|
+
function groupContainsCurrentPath(currentPath, group) {
|
|
10
|
+
return group.items.some((item) => isCurrentSitePath(currentPath, item.href));
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
SITE_NAV_GROUPS,
|
|
14
|
+
groupContainsCurrentPath,
|
|
15
|
+
isCurrentSitePath,
|
|
16
|
+
normalizeSitePath
|
|
17
|
+
};
|