@astryxdesign/cli 0.7.2 → 0.7.3-canary.06872b4
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 +99 -66
- package/api/build/_adapter.d.mts +58 -0
- package/api/build/_adapter.mjs +115 -3
- package/api/build/blocks/blocks.d.mts +42 -0
- package/api/build/blocks/blocks.mjs +169 -0
- package/api/build/blocks/blocks.test.mjs +108 -0
- package/api/build/blocks/blocks.weights.json +1 -0
- package/api/build/build.mjs +25 -6
- package/api/build/kit/answer.d.mts +14 -0
- package/api/build/kit/answer.mjs +85 -0
- package/api/build/kit/answer.test.mjs +38 -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 +60 -0
- package/api/build/kit/signals.mjs +284 -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 +52 -0
- package/api/build/tree.test.mjs +177 -0
- package/api/build/tree.weights.json +1 -0
- package/api/component/component.mjs +16 -2
- package/api/component/component.test.mjs +15 -0
- package/api/discover/_adapter.mjs +36 -9
- package/api/discover/_adapter.test.mjs +42 -0
- package/api/docs/_adapter.mjs +17 -5
- package/api/docs/docs.test.mjs +7 -1
- package/api/doctor/doctor.mjs +86 -12
- package/api/doctor/doctor.test.mjs +28 -3
- 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/authoring-checks.mjs +83 -9
- 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-gaps.test.mjs +1964 -0
- package/api/integration/validate-integration.d.mts +11 -2
- package/api/integration/validate-integration.mjs +226 -32
- package/api/integration/validate-integration.type.d.mts +58 -1
- package/api/integration/validate-integration.type.mjs +45 -2
- package/api/integration/validateIntegration.doc.mjs +1 -1
- package/api/search/ORDERING.md +28 -0
- package/api/search/_adapter.d.mts +66 -2
- package/api/search/_adapter.mjs +118 -10
- 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 +52 -0
- package/api/search/_entries.mjs +158 -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 +7 -5
- package/api/search/search.mjs +53 -2483
- 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/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/is-my-code-good.doc.mjs +287 -0
- package/assets/docs/tree/api.doc.mjs +6 -0
- package/assets/docs/tree/host-entry.doc.mjs +128 -0
- package/assets/docs/tree/template-grading-rubric.doc.mjs +16 -37
- package/assets/docs/tree/tokens-data.doc.mjs +2 -2
- 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/clients/cli/bin/astryx.mjs +7 -78
- package/clients/cli/commands/doctor.mjs +30 -0
- package/clients/cli/commands/doctor.test.mjs +65 -0
- 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/outside-project.test.mjs +2 -1
- package/clients/cli/commands/setup-nudge.test.mjs +61 -0
- 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 +19 -1
- package/clients/cli/run.mjs +108 -0
- package/foundation/agent-docs/agent-doc-state.d.mts +20 -7
- package/foundation/agent-docs/agent-doc-state.mjs +35 -8
- package/foundation/agent-docs/agent-docs.d.mts +100 -12
- package/foundation/agent-docs/agent-docs.mjs +1010 -99
- package/foundation/agent-docs/agent-docs.path-safety.test.mjs +1239 -17
- package/foundation/agent-docs/agent-docs.test.mjs +678 -35
- package/foundation/config/project.mjs +20 -22
- package/foundation/config/project.test.mjs +56 -0
- 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/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 +8 -0
- package/foundation/doc-compiler/read.mjs +59 -1
- package/foundation/doc-compiler/read.test.mjs +11 -2
- 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/integrations/autolink.d.mts +2 -1
- package/foundation/integrations/autolink.mjs +4 -13
- 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/integrations.d.mts +27 -1
- package/foundation/integrations/integrations.mjs +61 -2
- package/foundation/integrations/validate-contributions.d.mts +115 -0
- package/foundation/integrations/validate-contributions.mjs +1168 -13
- package/foundation/release/handoff.d.mts +23 -4
- package/foundation/release/handoff.mjs +175 -8
- 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/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
|
@@ -10,6 +10,14 @@
|
|
|
10
10
|
* @returns {string}
|
|
11
11
|
*/
|
|
12
12
|
export function whoAnsweredLine(choice: import("./choose.mjs").ReleaseChoice, computer?: boolean): string;
|
|
13
|
+
/**
|
|
14
|
+
* The line for a run this copy answers in place of the project's own CLI,
|
|
15
|
+
* which a host declined, when this copy is that CLI's release (FR2).
|
|
16
|
+
* @param {string} version
|
|
17
|
+
* @param {string} reason the reason, as {@link declinedReasonText} words it
|
|
18
|
+
* @returns {string}
|
|
19
|
+
*/
|
|
20
|
+
export function inPlaceOfProjectLine(version: string, reason: string): string;
|
|
13
21
|
/**
|
|
14
22
|
* The line for a run handed to the project's own CLI.
|
|
15
23
|
* @param {string} projectVersion
|
|
@@ -41,15 +49,26 @@ export function progressText(event: "install" | "wait", version: string): string
|
|
|
41
49
|
* @returns {string}
|
|
42
50
|
*/
|
|
43
51
|
export function fallbackLine(wanted: string, reason: string, answering: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* The fallback warning's reason for a project CLI a host declined.
|
|
54
|
+
* @param {string} reason the host's own words
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
57
|
+
export function declinedReasonText(reason: string): string;
|
|
44
58
|
/**
|
|
45
59
|
* Choose who answers and hand off when it is not this copy.
|
|
46
|
-
* @param {{cliRoot: string, argv: string[]}} input
|
|
47
|
-
*
|
|
60
|
+
* @param {{cliRoot: string, argv: string[], declinedProjectCli?: string}} input
|
|
61
|
+
* argv after `node astryx`; the reason a programmatic host declined the
|
|
62
|
+
* project's own CLI, when it did
|
|
63
|
+
* @returns {Promise<import('../../host/index.js').HostedCliResult | undefined>}
|
|
64
|
+
* resolves with nothing when this copy answers, and with that release's
|
|
65
|
+
* result when another package set's host entry answered a hosted run
|
|
48
66
|
*/
|
|
49
|
-
export function startRun({ cliRoot, argv }: {
|
|
67
|
+
export function startRun({ cliRoot, argv, declinedProjectCli }: {
|
|
50
68
|
cliRoot: string;
|
|
51
69
|
argv: string[];
|
|
52
|
-
|
|
70
|
+
declinedProjectCli?: string;
|
|
71
|
+
}): Promise<import("../../host/index.js").HostedCliResult | undefined>;
|
|
53
72
|
/**
|
|
54
73
|
* How long a hand-off waits after an interrupt before passing it on to a CLI
|
|
55
74
|
* that is still running. An interrupt sent to the whole process group (a
|
|
@@ -19,9 +19,26 @@
|
|
|
19
19
|
* (notices.mjs); a global copy also starts the daily update check, which
|
|
20
20
|
* installs nothing (global-state.mjs).
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
22
|
+
* A programmatic host that found the project's own CLI and did not run it
|
|
23
|
+
* passes the reason (spec AST-081 FR1, FR2). That run is never handed to the
|
|
24
|
+
* project's CLI: this copy answers in its place when it is that CLI's release,
|
|
25
|
+
* saying so in a line of its own; a package set of the host's whose CLI is
|
|
26
|
+
* that release answers through its own host entry; and otherwise this copy
|
|
27
|
+
* answers as for a release that cannot be obtained, with the warning naming
|
|
28
|
+
* the reason.
|
|
29
|
+
*
|
|
30
|
+
* A hosted run installs nothing (architecture:cli-surface INV30): a release
|
|
31
|
+
* other than this copy comes only from the first of the host's package sets
|
|
32
|
+
* that qualifies. When that CLI ships a host entry, the entry runs in this
|
|
33
|
+
* process with the same inputs, discover sources included, and the host's
|
|
34
|
+
* call settles with its result; otherwise its bin takes the run. With no such
|
|
35
|
+
* set, this copy answers, announced.
|
|
36
|
+
*
|
|
37
|
+
* @input the running copy, argv, the working folder, and a host's
|
|
38
|
+
* declined-project-CLI reason
|
|
39
|
+
* @output returns when this copy answers, or with another release's result
|
|
40
|
+
* when its host entry answered; never returns after a hand-off to a bin
|
|
41
|
+
* @position foundation/release — called once per run by clients/cli/run.mjs.
|
|
25
42
|
*/
|
|
26
43
|
|
|
27
44
|
import {spawn} from 'node:child_process';
|
|
@@ -32,8 +49,10 @@ import {
|
|
|
32
49
|
isGlobalCopy,
|
|
33
50
|
namesWhoAnswered,
|
|
34
51
|
packageRootOf,
|
|
52
|
+
projectRootOf,
|
|
35
53
|
runningCopy,
|
|
36
54
|
} from './choose.mjs';
|
|
55
|
+
import {readReleaseFacts} from './project.mjs';
|
|
37
56
|
import {ensureRelease, userCacheDir} from './cache.mjs';
|
|
38
57
|
import {
|
|
39
58
|
maybeFetchCore,
|
|
@@ -43,6 +62,8 @@ import {
|
|
|
43
62
|
import {recordRunChoice} from './run-context.mjs';
|
|
44
63
|
import {noticeLines} from './notices.mjs';
|
|
45
64
|
import {cliDoor, runWithCliDoor} from '../env/cli-command.mjs';
|
|
65
|
+
import {hostedRun} from '../runtime/package-root.mjs';
|
|
66
|
+
import {qualifyingRoot} from '../runtime/package-set.mjs';
|
|
46
67
|
|
|
47
68
|
/** Where each release's notes are published. */
|
|
48
69
|
|
|
@@ -63,6 +84,17 @@ export function whoAnsweredLine(choice, computer = false) {
|
|
|
63
84
|
: `astryx: answered by CLI ${choice.version} with Core ${core}, outside a project`;
|
|
64
85
|
}
|
|
65
86
|
|
|
87
|
+
/**
|
|
88
|
+
* The line for a run this copy answers in place of the project's own CLI,
|
|
89
|
+
* which a host declined, when this copy is that CLI's release (FR2).
|
|
90
|
+
* @param {string} version
|
|
91
|
+
* @param {string} reason the reason, as {@link declinedReasonText} words it
|
|
92
|
+
* @returns {string}
|
|
93
|
+
*/
|
|
94
|
+
export function inPlaceOfProjectLine(version, reason) {
|
|
95
|
+
return `astryx: answered by CLI ${version}, the release of this project's CLI, in its place (${reason})`;
|
|
96
|
+
}
|
|
97
|
+
|
|
66
98
|
/**
|
|
67
99
|
* The line for a run handed to the project's own CLI.
|
|
68
100
|
* @param {string} projectVersion
|
|
@@ -131,16 +163,32 @@ function failUnavailable(message, json) {
|
|
|
131
163
|
process.exit(1);
|
|
132
164
|
}
|
|
133
165
|
|
|
166
|
+
/**
|
|
167
|
+
* The fallback warning's reason for a project CLI a host declined.
|
|
168
|
+
* @param {string} reason the host's own words
|
|
169
|
+
* @returns {string}
|
|
170
|
+
*/
|
|
171
|
+
export function declinedReasonText(reason) {
|
|
172
|
+
return `project CLI skipped: ${reason}`;
|
|
173
|
+
}
|
|
174
|
+
|
|
134
175
|
/**
|
|
135
176
|
* Choose who answers and hand off when it is not this copy.
|
|
136
|
-
* @param {{cliRoot: string, argv: string[]}} input
|
|
137
|
-
*
|
|
177
|
+
* @param {{cliRoot: string, argv: string[], declinedProjectCli?: string}} input
|
|
178
|
+
* argv after `node astryx`; the reason a programmatic host declined the
|
|
179
|
+
* project's own CLI, when it did
|
|
180
|
+
* @returns {Promise<import('../../host/index.js').HostedCliResult | undefined>}
|
|
181
|
+
* resolves with nothing when this copy answers, and with that release's
|
|
182
|
+
* result when another package set's host entry answered a hosted run
|
|
138
183
|
*/
|
|
139
|
-
export async function startRun({cliRoot, argv}) {
|
|
184
|
+
export async function startRun({cliRoot, argv, declinedProjectCli}) {
|
|
140
185
|
const json = argv.includes('--json');
|
|
141
186
|
const self = runningCopy(cliRoot);
|
|
142
187
|
const cacheDir = userCacheDir();
|
|
143
|
-
|
|
188
|
+
// A host carries its own CLI and keeps it current itself: a hosted copy
|
|
189
|
+
// runs none of the global copy's background work, and installs nothing.
|
|
190
|
+
const hosted = hostedRun();
|
|
191
|
+
const global = !hosted && isGlobalCopy(cliRoot, cacheDir);
|
|
144
192
|
if (global) {
|
|
145
193
|
try {
|
|
146
194
|
maybeStartCheck();
|
|
@@ -189,7 +237,46 @@ export async function startRun({cliRoot, argv}) {
|
|
|
189
237
|
};
|
|
190
238
|
}
|
|
191
239
|
|
|
192
|
-
|
|
240
|
+
// A host declined the project's own CLI (FR2): the run is never handed to
|
|
241
|
+
// it. The release equal to that CLI's version answers in its place when
|
|
242
|
+
// this copy is that release, or when a package set of the host's holds it
|
|
243
|
+
// with a host entry; otherwise this copy answers, announced as for a release
|
|
244
|
+
// that cannot be obtained, naming the reason.
|
|
245
|
+
let declined = null;
|
|
246
|
+
/** Set when this copy answers in place of the declined CLI, its release. */
|
|
247
|
+
let inPlace = null;
|
|
248
|
+
if (
|
|
249
|
+
declinedProjectCli &&
|
|
250
|
+
choice.copy === 'project' &&
|
|
251
|
+
choice.answer !== 'self'
|
|
252
|
+
) {
|
|
253
|
+
if (choice.version === self.version) {
|
|
254
|
+
// Still the project CLI's release (`copy` stays `project`), never the
|
|
255
|
+
// release matched to the project's Core, which can be another.
|
|
256
|
+
choice = {...choice, answer: 'self', bin: null, unavailable: null};
|
|
257
|
+
inPlace = declinedReasonText(declinedProjectCli);
|
|
258
|
+
} else {
|
|
259
|
+
const served = hosted
|
|
260
|
+
? qualifyingRoot({
|
|
261
|
+
release: choice.version,
|
|
262
|
+
projectDir: projectDirOf(process.cwd()),
|
|
263
|
+
roots: hosted.roots,
|
|
264
|
+
needsHostEntry: true,
|
|
265
|
+
})
|
|
266
|
+
: null;
|
|
267
|
+
if (served && 'root' in served && served.hostEntry) {
|
|
268
|
+
const answered = await answerInPackageSet(
|
|
269
|
+
served.hostEntry,
|
|
270
|
+
served.root,
|
|
271
|
+
{argv, declinedProjectCli},
|
|
272
|
+
);
|
|
273
|
+
if (answered) return answered;
|
|
274
|
+
}
|
|
275
|
+
declined = declinedReasonText(declinedProjectCli);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (!declined && choice.unavailable && choice.copy === 'project') {
|
|
193
280
|
failUnavailable(
|
|
194
281
|
`This project's CLI ${choice.version} could not be started: ${choice.unavailable}. Reinstall the project's dependencies.`,
|
|
195
282
|
json,
|
|
@@ -245,6 +332,11 @@ export async function startRun({cliRoot, argv}) {
|
|
|
245
332
|
});
|
|
246
333
|
};
|
|
247
334
|
|
|
335
|
+
if (declined) {
|
|
336
|
+
await fallBack(declined);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
248
340
|
if (choice.unavailable) {
|
|
249
341
|
await fallBack(choice.unavailable);
|
|
250
342
|
return;
|
|
@@ -256,6 +348,8 @@ export async function startRun({cliRoot, argv}) {
|
|
|
256
348
|
// line; a hint after the command, once a day, says how to match it.
|
|
257
349
|
if (!json && (choice.copy === 'matched' || choice.copy === 'carried'))
|
|
258
350
|
console.error(whoAnsweredLine(choice, computer));
|
|
351
|
+
else if (!json && inPlace)
|
|
352
|
+
console.error(inPlaceOfProjectLine(choice.version, inPlace));
|
|
259
353
|
process.once('exit', code => {
|
|
260
354
|
if (code === 0) notify();
|
|
261
355
|
});
|
|
@@ -263,6 +357,32 @@ export async function startRun({cliRoot, argv}) {
|
|
|
263
357
|
}
|
|
264
358
|
|
|
265
359
|
let bin = choice.bin;
|
|
360
|
+
if (!bin && hosted) {
|
|
361
|
+
const served = qualifyingRoot({
|
|
362
|
+
release: choice.version,
|
|
363
|
+
projectDir: projectDirOf(process.cwd()),
|
|
364
|
+
roots: hosted.roots,
|
|
365
|
+
});
|
|
366
|
+
if (!('root' in served)) {
|
|
367
|
+
await fallBack(served.reason);
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (served.hostEntry) {
|
|
371
|
+
const answered = await answerInPackageSet(served.hostEntry, served.root, {
|
|
372
|
+
argv,
|
|
373
|
+
});
|
|
374
|
+
if (answered) return answered;
|
|
375
|
+
}
|
|
376
|
+
// A hosted run installs nothing (INV30): a set whose CLI starts through
|
|
377
|
+
// neither its host entry nor a bin leaves this copy to answer.
|
|
378
|
+
if (!served.bin) {
|
|
379
|
+
await fallBack(
|
|
380
|
+
`the CLI ${choice.version} in the package set at ${served.root} could not be started`,
|
|
381
|
+
);
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
bin = served.bin;
|
|
385
|
+
}
|
|
266
386
|
if (!bin) {
|
|
267
387
|
const release = ensureRelease(choice.version, {
|
|
268
388
|
cacheDir,
|
|
@@ -295,6 +415,53 @@ export async function startRun({cliRoot, argv}) {
|
|
|
295
415
|
*/
|
|
296
416
|
export const INTERRUPT_GRACE_MS = 5000;
|
|
297
417
|
|
|
418
|
+
/**
|
|
419
|
+
* The project folder a run in `cwd` belongs to, or null outside a project.
|
|
420
|
+
* @param {string} cwd
|
|
421
|
+
* @returns {string | null}
|
|
422
|
+
*/
|
|
423
|
+
function projectDirOf(cwd) {
|
|
424
|
+
try {
|
|
425
|
+
return projectRootOf(readReleaseFacts(cwd));
|
|
426
|
+
} catch {
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Hand a hosted run over to the CLI of one of the host's package sets,
|
|
433
|
+
* through that CLI's own host entry, in this process, with the inputs this run
|
|
434
|
+
* got: the arguments, the folder, the command name, the approved integrations,
|
|
435
|
+
* the discover sources, and the reason the host declined the project's CLI.
|
|
436
|
+
* Its roots are that package set alone. That CLI prints its own who-answered
|
|
437
|
+
* line and notices, and the host's call settles with its result.
|
|
438
|
+
* @param {string} hostEntry the package set's `host/index.mjs`
|
|
439
|
+
* @param {string} root the package set
|
|
440
|
+
* @param {{argv: string[], declinedProjectCli?: string}} run
|
|
441
|
+
* @returns {Promise<import('../../host/index.js').HostedCliResult | null>} null
|
|
442
|
+
* when the entry cannot be loaded, before anything ran
|
|
443
|
+
*/
|
|
444
|
+
async function answerInPackageSet(hostEntry, root, {argv, declinedProjectCli}) {
|
|
445
|
+
const hosted = hostedRun();
|
|
446
|
+
if (!hosted?.loadHostEntry) return null;
|
|
447
|
+
let answer;
|
|
448
|
+
try {
|
|
449
|
+
answer = await hosted.loadHostEntry(hostEntry);
|
|
450
|
+
} catch {
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
const door = cliDoor();
|
|
454
|
+
return answer({
|
|
455
|
+
argv,
|
|
456
|
+
cwd: process.cwd(),
|
|
457
|
+
roots: [root],
|
|
458
|
+
integrations: [...hosted.integrations],
|
|
459
|
+
discoverSources: [...hosted.discoverSources],
|
|
460
|
+
...(door ? {cliCommand: door} : {}),
|
|
461
|
+
...(declinedProjectCli ? {declinedProjectCli} : {}),
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
|
|
298
465
|
/**
|
|
299
466
|
* Run `bin` as this run and end with its exit status.
|
|
300
467
|
* @param {string} bin
|
|
@@ -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 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. 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).',
|
|
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
|
+
};
|