@astryxdesign/cli 0.7.2 → 0.7.3-canary.02f5fe4
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 +104 -71
- package/api/build/_adapter.d.mts +58 -0
- package/api/build/_adapter.mjs +127 -3
- package/api/build/blocks/blocks.d.mts +92 -0
- package/api/build/blocks/blocks.mjs +528 -0
- package/api/build/blocks/blocks.test.mjs +238 -0
- package/api/build/blocks/blocks.weights.json +1 -0
- package/api/build/build.mjs +25 -6
- package/api/build/build.type.mjs +1 -1
- package/api/build/kit/answer.d.mts +18 -0
- package/api/build/kit/answer.mjs +195 -0
- package/api/build/kit/answer.test.mjs +108 -0
- package/api/build/kit/kind.d.mts +25 -0
- package/api/build/kit/kind.mjs +170 -0
- package/api/build/kit/kit.d.mts +2 -4
- package/api/build/kit/kit.mjs +8 -398
- package/api/build/kit/rank.d.mts +3 -32
- package/api/build/kit/rank.mjs +25 -342
- package/api/build/kit/rank.test.mjs +2 -1
- package/api/build/kit/signals.d.mts +79 -0
- package/api/build/kit/signals.mjs +295 -0
- package/api/build/kit/start.d.mts +32 -0
- package/api/build/kit/start.mjs +163 -0
- package/api/build/kit/words.d.mts +72 -0
- package/api/build/kit/words.mjs +202 -0
- package/api/build/tree.d.mts +20 -0
- package/api/build/tree.mjs +53 -0
- package/api/build/tree.test.mjs +185 -0
- package/api/build/tree.weights.json +1 -0
- package/api/component/_adapter.mjs +39 -5
- package/api/component/component-replacement.test.mjs +1 -0
- package/api/component/component.mjs +17 -3
- package/api/component/component.test.mjs +15 -0
- package/api/component/doc-links.test.mjs +2 -2
- package/api/discover/_adapter.d.mts +1 -2
- package/api/discover/_adapter.mjs +42 -17
- package/api/discover/_adapter.test.mjs +42 -0
- package/api/discover/discover.mjs +0 -1
- package/api/docs/_adapter.d.mts +2 -2
- package/api/docs/_adapter.mjs +82 -23
- package/api/docs/docs-homes.test.mjs +127 -0
- package/api/docs/docs.doc.mjs +3 -3
- package/api/docs/docs.test.mjs +35 -19
- package/api/docs/integration-tree.test.mjs +20 -20
- package/api/docs/integrationDocs.test.mjs +1 -1
- package/api/docs/namespace-section.test.mjs +6 -6
- package/api/docs/reference-blocks.test.mjs +2 -2
- package/api/doctor/_adapter.d.mts +33 -13
- package/api/doctor/_adapter.mjs +55 -25
- package/api/doctor/doctor.d.mts +23 -5
- package/api/doctor/doctor.mjs +183 -40
- package/api/doctor/doctor.test.mjs +95 -12
- package/api/hook/hook.mjs +1 -1
- package/api/init/init.doc.mjs +20 -6
- package/api/init/init.test.mjs +18 -2
- package/api/init/init.type.d.mts +3 -3
- package/api/init/init.type.mjs +3 -3
- package/api/init/remove/remove.mjs +17 -4
- package/api/init/remove/remove.test.mjs +114 -2
- package/api/init/run/run.mjs +69 -6
- package/api/integration/_adapter.d.mts +8 -0
- package/api/integration/_adapter.mjs +21 -1
- package/api/integration/authoring-checks.mjs +83 -9
- package/api/integration/authoring-checks.test.mjs +220 -0
- package/api/integration/pack-check.mjs +123 -4
- package/api/integration/pack-check.test.mjs +87 -0
- package/api/integration/validate-integration-case-disk.test.mjs +111 -0
- package/api/integration/validate-integration-fixes.test.mjs +6 -5
- package/api/integration/validate-integration-gaps.test.mjs +1975 -0
- package/api/integration/validate-integration.d.mts +15 -2
- package/api/integration/validate-integration.mjs +298 -39
- package/api/integration/validate-integration.type.d.mts +90 -1
- package/api/integration/validate-integration.type.mjs +67 -2
- package/api/integration/validateIntegration.doc.mjs +1 -1
- package/api/search/ORDERING.md +28 -0
- package/api/search/_adapter.d.mts +82 -2
- package/api/search/_adapter.mjs +157 -10
- package/api/search/_adapter.test.mjs +173 -0
- package/api/search/_candidate-score.d.mts +40 -0
- package/api/search/_candidate-score.mjs +238 -0
- package/api/search/_cards.json +6098 -0
- package/api/search/_compound.d.mts +50 -0
- package/api/search/_compound.mjs +170 -0
- package/api/search/_doc-searcher.d.mts +4 -0
- package/api/search/_doc-searcher.mjs +23 -0
- package/api/search/_doc-searcher.test.mjs +36 -0
- package/api/search/_doc-searcher.weights.json +1 -0
- package/api/search/_doc-text.d.mts +30 -0
- package/api/search/_doc-text.mjs +87 -0
- package/api/search/_entries.d.mts +63 -0
- package/api/search/_entries.mjs +232 -0
- package/api/search/_entries.test.mjs +48 -0
- package/api/search/_features.d.mts +35 -0
- package/api/search/_features.mjs +155 -0
- package/api/search/_gather-components.d.mts +26 -0
- package/api/search/_gather-components.mjs +284 -0
- package/api/search/_gather-docs.d.mts +20 -0
- package/api/search/_gather-docs.mjs +254 -0
- package/api/search/_gather-hooks.d.mts +12 -0
- package/api/search/_gather-hooks.mjs +52 -0
- package/api/search/_gather-templates.d.mts +25 -0
- package/api/search/_gather-templates.mjs +107 -0
- package/api/search/_lexical.d.mts +135 -0
- package/api/search/_lexical.mjs +351 -0
- package/api/search/_main-searcher.d.mts +19 -0
- package/api/search/_main-searcher.mjs +115 -0
- package/api/search/_main-searcher.test.mjs +106 -0
- package/api/search/_main-searcher.weights.json +1 -0
- package/api/search/_module-doc.d.mts +32 -0
- package/api/search/_module-doc.mjs +78 -0
- package/api/search/_order.d.mts +32 -0
- package/api/search/_order.mjs +162 -0
- package/api/search/_order.test.mjs +72 -0
- package/api/search/_priority.d.mts +50 -0
- package/api/search/_priority.mjs +139 -0
- package/api/search/_query-words.d.mts +25 -0
- package/api/search/_query-words.mjs +92 -0
- package/api/search/_query.d.mts +65 -0
- package/api/search/_query.mjs +176 -0
- package/api/search/_result.d.mts +97 -0
- package/api/search/_result.mjs +150 -0
- package/api/search/_score.d.mts +60 -0
- package/api/search/_score.mjs +283 -0
- package/api/search/_synonyms.d.mts +21 -0
- package/api/search/_synonyms.mjs +67 -0
- package/api/search/_template-searcher.d.mts +4 -0
- package/api/search/_template-searcher.mjs +23 -0
- package/api/search/_template-searcher.test.mjs +40 -0
- package/api/search/_template-searcher.weights.json +1 -0
- package/api/search/_titles.d.mts +33 -0
- package/api/search/_titles.mjs +65 -0
- package/api/search/_words.d.mts +64 -0
- package/api/search/_words.mjs +157 -0
- package/api/search/search.d.mts +22 -305
- package/api/search/search.doc.mjs +8 -6
- package/api/search/search.mjs +56 -2482
- package/api/search/search.test.mjs +14 -14
- package/api/search/search.type.d.mts +6 -1
- package/api/search/search.type.mjs +6 -1
- package/api/search/tree.d.mts +15 -0
- package/api/search/tree.mjs +40 -0
- package/api/search/tree.test.mjs +66 -0
- package/api/search/tree.weights.json +1 -0
- package/api/template/template.mjs +5 -1
- package/api/theme/build/build.packed-old-core.test.mjs +1 -0
- package/api/upgrade/_adapter.d.mts +57 -9
- package/api/upgrade/_adapter.mjs +198 -28
- package/api/upgrade/registry/registry.d.mts +10 -4
- package/api/upgrade/registry/registry.mjs +33 -16
- package/api/upgrade/registry/registry.test.mjs +85 -0
- package/api/upgrade/run/run.d.mts +4 -2
- package/api/upgrade/run/run.mjs +13 -2
- package/api/upgrade/run/run.test.mjs +417 -3
- package/api/upgrade/upgrade.doc.mjs +10 -5
- package/api/upgrade/upgrade.mjs +13 -2
- package/api/upgrade/upgrade.test.mjs +194 -0
- package/api/upgrade/upgrade.type.d.mts +5 -3
- package/api/upgrade/upgrade.type.mjs +8 -6
- package/assets/codemods/transforms/v0.7.0/__tests__/validate-data-token-ownership.test.mjs +11 -0
- package/assets/codemods/transforms/v0.7.0/validate-data-token-ownership.mjs +3 -3
- package/assets/docs/author-a-theme.doc.mjs +2 -2
- package/assets/docs/is-my-code-good.doc.mjs +287 -0
- package/assets/docs/tree/add-a-component.doc.mjs +1 -1
- package/assets/docs/tree/add-a-theme.doc.mjs +1 -1
- package/assets/docs/tree/add-a-topic.doc.mjs +2 -2
- package/assets/docs/tree/agent-guidance.doc.mjs +1 -1
- package/assets/docs/tree/api.doc.mjs +6 -0
- package/assets/docs/tree/{integrations.doc.mjs → authoring.doc.mjs} +15 -6
- package/assets/docs/tree/block-template.doc.mjs +1 -1
- package/assets/docs/tree/build-the-template.doc.mjs +1 -1
- package/assets/docs/tree/building-blocks.doc.mjs +2 -2
- package/assets/docs/tree/check-the-props.doc.mjs +1 -1
- package/assets/docs/tree/check-your-docs.doc.mjs +2 -2
- package/assets/docs/tree/checks.doc.mjs +3 -3
- package/assets/docs/tree/ci-and-containers.doc.mjs +13 -0
- package/assets/docs/tree/cli-command.doc.mjs +1 -1
- package/assets/docs/tree/cli.doc.mjs +1 -1
- package/assets/docs/tree/codemods.doc.mjs +1 -1
- package/assets/docs/tree/component-family.doc.mjs +1 -1
- package/assets/docs/tree/component-imports.doc.mjs +1 -1
- package/assets/docs/tree/components.doc.mjs +1 -1
- package/assets/docs/tree/configuration.doc.mjs +1 -1
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +1 -1
- package/assets/docs/tree/define-the-theme.doc.mjs +1 -1
- package/assets/docs/tree/describe-the-component.doc.mjs +1 -1
- package/assets/docs/tree/docs.doc.mjs +1 -1
- package/assets/docs/tree/document-the-template.doc.mjs +1 -1
- package/assets/docs/tree/document-the-theme.doc.mjs +1 -1
- package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
- package/assets/docs/tree/extend-or-replace.doc.mjs +1 -1
- package/assets/docs/{authoring.doc.mjs → tree/field-reference.doc.mjs} +4 -3
- package/assets/docs/tree/fonts-and-assets.doc.mjs +1 -1
- package/assets/docs/tree/generate-a-palette.doc.mjs +1 -1
- package/assets/docs/tree/global-integrations.doc.mjs +2 -2
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +4 -4
- package/assets/docs/tree/help.doc.mjs +2 -2
- package/assets/docs/tree/host-entry.doc.mjs +128 -0
- package/assets/docs/tree/links.doc.mjs +1 -1
- package/assets/docs/tree/package-and-test.doc.mjs +1 -1
- package/assets/docs/tree/page-template.doc.mjs +1 -1
- package/assets/docs/tree/publishing.doc.mjs +1 -1
- package/assets/docs/tree/quick-start.doc.mjs +1 -1
- package/assets/docs/tree/replace-a-core-component.doc.mjs +1 -1
- package/assets/docs/tree/replace-a-core-template.doc.mjs +1 -1
- package/assets/docs/tree/sections-and-placement.doc.mjs +1 -1
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +1 -1
- package/assets/docs/tree/ship.doc.mjs +2 -2
- package/assets/docs/tree/short-and-findable.doc.mjs +1 -1
- package/assets/docs/tree/single-component.doc.mjs +1 -1
- package/assets/docs/tree/start-a-template.doc.mjs +1 -1
- package/assets/docs/tree/subcomponent.doc.mjs +1 -1
- package/assets/docs/tree/template-assets.doc.mjs +1 -1
- package/assets/docs/tree/template-doc-overview.doc.mjs +2 -2
- package/assets/docs/tree/template-fonts.doc.mjs +1 -1
- package/assets/docs/tree/template-grading-rubric.doc.mjs +17 -38
- package/assets/docs/tree/template-icons.doc.mjs +1 -1
- package/assets/docs/tree/template-images-media.doc.mjs +1 -1
- package/assets/docs/tree/template-styles.doc.mjs +1 -1
- package/assets/docs/tree/templates.doc.mjs +1 -1
- package/assets/docs/tree/test-in-an-app.doc.mjs +1 -1
- package/assets/docs/tree/test-template-in-app.doc.mjs +1 -1
- package/assets/docs/tree/themes.doc.mjs +1 -1
- package/assets/docs/tree/tokens-data.doc.mjs +2 -2
- package/assets/docs/tree/troubleshooting.doc.mjs +1 -1
- package/assets/docs/tree/upgrading.doc.mjs +1 -1
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +1 -1
- package/assets/docs/tree/verify-packed-template.doc.mjs +1 -1
- package/assets/docs/tree/versioning.doc.mjs +5 -1
- package/assets/docs/tree/write-good-templates.doc.mjs +1 -1
- package/assets/docs/tree/write-the-template-file.doc.mjs +1 -1
- package/assets/docs/use-integrations.doc.mjs +120 -0
- package/assets/docs/working-with-ai.doc.mjs +6 -2
- package/assets/templates/themes/butter/butterTheme.ts +4 -2
- package/assets/templates/themes/stone/stoneTheme.ts +4 -2
- package/assets/templates/themes/y2k/y2kTheme.ts +4 -2
- package/authoring/debug/parse.d.mts +1 -1
- package/authoring/doctypes/schema/schema.doc.mjs +1 -1
- package/authoring/integration/integration.doc.mjs +1 -1
- package/authoring/integration/type.ts +1 -1
- package/clients/cli/bin/astryx.mjs +7 -78
- package/clients/cli/command-result-coverage.test.mjs +6 -5
- package/clients/cli/commands/build-theme.color-scheme.test.mjs +1 -1
- package/clients/cli/commands/{component/index.mjs → component.mjs} +37 -37
- package/clients/cli/commands/component.test.mjs +6 -6
- package/clients/cli/commands/docs.doc.mjs +2 -2
- package/clients/cli/commands/docs.mjs +1 -1
- package/clients/cli/commands/docs.test.mjs +14 -14
- package/clients/cli/commands/doctor-integration.test.mjs +49 -1
- package/clients/cli/commands/doctor.doc.mjs +1 -1
- package/clients/cli/commands/doctor.mjs +40 -0
- package/clients/cli/commands/doctor.test.mjs +65 -0
- package/clients/cli/commands/{hook/index.mjs → hook.mjs} +22 -22
- package/clients/cli/commands/import-hint-correctness.test.mjs +1 -1
- package/clients/cli/commands/init.behavior.test.mjs +230 -1
- package/clients/cli/commands/init.doc.mjs +28 -9
- package/clients/cli/commands/init.flag-help.test.mjs +1 -0
- package/clients/cli/commands/init.mjs +2 -2
- package/clients/cli/commands/integration-check.test.mjs +48 -0
- package/clients/cli/commands/integration.doc.mjs +1 -1
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/manifest.mjs +67 -0
- package/clients/cli/commands/outside-project.test.mjs +101 -1
- package/clients/cli/commands/postinstall.doc.mjs +23 -0
- package/clients/cli/commands/postinstall.mjs +31 -0
- package/clients/cli/commands/setup-nudge.test.mjs +78 -0
- package/clients/cli/commands/{build-theme.mjs → theme.mjs} +1 -1
- package/clients/cli/commands/upgrade.doc.mjs +4 -2
- package/clients/cli/commands/upgrade.mjs +9 -2
- package/clients/cli/commands/upgrade.subfolder-path.test.mjs +97 -0
- package/clients/cli/index.mjs +54 -94
- package/clients/cli/lib/component-format.mjs +1 -1
- package/clients/cli/lib/define-command.mjs +12 -7
- package/clients/cli/lib/exit-codes.test.mjs +5 -0
- package/clients/cli/lib/manifest.test.mjs +12 -0
- package/clients/cli/lib/welcome-box.mjs +50 -0
- package/clients/cli/run.mjs +108 -0
- package/foundation/agent-docs/agent-doc-state.d.mts +32 -7
- package/foundation/agent-docs/agent-doc-state.mjs +58 -9
- package/foundation/agent-docs/agent-docs.d.mts +100 -12
- package/foundation/agent-docs/agent-docs.mjs +1017 -105
- package/foundation/agent-docs/agent-docs.path-safety.test.mjs +1239 -17
- package/foundation/agent-docs/agent-docs.test.mjs +683 -39
- package/foundation/agent-docs/computer-agent-text.d.mts +39 -2
- package/foundation/agent-docs/computer-agent-text.mjs +135 -8
- package/foundation/agent-docs/computer-agent-text.test.mjs +99 -2
- package/foundation/config/project.mjs +20 -22
- package/foundation/config/project.test.mjs +56 -0
- package/foundation/discovery/authoring-self-docs.d.mts +7 -0
- package/foundation/discovery/authoring-self-docs.mjs +16 -4
- package/foundation/discovery/authoring-self-docs.test.mjs +15 -3
- package/foundation/discovery/authoring-surface.d.mts +1 -1
- package/foundation/discovery/authoring-surface.mjs +2 -2
- package/foundation/discovery/authoring-surface.test.mjs +1 -1
- package/foundation/discovery/cli-self-docs.d.mts +2 -1
- package/foundation/discovery/cli-self-docs.mjs +4 -3
- package/foundation/discovery/cli-self-docs.test.mjs +2 -2
- package/foundation/discovery/component-discovery.d.mts +37 -0
- package/foundation/discovery/component-discovery.mjs +80 -5
- package/foundation/discovery/component-loader.d.mts +1 -1
- package/foundation/discovery/docs-discovery.mjs +14 -1
- package/foundation/discovery/module-exports.d.mts +41 -0
- package/foundation/discovery/module-exports.mjs +253 -0
- package/foundation/discovery/runner-allowlist.d.mts +2 -4
- package/foundation/discovery/runner-allowlist.mjs +2 -4
- package/foundation/discovery/runner-commands.d.mts +77 -0
- package/foundation/discovery/runner-commands.mjs +294 -0
- package/foundation/discovery/runner-commands.test.mjs +128 -0
- package/foundation/discovery/stray-pointers.test.mjs +1 -1
- package/foundation/discovery/template-adapter.mjs +18 -1
- package/foundation/discovery/template-needs.mjs +1 -44
- package/foundation/discovery/theme-discovery.mjs +147 -3
- package/foundation/doc-compiler/doc-loads.test.mjs +33 -9
- package/foundation/doc-compiler/read.mjs +59 -1
- package/foundation/doc-compiler/read.test.mjs +11 -2
- package/foundation/doc-compiler/split-topic-keywords.test.mjs +3 -2
- package/foundation/doc-compiler/tree.d.mts +32 -6
- package/foundation/doc-compiler/tree.mjs +77 -43
- package/foundation/doc-compiler/tree.test.mjs +7 -7
- package/foundation/fs/paths.d.mts +70 -8
- package/foundation/fs/paths.mjs +556 -38
- package/foundation/fs/paths.test.mjs +430 -54
- package/foundation/fs/read-record.d.mts +18 -0
- package/foundation/fs/read-record.mjs +131 -0
- package/foundation/fs/read-record.test.mjs +77 -0
- package/foundation/integrations/autolink.d.mts +2 -1
- package/foundation/integrations/autolink.mjs +4 -13
- package/foundation/integrations/cli-peer-version.d.mts +36 -0
- package/foundation/integrations/cli-peer-version.mjs +132 -0
- package/foundation/integrations/cli-peer-version.test.mjs +354 -0
- package/foundation/integrations/computer-integrations.d.mts +6 -3
- package/foundation/integrations/computer-integrations.mjs +38 -9
- package/foundation/integrations/contribution-inventory.d.mts +15 -20
- package/foundation/integrations/contribution-inventory.mjs +41 -5
- package/foundation/integrations/exports-subpaths.d.mts +57 -0
- package/foundation/integrations/exports-subpaths.mjs +113 -0
- package/foundation/integrations/integrations.d.mts +27 -1
- package/foundation/integrations/integrations.mjs +61 -2
- package/foundation/integrations/public-imports.d.mts +118 -0
- package/foundation/integrations/public-imports.mjs +1769 -0
- package/foundation/integrations/public-imports.test.mjs +1793 -0
- package/foundation/integrations/validate-contributions.d.mts +115 -0
- package/foundation/integrations/validate-contributions.mjs +1168 -13
- package/foundation/release/cache.test.mjs +24 -21
- package/foundation/release/global-state.d.mts +8 -4
- package/foundation/release/global-state.mjs +4 -2
- package/foundation/release/handoff.d.mts +23 -4
- package/foundation/release/handoff.mjs +175 -8
- package/foundation/release/notices.d.mts +62 -8
- package/foundation/release/notices.mjs +136 -25
- package/foundation/release/notices.test.mjs +21 -0
- package/foundation/release/run-context.mjs +14 -0
- package/foundation/response/response-types.doc.mjs +1 -1
- package/foundation/route/route.d.mts +285 -0
- package/foundation/route/route.mjs +324 -0
- package/foundation/route/route.test.mjs +153 -0
- package/foundation/runtime/hosted-runtime.test.mjs +403 -0
- package/foundation/runtime/locked-versions.d.mts +32 -0
- package/foundation/runtime/locked-versions.mjs +65 -0
- package/foundation/runtime/package-root.d.mts +91 -0
- package/foundation/runtime/package-root.mjs +174 -0
- package/foundation/runtime/package-set.d.mts +62 -0
- package/foundation/runtime/package-set.mjs +130 -0
- package/foundation/runtime/package-set.test.mjs +432 -0
- package/foundation/text/string-utils.d.mts +2 -1
- package/foundation/text/string-utils.mjs +16 -5
- package/foundation/text/suggest-order.d.mts +72 -0
- package/foundation/text/suggest-order.mjs +363 -0
- package/foundation/text/suggest-order.test.mjs +259 -0
- package/host/door-conformance.test.mjs +274 -0
- package/host/index.d.ts +116 -0
- package/host/index.mjs +295 -0
- package/host/index.test.mjs +302 -0
- package/package.json +14 -9
|
@@ -43,9 +43,11 @@ import {userConfigDir} from '../env/user-dirs.mjs';
|
|
|
43
43
|
import {astryxCommandsOnSearchPath} from '../env/search-path.mjs';
|
|
44
44
|
import {
|
|
45
45
|
CLI_PACKAGE,
|
|
46
|
+
commandInFolder,
|
|
46
47
|
detectPackageManager,
|
|
47
48
|
getCliInvocation,
|
|
48
49
|
} from '../env/package-manager.mjs';
|
|
50
|
+
import {findAstryxProject, findPackageRoot} from '../fs/paths.mjs';
|
|
49
51
|
import {satisfiesRange, semverCompare} from '../env/semver.mjs';
|
|
50
52
|
import {isInReleaseCache, isReleaseVersion} from './cache.mjs';
|
|
51
53
|
import {
|
|
@@ -55,7 +57,12 @@ import {
|
|
|
55
57
|
tryStateLock,
|
|
56
58
|
writeGlobalState,
|
|
57
59
|
} from './global-state.mjs';
|
|
58
|
-
import {
|
|
60
|
+
import {
|
|
61
|
+
coreVersionOf,
|
|
62
|
+
globalFolderOf,
|
|
63
|
+
isGlobalCopy,
|
|
64
|
+
projectRootOf,
|
|
65
|
+
} from './choose.mjs';
|
|
59
66
|
import {readReleaseFacts} from './project.mjs';
|
|
60
67
|
import {samePath} from '../fs/path-compare.mjs';
|
|
61
68
|
import {updateNoticesOff} from './update-notice-env.mjs';
|
|
@@ -375,16 +382,49 @@ const ADD = {
|
|
|
375
382
|
bun: 'bun add',
|
|
376
383
|
};
|
|
377
384
|
|
|
385
|
+
/**
|
|
386
|
+
* The command that adds a package to the project of a run in `cwd`, with the
|
|
387
|
+
* project's package manager (spec AST-081 FR12). Null when `cwd` belongs to
|
|
388
|
+
* no project `spec:AST-040` FR9 defines, and in a folder inside the project
|
|
389
|
+
* whose package.json is not the project's (see {@link installFolder}): a run
|
|
390
|
+
* there loads integrations from that package.json, so a package added to the
|
|
391
|
+
* project would stay unused there, and the advice is
|
|
392
|
+
* {@link RUN_FROM_PROJECT}.
|
|
393
|
+
* @param {string} cwd
|
|
394
|
+
* @returns {((name: string) => string) | null}
|
|
395
|
+
*/
|
|
396
|
+
export function projectAddCommand(cwd) {
|
|
397
|
+
const target = installFolder(cwd);
|
|
398
|
+
if (target == null || target.moved) return null;
|
|
399
|
+
const add = ADD[detectPackageManager(cwd)] ?? ADD.npm;
|
|
400
|
+
return name => `${add} ${name}`;
|
|
401
|
+
}
|
|
402
|
+
|
|
378
403
|
/**
|
|
379
404
|
* The commands that bring a project's own CLI and Core to one release, with
|
|
380
405
|
* the project's package manager: when the CLI is newer, Core up to it and then
|
|
381
406
|
* the codemods from Core's release; otherwise the CLI to Core's release.
|
|
407
|
+
* Null in a folder that belongs to no project, or whose package.json is not
|
|
408
|
+
* the project's (see {@link installFolder}).
|
|
382
409
|
* @param {{cwd: string, cli: string, core: string}} options
|
|
383
|
-
* @returns {string}
|
|
410
|
+
* @returns {string | null}
|
|
384
411
|
*/
|
|
385
412
|
export function alignCliAndCore({cwd, cli, core}) {
|
|
386
|
-
const
|
|
387
|
-
|
|
413
|
+
const target = installFolder(cwd);
|
|
414
|
+
if (target == null || target.moved) return null;
|
|
415
|
+
const root = projectRootOf(readReleaseFacts(cwd)) ?? cwd;
|
|
416
|
+
return alignIn(root, cli, core);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* The commands that bring the CLI and Core of the project at `root` to one
|
|
421
|
+
* release, run in `root`.
|
|
422
|
+
* @param {string} root
|
|
423
|
+
* @param {string} cli
|
|
424
|
+
* @param {string} core
|
|
425
|
+
* @returns {string}
|
|
426
|
+
*/
|
|
427
|
+
function alignIn(root, cli, core) {
|
|
388
428
|
const add = ADD[detectPackageManager(root)] ?? ADD.npm;
|
|
389
429
|
if (semverCompare(cli, core) > 0) {
|
|
390
430
|
return `${add} @astryxdesign/core@${cli}, then ${getCliInvocation(root, {installed: true})} upgrade --from ${core} --apply`;
|
|
@@ -392,27 +432,81 @@ export function alignCliAndCore({cwd, cli, core}) {
|
|
|
392
432
|
return `${add} ${CLI_PACKAGE}@${core}`;
|
|
393
433
|
}
|
|
394
434
|
|
|
435
|
+
/**
|
|
436
|
+
* Where a command that adds an Astryx package runs, for a run in `cwd`: in
|
|
437
|
+
* the project `spec:AST-040` FR9 defines, which stops at a repository root
|
|
438
|
+
* and never counts the home folder (spec AST-081 FR2, FR10). Null when `cwd`
|
|
439
|
+
* belongs to no such project, so no command adds anything. When `cwd`'s
|
|
440
|
+
* nearest package.json is not the project's, as in a tool folder that
|
|
441
|
+
* installs its own Core, a package manager would add to the tool's
|
|
442
|
+
* package.json, so `moved` says the command runs in the project's folder.
|
|
443
|
+
* @param {string} cwd
|
|
444
|
+
* @returns {{dir: string, moved: boolean} | null}
|
|
445
|
+
*/
|
|
446
|
+
export function installFolder(cwd) {
|
|
447
|
+
const project = findAstryxProject(cwd);
|
|
448
|
+
if (project == null) return null;
|
|
449
|
+
const nearest = findPackageRoot(cwd);
|
|
450
|
+
if (nearest == null || nearest === project) return {dir: cwd, moved: false};
|
|
451
|
+
return {dir: project, moved: true};
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* What to tell a run in a folder inside a project whose package.json is not
|
|
456
|
+
* the project's: run from the project's folder, since adding there would make
|
|
457
|
+
* the folder a project of its own (spec AST-081 FR2).
|
|
458
|
+
*/
|
|
459
|
+
export const RUN_FROM_PROJECT =
|
|
460
|
+
"Run this from the Astryx project's folder, or declare an Astryx package in this folder's package.json to make it a project of its own.";
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* The command that adds the CLI at Core's version, for a run in `cwd` whose
|
|
464
|
+
* Core is `core`, with the project's package manager in the project root.
|
|
465
|
+
* `command` is null in a folder inside the project whose package.json is not
|
|
466
|
+
* the project's (see {@link installFolder}), where the advice is
|
|
467
|
+
* {@link RUN_FROM_PROJECT}. Null when the folder belongs to no project.
|
|
468
|
+
* @param {{cwd: string, core: string}} options
|
|
469
|
+
* @returns {{root: string, core: string, command: string | null} | null}
|
|
470
|
+
*/
|
|
471
|
+
export function cliInstallAdvice({cwd, core}) {
|
|
472
|
+
const target = installFolder(cwd);
|
|
473
|
+
if (target == null) return null;
|
|
474
|
+
if (target.moved) return {root: target.dir, core, command: null};
|
|
475
|
+
const root = projectRootOf(readReleaseFacts(cwd)) ?? cwd;
|
|
476
|
+
return {root, core, command: addCliCommand(root, core)};
|
|
477
|
+
}
|
|
478
|
+
|
|
395
479
|
/**
|
|
396
480
|
* The hint for a project with no CLI of its own, answered by `answered` while
|
|
397
481
|
* its Core is `core`: the command that adds the CLI at Core's version, with
|
|
398
|
-
* the project's package manager.
|
|
482
|
+
* the project's package manager (see {@link cliInstallAdvice}). Null when no
|
|
483
|
+
* command fits, or when the project the command adds to already matches.
|
|
399
484
|
* @param {{cwd: string, answered: string, core: string}} options
|
|
400
|
-
* @returns {{root: string, line: string}}
|
|
485
|
+
* @returns {{root: string, line: string} | null}
|
|
401
486
|
*/
|
|
402
487
|
export function noCliHint({cwd, answered, core}) {
|
|
403
|
-
|
|
404
|
-
|
|
488
|
+
if (core === answered) return null;
|
|
489
|
+
const advice = cliInstallAdvice({cwd, core});
|
|
490
|
+
if (advice == null) return null;
|
|
491
|
+
return {
|
|
492
|
+
root: advice.root,
|
|
493
|
+
line: noCliHintLine(answered, core, advice.command),
|
|
494
|
+
};
|
|
405
495
|
}
|
|
406
496
|
|
|
407
497
|
/**
|
|
408
498
|
* The hint's text.
|
|
409
499
|
* @param {string} answered
|
|
410
500
|
* @param {string} core
|
|
411
|
-
* @param {string} command the command that adds the CLI at Core's
|
|
501
|
+
* @param {string | null} command the command that adds the CLI at Core's
|
|
502
|
+
* version; null in a folder whose package.json is not the project's
|
|
412
503
|
* @returns {string}
|
|
413
504
|
*/
|
|
414
505
|
export function noCliHintLine(answered, core, command) {
|
|
415
|
-
|
|
506
|
+
const head = `astryx: this project has no Astryx CLI installed; answered by CLI ${answered} while its Core is ${core}.`;
|
|
507
|
+
return command
|
|
508
|
+
? `${head} To match, run: ${command}`
|
|
509
|
+
: `${head} ${RUN_FROM_PROJECT}`;
|
|
416
510
|
}
|
|
417
511
|
|
|
418
512
|
/**
|
|
@@ -432,17 +526,29 @@ export function addCliCommand(root, version) {
|
|
|
432
526
|
* @param {{cwd: string, current: string, stateDir?: string}} options
|
|
433
527
|
* @returns {ProjectLag | null}
|
|
434
528
|
*/
|
|
435
|
-
export function projectLag({cwd, current, stateDir = userConfigDir()}) {
|
|
529
|
+
export function projectLag({cwd, current: given, stateDir = userConfigDir()}) {
|
|
436
530
|
const latest = knownLatest(stateDir);
|
|
437
|
-
if (!latest
|
|
438
|
-
const newest = latest.version;
|
|
531
|
+
if (!latest) return null;
|
|
439
532
|
const facts = readReleaseFacts(cwd);
|
|
440
533
|
if (!facts.inProject) return null;
|
|
441
|
-
const
|
|
534
|
+
const target = installFolder(cwd);
|
|
535
|
+
if (target == null) return null;
|
|
536
|
+
const root = target.moved ? target.dir : (projectRootOf(facts) ?? cwd);
|
|
537
|
+
// From a folder inside the project, the project's own release: its CLI's,
|
|
538
|
+
// else its Core's, so the project gets one notice and one --from.
|
|
539
|
+
const projectFacts = target.moved ? readReleaseFacts(root) : null;
|
|
540
|
+
const current = projectFacts
|
|
541
|
+
? (projectFacts.cli?.version ?? coreVersionOf(projectFacts) ?? given)
|
|
542
|
+
: given;
|
|
543
|
+
if (!isBehind(current, latest.version)) return null;
|
|
544
|
+
const newest = latest.version;
|
|
442
545
|
const pm = detectPackageManager(root);
|
|
443
546
|
// The CLI is always installed beside Core: a project that installed only
|
|
444
547
|
// Core gets it too, as recommended, so its version is pinned with Core's.
|
|
445
|
-
|
|
548
|
+
// From a folder inside the project whose package.json is not the
|
|
549
|
+
// project's, the install runs in the project's folder (see installFolder).
|
|
550
|
+
const add = `${ADD[pm] ?? ADD.npm} @astryxdesign/core@${newest} ${CLI_PACKAGE}@${newest}`;
|
|
551
|
+
const install = target.moved ? commandInFolder(root, add) : add;
|
|
446
552
|
// The command runs after the install above, so the picker's guess is the
|
|
447
553
|
// project's own CLI (spec AST-081 FR5).
|
|
448
554
|
const stem = getCliInvocation(root, {installed: true});
|
|
@@ -452,7 +558,9 @@ export function projectLag({cwd, current, stateDir = userConfigDir()}) {
|
|
|
452
558
|
newest,
|
|
453
559
|
node: latest.node,
|
|
454
560
|
install,
|
|
455
|
-
upgrade:
|
|
561
|
+
upgrade: target.moved
|
|
562
|
+
? commandInFolder(root, `${stem} upgrade --from ${current} --apply`)
|
|
563
|
+
: `${stem} upgrade --from ${current} --apply`,
|
|
456
564
|
};
|
|
457
565
|
}
|
|
458
566
|
|
|
@@ -536,18 +644,13 @@ export function noticeLines({
|
|
|
536
644
|
try {
|
|
537
645
|
// A project with no CLI of its own, answered by a release other than its
|
|
538
646
|
// Core's: once a day per project, how to match them (FR2).
|
|
539
|
-
if (
|
|
540
|
-
choice.inProject &&
|
|
541
|
-
choice.copy === 'starting' &&
|
|
542
|
-
choice.coreVersion &&
|
|
543
|
-
choice.coreVersion !== choice.version
|
|
544
|
-
) {
|
|
647
|
+
if (choice.inProject && choice.copy === 'starting' && choice.coreVersion) {
|
|
545
648
|
const hint = noCliHint({
|
|
546
649
|
cwd,
|
|
547
650
|
answered: choice.version,
|
|
548
651
|
core: choice.coreVersion,
|
|
549
652
|
});
|
|
550
|
-
if (take(`no-cli:${hint.root}`)) lines.push(hint.line);
|
|
653
|
+
if (hint && take(`no-cli:${hint.root}`)) lines.push(hint.line);
|
|
551
654
|
}
|
|
552
655
|
} catch {
|
|
553
656
|
// A hint never fails a run.
|
|
@@ -559,8 +662,16 @@ export function noticeLines({
|
|
|
559
662
|
choice.copy === 'starting' && choice.coreVersion
|
|
560
663
|
? choice.coreVersion
|
|
561
664
|
: choice.version;
|
|
562
|
-
|
|
563
|
-
|
|
665
|
+
// A folder that belongs to no project (spec AST-040 FR9) gets no
|
|
666
|
+
// project notice; the skip says why.
|
|
667
|
+
const noProject = installFolder(cwd) == null;
|
|
668
|
+
const lag = noProject ? null : projectLag({cwd, current, stateDir});
|
|
669
|
+
if (!lag) {
|
|
670
|
+
recordNoticeSkip('project', noProject ? 'no-project' : 'no-newer', {
|
|
671
|
+
stateDir,
|
|
672
|
+
now,
|
|
673
|
+
});
|
|
674
|
+
}
|
|
564
675
|
if (lag && take(`project:${lag.root}`)) {
|
|
565
676
|
lines.push(
|
|
566
677
|
availableLine(lag.current, lag.newest),
|
|
@@ -355,6 +355,27 @@ describe('globalBehind and projectLag', () => {
|
|
|
355
355
|
});
|
|
356
356
|
});
|
|
357
357
|
|
|
358
|
+
describe('projectLag from a tool folder inside a project', () => {
|
|
359
|
+
it("uses the project's own CLI release, so the project gets one notice and one --from", () => {
|
|
360
|
+
const stateDir = checked('0.7.3');
|
|
361
|
+
const app = project(tempDir(), {
|
|
362
|
+
'@astryxdesign/core': '0.7.1',
|
|
363
|
+
'@astryxdesign/cli': '0.7.2',
|
|
364
|
+
});
|
|
365
|
+
writeJson(path.join(app, 'package-lock.json'), {lockfileVersion: 3});
|
|
366
|
+
installCore(app, '0.7.1');
|
|
367
|
+
installStandInCli(app, '0.7.2');
|
|
368
|
+
const tool = path.join(app, 'tools', 'codegen');
|
|
369
|
+
writeJson(path.join(tool, 'package.json'), {name: 'codegen'});
|
|
370
|
+
installCore(tool, '0.7.0');
|
|
371
|
+
|
|
372
|
+
const fromApp = projectLag({cwd: app, current: '0.7.2', stateDir});
|
|
373
|
+
const fromTool = projectLag({cwd: tool, current: '0.7.0', stateDir});
|
|
374
|
+
expect(fromTool).toMatchObject({root: app, current: '0.7.2'});
|
|
375
|
+
expect(fromTool?.upgrade).toBe(`cd ${app} && ${fromApp?.upgrade}`);
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
358
379
|
describe('the commands notices print go through the command-name picker (spec AST-081 FR5)', () => {
|
|
359
380
|
/** A Core-only npm project behind the newest release. */
|
|
360
381
|
const coreOnlyProject = () => {
|
|
@@ -22,6 +22,7 @@ import {progressLine} from './handoff.mjs';
|
|
|
22
22
|
import {isJsonMode} from '../response/json.mjs';
|
|
23
23
|
import {cachedRelease, ensureRelease, userCacheDir} from './cache.mjs';
|
|
24
24
|
import {readJson, findReadCore, CORE_PACKAGE_NAME} from './project.mjs';
|
|
25
|
+
import {hostedRun} from '../runtime/package-root.mjs';
|
|
25
26
|
|
|
26
27
|
/** The running CLI package's folder. */
|
|
27
28
|
const CLI_ROOT = path.resolve(
|
|
@@ -105,6 +106,19 @@ export function carriedCore(options = {}) {
|
|
|
105
106
|
if (besidePkg?.name === CORE_PACKAGE_NAME && besidePkg.version === version) {
|
|
106
107
|
return {dir: beside, unavailable: null};
|
|
107
108
|
}
|
|
109
|
+
// A hosted run resolves from its package set alone and installs nothing
|
|
110
|
+
// (architecture:cli-surface INV30): the Core beside the CLI, or none.
|
|
111
|
+
if (hostedRun()) {
|
|
112
|
+
if (!fetch) return {dir: null, unavailable: null};
|
|
113
|
+
const reason =
|
|
114
|
+
"a hosted run installs nothing, and the host's package set holds no Core beside its CLI";
|
|
115
|
+
return {
|
|
116
|
+
dir: null,
|
|
117
|
+
unavailable: `Core ${version} could not be found: ${reason}`,
|
|
118
|
+
version,
|
|
119
|
+
reason,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
108
122
|
const cached = cachedRelease(version, cacheDir);
|
|
109
123
|
if (cached) return {dir: cached.coreDir, unavailable: null};
|
|
110
124
|
if (!fetch) return {dir: null, unavailable: null};
|
|
@@ -338,7 +338,7 @@ export const doc = {
|
|
|
338
338
|
{
|
|
339
339
|
value: 'integration.validate',
|
|
340
340
|
description:
|
|
341
|
-
'The validation result: validated (false when nothing was validated: with no package.json the issues list carries one no_package error so the command exits 1, and with a package.json but no integration manifest the issues list is empty and proves nothing), the package name and version (both null when validated is false) plus issues, an AstryxIntegrationIssue[] of {code, severity: warning | error, message, fix?, file?, line?} (fix: the change that resolves it; file and line: where, relative to the package), and notes when there are any: {code, message} information that fails nothing, such as invalid_cli_command for a malformed cliCommand. When the manifest loads, docTypes checks each doc against its published authoring type: status (checked | skipped), reason, typescript, docs, findings (all warnings, each naming the field and a fix), unchecked, and fixtures (test fixture docs not checked).',
|
|
341
|
+
'The validation result: validated (false when nothing was validated: with no package.json the issues list carries one no_package error so the command exits 1, and with a package.json but no integration manifest the issues list is empty and proves nothing), the package name and version (both null when validated is false) plus issues, an AstryxIntegrationIssue[] of {code, severity: warning | error, message, fix?, file?, line?} (fix: the change that resolves it; file and line: where, relative to the package), and notes when there are any: {code, message} information that fails nothing, such as invalid_cli_command for a malformed cliCommand and cli_peer_version when the running CLI is outside the @astryxdesign/cli peer range of the package, and the package layout findings added after the last minor release, each with its fix in the message (duplicate_component_doc, symlinked_root, unreadable_file, invalid_package_json, no_provider_id, source_without_component_doc where a doc and its source still pair), and doc_name_mismatch and unknown_block_component, until they become warnings in the next minor release. A runner_command note lists each Astryx command a topic writes with a package runner (its file, line and the bare command to write). When the manifest loads, docTypes checks each doc against its published authoring type: status (checked | skipped), reason, typescript, docs, findings (all warnings, each naming the field and a fix), unchecked, and fixtures (test fixture docs not checked). When the manifest loads, docNames lists the component doc names it could not judge: status (checked), findings (always empty; a doc name the module its import names provably does not export is a doc_name_mismatch note, with its fix in the message) and unchecked ({file, name, reason}: a doc whose name differs from the name it is listed under and whose source exports cannot all be read, such as a re-export from another package). When the manifest loads, blockComponents lists the component names templates give in exampleFor or componentsUsed that could not be judged: status (checked), findings (always empty; a name neither the package nor Core has, and the template does not import, is an unknown_block_component note, with its fix in the message) and unchecked ({file, name, reason}: a name the template may reach through anything other than named imports and re-exports from Core, React, StyleX, local helpers or the entry of the package itself, such as an import from another package, a default or namespace import, an alias of or member read off an imported binding, require() or a dynamic import(), or a local module that cannot be read, or any name Core would have to resolve when Core is not installed). Since 0.7.3 each import apps cannot use is also a note (its fix in the message), listed only and failing --strict from the next minor. publicImports ({status: checked, findings: [], unchecked}) lists each import the check could not judge as {file, specifier, reason}; never counted or failed on.',
|
|
342
342
|
},
|
|
343
343
|
{
|
|
344
344
|
value: 'integration.template-conflicts',
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in foundation/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @file The small routing helper the commands that pick among candidates
|
|
6
|
+
* share (build, search): two node kinds and the runner that walks them.
|
|
7
|
+
*
|
|
8
|
+
* A searcher answers a request in its command's own result shape, or returns
|
|
9
|
+
* null to pass. A dispatcher scores nothing: it names the children that should
|
|
10
|
+
* answer, best first, with a confidence from 0 to 1. Below its floor, or when
|
|
11
|
+
* none of the children it named answers, its fallback searcher answers. A
|
|
12
|
+
* dispatcher's children may be dispatchers, so trees nest. A classifier is a
|
|
13
|
+
* dispatcher whose route is a static word-weight classifier: the request's
|
|
14
|
+
* tokens vote for a class, and a class with a searcher takes the request when
|
|
15
|
+
* the classifier is sure enough.
|
|
16
|
+
*
|
|
17
|
+
* A tree file types the helpers for its command once, by taking them from
|
|
18
|
+
* `routeKit` typed as `RouteKit<Request, Context, Answer>` (see
|
|
19
|
+
* api/search/tree.mjs); each node is then plain `{id, summary, run}`.
|
|
20
|
+
*
|
|
21
|
+
* Every node gets the same context, so any node can be run, measured, and
|
|
22
|
+
* tuned on its own: `runTree` takes an optional `tuning` with weights that
|
|
23
|
+
* replace a node's shipped weights for one call, and a trace callback that
|
|
24
|
+
* sees every step. Neither ever reaches a command's output.
|
|
25
|
+
*
|
|
26
|
+
* @input a tree of nodes, a request, and the context the command's adapter
|
|
27
|
+
* gathered
|
|
28
|
+
* @output the first answer a searcher gives
|
|
29
|
+
* @position foundation; api/build and api/search build their trees with it
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* @template Request, Context, Answer
|
|
33
|
+
* @typedef {object} Searcher
|
|
34
|
+
* @property {'searcher'} kind
|
|
35
|
+
* @property {string} id
|
|
36
|
+
* @property {string} summary One plain line: what it answers.
|
|
37
|
+
* @property {(request: Request, ctx: Context, weights: unknown) => Answer | null | Promise<Answer | null>} run
|
|
38
|
+
* `weights` is a tuning override for this node, or null for its shipped weights.
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* @typedef {object} Route
|
|
42
|
+
* @property {readonly string[]} ids The children to try, best first.
|
|
43
|
+
* @property {number} confidence From 0 to 1.
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* @template Request, Context
|
|
47
|
+
* @typedef {object} Dispatcher
|
|
48
|
+
* @property {'dispatcher'} kind
|
|
49
|
+
* @property {string} id
|
|
50
|
+
* @property {string} summary
|
|
51
|
+
* @property {readonly string[]} children
|
|
52
|
+
* @property {number} floor Below this confidence the fallback answers.
|
|
53
|
+
* @property {string} fallback A searcher's id.
|
|
54
|
+
* @property {(request: Request, ctx: Context, weights: unknown) => Route | Promise<Route>} route
|
|
55
|
+
*/
|
|
56
|
+
/**
|
|
57
|
+
* @template Request, Context, Answer
|
|
58
|
+
* @typedef {Searcher<Request, Context, Answer> | Dispatcher<Request, Context>} TreeNode
|
|
59
|
+
*/
|
|
60
|
+
/**
|
|
61
|
+
* @template Request, Context, Answer
|
|
62
|
+
* @typedef {object} Tree
|
|
63
|
+
* @property {string} root
|
|
64
|
+
* @property {ReadonlyMap<string, TreeNode<Request, Context, Answer>>} nodes
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* One step the runner took.
|
|
68
|
+
* @typedef {object} TraceStep
|
|
69
|
+
* @property {string} id
|
|
70
|
+
* @property {'searcher' | 'dispatcher'} kind
|
|
71
|
+
* @property {number} depth
|
|
72
|
+
* @property {boolean} fallback Whether this step ran as a fallback.
|
|
73
|
+
* @property {Route} [route] A dispatcher's route.
|
|
74
|
+
* @property {boolean} [answered] Whether a searcher answered.
|
|
75
|
+
*/
|
|
76
|
+
/**
|
|
77
|
+
* @typedef {object} Tuning
|
|
78
|
+
* @property {Readonly<Record<string, unknown>>} [weights] Weights by node id, replacing that node's shipped weights for this call.
|
|
79
|
+
* @property {(step: TraceStep) => void} [onTrace]
|
|
80
|
+
*/
|
|
81
|
+
/**
|
|
82
|
+
* Static classifier weights: one row of numbers per token, one number per
|
|
83
|
+
* class. A request's score for a class is the sum of its tokens' numbers.
|
|
84
|
+
* @typedef {object} ClassifierWeights
|
|
85
|
+
* @property {readonly string[]} classes
|
|
86
|
+
* @property {Readonly<Record<string, readonly number[]>>} tokens
|
|
87
|
+
*/
|
|
88
|
+
/**
|
|
89
|
+
* @template Request, Context
|
|
90
|
+
* @typedef {object} ClassifierSpec
|
|
91
|
+
* @property {string} id
|
|
92
|
+
* @property {string} summary
|
|
93
|
+
* @property {Readonly<Record<string, string>>} searchers Class name -> the
|
|
94
|
+
* searcher that answers it. A class with no searcher goes to the fallback.
|
|
95
|
+
* @property {string} fallback The searcher that keeps every other request.
|
|
96
|
+
* @property {number} floor A searcher takes a request only when its class's
|
|
97
|
+
* probability is at least this.
|
|
98
|
+
* @property {(request: Request, ctx: Context) => readonly string[]} features
|
|
99
|
+
* The request's tokens.
|
|
100
|
+
* @property {(ctx: Context) => ClassifierWeights} weights The shipped weights,
|
|
101
|
+
* which the command's adapter put in the context.
|
|
102
|
+
*/
|
|
103
|
+
/**
|
|
104
|
+
* The helpers, typed for one command's request, context, and answer.
|
|
105
|
+
* @template Request, Context, Answer
|
|
106
|
+
* @typedef {object} RouteKit
|
|
107
|
+
* @property {(node: Omit<Searcher<Request, Context, Answer>, 'kind'>) => Searcher<Request, Context, Answer>} defineSearcher
|
|
108
|
+
* @property {(node: Omit<Dispatcher<Request, Context>, 'kind'>) => Dispatcher<Request, Context>} defineDispatcher
|
|
109
|
+
* @property {(spec: ClassifierSpec<Request, Context>) => Dispatcher<Request, Context>} defineClassifier
|
|
110
|
+
* @property {(root: string, nodes: readonly TreeNode<Request, Context, Answer>[]) => Tree<Request, Context, Answer>} defineTree
|
|
111
|
+
*/
|
|
112
|
+
/**
|
|
113
|
+
* The probability of each class for these tokens: a softmax over the summed
|
|
114
|
+
* rows of the tokens the weights know.
|
|
115
|
+
* @param {ClassifierWeights} weights
|
|
116
|
+
* @param {readonly string[]} tokens
|
|
117
|
+
* @returns {number[]}
|
|
118
|
+
*/
|
|
119
|
+
export function classify(weights: ClassifierWeights, tokens: readonly string[]): number[];
|
|
120
|
+
/**
|
|
121
|
+
* A dispatcher whose route is a static classifier. The most probable class
|
|
122
|
+
* (the first on a tie) is handed to its searcher; a class with no searcher,
|
|
123
|
+
* or the fallback's own class, stays with the fallback. Tuning weights for
|
|
124
|
+
* this node replace its shipped weights.
|
|
125
|
+
* @template Request, Context
|
|
126
|
+
* @param {ClassifierSpec<Request, Context>} spec
|
|
127
|
+
* @returns {Dispatcher<Request, Context>}
|
|
128
|
+
*/
|
|
129
|
+
export function defineClassifier<Request, Context>(spec: ClassifierSpec<Request, Context>): Dispatcher<Request, Context>;
|
|
130
|
+
/**
|
|
131
|
+
* @template Request, Context, Answer
|
|
132
|
+
* @param {Omit<Searcher<Request, Context, Answer>, 'kind'>} node
|
|
133
|
+
* @returns {Searcher<Request, Context, Answer>}
|
|
134
|
+
*/
|
|
135
|
+
export function defineSearcher<Request, Context, Answer>(node: Omit<Searcher<Request, Context, Answer>, "kind">): Searcher<Request, Context, Answer>;
|
|
136
|
+
/**
|
|
137
|
+
* @template Request, Context
|
|
138
|
+
* @param {Omit<Dispatcher<Request, Context>, 'kind'>} node
|
|
139
|
+
* @returns {Dispatcher<Request, Context>}
|
|
140
|
+
*/
|
|
141
|
+
export function defineDispatcher<Request, Context>(node: Omit<Dispatcher<Request, Context>, "kind">): Dispatcher<Request, Context>;
|
|
142
|
+
/**
|
|
143
|
+
* A tree from its nodes. Throws on a duplicate id, a missing root, child, or
|
|
144
|
+
* fallback, a fallback that is not a searcher, or a dispatcher cycle.
|
|
145
|
+
* @template Request, Context, Answer
|
|
146
|
+
* @param {string} root
|
|
147
|
+
* @param {readonly TreeNode<Request, Context, Answer>[]} list
|
|
148
|
+
* @returns {Tree<Request, Context, Answer>}
|
|
149
|
+
*/
|
|
150
|
+
export function defineTree<Request, Context, Answer>(root: string, list: readonly TreeNode<Request, Context, Answer>[]): Tree<Request, Context, Answer>;
|
|
151
|
+
/**
|
|
152
|
+
* Runs the tree from its root, or from `start` to run one node alone: a
|
|
153
|
+
* dispatcher below its floor runs its fallback; otherwise the children it
|
|
154
|
+
* names run in order and the first answer wins; when none answers, the
|
|
155
|
+
* fallback runs.
|
|
156
|
+
* @template Request, Context, Answer
|
|
157
|
+
* @param {Tree<Request, Context, Answer>} tree
|
|
158
|
+
* @param {Request} request
|
|
159
|
+
* @param {Context} ctx
|
|
160
|
+
* @param {{tuning?: Tuning, start?: string}} [options]
|
|
161
|
+
* @returns {Promise<Answer | null>}
|
|
162
|
+
*/
|
|
163
|
+
export function runTree<Request, Context, Answer>(tree: Tree<Request, Context, Answer>, request: Request, ctx: Context, options?: {
|
|
164
|
+
tuning?: Tuning;
|
|
165
|
+
start?: string;
|
|
166
|
+
}): Promise<Answer | null>;
|
|
167
|
+
/**
|
|
168
|
+
* The helpers in one object, for a tree file to type once (see the file
|
|
169
|
+
* comment).
|
|
170
|
+
* @type {RouteKit<any, any, any>}
|
|
171
|
+
*/
|
|
172
|
+
export const routeKit: RouteKit<any, any, any>;
|
|
173
|
+
export type Searcher<Request, Context, Answer> = {
|
|
174
|
+
kind: "searcher";
|
|
175
|
+
id: string;
|
|
176
|
+
/**
|
|
177
|
+
* One plain line: what it answers.
|
|
178
|
+
*/
|
|
179
|
+
summary: string;
|
|
180
|
+
/**
|
|
181
|
+
* `weights` is a tuning override for this node, or null for its shipped weights.
|
|
182
|
+
*/
|
|
183
|
+
run: (request: Request, ctx: Context, weights: unknown) => Answer | null | Promise<Answer | null>;
|
|
184
|
+
};
|
|
185
|
+
export type Route = {
|
|
186
|
+
/**
|
|
187
|
+
* The children to try, best first.
|
|
188
|
+
*/
|
|
189
|
+
ids: readonly string[];
|
|
190
|
+
/**
|
|
191
|
+
* From 0 to 1.
|
|
192
|
+
*/
|
|
193
|
+
confidence: number;
|
|
194
|
+
};
|
|
195
|
+
export type Dispatcher<Request, Context> = {
|
|
196
|
+
kind: "dispatcher";
|
|
197
|
+
id: string;
|
|
198
|
+
summary: string;
|
|
199
|
+
children: readonly string[];
|
|
200
|
+
/**
|
|
201
|
+
* Below this confidence the fallback answers.
|
|
202
|
+
*/
|
|
203
|
+
floor: number;
|
|
204
|
+
/**
|
|
205
|
+
* A searcher's id.
|
|
206
|
+
*/
|
|
207
|
+
fallback: string;
|
|
208
|
+
route: (request: Request, ctx: Context, weights: unknown) => Route | Promise<Route>;
|
|
209
|
+
};
|
|
210
|
+
export type TreeNode<Request, Context, Answer> = Searcher<Request, Context, Answer> | Dispatcher<Request, Context>;
|
|
211
|
+
export type Tree<Request, Context, Answer> = {
|
|
212
|
+
root: string;
|
|
213
|
+
nodes: ReadonlyMap<string, TreeNode<Request, Context, Answer>>;
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* One step the runner took.
|
|
217
|
+
*/
|
|
218
|
+
export type TraceStep = {
|
|
219
|
+
id: string;
|
|
220
|
+
kind: "searcher" | "dispatcher";
|
|
221
|
+
depth: number;
|
|
222
|
+
/**
|
|
223
|
+
* Whether this step ran as a fallback.
|
|
224
|
+
*/
|
|
225
|
+
fallback: boolean;
|
|
226
|
+
/**
|
|
227
|
+
* A dispatcher's route.
|
|
228
|
+
*/
|
|
229
|
+
route?: Route | undefined;
|
|
230
|
+
/**
|
|
231
|
+
* Whether a searcher answered.
|
|
232
|
+
*/
|
|
233
|
+
answered?: boolean | undefined;
|
|
234
|
+
};
|
|
235
|
+
export type Tuning = {
|
|
236
|
+
/**
|
|
237
|
+
* Weights by node id, replacing that node's shipped weights for this call.
|
|
238
|
+
*/
|
|
239
|
+
weights?: Readonly<Record<string, unknown>> | undefined;
|
|
240
|
+
onTrace?: ((step: TraceStep) => void) | undefined;
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* Static classifier weights: one row of numbers per token, one number per
|
|
244
|
+
* class. A request's score for a class is the sum of its tokens' numbers.
|
|
245
|
+
*/
|
|
246
|
+
export type ClassifierWeights = {
|
|
247
|
+
classes: readonly string[];
|
|
248
|
+
tokens: Readonly<Record<string, readonly number[]>>;
|
|
249
|
+
};
|
|
250
|
+
export type ClassifierSpec<Request, Context> = {
|
|
251
|
+
id: string;
|
|
252
|
+
summary: string;
|
|
253
|
+
/**
|
|
254
|
+
* Class name -> the
|
|
255
|
+
* searcher that answers it. A class with no searcher goes to the fallback.
|
|
256
|
+
*/
|
|
257
|
+
searchers: Readonly<Record<string, string>>;
|
|
258
|
+
/**
|
|
259
|
+
* The searcher that keeps every other request.
|
|
260
|
+
*/
|
|
261
|
+
fallback: string;
|
|
262
|
+
/**
|
|
263
|
+
* A searcher takes a request only when its class's
|
|
264
|
+
* probability is at least this.
|
|
265
|
+
*/
|
|
266
|
+
floor: number;
|
|
267
|
+
/**
|
|
268
|
+
* The request's tokens.
|
|
269
|
+
*/
|
|
270
|
+
features: (request: Request, ctx: Context) => readonly string[];
|
|
271
|
+
/**
|
|
272
|
+
* The shipped weights,
|
|
273
|
+
* which the command's adapter put in the context.
|
|
274
|
+
*/
|
|
275
|
+
weights: (ctx: Context) => ClassifierWeights;
|
|
276
|
+
};
|
|
277
|
+
/**
|
|
278
|
+
* The helpers, typed for one command's request, context, and answer.
|
|
279
|
+
*/
|
|
280
|
+
export type RouteKit<Request, Context, Answer> = {
|
|
281
|
+
defineSearcher: (node: Omit<Searcher<Request, Context, Answer>, "kind">) => Searcher<Request, Context, Answer>;
|
|
282
|
+
defineDispatcher: (node: Omit<Dispatcher<Request, Context>, "kind">) => Dispatcher<Request, Context>;
|
|
283
|
+
defineClassifier: (spec: ClassifierSpec<Request, Context>) => Dispatcher<Request, Context>;
|
|
284
|
+
defineTree: (root: string, nodes: readonly TreeNode<Request, Context, Answer>[]) => Tree<Request, Context, Answer>;
|
|
285
|
+
};
|