@canonical/pragma-cli 0.38.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/package.json +14 -14
- package/dist/pragma.conf.js +273 -176
- package/dist/pragma.conf.js.map +1 -1
- package/dist/src/capabilities/capabilities/capabilities.verb.js +2 -0
- package/dist/src/capabilities/capabilities/capabilities.verb.js.map +1 -1
- package/dist/src/capabilities/capabilities/catalog.js +47 -51
- package/dist/src/capabilities/capabilities/catalog.js.map +1 -1
- package/dist/src/capabilities/capabilities/index.js +2 -0
- package/dist/src/capabilities/capabilities/index.js.map +1 -1
- package/dist/src/capabilities/capabilities/types.js +5 -5
- package/dist/src/capabilities/colophon/colophon.render.js +7 -4
- package/dist/src/capabilities/colophon/colophon.render.js.map +1 -1
- package/dist/src/capabilities/colophon/colophon.verb.js +1 -0
- package/dist/src/capabilities/colophon/colophon.verb.js.map +1 -1
- package/dist/src/capabilities/config/get.verb.js +2 -0
- package/dist/src/capabilities/config/get.verb.js.map +1 -1
- package/dist/src/capabilities/config/runField.js +2 -2
- package/dist/src/capabilities/config/runField.js.map +1 -1
- package/dist/src/capabilities/config/set.verb.js +2 -0
- package/dist/src/capabilities/config/set.verb.js.map +1 -1
- package/dist/src/capabilities/config/show.verb.js +1 -0
- package/dist/src/capabilities/config/show.verb.js.map +1 -1
- package/dist/src/capabilities/config/unset.verb.js +2 -0
- package/dist/src/capabilities/config/unset.verb.js.map +1 -1
- package/dist/src/capabilities/create/constants.js +2 -2
- package/dist/src/capabilities/create/create.verb.js +14 -4
- package/dist/src/capabilities/create/create.verb.js.map +1 -1
- package/dist/src/capabilities/distribution.js +3 -1
- package/dist/src/capabilities/distribution.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/checkPackageRefs.js +10 -2
- package/dist/src/capabilities/doctor/checks/checkPackageRefs.js.map +1 -1
- package/dist/src/capabilities/doctor/doctor.verb.js +2 -0
- package/dist/src/capabilities/doctor/doctor.verb.js.map +1 -1
- package/dist/src/capabilities/graph/connect.verb.js +2 -0
- package/dist/src/capabilities/graph/connect.verb.js.map +1 -1
- package/dist/src/capabilities/graph/inspect.render.js +7 -1
- package/dist/src/capabilities/graph/inspect.render.js.map +1 -1
- package/dist/src/capabilities/graph/inspect.verb.js +2 -0
- package/dist/src/capabilities/graph/inspect.verb.js.map +1 -1
- package/dist/src/capabilities/graph/query.render.js +37 -5
- package/dist/src/capabilities/graph/query.render.js.map +1 -1
- package/dist/src/capabilities/graph/query.verb.js +2 -0
- package/dist/src/capabilities/graph/query.verb.js.map +1 -1
- package/dist/src/capabilities/graph/queryText.js +28 -0
- package/dist/src/capabilities/graph/queryText.js.map +1 -1
- package/dist/src/capabilities/graph/runConnect.js +3 -3
- package/dist/src/capabilities/graph/runConnect.js.map +1 -1
- package/dist/src/capabilities/graph/runQuery.js +8 -6
- package/dist/src/capabilities/graph/runQuery.js.map +1 -1
- package/dist/src/capabilities/info/info.verb.js +2 -0
- package/dist/src/capabilities/info/info.verb.js.map +1 -1
- package/dist/src/capabilities/meta/mcp.verb.js +1 -0
- package/dist/src/capabilities/meta/mcp.verb.js.map +1 -1
- package/dist/src/capabilities/ontology/verbs.js +7 -10
- package/dist/src/capabilities/ontology/verbs.js.map +1 -1
- package/dist/src/capabilities/prompt/verbs.js +5 -4
- package/dist/src/capabilities/prompt/verbs.js.map +1 -1
- package/dist/src/capabilities/resources/provider.js +6 -3
- package/dist/src/capabilities/resources/provider.js.map +1 -1
- package/dist/src/capabilities/setup/setup.verb.js +13 -5
- package/dist/src/capabilities/setup/setup.verb.js.map +1 -1
- package/dist/src/capabilities/shared/calls.js +16 -0
- package/dist/src/capabilities/shared/calls.js.map +1 -0
- package/dist/src/capabilities/skill/render.js +7 -5
- package/dist/src/capabilities/skill/render.js.map +1 -1
- package/dist/src/capabilities/skill/verbs.js +5 -4
- package/dist/src/capabilities/skill/verbs.js.map +1 -1
- package/dist/src/capabilities/sources/collectStatus.js +6 -1
- package/dist/src/capabilities/sources/collectStatus.js.map +1 -1
- package/dist/src/capabilities/sources/index.js +4 -3
- package/dist/src/capabilities/sources/index.js.map +1 -1
- package/dist/src/capabilities/sources/reset.render.js +37 -0
- package/dist/src/capabilities/sources/reset.render.js.map +1 -0
- package/dist/src/capabilities/sources/reset.verb.js +51 -0
- package/dist/src/capabilities/sources/reset.verb.js.map +1 -0
- package/dist/src/capabilities/sources/runReset.js +59 -0
- package/dist/src/capabilities/sources/runReset.js.map +1 -0
- package/dist/src/capabilities/sources/runUpdate.js +7 -6
- package/dist/src/capabilities/sources/runUpdate.js.map +1 -1
- package/dist/src/capabilities/sources/status.render.js +24 -8
- package/dist/src/capabilities/sources/status.render.js.map +1 -1
- package/dist/src/capabilities/sources/status.verb.js +1 -0
- package/dist/src/capabilities/sources/status.verb.js.map +1 -1
- package/dist/src/capabilities/sources/update.verb.js +2 -0
- package/dist/src/capabilities/sources/update.verb.js.map +1 -1
- package/dist/src/capabilities/upgrade/upgrade.verb.js +1 -0
- package/dist/src/capabilities/upgrade/upgrade.verb.js.map +1 -1
- package/dist/src/capabilities/version/version.verb.js +1 -0
- package/dist/src/capabilities/version/version.verb.js.map +1 -1
- package/dist/src/constants.js +4 -3
- package/dist/src/constants.js.map +1 -1
- package/dist/src/kernel/error/index.js +1 -1
- package/dist/src/kernel/error/index.js.map +1 -1
- package/dist/src/kernel/error/recovery.js +24 -42
- package/dist/src/kernel/error/recovery.js.map +1 -1
- package/dist/src/kernel/packs/collect.js +123 -9
- package/dist/src/kernel/packs/collect.js.map +1 -1
- package/dist/src/kernel/packs/compile.js +74 -15
- package/dist/src/kernel/packs/compile.js.map +1 -1
- package/dist/src/kernel/packs/graphql/fetchGraphqlLookup.js +3 -3
- package/dist/src/kernel/packs/graphql/fetchGraphqlLookup.js.map +1 -1
- package/dist/src/kernel/packs/iri.js +2 -4
- package/dist/src/kernel/packs/iri.js.map +1 -1
- package/dist/src/kernel/packs/renderPack.js +90 -50
- package/dist/src/kernel/packs/renderPack.js.map +1 -1
- package/dist/src/kernel/packs/resolveEntity.js +202 -90
- package/dist/src/kernel/packs/resolveEntity.js.map +1 -1
- package/dist/src/kernel/packs/runBodies.js +89 -30
- package/dist/src/kernel/packs/runBodies.js.map +1 -1
- package/dist/src/kernel/packs/schema.js +66 -12
- package/dist/src/kernel/packs/schema.js.map +1 -1
- package/dist/src/kernel/packs/sparql/buildListQuery.js +80 -13
- package/dist/src/kernel/packs/sparql/buildListQuery.js.map +1 -1
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js +41 -13
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js.map +1 -1
- package/dist/src/kernel/packs/sparql/filterValues.js +32 -23
- package/dist/src/kernel/packs/sparql/filterValues.js.map +1 -1
- package/dist/src/kernel/packs/sparql/runSelect.js +3 -5
- package/dist/src/kernel/packs/sparql/runSelect.js.map +1 -1
- package/dist/src/kernel/packs/storyRules.js +31 -4
- package/dist/src/kernel/packs/storyRules.js.map +1 -1
- package/dist/src/kernel/packs/tierScope.js +3 -3
- package/dist/src/kernel/packs/tierScope.js.map +1 -1
- package/dist/src/kernel/packs/types.js +4 -0
- package/dist/src/kernel/packs/types.js.map +1 -1
- package/dist/src/kernel/project/cli/buildProgram.js +4 -0
- package/dist/src/kernel/project/cli/buildProgram.js.map +1 -1
- package/dist/src/kernel/project/cli/dispatch.js +32 -8
- package/dist/src/kernel/project/cli/dispatch.js.map +1 -1
- package/dist/src/kernel/project/cli/suggestNames.js +44 -1
- package/dist/src/kernel/project/cli/suggestNames.js.map +1 -1
- package/dist/src/kernel/project/cli/verbHelp.js +17 -18
- package/dist/src/kernel/project/cli/verbHelp.js.map +1 -1
- package/dist/src/kernel/project/mcp/buildServer.js +11 -4
- package/dist/src/kernel/project/mcp/buildServer.js.map +1 -1
- package/dist/src/kernel/project/mcp/envelope.js +3 -2
- package/dist/src/kernel/project/mcp/envelope.js.map +1 -1
- package/dist/src/kernel/project/mcp/instructions.js +101 -31
- package/dist/src/kernel/project/mcp/instructions.js.map +1 -1
- package/dist/src/kernel/project/mcp/registerVerb.js +59 -23
- package/dist/src/kernel/project/mcp/registerVerb.js.map +1 -1
- package/dist/src/kernel/render/renderers.js +3 -3
- package/dist/src/kernel/render/turtle.js +21 -4
- package/dist/src/kernel/render/turtle.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/build.js +54 -1
- package/dist/src/kernel/runtime/graphpack/build.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/manifest.js +14 -0
- package/dist/src/kernel/runtime/graphpack/manifest.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/read.js +3 -5
- package/dist/src/kernel/runtime/graphpack/read.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/schemas.js +1 -0
- package/dist/src/kernel/runtime/graphpack/schemas.js.map +1 -1
- package/dist/src/kernel/runtime/loadSession.js +8 -1
- package/dist/src/kernel/runtime/loadSession.js.map +1 -1
- package/dist/src/kernel/runtime/packVersion.js +75 -0
- package/dist/src/kernel/runtime/packVersion.js.map +1 -0
- package/dist/src/kernel/runtime/readEntity.js +43 -4
- package/dist/src/kernel/runtime/readEntity.js.map +1 -1
- package/dist/src/kernel/runtime/resolveSources.js +61 -9
- package/dist/src/kernel/runtime/resolveSources.js.map +1 -1
- package/dist/src/kernel/runtime/storeReadiness.js +3 -2
- package/dist/src/kernel/runtime/storeReadiness.js.map +1 -1
- package/dist/src/kernel/spec/call.js +167 -0
- package/dist/src/kernel/spec/call.js.map +1 -0
- package/dist/src/kernel/spec/emitReference.js +9 -13
- package/dist/src/kernel/spec/emitReference.js.map +1 -1
- package/dist/src/kernel/spec/emitSurface.js +8 -1
- package/dist/src/kernel/spec/emitSurface.js.map +1 -1
- package/dist/src/kernel/spec/guidance.js +63 -0
- package/dist/src/kernel/spec/guidance.js.map +1 -0
- package/dist/src/kernel/spec/wireType.js +36 -0
- package/dist/src/kernel/spec/wireType.js.map +1 -0
- package/package.json +14 -14
- package/pragma.conf.ts +294 -177
- package/src/capabilities/block.parity.test.ts +1 -1
- package/src/capabilities/callRule.test.ts +147 -0
- package/src/capabilities/capabilities/capabilities.test.ts +47 -19
- package/src/capabilities/capabilities/capabilities.verb.ts +2 -0
- package/src/capabilities/capabilities/catalog.ts +60 -55
- package/src/capabilities/capabilities/index.ts +2 -0
- package/src/capabilities/capabilities/types.ts +16 -19
- package/src/capabilities/colophon/colophon.render.ts +9 -5
- package/src/capabilities/colophon/colophon.verb.ts +1 -0
- package/src/capabilities/config/get.verb.ts +2 -0
- package/src/capabilities/config/runField.ts +3 -3
- package/src/capabilities/config/set.verb.ts +3 -0
- package/src/capabilities/config/show.verb.ts +2 -0
- package/src/capabilities/config/unset.verb.ts +2 -0
- package/src/capabilities/create/constants.ts +2 -2
- package/src/capabilities/create/create.verb.ts +16 -0
- package/src/capabilities/create/createGrammar.test.ts +1 -1
- package/src/capabilities/distribution.test.ts +6 -3
- package/src/capabilities/distribution.ts +6 -0
- package/src/capabilities/doctor/checks/checkPackageRefs.ts +14 -2
- package/src/capabilities/doctor/doctor.test.ts +38 -1
- package/src/capabilities/doctor/doctor.verb.ts +2 -0
- package/src/capabilities/emptyRecovery.test.ts +5 -0
- package/src/capabilities/graph/connect.verb.ts +2 -0
- package/src/capabilities/graph/inspect.render.ts +9 -1
- package/src/capabilities/graph/inspect.test.ts +73 -0
- package/src/capabilities/graph/inspect.verb.ts +2 -0
- package/src/capabilities/graph/query.render.test.ts +35 -0
- package/src/capabilities/graph/query.render.ts +45 -7
- package/src/capabilities/graph/query.shipped.exec.test.ts +44 -0
- package/src/capabilities/graph/query.verb.ts +2 -0
- package/src/capabilities/graph/queryText.test.ts +55 -1
- package/src/capabilities/graph/queryText.ts +47 -0
- package/src/capabilities/graph/runConnect.ts +4 -5
- package/src/capabilities/graph/runQuery.ts +23 -9
- package/src/capabilities/info/info.verb.ts +2 -0
- package/src/capabilities/links.shipped.exec.test.ts +398 -0
- package/src/capabilities/listBudget.shipped.exec.test.ts +2 -2
- package/src/capabilities/listLookup.shipped.exec.test.ts +122 -13
- package/src/capabilities/listQuery.shipped.exec.test.ts +39 -16
- package/src/capabilities/lookupBudget.shipped.exec.test.ts +208 -0
- package/src/capabilities/meta/mcp.verb.ts +2 -0
- package/src/capabilities/ontology/ontology.test.ts +24 -0
- package/src/capabilities/ontology/verbs.ts +16 -12
- package/src/capabilities/prompt/verbs.ts +10 -4
- package/src/capabilities/resources/provider.ts +7 -3
- package/src/capabilities/resources/resources.test.ts +2 -1
- package/src/capabilities/setup/setup.verb.ts +16 -0
- package/src/capabilities/shared/calls.ts +20 -0
- package/src/capabilities/skill/render.ts +9 -6
- package/src/capabilities/skill/verbs.ts +8 -4
- package/src/capabilities/sources/collectStatus.ts +6 -1
- package/src/capabilities/sources/index.ts +4 -3
- package/src/capabilities/sources/reset.render.test.ts +33 -0
- package/src/capabilities/sources/reset.render.ts +43 -0
- package/src/capabilities/sources/reset.verb.ts +59 -0
- package/src/capabilities/sources/runReset.ts +65 -0
- package/src/capabilities/sources/runUpdate.ts +12 -11
- package/src/capabilities/sources/sources.test.ts +158 -3
- package/src/capabilities/sources/status.render.test.ts +63 -1
- package/src/capabilities/sources/status.render.ts +25 -8
- package/src/capabilities/sources/status.verb.ts +2 -0
- package/src/capabilities/sources/types.ts +26 -0
- package/src/capabilities/sources/update.verb.ts +3 -0
- package/src/capabilities/surface.test.ts +2 -2
- package/src/capabilities/token.parity.test.ts +3 -2
- package/src/capabilities/tokenGraph.shipped.exec.test.ts +14 -2
- package/src/capabilities/upgrade/upgrade.verb.ts +1 -0
- package/src/capabilities/variable.parity.test.ts +2 -1
- package/src/capabilities/version/version.verb.ts +1 -0
- package/src/capabilities/wireContract.test.ts +110 -0
- package/src/constants.ts +4 -3
- package/src/kernel/copy.test.ts +1 -1
- package/src/kernel/error/PragmaError.test.ts +7 -3
- package/src/kernel/error/index.ts +1 -1
- package/src/kernel/error/recovery.test.ts +52 -18
- package/src/kernel/error/recovery.ts +25 -46
- package/src/kernel/error/types.ts +1 -1
- package/src/kernel/packs/collect.test.ts +79 -0
- package/src/kernel/packs/collect.ts +151 -11
- package/src/kernel/packs/compile.test.ts +107 -10
- package/src/kernel/packs/compile.ts +100 -11
- package/src/kernel/packs/filteredEmpty.test.ts +22 -5
- package/src/kernel/packs/graphql/fetchGraphqlLookup.ts +5 -6
- package/src/kernel/packs/graphqlSource.test.ts +42 -0
- package/src/kernel/packs/iri.ts +5 -4
- package/src/kernel/packs/listNotice.test.ts +1 -1
- package/src/kernel/packs/nounLink.test.ts +385 -0
- package/src/kernel/packs/renderPack.ts +137 -57
- package/src/kernel/packs/resolveEntity.test.ts +170 -1
- package/src/kernel/packs/resolveEntity.ts +281 -101
- package/src/kernel/packs/runBodies.ts +133 -31
- package/src/kernel/packs/schema.ts +77 -12
- package/src/kernel/packs/sparql/buildListQuery.test.ts +78 -1
- package/src/kernel/packs/sparql/buildListQuery.ts +106 -16
- package/src/kernel/packs/sparql/buildLookupQuery.ts +44 -13
- package/src/kernel/packs/sparql/filterValues.test.ts +36 -4
- package/src/kernel/packs/sparql/filterValues.ts +50 -31
- package/src/kernel/packs/sparql/runSelect.ts +4 -6
- package/src/kernel/packs/storyRules.ts +37 -4
- package/src/kernel/packs/tierScope.test.ts +120 -6
- package/src/kernel/packs/tierScope.ts +5 -7
- package/src/kernel/packs/toolDescription.test.ts +59 -74
- package/src/kernel/packs/types.ts +93 -11
- package/src/kernel/project/cli/buildProgram.ts +4 -0
- package/src/kernel/project/cli/dispatch.ts +34 -8
- package/src/kernel/project/cli/suggest.test.ts +77 -0
- package/src/kernel/project/cli/suggestNames.ts +47 -1
- package/src/kernel/project/cli/verbHelp.ts +16 -19
- package/src/kernel/project/mcp/buildServer.ts +15 -4
- package/src/kernel/project/mcp/envelope.ts +3 -2
- package/src/kernel/project/mcp/instructions.ts +123 -35
- package/src/kernel/project/mcp/prompts/prompts.test.ts +136 -20
- package/src/kernel/project/mcp/registerVerb.test.ts +28 -0
- package/src/kernel/project/mcp/registerVerb.ts +67 -29
- package/src/kernel/render/__snapshots__/renderers.test.ts.snap +1 -1
- package/src/kernel/render/renderers.test.ts +2 -2
- package/src/kernel/render/renderers.ts +3 -3
- package/src/kernel/render/turtle.ts +24 -4
- package/src/kernel/runtime/graphpack/build.ts +58 -1
- package/src/kernel/runtime/graphpack/graphpack.test.ts +20 -0
- package/src/kernel/runtime/graphpack/manifest.ts +15 -0
- package/src/kernel/runtime/graphpack/read.ts +4 -6
- package/src/kernel/runtime/graphpack/schemas.ts +1 -0
- package/src/kernel/runtime/graphpack/types.ts +13 -0
- package/src/kernel/runtime/loadSession.ts +8 -1
- package/src/kernel/runtime/packVersion.test.ts +61 -0
- package/src/kernel/runtime/packVersion.ts +84 -0
- package/src/kernel/runtime/readEntity.ts +61 -6
- package/src/kernel/runtime/resolveSources.test.ts +90 -7
- package/src/kernel/runtime/resolveSources.ts +91 -10
- package/src/kernel/runtime/storeReadiness.ts +4 -4
- package/src/kernel/runtime/types.ts +12 -0
- package/src/kernel/spec/call.test.ts +95 -0
- package/src/kernel/spec/call.ts +186 -0
- package/src/kernel/spec/emitReference.ts +9 -13
- package/src/kernel/spec/emitSurface.ts +9 -1
- package/src/kernel/spec/guidance.test.ts +49 -0
- package/src/kernel/spec/guidance.ts +68 -0
- package/src/kernel/spec/index.ts +4 -0
- package/src/kernel/spec/surfaceConformance.test.ts +2 -2
- package/src/kernel/spec/types.ts +64 -7
- package/src/kernel/spec/wireType.ts +53 -0
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +2 -1
- package/src/testing/behavioral/journeys.firstInstall.test.ts +72 -2
- package/src/testing/behavioral/parity.test.ts +40 -0
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +1 -1
- package/src/testing/eval/cases/assembly.ts +4 -3
- package/src/testing/eval/cases/stable.ts +2 -3
- package/src/testing/helpers/callSchema.ts +40 -0
- package/src/testing/helpers/parity.ts +35 -2
- package/src/testing/setupCallChecking.ts +30 -0
- package/dist/src/capabilities/capabilities/hints.js +0 -223
- package/dist/src/capabilities/capabilities/hints.js.map +0 -1
- package/src/capabilities/capabilities/hints.ts +0 -266
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
* (including the GraphQL path) stay off the storeless fast path.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import {
|
|
24
|
-
import { suggestNames } from "../project/cli/suggestNames.js";
|
|
23
|
+
import { callRecovery, PragmaError, type Recovery } from "../error/index.js";
|
|
24
|
+
import { MAX_SUGGESTIONS, suggestNames } from "../project/cli/suggestNames.js";
|
|
25
25
|
import { compactUri } from "../render/index.js";
|
|
26
26
|
import type { PragmaRuntime } from "../runtime/index.js";
|
|
27
27
|
import { activeExpands } from "./disclosure.js";
|
|
@@ -39,9 +39,9 @@ import {
|
|
|
39
39
|
SCOPE_TIER_VARIABLE,
|
|
40
40
|
} from "./sparql/buildLookupQuery.js";
|
|
41
41
|
import { runSelect } from "./sparql/runSelect.js";
|
|
42
|
+
import { localName } from "./tierScope.js";
|
|
42
43
|
import {
|
|
43
44
|
expandIsSparql,
|
|
44
|
-
type PackChildRow,
|
|
45
45
|
type PackEntity,
|
|
46
46
|
type PackLookup,
|
|
47
47
|
type PackRow,
|
|
@@ -107,11 +107,39 @@ export interface LookupOutput {
|
|
|
107
107
|
* case, and the case the payload speaks for itself in.
|
|
108
108
|
*/
|
|
109
109
|
readonly outOfScope?: OutOfScopeAnswer[];
|
|
110
|
+
/** Set when the patterns matched more entities than {@link GLOB_EXPANSION_CAP}. */
|
|
111
|
+
readonly truncated?: true;
|
|
112
|
+
/**
|
|
113
|
+
* The matched entities the cut was made in: the in-scope ones when they alone
|
|
114
|
+
* exceed the cap, else every match. Present only when truncated.
|
|
115
|
+
*/
|
|
116
|
+
readonly total?: number;
|
|
117
|
+
/** Out-of-scope matches not counted in `total`, when there are any. */
|
|
118
|
+
readonly elsewhere?: number;
|
|
119
|
+
/** The level the cut answer was built at, present only when truncated. */
|
|
120
|
+
readonly detail?: string;
|
|
110
121
|
}
|
|
111
122
|
|
|
123
|
+
/**
|
|
124
|
+
* The most entities the patterns of ONE lookup may expand to (derivation in
|
|
125
|
+
* BUDGETS.md). Literal arguments are never counted or cut.
|
|
126
|
+
*/
|
|
127
|
+
export const GLOB_EXPANSION_CAP = 50;
|
|
128
|
+
|
|
112
129
|
/** What the resolver needs from the runtime: the store + the query facade. */
|
|
113
130
|
type LookupRuntime = Pick<PragmaRuntime, "store" | "query">;
|
|
114
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Point a missed name at the noun's list — when it has one. A story may declare
|
|
134
|
+
* a lookup alone, and a recovery naming a `list` that does not exist is a dead
|
|
135
|
+
* end dressed as a way out.
|
|
136
|
+
*/
|
|
137
|
+
export function listRecovery(noun: string, hasList: boolean): Recovery {
|
|
138
|
+
return hasList
|
|
139
|
+
? callRecovery({ verb: `${noun} list` }, `List available ${noun} entries.`)
|
|
140
|
+
: { message: `Check the name: ${noun} entries cannot be listed.` };
|
|
141
|
+
}
|
|
142
|
+
|
|
115
143
|
/**
|
|
116
144
|
* Resolve a batch of lookup queries, collecting per-query failures.
|
|
117
145
|
*
|
|
@@ -125,41 +153,59 @@ export async function resolveLookup(
|
|
|
125
153
|
source: StorySource,
|
|
126
154
|
prefixes: Readonly<Record<string, string>>,
|
|
127
155
|
level: string | undefined,
|
|
156
|
+
hasList: boolean,
|
|
128
157
|
scope?: LookupScope,
|
|
129
158
|
): Promise<LookupOutput> {
|
|
130
159
|
if (queries.length === 0) {
|
|
131
160
|
throw PragmaError.invalidInput("names", "(empty)", {
|
|
132
|
-
recovery:
|
|
133
|
-
tool: `${noun}_list`,
|
|
134
|
-
// A concrete, valid argument bag rather than a bare tool name: an
|
|
135
|
-
// agent can call the recovery as written instead of guessing one.
|
|
136
|
-
params: {},
|
|
137
|
-
}),
|
|
161
|
+
recovery: listRecovery(noun, hasList),
|
|
138
162
|
});
|
|
139
163
|
}
|
|
140
164
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
);
|
|
165
|
+
// Read at most once per call, however many patterns and misses need it.
|
|
166
|
+
let pool: Promise<Addressable[]> | undefined;
|
|
167
|
+
const addressable = (): Promise<Addressable[]> => {
|
|
168
|
+
pool ??= listAddressable(rt, lookup, source, prefixes, scope?.via);
|
|
169
|
+
return pool;
|
|
170
|
+
};
|
|
171
|
+
const expanded = await expandQueries(noun, queries, addressable, scope);
|
|
149
172
|
const results: PackEntity[] = [];
|
|
150
173
|
const errors: LookupError[] = [...expanded.globErrors];
|
|
151
|
-
const outOfScope: OutOfScopeAnswer[] = [];
|
|
174
|
+
const outOfScope: OutOfScopeAnswer[] = [...expanded.outOfScope];
|
|
175
|
+
// Two arguments may reach one entity by different routes — a name pattern
|
|
176
|
+
// and an IRI pattern, a name and that entity's own IRI. It is answered once.
|
|
177
|
+
const answered = new Set<string>();
|
|
152
178
|
const settled = await Promise.allSettled(
|
|
153
179
|
expanded.names.map((query) =>
|
|
154
|
-
lookupOne(
|
|
180
|
+
lookupOne(
|
|
181
|
+
rt,
|
|
182
|
+
lookup,
|
|
183
|
+
noun,
|
|
184
|
+
query,
|
|
185
|
+
source,
|
|
186
|
+
prefixes,
|
|
187
|
+
level,
|
|
188
|
+
addressable,
|
|
189
|
+
scope,
|
|
190
|
+
),
|
|
155
191
|
),
|
|
156
192
|
);
|
|
157
193
|
for (const [index, outcome] of settled.entries()) {
|
|
158
194
|
const query = expanded.names[index];
|
|
159
195
|
if (query === undefined) continue;
|
|
160
196
|
if (outcome.status === "fulfilled") {
|
|
161
|
-
|
|
162
|
-
|
|
197
|
+
for (const entity of outcome.value.entities) {
|
|
198
|
+
const uri = String(entity.uri);
|
|
199
|
+
if (answered.has(uri)) continue;
|
|
200
|
+
answered.add(uri);
|
|
201
|
+
results.push(entity);
|
|
202
|
+
}
|
|
203
|
+
const fallback = outcome.value.outOfScope;
|
|
204
|
+
const key = (answer: OutOfScopeAnswer): string =>
|
|
205
|
+
`${answer.query.toLowerCase()}|${answer.tiers.join()}`;
|
|
206
|
+
if (fallback && !outOfScope.some((a) => key(a) === key(fallback))) {
|
|
207
|
+
outOfScope.push(fallback);
|
|
208
|
+
}
|
|
163
209
|
continue;
|
|
164
210
|
}
|
|
165
211
|
const error = outcome.reason;
|
|
@@ -184,66 +230,190 @@ export async function resolveLookup(
|
|
|
184
230
|
results,
|
|
185
231
|
errors,
|
|
186
232
|
...(outOfScope.length > 0 ? { outOfScope } : {}),
|
|
233
|
+
...(expanded.total === undefined
|
|
234
|
+
? {}
|
|
235
|
+
: {
|
|
236
|
+
truncated: true as const,
|
|
237
|
+
total: expanded.total,
|
|
238
|
+
...(expanded.elsewhere ? { elsewhere: expanded.elsewhere } : {}),
|
|
239
|
+
...(level ? { detail: level } : {}),
|
|
240
|
+
}),
|
|
187
241
|
};
|
|
188
242
|
}
|
|
189
243
|
|
|
190
244
|
/**
|
|
191
|
-
*
|
|
192
|
-
*
|
|
245
|
+
* The IRIs of every entity the given lookup arguments reach — the resolve
|
|
246
|
+
* alone, with nothing fetched. Each is read as {@link resolveLookup} reads a
|
|
247
|
+
* literal argument (a name, a prefixed IRI, an absolute IRI; never a pattern),
|
|
248
|
+
* under no tier scope: a name reaches its entity in every tier.
|
|
193
249
|
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
* offered nothing BUT those IRIs. Each population is fetched at most once, and
|
|
199
|
-
* only when a glob of that shape is actually present.
|
|
250
|
+
* @returns The distinct IRIs; none when the store holds no entity of the noun.
|
|
251
|
+
* @throws PragmaError INVALID_INPUT naming every argument that reaches nothing,
|
|
252
|
+
* with the suggestions a lookup miss offers; when an argument is empty; or
|
|
253
|
+
* when an IRI-shaped argument cannot be embedded in a query.
|
|
200
254
|
*/
|
|
201
|
-
async function
|
|
255
|
+
export async function resolveEntityIris(
|
|
202
256
|
rt: LookupRuntime,
|
|
203
257
|
lookup: PackLookup,
|
|
204
258
|
noun: string,
|
|
205
|
-
source: StorySource,
|
|
206
259
|
queries: readonly string[],
|
|
260
|
+
source: StorySource,
|
|
207
261
|
prefixes: Readonly<Record<string, string>>,
|
|
208
|
-
): Promise<
|
|
209
|
-
|
|
210
|
-
|
|
262
|
+
): Promise<string[]> {
|
|
263
|
+
const blank = queries.find((query) => query.trim() === "");
|
|
264
|
+
if (blank !== undefined) {
|
|
265
|
+
throw PragmaError.invalidInput(noun, "(empty)", {
|
|
266
|
+
recovery: { message: `Give a ${noun} name or IRI.` },
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
const iris = new Set<string>();
|
|
270
|
+
const missed: string[] = [];
|
|
271
|
+
// The graphql-sourced resolve is the bare `?uri ?name` pair: no field read.
|
|
272
|
+
const bare: PackLookup = { ...lookup, source: "graphql" };
|
|
273
|
+
for (const query of queries) {
|
|
274
|
+
const rows = await runSelect(
|
|
275
|
+
rt,
|
|
276
|
+
buildResolveQuery(bare, query, prefixes, undefined),
|
|
277
|
+
source,
|
|
278
|
+
);
|
|
279
|
+
if (rows.length === 0) missed.push(query);
|
|
280
|
+
for (const row of firstRowPerEntity(rows)) iris.add(String(row.uri));
|
|
281
|
+
}
|
|
282
|
+
if (missed.length === 0) return [...iris];
|
|
283
|
+
const pool = listAddressable(rt, lookup, source, prefixes, undefined);
|
|
284
|
+
if ((await pool).length === 0) return [];
|
|
285
|
+
const suggestions = await Promise.all(
|
|
286
|
+
missed.map((query) => suggestForMiss(() => pool, query)),
|
|
287
|
+
);
|
|
288
|
+
throw new PragmaError({
|
|
289
|
+
code: "INVALID_INPUT",
|
|
290
|
+
message: `No ${noun} is named "${missed.join('", "')}".`,
|
|
291
|
+
// Interleaved, so every miss gets a share of the slots.
|
|
292
|
+
suggestions: [
|
|
293
|
+
...new Set(
|
|
294
|
+
suggestions
|
|
295
|
+
.flatMap((list, miss) =>
|
|
296
|
+
list.map((name, rank) => ({ name, rank, miss })),
|
|
297
|
+
)
|
|
298
|
+
.sort((a, b) => a.rank - b.rank || a.miss - b.miss)
|
|
299
|
+
.map((entry) => entry.name),
|
|
300
|
+
),
|
|
301
|
+
].slice(0, MAX_SUGGESTIONS),
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Expand glob queries to the ENTITIES they reach; literals pass through.
|
|
307
|
+
*
|
|
308
|
+
* An IRI-shaped glob is matched against both spellings of an IRI, a prefix-less
|
|
309
|
+
* one against names and IRI local names. Matches are keyed by entity, so two
|
|
310
|
+
* routes to one entity count once. Under a tier scope the in-scope matches come
|
|
311
|
+
* first and an out-of-scope namesake of one is dropped, as a name lookup would;
|
|
312
|
+
* the cap is applied after that, over a deterministic order.
|
|
313
|
+
*/
|
|
314
|
+
async function expandQueries(
|
|
315
|
+
noun: string,
|
|
316
|
+
queries: readonly string[],
|
|
317
|
+
addressable: () => Promise<Addressable[]>,
|
|
318
|
+
scope: LookupScope | undefined,
|
|
319
|
+
): Promise<{
|
|
320
|
+
names: string[];
|
|
321
|
+
globErrors: LookupError[];
|
|
322
|
+
outOfScope: OutOfScopeAnswer[];
|
|
323
|
+
total?: number;
|
|
324
|
+
elsewhere?: number;
|
|
325
|
+
}> {
|
|
326
|
+
const literals = [...new Set(queries.filter((q) => !isGlobPattern(q)))];
|
|
211
327
|
const globs = queries.filter(isGlobPattern);
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
const
|
|
216
|
-
? await listEntityNames(rt, lookup, source)
|
|
217
|
-
: [];
|
|
218
|
-
const names: string[] = [];
|
|
328
|
+
if (globs.length === 0) {
|
|
329
|
+
return { names: literals, globErrors: [], outOfScope: [] };
|
|
330
|
+
}
|
|
331
|
+
const pool = await addressable();
|
|
219
332
|
const globErrors: LookupError[] = [];
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
),
|
|
234
|
-
]
|
|
235
|
-
: expandGlob(query, byName);
|
|
236
|
-
if (matches.length === 0) {
|
|
333
|
+
const matched = new Map<string, Addressable>();
|
|
334
|
+
const inScope = (entity: Addressable): boolean =>
|
|
335
|
+
!scope || entity.tier === undefined || scope.tiers.includes(entity.tier);
|
|
336
|
+
for (const glob of globs) {
|
|
337
|
+
const forms = (entity: Addressable): string[] =>
|
|
338
|
+
looksLikeIri(glob)
|
|
339
|
+
? [entity.uri, entity.compact]
|
|
340
|
+
: [entity.name ?? "", entity.local];
|
|
341
|
+
const hits = new Set(expandGlob(glob, pool.flatMap(forms)));
|
|
342
|
+
const entities = pool.filter((entity) =>
|
|
343
|
+
forms(entity).some((form) => hits.has(form)),
|
|
344
|
+
);
|
|
345
|
+
if (entities.length === 0) {
|
|
237
346
|
globErrors.push({
|
|
238
|
-
query,
|
|
347
|
+
query: glob,
|
|
239
348
|
code: "EMPTY_RESULTS",
|
|
240
|
-
message: `No ${noun} entries matching "${
|
|
349
|
+
message: `No ${noun} entries matching "${glob}".`,
|
|
241
350
|
});
|
|
242
|
-
} else {
|
|
243
|
-
names.push(...matches);
|
|
244
351
|
}
|
|
352
|
+
for (const entity of entities) {
|
|
353
|
+
// An entity in two tiers is in scope when either row is.
|
|
354
|
+
const known = matched.get(entity.uri);
|
|
355
|
+
if (!known || (!inScope(known) && inScope(entity))) {
|
|
356
|
+
matched.set(entity.uri, entity);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
const label = (entity: Addressable): string => entity.name ?? entity.compact;
|
|
361
|
+
const scoped = new Set(
|
|
362
|
+
[...matched.values()].filter(inScope).map((e) => label(e).toLowerCase()),
|
|
363
|
+
);
|
|
364
|
+
const ordered = [...matched.values()]
|
|
365
|
+
.filter((e) => inScope(e) || !scoped.has(label(e).toLowerCase()))
|
|
366
|
+
.sort(
|
|
367
|
+
(a, b) =>
|
|
368
|
+
Number(!inScope(a)) - Number(!inScope(b)) ||
|
|
369
|
+
label(a).localeCompare(label(b)) ||
|
|
370
|
+
a.uri.localeCompare(b.uri),
|
|
371
|
+
);
|
|
372
|
+
const kept = ordered.slice(0, GLOB_EXPANSION_CAP);
|
|
373
|
+
const within = ordered.filter(inScope).length;
|
|
374
|
+
return {
|
|
375
|
+
names: [...literals, ...kept.map((entity) => entity.compact)],
|
|
376
|
+
globErrors,
|
|
377
|
+
outOfScope: kept
|
|
378
|
+
.filter((entity) => !inScope(entity))
|
|
379
|
+
.map((entity) => ({
|
|
380
|
+
query: label(entity),
|
|
381
|
+
tiers: [scopeTierName(entity.tier ?? "")],
|
|
382
|
+
scope: scope?.label ?? "",
|
|
383
|
+
})),
|
|
384
|
+
...(ordered.length <= kept.length
|
|
385
|
+
? {}
|
|
386
|
+
: within > kept.length
|
|
387
|
+
? { total: within, elsewhere: ordered.length - within }
|
|
388
|
+
: { total: ordered.length }),
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* What to offer for an argument that reached nothing: near names, and the
|
|
394
|
+
* prefixed IRI of an entity whose local name is what was typed (exact match
|
|
395
|
+
* first). A bare local name is not an address; the miss names the form that is.
|
|
396
|
+
*/
|
|
397
|
+
async function suggestForMiss(
|
|
398
|
+
addressable: () => Promise<Addressable[]>,
|
|
399
|
+
query: string,
|
|
400
|
+
): Promise<string[]> {
|
|
401
|
+
const pool = await addressable();
|
|
402
|
+
const names = [...new Set(pool.flatMap((e) => (e.name ? [e.name] : [])))];
|
|
403
|
+
const taken = new Set(names.map((name) => name.trim().toLowerCase()));
|
|
404
|
+
const byLocal = new Map<string, string[]>();
|
|
405
|
+
for (const entity of pool) {
|
|
406
|
+
const key = entity.local.toLowerCase();
|
|
407
|
+
if (taken.has(key)) continue;
|
|
408
|
+
byLocal.set(key, [
|
|
409
|
+
...new Set([...(byLocal.get(key) ?? []), entity.compact]),
|
|
410
|
+
]);
|
|
245
411
|
}
|
|
246
|
-
|
|
412
|
+
const exact = byLocal.get(query.trim().toLowerCase()) ?? [];
|
|
413
|
+
const ranked = suggestNames(query, [...names, ...byLocal.keys()]).flatMap(
|
|
414
|
+
(candidate) => byLocal.get(candidate) ?? [candidate],
|
|
415
|
+
);
|
|
416
|
+
return [...new Set([...exact, ...ranked])].slice(0, MAX_SUGGESTIONS);
|
|
247
417
|
}
|
|
248
418
|
|
|
249
419
|
/**
|
|
@@ -283,6 +453,7 @@ async function lookupOne(
|
|
|
283
453
|
source: StorySource,
|
|
284
454
|
prefixes: Readonly<Record<string, string>>,
|
|
285
455
|
level: string | undefined,
|
|
456
|
+
addressable: () => Promise<Addressable[]>,
|
|
286
457
|
scope?: LookupScope,
|
|
287
458
|
): Promise<{ entities: PackEntity[]; outOfScope?: OutOfScopeAnswer }> {
|
|
288
459
|
const graphqlSourced = lookup.source === "graphql";
|
|
@@ -293,15 +464,8 @@ async function lookupOne(
|
|
|
293
464
|
);
|
|
294
465
|
const resolved = firstRowPerEntity(rows);
|
|
295
466
|
if (resolved.length === 0) {
|
|
296
|
-
const candidates = await listEntityNames(rt, lookup, source);
|
|
297
467
|
throw PragmaError.notFound(noun, query, {
|
|
298
|
-
suggestions:
|
|
299
|
-
recovery: cliRecovery(`${noun} list`, `List available ${noun} entries.`, {
|
|
300
|
-
tool: `${noun}_list`,
|
|
301
|
-
// A concrete, valid argument bag rather than a bare tool name: an
|
|
302
|
-
// agent can call the recovery as written instead of guessing one.
|
|
303
|
-
params: {},
|
|
304
|
-
}),
|
|
468
|
+
suggestions: await suggestForMiss(addressable, query),
|
|
305
469
|
});
|
|
306
470
|
}
|
|
307
471
|
|
|
@@ -429,7 +593,10 @@ async function addSparqlExpands(
|
|
|
429
593
|
): Promise<PackEntity> {
|
|
430
594
|
for (const expand of activeExpands(lookup, level)) {
|
|
431
595
|
if (!expandIsSparql(lookup, expand)) continue;
|
|
432
|
-
|
|
596
|
+
const many = expand.select.flatMap((field) =>
|
|
597
|
+
"many" in field && field.many ? [field.name] : [],
|
|
598
|
+
);
|
|
599
|
+
const rows = (await runSelect(
|
|
433
600
|
rt,
|
|
434
601
|
buildExpandQuery(expand, String(entity.uri), lookup),
|
|
435
602
|
source,
|
|
@@ -440,7 +607,16 @@ async function addSparqlExpands(
|
|
|
440
607
|
// without that pack does not bind, and every other section of that
|
|
441
608
|
// block is still perfectly answerable.
|
|
442
609
|
{ degradeOnUnboundPrefix: true },
|
|
443
|
-
)) as
|
|
610
|
+
)) as PackRow[];
|
|
611
|
+
// An aggregate has no order of its own; a `many` cell is sorted here.
|
|
612
|
+
entity[expand.name] = rows.map((row) => ({
|
|
613
|
+
...row,
|
|
614
|
+
...Object.fromEntries(
|
|
615
|
+
many
|
|
616
|
+
.filter((name) => row[name] !== undefined)
|
|
617
|
+
.map((name) => [name, (row[name] ?? "").split(" ").sort().join(" ")]),
|
|
618
|
+
),
|
|
619
|
+
}));
|
|
444
620
|
}
|
|
445
621
|
return entity;
|
|
446
622
|
}
|
|
@@ -509,38 +685,42 @@ function looksLikeIri(query: string): boolean {
|
|
|
509
685
|
);
|
|
510
686
|
}
|
|
511
687
|
|
|
512
|
-
/**
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
async function listEntityIriSpellings(
|
|
688
|
+
/** One way to address an entity: a row per name and per tier it carries. */
|
|
689
|
+
interface Addressable {
|
|
690
|
+
/** The canonical (absolute) IRI. */
|
|
691
|
+
readonly uri: string;
|
|
692
|
+
/** The prefixed form, or the IRI itself when no registered prefix matches. */
|
|
693
|
+
readonly compact: string;
|
|
694
|
+
/** The IRI's local name. */
|
|
695
|
+
readonly local: string;
|
|
696
|
+
/** The `by` value the entity carries, when it carries one. */
|
|
697
|
+
readonly name?: string;
|
|
698
|
+
/** The tier IRI, when the lookup is scoped and the entity is in one. */
|
|
699
|
+
readonly tier?: string;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/** List every entity the lookup can address by IRI. */
|
|
703
|
+
async function listAddressable(
|
|
529
704
|
rt: LookupRuntime,
|
|
530
705
|
lookup: PackLookup,
|
|
531
706
|
source: StorySource,
|
|
532
707
|
prefixes: Readonly<Record<string, string>>,
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
708
|
+
via: string | undefined,
|
|
709
|
+
): Promise<Addressable[]> {
|
|
710
|
+
const rows = await runSelect(rt, buildLookupIrisQuery(lookup, via), source);
|
|
711
|
+
return rows
|
|
712
|
+
.filter((row) => (row.uri ?? "") !== "")
|
|
713
|
+
.map((row) => {
|
|
714
|
+
const uri = row.uri as string;
|
|
715
|
+
const tier = row[SCOPE_TIER_VARIABLE];
|
|
716
|
+
return {
|
|
717
|
+
uri,
|
|
718
|
+
compact: compactUri(uri, prefixes),
|
|
719
|
+
local: localName(uri),
|
|
720
|
+
...(row.name ? { name: row.name } : {}),
|
|
721
|
+
...(tier ? { tier } : {}),
|
|
722
|
+
};
|
|
723
|
+
});
|
|
544
724
|
}
|
|
545
725
|
|
|
546
726
|
/** List every entity name the lookup can address (miss suggestions + sample/glob). */
|