@canonical/pragma-cli 0.27.1-experimental.0 → 0.30.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 +67 -15
- package/dist/pragma +0 -0
- package/package.json +16 -17
- package/src/config/defaultConfig.test.ts +33 -0
- package/src/config/defaultConfig.ts +59 -0
- package/src/config/defaults.json +17 -0
- package/src/config/findProjectConfigPath.test.ts +53 -0
- package/src/config/findProjectConfigPath.ts +36 -0
- package/src/config/index.ts +17 -2
- package/src/config/mergeConfigFileUpdate.ts +58 -0
- package/src/config/parseConfigValues.ts +215 -0
- package/src/config/readConfig.test.ts +104 -13
- package/src/config/readConfig.ts +12 -117
- package/src/config/readConfigLayers.test.ts +107 -0
- package/src/config/readConfigLayers.ts +115 -0
- package/src/config/resolveGlobalConfigPath.ts +13 -0
- package/src/config/resolveWriteConfigPath.test.ts +53 -0
- package/src/config/resolveWriteConfigPath.ts +31 -0
- package/src/config/types.ts +88 -2
- package/src/config/writeConfig.ts +25 -43
- package/src/constants.ts +12 -1
- package/src/domains/block/commands/index.ts +2 -1
- package/src/domains/block/commands/list.ts +5 -90
- package/src/domains/block/commands/lookup.ts +8 -167
- package/src/domains/block/commands/sample.ts +55 -0
- package/src/domains/block/formatters/index.ts +2 -1
- package/src/domains/block/formatters/sample.ts +21 -0
- package/src/domains/block/index.ts +3 -3
- package/src/domains/block/mcp/specs.ts +36 -168
- package/src/domains/block/operations/index.ts +2 -1
- package/src/domains/block/operations/lookup.ts +9 -0
- package/src/domains/block/operations/sample.ts +41 -0
- package/src/domains/block/orchestration/blockEmptyError.test.ts +26 -0
- package/src/domains/block/orchestration/resolveBlockLookup.ts +11 -3
- package/src/domains/block/stories.test.ts +28 -0
- package/src/domains/block/stories.ts +254 -0
- package/src/domains/config/commands/channel.test.ts +14 -3
- package/src/domains/config/commands/channel.ts +11 -7
- package/src/domains/config/commands/configScope.ts +46 -0
- package/src/domains/config/commands/framework.test.ts +105 -0
- package/src/domains/config/commands/framework.ts +91 -0
- package/src/domains/config/commands/index.ts +2 -0
- package/src/domains/config/commands/show.ts +5 -45
- package/src/domains/config/commands/tier.test.ts +13 -2
- package/src/domains/config/commands/tier.ts +11 -7
- package/src/domains/config/commands/trace.test.ts +165 -0
- package/src/domains/config/commands/trace.ts +83 -0
- package/src/domains/config/formatters/channel.test.ts +20 -6
- package/src/domains/config/formatters/channel.ts +14 -11
- package/src/domains/config/formatters/framework.ts +37 -0
- package/src/domains/config/formatters/index.ts +2 -0
- package/src/domains/config/formatters/show.test.ts +27 -0
- package/src/domains/config/formatters/show.ts +27 -4
- package/src/domains/config/formatters/tier.test.ts +26 -10
- package/src/domains/config/formatters/tier.ts +19 -11
- package/src/domains/config/formatters/trace.ts +28 -0
- package/src/domains/config/index.ts +15 -2
- package/src/domains/config/mcp/specs.ts +33 -53
- package/src/domains/config/operations/index.ts +1 -0
- package/src/domains/config/operations/show.test.ts +18 -0
- package/src/domains/config/operations/show.ts +7 -1
- package/src/domains/config/operations/types.ts +7 -0
- package/src/domains/config/operations/validateFramework.ts +24 -0
- package/src/domains/config/stories.ts +42 -0
- package/src/domains/config/tasks/index.ts +3 -0
- package/src/domains/config/tasks/setChannel.ts +13 -22
- package/src/domains/config/tasks/setFramework.ts +21 -0
- package/src/domains/config/tasks/setTier.ts +10 -23
- package/src/domains/config/tasks/setTrace.ts +20 -0
- package/src/domains/config/tasks/writeConfigField.ts +41 -0
- package/src/domains/create/commands/component.ts +5 -5
- package/src/domains/doctor/operations/checks/checkConfigFile.ts +19 -5
- package/src/domains/doctor/operations/checks/checkKeStore.ts +5 -5
- package/src/domains/doctor/operations/checks/checkMcpCommands.ts +130 -0
- package/src/domains/doctor/operations/checks/checkMcpConfigured.ts +1 -1
- package/src/domains/doctor/operations/checks/checkPackageRefs.ts +30 -48
- package/src/domains/doctor/operations/checks/checkSkillsSymlinked.ts +1 -1
- package/src/domains/doctor/operations/checks/index.ts +1 -0
- package/src/domains/doctor/operations/checks.test.ts +162 -8
- package/src/domains/doctor/operations/runChecks.test.ts +85 -4
- package/src/domains/doctor/operations/runChecks.ts +50 -12
- package/src/domains/graph/helpers/resolveUri.test.ts +50 -0
- package/src/domains/graph/helpers/resolveUri.ts +28 -21
- package/src/domains/graphql/commands/build.test.ts +196 -0
- package/src/domains/graphql/commands/build.ts +117 -0
- package/src/domains/graphql/commands/check.test.ts +141 -0
- package/src/domains/graphql/commands/check.ts +81 -0
- package/src/domains/graphql/commands/index.ts +5 -0
- package/src/domains/graphql/commands/serve.test.ts +40 -0
- package/src/domains/graphql/commands/serve.ts +131 -0
- package/src/domains/graphql/constants.ts +10 -0
- package/src/domains/graphql/formatters/index.ts +3 -0
- package/src/domains/graphql/formatters/report.ts +78 -0
- package/src/domains/graphql/helpers/gatherSources.test.ts +92 -0
- package/src/domains/graphql/helpers/gatherSources.ts +58 -0
- package/src/domains/graphql/helpers/index.ts +6 -0
- package/src/domains/graphql/helpers/parsePrefixes.test.ts +44 -0
- package/src/domains/graphql/helpers/parsePrefixes.ts +38 -0
- package/src/domains/graphql/helpers/resolveSourceFiles.test.ts +56 -0
- package/src/domains/graphql/helpers/resolveSourceFiles.ts +45 -0
- package/src/domains/graphql/helpers/routeGraphql.test.ts +43 -0
- package/src/domains/graphql/helpers/routeGraphql.ts +28 -0
- package/src/domains/graphql/index.ts +24 -0
- package/src/domains/graphql/operations/compileSchema.test.ts +95 -0
- package/src/domains/graphql/operations/compileSchema.ts +107 -0
- package/src/domains/graphql/operations/createSchemaServer.test.ts +50 -0
- package/src/domains/graphql/operations/createSchemaServer.ts +75 -0
- package/src/domains/graphql/operations/index.ts +12 -0
- package/src/domains/graphql/types.ts +29 -0
- package/src/domains/info/operations/collectInfo.test.ts +16 -5
- package/src/domains/info/operations/collectInfo.ts +16 -19
- package/src/domains/llm/capabilities.test.ts +91 -0
- package/src/domains/llm/commands/capabilities.ts +28 -0
- package/src/domains/llm/commands/index.ts +1 -0
- package/src/domains/llm/data/commandReference.ts +90 -18
- package/src/domains/llm/data/decisionTrees.ts +15 -13
- package/src/domains/llm/data/index.ts +2 -0
- package/src/domains/llm/data/toolCatalog.ts +190 -0
- package/src/domains/llm/formatters/capabilities.ts +50 -0
- package/src/domains/llm/formatters/index.ts +1 -0
- package/src/domains/llm/index.ts +3 -2
- package/src/domains/llm/mcp/index.ts +1 -1
- package/src/domains/llm/mcp/specs.ts +59 -52
- package/src/domains/llm/types.ts +40 -0
- package/src/domains/modifier/commands/index.ts +2 -1
- package/src/domains/modifier/commands/list.ts +5 -38
- package/src/domains/modifier/commands/lookup.ts +8 -79
- package/src/domains/modifier/commands/sample.ts +53 -0
- package/src/domains/modifier/formatters/index.ts +2 -1
- package/src/domains/modifier/formatters/sample.ts +15 -0
- package/src/domains/modifier/index.ts +7 -3
- package/src/domains/modifier/mcp/specs.ts +38 -70
- package/src/domains/modifier/operations/index.ts +2 -1
- package/src/domains/modifier/operations/lookup.ts +9 -0
- package/src/domains/modifier/operations/sample.ts +32 -0
- package/src/domains/modifier/orchestration/modifierEmptyError.test.ts +26 -0
- package/src/domains/modifier/orchestration/modifierEmptyError.ts +7 -2
- package/src/domains/modifier/orchestration/resolveModifierLookup.ts +15 -2
- package/src/domains/modifier/stories.test.ts +20 -0
- package/src/domains/modifier/stories.ts +77 -0
- package/src/domains/ontology/commands/list.ts +5 -58
- package/src/domains/ontology/commands/show.ts +6 -58
- package/src/domains/ontology/formatters/show.ts +7 -1
- package/src/domains/ontology/mcp/specs.ts +7 -84
- package/src/domains/ontology/stories.test.ts +36 -0
- package/src/domains/ontology/stories.ts +108 -0
- package/src/domains/refs/operations/index.ts +1 -1
- package/src/domains/refs/operations/paths.ts +29 -1
- package/src/domains/refs/operations/updateRefs.test.ts +6 -3
- package/src/domains/refs/operations/updateRefs.ts +2 -36
- package/src/domains/setup/commands/skills.test.ts +6 -2
- package/src/domains/setup/commands/skills.ts +6 -2
- package/src/domains/setup/helpers/runSetupTask.test.ts +148 -150
- package/src/domains/setup/helpers/runSetupTask.ts +62 -70
- package/src/domains/setup/operations/setupMcp.test.ts +6 -1
- package/src/domains/shared/bootStore.ts +92 -50
- package/src/domains/shared/compactUri.test.ts +11 -0
- package/src/domains/shared/compactUri.ts +10 -5
- package/src/domains/shared/context.ts +2 -2
- package/src/domains/shared/contracts.ts +12 -0
- package/src/domains/shared/createInteractivePromptSession.test.ts +439 -0
- package/src/domains/shared/createInteractivePromptSession.ts +236 -0
- package/src/domains/shared/emptyErrorRecovery.test.ts +109 -0
- package/src/domains/shared/loaders/bundledLoader.test.ts +248 -0
- package/src/domains/shared/loaders/bundledLoader.ts +206 -0
- package/src/domains/shared/loaders/gitLoader.ts +31 -0
- package/src/domains/shared/loaders/index.ts +9 -0
- package/src/domains/shared/loaders/localLoader.ts +87 -0
- package/src/domains/shared/loaders/readPackageDir.ts +147 -0
- package/src/domains/shared/loaders/storyAssetsPlugin.test.ts +84 -0
- package/src/domains/shared/loaders/storyAssetsPlugin.ts +46 -0
- package/src/domains/shared/lookupMany.test.ts +120 -0
- package/src/domains/shared/lookupMany.ts +43 -3
- package/src/domains/shared/mergeAndParseRefs.test.ts +89 -0
- package/src/domains/shared/mergeAndParseRefs.ts +44 -0
- package/src/domains/shared/packages.ts +14 -120
- package/src/domains/shared/pickRandom.ts +22 -0
- package/src/domains/shared/resolveConfiguredGraphs.test.ts +27 -0
- package/src/domains/shared/resolveConfiguredGraphs.ts +41 -0
- package/src/domains/shared/runtime.ts +7 -63
- package/src/domains/shared/sampleFormatters.ts +47 -0
- package/src/domains/shared/semanticPackage.ts +112 -0
- package/src/domains/shared/stories/compileLookupCommand.test.ts +145 -0
- package/src/domains/shared/stories/compileLookupCommand.ts +100 -0
- package/src/domains/shared/stories/compileLookupTool.test.ts +105 -0
- package/src/domains/shared/stories/compileLookupTool.ts +96 -0
- package/src/domains/shared/stories/compileReadCommand.test.ts +121 -0
- package/src/domains/shared/stories/compileReadCommand.ts +48 -0
- package/src/domains/shared/stories/compileReadTool.test.ts +64 -0
- package/src/domains/shared/stories/compileReadTool.ts +38 -0
- package/src/domains/shared/stories/condense.test.ts +18 -0
- package/src/domains/shared/stories/condense.ts +15 -0
- package/src/domains/shared/stories/index.ts +20 -0
- package/src/domains/shared/stories/normalizeNames.test.ts +20 -0
- package/src/domains/shared/stories/normalizeNames.ts +22 -0
- package/src/domains/shared/stories/pack/applyPackFilters.test.ts +102 -0
- package/src/domains/shared/stories/pack/applyPackFilters.ts +76 -0
- package/src/domains/shared/stories/pack/buildLookupQuery.test.ts +51 -0
- package/src/domains/shared/stories/pack/buildLookupQuery.ts +80 -0
- package/src/domains/shared/stories/pack/collectPackStories.test.ts +108 -0
- package/src/domains/shared/stories/pack/collectPackStories.ts +76 -0
- package/src/domains/shared/stories/pack/compilePackCommands.ts +40 -0
- package/src/domains/shared/stories/pack/compilePackStories.test.ts +146 -0
- package/src/domains/shared/stories/pack/compilePackStories.ts +253 -0
- package/src/domains/shared/stories/pack/compilePackToolSpecs.ts +43 -0
- package/src/domains/shared/stories/pack/index.ts +28 -0
- package/src/domains/shared/stories/pack/runSelectQuery.ts +31 -0
- package/src/domains/shared/stories/pack/standardParity.test.ts +308 -0
- package/src/domains/shared/stories/pack/types.ts +104 -0
- package/src/domains/shared/stories/pack/validateStoryPackDefinition.test.ts +240 -0
- package/src/domains/shared/stories/pack/validateStoryPackDefinition.ts +408 -0
- package/src/domains/shared/stories/projectCliParameters.test.ts +59 -0
- package/src/domains/shared/stories/projectCliParameters.ts +57 -0
- package/src/domains/shared/stories/projectToolParams.test.ts +50 -0
- package/src/domains/shared/stories/projectToolParams.ts +32 -0
- package/src/domains/shared/stories/requirePragmaContext.test.ts +23 -0
- package/src/domains/shared/stories/requirePragmaContext.ts +23 -0
- package/src/domains/shared/stories/resolveLookupDetailed.test.ts +57 -0
- package/src/domains/shared/stories/resolveLookupDetailed.ts +27 -0
- package/src/domains/shared/stories/types.ts +171 -0
- package/src/domains/shared/suggestions/detectCrossDomain.test.ts +43 -0
- package/src/domains/shared/suggestions/detectCrossDomain.ts +116 -0
- package/src/domains/shared/suggestions/expandGlob.test.ts +92 -0
- package/src/domains/shared/suggestions/expandGlob.ts +52 -0
- package/src/domains/shared/suggestions/expandLookupQueries.ts +57 -0
- package/src/domains/shared/suggestions/index.ts +7 -0
- package/src/domains/shared/suggestions/listDomainNames.ts +61 -0
- package/src/domains/shared/suggestions/suggestNames.test.ts +70 -0
- package/src/domains/shared/suggestions/suggestNames.ts +130 -0
- package/src/domains/shared/types/index.ts +1 -0
- package/src/domains/shared/types/runtime.ts +4 -1
- package/src/domains/shared/types/sample.ts +17 -0
- package/src/domains/skill/commands/index.ts +3 -1
- package/src/domains/skill/commands/list.test.ts +6 -2
- package/src/domains/skill/commands/list.ts +5 -63
- package/src/domains/skill/commands/lookup.test.ts +118 -0
- package/src/domains/skill/commands/lookup.ts +14 -0
- package/src/domains/skill/formatters/index.ts +1 -0
- package/src/domains/skill/formatters/lookup.test.ts +46 -0
- package/src/domains/skill/formatters/lookup.ts +57 -0
- package/src/domains/skill/helpers/resolveSkillSources.ts +48 -16
- package/src/domains/skill/index.ts +7 -3
- package/src/domains/skill/mcp/specs.ts +10 -29
- package/src/domains/skill/operations/discover.test.ts +61 -30
- package/src/domains/skill/operations/discover.ts +28 -37
- package/src/domains/skill/operations/index.ts +2 -1
- package/src/domains/skill/operations/list.test.ts +15 -7
- package/src/domains/skill/operations/lookup.test.ts +91 -0
- package/src/domains/skill/operations/lookup.ts +70 -0
- package/src/domains/skill/stories.test.ts +43 -0
- package/src/domains/skill/stories.ts +103 -0
- package/src/domains/skill/types.ts +8 -0
- package/src/domains/standard/commands/index.ts +2 -1
- package/src/domains/standard/commands/list.ts +5 -84
- package/src/domains/standard/commands/lookup.ts +8 -93
- package/src/domains/standard/commands/sample.ts +57 -0
- package/src/domains/standard/formatters/index.ts +2 -1
- package/src/domains/standard/formatters/sample.ts +15 -0
- package/src/domains/standard/index.ts +8 -1
- package/src/domains/standard/mcp/specs.ts +44 -152
- package/src/domains/standard/operations/index.ts +2 -1
- package/src/domains/standard/operations/lookup.ts +9 -0
- package/src/domains/standard/operations/sample.ts +35 -0
- package/src/domains/standard/orchestration/resolveStandardLookup.ts +15 -2
- package/src/domains/standard/orchestration/standardEmptyError.test.ts +33 -0
- package/src/domains/standard/orchestration/standardEmptyError.ts +16 -6
- package/src/domains/standard/stories.test.ts +24 -0
- package/src/domains/standard/stories.ts +151 -0
- package/src/domains/tier/commands/list.ts +5 -55
- package/src/domains/tier/mcp/specs.ts +5 -31
- package/src/domains/tier/stories.test.ts +22 -0
- package/src/domains/tier/stories.ts +52 -0
- package/src/domains/token/commands/index.ts +2 -1
- package/src/domains/token/commands/sample.ts +53 -0
- package/src/domains/token/formatters/index.ts +2 -1
- package/src/domains/token/formatters/sample.ts +16 -0
- package/src/domains/token/index.ts +8 -1
- package/src/domains/token/mcp/specs.ts +52 -2
- package/src/domains/token/operations/index.ts +2 -1
- package/src/domains/token/operations/lookup.ts +9 -0
- package/src/domains/token/operations/sample.ts +32 -0
- package/src/domains/token/orchestration/resolveTokenLookup.ts +15 -2
- package/src/domains/token/orchestration/tokenEmptyError.test.ts +33 -0
- package/src/domains/token/orchestration/tokenEmptyError.ts +5 -2
- package/src/domains/trace/commands/clear.ts +71 -0
- package/src/domains/trace/commands/index.ts +5 -0
- package/src/domains/trace/commands/sessions.ts +32 -0
- package/src/domains/trace/commands/show.ts +145 -0
- package/src/domains/trace/formatters/index.ts +9 -0
- package/src/domains/trace/formatters/sessions.ts +80 -0
- package/src/domains/trace/formatters/show.ts +122 -0
- package/src/domains/trace/index.ts +17 -0
- package/src/domains/trace/operations/index.ts +8 -0
- package/src/domains/trace/operations/listSessions.test.ts +55 -0
- package/src/domains/trace/operations/listSessions.ts +52 -0
- package/src/domains/trace/operations/readTraceLog.test.ts +100 -0
- package/src/domains/trace/operations/readTraceLog.ts +104 -0
- package/src/domains/trace/tracePlugin.test.ts +171 -0
- package/src/domains/trace/tracePlugin.ts +159 -0
- package/src/domains/trace/types.ts +65 -0
- package/src/error/PragmaError.ts +15 -2
- package/src/error/types.ts +15 -1
- package/src/mcp/error/serializeErrorPayload.ts +7 -0
- package/src/mcp/error/types.ts +8 -0
- package/src/mcp/registerResources.test.ts +405 -75
- package/src/mcp/registerResources.ts +5 -299
- package/src/mcp/resources/buildGraphIndex.ts +167 -0
- package/src/mcp/resources/buildResourceList.test.ts +97 -0
- package/src/mcp/resources/buildResourceList.ts +176 -0
- package/src/mcp/resources/classifyEntity.test.ts +40 -0
- package/src/mcp/resources/classifyEntity.ts +27 -0
- package/src/mcp/resources/constants.ts +105 -0
- package/src/mcp/resources/displayPredicates.ts +62 -0
- package/src/mcp/resources/pickFirstValue.test.ts +29 -0
- package/src/mcp/resources/pickFirstValue.ts +26 -0
- package/src/mcp/resources/pickPrimaryType.test.ts +41 -0
- package/src/mcp/resources/pickPrimaryType.ts +26 -0
- package/src/mcp/resources/rankUriCompletions.test.ts +52 -0
- package/src/mcp/resources/rankUriCompletions.ts +64 -0
- package/src/mcp/resources/readEntity.ts +169 -0
- package/src/mcp/resources/registerResources.ts +126 -0
- package/src/mcp/resources/types.ts +128 -0
- package/src/mcp/tools/index.ts +9 -0
- package/src/mcp/tools/registerTools.test.ts +84 -12
- package/src/mcp/types.ts +4 -0
- package/src/mcp/utils/wrapTool.test.ts +1 -0
- package/src/pipeline/collectCommands.ts +15 -2
- package/src/pipeline/renderError.ts +15 -0
- package/src/pipeline/resolveCommandKind.ts +8 -1
- package/src/pipeline/runCli.ts +51 -6
- package/src/testing/createTestMcpClient.ts +5 -1
- package/src/testing/graphqlFixtures.ts +72 -0
- package/src/testing/index.ts +17 -0
- package/src/testing/integration/__snapshots__/executor-golden.test.ts.snap +1207 -0
- package/src/testing/integration/cross-binary-byte-equality.test.ts +129 -0
- package/src/testing/integration/executor-execution.test.ts +101 -0
- package/src/testing/integration/executor-golden.test.ts +145 -0
- package/src/testing/integration/mcp-surface.test.ts +11 -5
- package/src/testing/integration/parity.test.ts +17 -12
- package/src/testing/regression/0001-skill-discovery-granularity.test.ts +71 -0
- package/src/testing/setupXdgIsolation.ts +15 -0
- package/src/testing/standardParityFixtures.ts +92 -0
- package/src/testing/storyFixtures.ts +63 -0
- package/src/pipeline/runInteractiveCommand.ts +0 -198
|
@@ -1,173 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
* Wires the `pragma block lookup <name-or-uri...>` CLI command.
|
|
3
|
-
*
|
|
4
|
-
* Accepts a positional block name or IRI and optional aspect flags (anatomy,
|
|
5
|
-
* modifiers, tokens, implementations). Delegates to {@link lookupBlock} for
|
|
6
|
-
* data retrieval and {@link lookupFormatters} for output rendering.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
type CommandDefinition,
|
|
11
|
-
type CommandResult,
|
|
12
|
-
createOutputResult,
|
|
13
|
-
} from "@canonical/cli-core";
|
|
14
|
-
import { PragmaError } from "#error";
|
|
15
|
-
import { createLookupView } from "#tui";
|
|
1
|
+
import type { CommandDefinition } from "@canonical/cli-core";
|
|
16
2
|
import type { PragmaContext } from "../../shared/context.js";
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
19
|
-
import type { BlockDetailed } from "../../shared/types/index.js";
|
|
20
|
-
import { createLookupOptions, lookupFormatters } from "../formatters/index.js";
|
|
21
|
-
import { resolveAspects } from "../helpers/index.js";
|
|
22
|
-
import { listBlocks } from "../operations/index.js";
|
|
23
|
-
import {
|
|
24
|
-
buildBlockFilters,
|
|
25
|
-
resolveBlockLookup,
|
|
26
|
-
} from "../orchestration/index.js";
|
|
27
|
-
import type { AspectFlags } from "../types.js";
|
|
28
|
-
|
|
29
|
-
interface BlockLookupOutput {
|
|
30
|
-
readonly result: LookupResult<BlockDetailed>;
|
|
31
|
-
readonly detailed: boolean;
|
|
32
|
-
readonly aspects: AspectFlags;
|
|
33
|
-
}
|
|
3
|
+
import { compileLookupCommand } from "../../shared/stories/index.js";
|
|
4
|
+
import { blockLookupStory } from "../stories.js";
|
|
34
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Wire the `pragma block lookup <name-or-uri...>` CLI command from the
|
|
8
|
+
* block lookup story.
|
|
9
|
+
*/
|
|
35
10
|
export default function buildLookupCommand(
|
|
36
11
|
ctx: PragmaContext,
|
|
37
12
|
): CommandDefinition {
|
|
38
|
-
return
|
|
39
|
-
path: ["block", "lookup"],
|
|
40
|
-
description: "Look up block details",
|
|
41
|
-
parameters: [
|
|
42
|
-
{
|
|
43
|
-
name: "names",
|
|
44
|
-
description: "Block names or IRIs",
|
|
45
|
-
type: "multiselect",
|
|
46
|
-
positional: true,
|
|
47
|
-
required: true,
|
|
48
|
-
complete: async (partial: string) => {
|
|
49
|
-
const all = await listBlocks(ctx.store, ctx.config);
|
|
50
|
-
return all
|
|
51
|
-
.map((c) => c.name)
|
|
52
|
-
.filter((n) => n.toLowerCase().startsWith(partial.toLowerCase()));
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: "detailed",
|
|
57
|
-
description:
|
|
58
|
-
"Show full details including anatomy, modifiers, tokens, and implementations",
|
|
59
|
-
type: "boolean",
|
|
60
|
-
default: false,
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
name: "anatomy",
|
|
64
|
-
description: "Show anatomy tree",
|
|
65
|
-
type: "boolean",
|
|
66
|
-
default: false,
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
name: "modifiers",
|
|
70
|
-
description: "Show modifier values",
|
|
71
|
-
type: "boolean",
|
|
72
|
-
default: false,
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
name: "tokens",
|
|
76
|
-
description: "Show token references",
|
|
77
|
-
type: "boolean",
|
|
78
|
-
default: false,
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
name: "implementations",
|
|
82
|
-
description: "Show implementation paths",
|
|
83
|
-
type: "boolean",
|
|
84
|
-
default: false,
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
parameterGroups: {
|
|
88
|
-
"Aspect filters": ["anatomy", "modifiers", "tokens", "implementations"],
|
|
89
|
-
},
|
|
90
|
-
meta: {
|
|
91
|
-
examples: [
|
|
92
|
-
"pragma block lookup Button",
|
|
93
|
-
"pragma block lookup Button Card",
|
|
94
|
-
"pragma block lookup Button --detailed",
|
|
95
|
-
"pragma block lookup Button --anatomy --modifiers",
|
|
96
|
-
"pragma block lookup Button --detailed --llm",
|
|
97
|
-
"pragma block lookup ds:global.component.button",
|
|
98
|
-
],
|
|
99
|
-
},
|
|
100
|
-
execute: async (
|
|
101
|
-
params: Record<string, unknown>,
|
|
102
|
-
): Promise<CommandResult> => {
|
|
103
|
-
const names = normalizeNames(params.names, params.name);
|
|
104
|
-
if (names.length === 0) {
|
|
105
|
-
throw PragmaError.invalidInput("names", "(empty)", {
|
|
106
|
-
recovery: {
|
|
107
|
-
message: "List available blocks.",
|
|
108
|
-
cli: "pragma block list",
|
|
109
|
-
mcp: { tool: "block_list" },
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const detailed = params.detailed === true;
|
|
115
|
-
const aspectInput: Partial<AspectFlags> = {
|
|
116
|
-
anatomy: params.anatomy === true,
|
|
117
|
-
modifiers: params.modifiers === true,
|
|
118
|
-
tokens: params.tokens === true,
|
|
119
|
-
implementations: params.implementations === true,
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const isAspectSelected =
|
|
123
|
-
aspectInput.anatomy ||
|
|
124
|
-
aspectInput.modifiers ||
|
|
125
|
-
aspectInput.tokens ||
|
|
126
|
-
aspectInput.implementations;
|
|
127
|
-
const showDetailed = detailed || (isAspectSelected ?? false);
|
|
128
|
-
const aspects = resolveAspects(aspectInput);
|
|
129
|
-
|
|
130
|
-
const contract = await resolveBlockLookup(
|
|
131
|
-
ctx.store,
|
|
132
|
-
names,
|
|
133
|
-
buildBlockFilters(ctx),
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
return createOutputResult<BlockLookupOutput>(
|
|
137
|
-
{ result: contract.result, detailed: showDetailed, aspects },
|
|
138
|
-
{
|
|
139
|
-
plain: ({ result, detailed: isDetailed, aspects: selectedAspects }) =>
|
|
140
|
-
renderLookupResults({
|
|
141
|
-
ctx,
|
|
142
|
-
result,
|
|
143
|
-
formatters: lookupFormatters,
|
|
144
|
-
mapResult: (block) => ({
|
|
145
|
-
block,
|
|
146
|
-
detailed: isDetailed,
|
|
147
|
-
aspects: selectedAspects,
|
|
148
|
-
}),
|
|
149
|
-
}),
|
|
150
|
-
ink: ({ result, detailed: isDetailed, aspects: selectedAspects }) =>
|
|
151
|
-
createLookupView({
|
|
152
|
-
results: result.results,
|
|
153
|
-
errors: result.errors,
|
|
154
|
-
domain: "block",
|
|
155
|
-
options: createLookupOptions(isDetailed, selectedAspects),
|
|
156
|
-
}),
|
|
157
|
-
},
|
|
158
|
-
);
|
|
159
|
-
},
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function normalizeNames(names: unknown, legacyName?: unknown): string[] {
|
|
164
|
-
if (Array.isArray(names)) {
|
|
165
|
-
return names.filter(
|
|
166
|
-
(name): name is string => typeof name === "string" && name.length > 0,
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
if (typeof legacyName === "string" && legacyName.length > 0) {
|
|
170
|
-
return [legacyName];
|
|
171
|
-
}
|
|
172
|
-
return [];
|
|
13
|
+
return compileLookupCommand(ctx, blockLookupStory);
|
|
173
14
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wires the `pragma block sample` CLI command.
|
|
3
|
+
*
|
|
4
|
+
* Returns 1–5 complete block instances as exemplars so agents
|
|
5
|
+
* can learn the data shape before writing queries.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
type CommandDefinition,
|
|
10
|
+
createOutputResult,
|
|
11
|
+
} from "@canonical/cli-core";
|
|
12
|
+
import type { PragmaContext } from "../../shared/context.js";
|
|
13
|
+
import { selectFormatter } from "../../shared/formatters.js";
|
|
14
|
+
import type { BlockDetailed, SampleOutput } from "../../shared/types/index.js";
|
|
15
|
+
import { sampleFormatters } from "../formatters/index.js";
|
|
16
|
+
import { sampleBlocks } from "../operations/index.js";
|
|
17
|
+
import { buildBlockFilters } from "../orchestration/index.js";
|
|
18
|
+
|
|
19
|
+
const NEXT_STEPS = [
|
|
20
|
+
"Use block_lookup to inspect specific blocks by name.",
|
|
21
|
+
"Use block_list to see all available blocks with filtering.",
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export default function sampleCommand(ctx: PragmaContext): CommandDefinition {
|
|
25
|
+
return {
|
|
26
|
+
path: ["block", "sample"],
|
|
27
|
+
description:
|
|
28
|
+
"Return randomly selected complete block instances as exemplars for shape discovery",
|
|
29
|
+
parameters: [
|
|
30
|
+
{
|
|
31
|
+
name: "count",
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "Number of samples to return (1–5, default 2)",
|
|
34
|
+
required: false,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
meta: {
|
|
38
|
+
examples: ["pragma block sample", "pragma block sample --count 3"],
|
|
39
|
+
},
|
|
40
|
+
async execute(params) {
|
|
41
|
+
const count = Number(params.count ?? 2);
|
|
42
|
+
const filters = buildBlockFilters(ctx);
|
|
43
|
+
const result = await sampleBlocks(ctx.store, filters, count);
|
|
44
|
+
|
|
45
|
+
const output: SampleOutput<BlockDetailed> = {
|
|
46
|
+
...result,
|
|
47
|
+
nextSteps: NEXT_STEPS,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return createOutputResult(output, {
|
|
51
|
+
plain: selectFormatter(ctx, sampleFormatters),
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/** @module Re-exports block formatters (`lookupFormatters`, `
|
|
1
|
+
/** @module Re-exports block formatters (`listFormatters`, `lookupFormatters`, `sampleFormatters`). */
|
|
2
2
|
|
|
3
3
|
export { default as listFormatters } from "./list.js";
|
|
4
4
|
export { createLookupOptions, default as lookupFormatters } from "./lookup.js";
|
|
5
|
+
export { default as sampleFormatters } from "./sample.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sample formatter for the block domain.
|
|
3
|
+
*
|
|
4
|
+
* Delegates to the shared factory, rendering each item via the
|
|
5
|
+
* existing block lookup formatter with all aspects enabled.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import createSampleFormatters from "../../shared/sampleFormatters.js";
|
|
9
|
+
import type { BlockDetailed } from "../../shared/types/index.js";
|
|
10
|
+
import lookupFormatters from "./lookup.js";
|
|
11
|
+
|
|
12
|
+
const ALL_ASPECTS = {
|
|
13
|
+
anatomy: true,
|
|
14
|
+
modifiers: true,
|
|
15
|
+
tokens: true,
|
|
16
|
+
implementations: true,
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
export default createSampleFormatters<BlockDetailed>("blocks", (block, mode) =>
|
|
20
|
+
lookupFormatters[mode]({ block, detailed: true, aspects: ALL_ASPECTS }),
|
|
21
|
+
);
|
|
@@ -7,15 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
import type { CommandDefinition } from "@canonical/cli-core";
|
|
9
9
|
import type { PragmaContext } from "../shared/context.js";
|
|
10
|
-
import { listCommand, lookupCommand } from "./commands/index.js";
|
|
10
|
+
import { listCommand, lookupCommand, sampleCommand } from "./commands/index.js";
|
|
11
11
|
|
|
12
12
|
export function commands(ctx: PragmaContext): CommandDefinition[] {
|
|
13
|
-
return [listCommand(ctx), lookupCommand(ctx)];
|
|
13
|
+
return [listCommand(ctx), lookupCommand(ctx), sampleCommand(ctx)];
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export { blockConfig } from "./blockConfig.js";
|
|
17
17
|
export { specs as mcpSpecs } from "./mcp/index.js";
|
|
18
|
-
export { listBlocks, lookupBlock } from "./operations/index.js";
|
|
18
|
+
export { listBlocks, lookupBlock, sampleBlocks } from "./operations/index.js";
|
|
19
19
|
export {
|
|
20
20
|
blockEmptyError,
|
|
21
21
|
buildBlockFilters,
|
|
@@ -1,40 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MCP tool specs for the block domain — block_list, block_lookup
|
|
2
|
+
* MCP tool specs for the block domain — block_list, block_lookup,
|
|
3
|
+
* block_sample.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
5
|
+
* The list and lookup tools are compiled from the block read stories in
|
|
6
|
+
* `../stories.ts`; only the sample tool is spec'd by hand. The adapter
|
|
7
|
+
* layer converts these into registered MCP tools via `registerFromSpec()`.
|
|
6
8
|
*/
|
|
7
9
|
|
|
8
|
-
import type { ToolSpec } from "../../shared/ToolSpec.js";
|
|
9
|
-
import {
|
|
10
|
-
listFormatters as blockListFmt,
|
|
11
|
-
lookupFormatters as blockLookupFmt,
|
|
12
|
-
} from "../formatters/index.js";
|
|
13
10
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from "
|
|
11
|
+
compileLookupTool,
|
|
12
|
+
compileReadTool,
|
|
13
|
+
condense,
|
|
14
|
+
} from "../../shared/stories/index.js";
|
|
15
|
+
import type { ToolSpec } from "../../shared/ToolSpec.js";
|
|
16
|
+
import { sampleFormatters as blockSampleFmt } from "../formatters/index.js";
|
|
17
|
+
import { sampleBlocks } from "../operations/index.js";
|
|
18
|
+
import { buildBlockFilters } from "../orchestration/index.js";
|
|
19
|
+
import { blockListStory, blockLookupStory } from "../stories.js";
|
|
18
20
|
|
|
19
21
|
const specs: readonly ToolSpec[] = [
|
|
22
|
+
compileReadTool(blockListStory),
|
|
23
|
+
compileLookupTool(blockLookupStory),
|
|
20
24
|
{
|
|
21
|
-
name: "
|
|
25
|
+
name: "block_sample",
|
|
22
26
|
description:
|
|
23
|
-
"
|
|
27
|
+
"Return 1–5 randomly selected complete block instances as exemplars. Use BEFORE writing queries to see actual data shapes, property names, and value formats. Each call returns different instances.",
|
|
24
28
|
params: {
|
|
25
|
-
|
|
26
|
-
type: "
|
|
27
|
-
description: "
|
|
28
|
-
optional: true,
|
|
29
|
-
},
|
|
30
|
-
digest: {
|
|
31
|
-
type: "boolean",
|
|
32
|
-
description: "Include implementations per block",
|
|
33
|
-
optional: true,
|
|
34
|
-
},
|
|
35
|
-
detailed: {
|
|
36
|
-
type: "boolean",
|
|
37
|
-
description: "Include full details per block",
|
|
29
|
+
count: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Number of samples (1–5, default 2)",
|
|
38
32
|
optional: true,
|
|
39
33
|
},
|
|
40
34
|
condensed: {
|
|
@@ -44,156 +38,30 @@ const specs: readonly ToolSpec[] = [
|
|
|
44
38
|
},
|
|
45
39
|
},
|
|
46
40
|
readOnly: true,
|
|
47
|
-
async execute(rt, {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
41
|
+
async execute(rt, { count, condensed }) {
|
|
42
|
+
const n = Number(count ?? 2);
|
|
43
|
+
const filters = buildBlockFilters(rt);
|
|
44
|
+
const result = await sampleBlocks(rt.store, filters, n);
|
|
45
|
+
const nextSteps = [
|
|
46
|
+
`These are ${result.samples.length} of ${result.totalCount} total blocks.`,
|
|
47
|
+
"Use block_lookup to inspect specific blocks by name.",
|
|
48
|
+
"Use block_list to see all available blocks with filtering.",
|
|
49
|
+
];
|
|
53
50
|
|
|
54
51
|
if (condensed) {
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
condensed: true,
|
|
58
|
-
text,
|
|
59
|
-
tokens: `~${Math.ceil(text.length / 4)}`,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (contract.result.disclosure.level === "detailed") {
|
|
64
|
-
return {
|
|
65
|
-
data: contract.result.items,
|
|
66
|
-
meta: {
|
|
67
|
-
count: contract.result.items.length,
|
|
68
|
-
disclosure: "detailed",
|
|
69
|
-
filters: contract.result.filters,
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (contract.result.disclosure.level === "digest") {
|
|
75
|
-
return {
|
|
76
|
-
data: contract.result.items,
|
|
77
|
-
meta: {
|
|
78
|
-
count: contract.result.items.length,
|
|
79
|
-
disclosure: "digest",
|
|
80
|
-
filters: contract.result.filters,
|
|
81
|
-
},
|
|
82
|
-
};
|
|
52
|
+
return condense(blockSampleFmt.llm({ ...result, nextSteps }));
|
|
83
53
|
}
|
|
84
54
|
|
|
85
55
|
return {
|
|
86
|
-
data:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
56
|
+
data: {
|
|
57
|
+
samples: result.samples,
|
|
58
|
+
totalCount: result.totalCount,
|
|
59
|
+
nextSteps,
|
|
90
60
|
},
|
|
61
|
+
meta: { count: result.samples.length },
|
|
91
62
|
};
|
|
92
63
|
},
|
|
93
64
|
},
|
|
94
|
-
|
|
95
|
-
{
|
|
96
|
-
name: "block_lookup",
|
|
97
|
-
description:
|
|
98
|
-
"Get detailed information about one or more design system blocks including anatomy, modifiers, tokens, and applicable standards.",
|
|
99
|
-
params: {
|
|
100
|
-
names: {
|
|
101
|
-
type: "string[]",
|
|
102
|
-
description:
|
|
103
|
-
"Block names or IRIs to look up (e.g. ['Button', 'ds:global.component.card'])",
|
|
104
|
-
optional: false,
|
|
105
|
-
},
|
|
106
|
-
detailed: {
|
|
107
|
-
type: "boolean",
|
|
108
|
-
description: "Return full details (default: true for MCP)",
|
|
109
|
-
optional: true,
|
|
110
|
-
},
|
|
111
|
-
condensed: {
|
|
112
|
-
type: "boolean",
|
|
113
|
-
description: "Token-optimized output",
|
|
114
|
-
optional: true,
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
readOnly: true,
|
|
118
|
-
async execute(rt, { names, detailed, condensed }) {
|
|
119
|
-
const queries = names as string[];
|
|
120
|
-
const showDetailed = (detailed as boolean | undefined) ?? true;
|
|
121
|
-
const contract = await resolveBlockLookup(
|
|
122
|
-
rt.store,
|
|
123
|
-
queries,
|
|
124
|
-
buildBlockFilters(rt),
|
|
125
|
-
);
|
|
126
|
-
const result = contract.result;
|
|
127
|
-
|
|
128
|
-
if (condensed) {
|
|
129
|
-
const textParts = result.results.map((block) =>
|
|
130
|
-
blockLookupFmt.llm({
|
|
131
|
-
block,
|
|
132
|
-
detailed: showDetailed,
|
|
133
|
-
aspects: {
|
|
134
|
-
anatomy: true,
|
|
135
|
-
modifiers: true,
|
|
136
|
-
tokens: true,
|
|
137
|
-
implementations: true,
|
|
138
|
-
},
|
|
139
|
-
}),
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
if (result.errors.length > 0) {
|
|
143
|
-
textParts.push(
|
|
144
|
-
[
|
|
145
|
-
"### Errors",
|
|
146
|
-
...result.errors.map(
|
|
147
|
-
(error) => `- ${error.query}: ${error.message}`,
|
|
148
|
-
),
|
|
149
|
-
].join("\n"),
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return {
|
|
154
|
-
condensed: true,
|
|
155
|
-
text: textParts.join("\n\n"),
|
|
156
|
-
tokens: `~${Math.ceil(textParts.join("\n\n").length / 4)}`,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (!showDetailed) {
|
|
161
|
-
const summaries = result.results.map(
|
|
162
|
-
({
|
|
163
|
-
uri,
|
|
164
|
-
name,
|
|
165
|
-
type,
|
|
166
|
-
tier,
|
|
167
|
-
modifiers,
|
|
168
|
-
implementations,
|
|
169
|
-
nodeCount,
|
|
170
|
-
tokenCount,
|
|
171
|
-
summary,
|
|
172
|
-
}) => ({
|
|
173
|
-
uri,
|
|
174
|
-
name,
|
|
175
|
-
type,
|
|
176
|
-
tier,
|
|
177
|
-
modifiers,
|
|
178
|
-
implementations,
|
|
179
|
-
nodeCount,
|
|
180
|
-
tokenCount,
|
|
181
|
-
summary,
|
|
182
|
-
}),
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
return {
|
|
186
|
-
data: {
|
|
187
|
-
results: summaries,
|
|
188
|
-
errors: result.errors,
|
|
189
|
-
},
|
|
190
|
-
meta: { count: summaries.length },
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return { data: result, meta: { count: result.results.length } };
|
|
195
|
-
},
|
|
196
|
-
},
|
|
197
65
|
] as const;
|
|
198
66
|
|
|
199
67
|
export default specs;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/** @module Re-exports block operations (`lookupBlock`, `
|
|
1
|
+
/** @module Re-exports block operations (`listBlocks`, `lookupBlock`, `sampleBlocks`). */
|
|
2
2
|
|
|
3
3
|
export { default as listBlocks } from "./list.js";
|
|
4
4
|
export { default as lookupBlock } from "./lookup.js";
|
|
5
|
+
export { default as sampleBlocks } from "./sample.js";
|
|
@@ -21,6 +21,11 @@ import { buildQuery } from "../../shared/buildQuery.js";
|
|
|
21
21
|
import extractLocalName from "../../shared/extractLocalName.js";
|
|
22
22
|
import { buildFilters } from "../../shared/filters/buildFilters.js";
|
|
23
23
|
import { P } from "../../shared/prefixes.js";
|
|
24
|
+
import {
|
|
25
|
+
detectCrossDomain,
|
|
26
|
+
listDomainNames,
|
|
27
|
+
suggestNames,
|
|
28
|
+
} from "../../shared/suggestions/index.js";
|
|
24
29
|
import type {
|
|
25
30
|
BlockDetailed,
|
|
26
31
|
BlockSubcomponent,
|
|
@@ -80,12 +85,16 @@ export default async function lookupBlock(
|
|
|
80
85
|
);
|
|
81
86
|
|
|
82
87
|
if (baseResult.type !== "select" || baseResult.bindings.length === 0) {
|
|
88
|
+
const candidates = await listDomainNames(store, "block");
|
|
89
|
+
const crossDomain = await detectCrossDomain(nameOrUri, "block", store);
|
|
83
90
|
throw PragmaError.notFound("block", nameOrUri, {
|
|
91
|
+
suggestions: suggestNames(nameOrUri, candidates),
|
|
84
92
|
recovery: {
|
|
85
93
|
message: "List available blocks.",
|
|
86
94
|
cli: "pragma block list",
|
|
87
95
|
mcp: { tool: "block_list" },
|
|
88
96
|
},
|
|
97
|
+
crossDomain: crossDomain ?? undefined,
|
|
89
98
|
});
|
|
90
99
|
}
|
|
91
100
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a small number of complete block instances as exemplars.
|
|
3
|
+
*
|
|
4
|
+
* Composes the existing list and lookup operations to avoid duplicating
|
|
5
|
+
* any SPARQL logic. Agents use this to learn the data shape before querying.
|
|
6
|
+
*
|
|
7
|
+
* @param store - ke store to query
|
|
8
|
+
* @param filters - tier and channel filter configuration
|
|
9
|
+
* @param count - number of samples (clamped 1–5, default 2)
|
|
10
|
+
* @returns sample result with detailed blocks and total count
|
|
11
|
+
* @note Queries ke store
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { Store } from "@canonical/ke";
|
|
15
|
+
import pickRandom from "../../shared/pickRandom.js";
|
|
16
|
+
import type {
|
|
17
|
+
BlockDetailed,
|
|
18
|
+
FilterConfig,
|
|
19
|
+
SampleResult,
|
|
20
|
+
} from "../../shared/types/index.js";
|
|
21
|
+
import listBlocks from "./list.js";
|
|
22
|
+
import lookupBlock from "./lookup.js";
|
|
23
|
+
|
|
24
|
+
export default async function sampleBlocks(
|
|
25
|
+
store: Store,
|
|
26
|
+
filters: FilterConfig,
|
|
27
|
+
count = 2,
|
|
28
|
+
): Promise<SampleResult<BlockDetailed>> {
|
|
29
|
+
const clamped = Math.max(1, Math.min(5, count));
|
|
30
|
+
const all = await listBlocks(store, filters);
|
|
31
|
+
const selected = pickRandom(all, clamped);
|
|
32
|
+
|
|
33
|
+
const samples = await Promise.all(
|
|
34
|
+
selected.map(async (b) => {
|
|
35
|
+
const results = await lookupBlock(store, b.name, filters);
|
|
36
|
+
return results[0] as BlockDetailed;
|
|
37
|
+
}),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return { samples, totalCount: all.length };
|
|
41
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import type { FilterConfig } from "../../shared/types/index.js";
|
|
3
|
+
import blockEmptyError from "./blockEmptyError.js";
|
|
4
|
+
|
|
5
|
+
const filters: FilterConfig = { tier: "Apps/WPE", channel: "normal" };
|
|
6
|
+
|
|
7
|
+
describe("blockEmptyError", () => {
|
|
8
|
+
it("filter-narrowing: a tier was active → widen to all tiers", () => {
|
|
9
|
+
const err = blockEmptyError(filters, false);
|
|
10
|
+
|
|
11
|
+
expect(err.filters).toEqual({ tier: "Apps/WPE", channel: "normal" });
|
|
12
|
+
expect(err.recovery).toEqual({
|
|
13
|
+
message: "Widen the search to show all tiers.",
|
|
14
|
+
cli: "pragma block list --all-tiers",
|
|
15
|
+
mcp: { tool: "block_list", params: { allTiers: true } },
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("honest terminal: already at all-tiers → no recovery (no self-loop)", () => {
|
|
20
|
+
const err = blockEmptyError({ tier: undefined, channel: "normal" }, true);
|
|
21
|
+
|
|
22
|
+
// The widest tier query already returned empty; suggesting --all-tiers
|
|
23
|
+
// again would loop. recovery: undefined is the correct terminal state.
|
|
24
|
+
expect(err.recovery).toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { LookupContract, LookupResult } from "../../shared/contracts.js";
|
|
2
2
|
import lookupMany from "../../shared/lookupMany.js";
|
|
3
3
|
import type { PragmaRuntime } from "../../shared/runtime.js";
|
|
4
|
+
import { expandLookupQueries } from "../../shared/suggestions/index.js";
|
|
4
5
|
import type { BlockDetailed, FilterConfig } from "../../shared/types/index.js";
|
|
5
6
|
import { lookupBlock } from "../operations/index.js";
|
|
6
7
|
|
|
@@ -9,15 +10,22 @@ export default async function resolveBlockLookup(
|
|
|
9
10
|
queries: readonly string[],
|
|
10
11
|
filters: FilterConfig,
|
|
11
12
|
): Promise<LookupContract<BlockDetailed>> {
|
|
12
|
-
const
|
|
13
|
+
const { names, globErrors } = await expandLookupQueries(
|
|
13
14
|
queries,
|
|
14
|
-
|
|
15
|
+
store,
|
|
16
|
+
"block",
|
|
15
17
|
);
|
|
16
18
|
|
|
19
|
+
const nested: LookupResult<BlockDetailed[]> =
|
|
20
|
+
names.length > 0
|
|
21
|
+
? await lookupMany(names, (query) => lookupBlock(store, query, filters))
|
|
22
|
+
: { results: [], errors: [], meta: { internalErrorCount: 0 } };
|
|
23
|
+
|
|
17
24
|
// lookupBlock returns BlockDetailed[] (multiple matches per name) — flatten
|
|
18
25
|
const result: LookupResult<BlockDetailed> = {
|
|
19
26
|
results: nested.results.flat(),
|
|
20
|
-
errors: nested.errors,
|
|
27
|
+
errors: [...nested.errors, ...globErrors],
|
|
28
|
+
meta: nested.meta ?? { internalErrorCount: 0 },
|
|
21
29
|
};
|
|
22
30
|
|
|
23
31
|
return {
|