@canonical/pragma-cli 0.29.0 → 0.31.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 +128 -47
- package/dist/pragma +0 -0
- package/package.json +15 -13
- package/src/completions/constants.ts +7 -0
- package/src/completions/handleQuery.test.ts +32 -0
- package/src/completions/handleQuery.ts +20 -1
- package/src/completions/queryCompletions.test.ts +5 -0
- package/src/completions/queryCompletions.ts +17 -3
- package/src/completions/querySocket.test.ts +31 -0
- package/src/completions/querySocket.ts +36 -9
- 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 +217 -0
- package/src/config/readConfig.test.ts +104 -13
- package/src/config/readConfig.ts +12 -153
- package/src/config/readConfigLayers.test.ts +109 -0
- package/src/config/readConfigLayers.ts +118 -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 +83 -1
- package/src/config/writeConfig.ts +25 -55
- package/src/constants.ts +3 -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 +2 -1
- package/src/domains/block/formatters/list.test.ts +3 -3
- package/src/domains/block/formatters/lookup.test.ts +5 -5
- package/src/domains/block/mcp/specs.ts +16 -196
- package/src/domains/block/orchestration/enrichBlocks.ts +6 -3
- package/src/domains/block/orchestration/resolveBlockLookup.ts +2 -1
- package/src/domains/block/stories.test.ts +28 -0
- package/src/domains/block/stories.ts +260 -0
- package/src/domains/config/commands/channel.test.ts +30 -3
- package/src/domains/config/commands/channel.ts +25 -8
- package/src/domains/config/commands/configScope.ts +46 -0
- package/src/domains/config/commands/framework.test.ts +32 -1
- package/src/domains/config/commands/framework.ts +26 -8
- package/src/domains/config/commands/show.ts +5 -45
- package/src/domains/config/commands/tier.test.ts +20 -2
- package/src/domains/config/commands/tier.ts +25 -8
- package/src/domains/config/commands/trace.test.ts +19 -2
- package/src/domains/config/commands/trace.ts +6 -3
- 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 +14 -11
- 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 +7 -7
- package/src/domains/config/mcp/specs.ts +33 -53
- 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/validateTier.test.ts +9 -0
- package/src/domains/config/operations/validateTier.ts +10 -2
- package/src/domains/config/stories.ts +42 -0
- package/src/domains/config/tasks/index.ts +1 -0
- package/src/domains/config/tasks/setChannel.ts +13 -28
- package/src/domains/config/tasks/setFramework.ts +11 -30
- package/src/domains/config/tasks/setTier.ts +10 -29
- package/src/domains/config/tasks/setTrace.ts +10 -28
- package/src/domains/config/tasks/writeConfigField.ts +41 -0
- package/src/domains/create/generatorPack/bundled.ts +49 -0
- package/src/domains/create/generatorPack/compileGeneratorPack.test.ts +159 -0
- package/src/domains/create/generatorPack/compileGeneratorPack.ts +312 -0
- package/src/domains/create/index.ts +13 -7
- package/src/domains/create/mcp/specs.ts +6 -161
- package/src/domains/create/renderGeneratorUi.test.ts +103 -0
- package/src/domains/create/renderGeneratorUi.ts +65 -0
- package/src/domains/doctor/formatters/doctor.test.ts +50 -2
- package/src/domains/doctor/formatters/doctor.ts +90 -38
- package/src/domains/doctor/operations/checks/checkConfigFile.ts +19 -5
- package/src/domains/doctor/operations/checks/checkMcpCommands.ts +133 -0
- package/src/domains/doctor/operations/checks/checkMcpConfigured.ts +1 -1
- package/src/domains/doctor/operations/checks/checkPackageRefs.ts +32 -26
- 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 +160 -7
- package/src/domains/doctor/operations/runChecks.test.ts +15 -6
- package/src/domains/doctor/operations/runChecks.ts +2 -0
- package/src/domains/doctor/operations/types.ts +23 -1
- package/src/domains/graph/commands/inspect.test.ts +2 -2
- package/src/domains/graph/commands/query.test.ts +5 -3
- package/src/domains/graph/formatters/inspect.ts +7 -7
- package/src/domains/graph/formatters/query.test.ts +87 -0
- package/src/domains/graph/formatters/query.ts +42 -5
- package/src/domains/graph/helpers/resolveUri.test.ts +50 -0
- package/src/domains/graph/helpers/resolveUri.ts +28 -21
- package/src/domains/graph/operations/inspectUri.test.ts +5 -5
- package/src/domains/graphql/commands/build.test.ts +5 -3
- package/src/domains/graphql/commands/build.ts +8 -16
- package/src/domains/graphql/commands/check.test.ts +5 -3
- package/src/domains/graphql/commands/check.ts +7 -13
- package/src/domains/graphql/commands/index.ts +1 -0
- package/src/domains/graphql/commands/serve.test.ts +46 -0
- package/src/domains/graphql/commands/serve.ts +141 -0
- package/src/domains/graphql/constants.ts +10 -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 +2 -0
- package/src/domains/graphql/helpers/parsePrefixes.test.ts +3 -3
- package/src/domains/graphql/helpers/parsePrefixes.ts +3 -3
- package/src/domains/graphql/helpers/resolveSourceFiles.test.ts +9 -0
- package/src/domains/graphql/helpers/resolveSourceFiles.ts +24 -3
- 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 +9 -6
- package/src/domains/graphql/operations/compileSchema.test.ts +23 -47
- package/src/domains/graphql/operations/compileSchema.ts +23 -25
- package/src/domains/graphql/operations/createSchemaServer.test.ts +50 -0
- package/src/domains/graphql/operations/createSchemaServer.ts +75 -0
- package/src/domains/graphql/operations/ensureSchemaArtifact.test.ts +167 -0
- package/src/domains/graphql/operations/ensureSchemaArtifact.ts +178 -0
- package/src/domains/graphql/operations/index.ts +10 -0
- package/src/domains/info/formatters/upgrade.test.ts +7 -4
- package/src/domains/info/formatters/upgrade.ts +3 -1
- package/src/domains/info/operations/collectEntityCounts.test.ts +156 -0
- package/src/domains/info/operations/collectEntityCounts.ts +123 -0
- package/src/domains/info/operations/collectInfo.test.ts +14 -3
- package/src/domains/info/operations/collectInfo.ts +12 -15
- package/src/domains/info/operations/index.ts +1 -0
- package/src/domains/info/types.ts +13 -0
- package/src/domains/llm/capabilities.test.ts +24 -4
- package/src/domains/llm/commands/capabilities.ts +12 -3
- package/src/domains/llm/commands/llm.ts +5 -1
- package/src/domains/llm/data/commandReference.ts +20 -11
- package/src/domains/llm/data/decisionTrees.ts +10 -5
- package/src/domains/llm/data/toolCatalog.ts +55 -18
- package/src/domains/llm/formatters/orientation.ts +5 -1
- package/src/domains/llm/llmCommand.test.ts +11 -3
- package/src/domains/llm/mcp/specs.ts +3 -4
- package/src/domains/llm/operations/collectContext.test.ts +64 -0
- package/src/domains/llm/operations/collectContext.ts +7 -17
- 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 +2 -1
- package/src/domains/modifier/mcp/specs.ts +15 -94
- package/src/domains/modifier/operations/lookup.ts +5 -3
- package/src/domains/modifier/orchestration/resolveModifierLookup.ts +2 -1
- package/src/domains/modifier/stories.test.ts +20 -0
- package/src/domains/modifier/stories.ts +86 -0
- package/src/domains/ontology/commands/list.test.ts +5 -3
- package/src/domains/ontology/commands/list.ts +5 -58
- package/src/domains/ontology/commands/show.test.ts +85 -9
- package/src/domains/ontology/commands/show.ts +6 -58
- package/src/domains/ontology/formatters/index.ts +1 -0
- package/src/domains/ontology/formatters/list.ts +37 -12
- package/src/domains/ontology/formatters/show.ts +361 -64
- package/src/domains/ontology/helpers/buildClassTree.ts +89 -0
- package/src/domains/ontology/helpers/completeClassNames.ts +43 -0
- package/src/domains/ontology/helpers/expandOntologyIris.ts +79 -0
- package/src/domains/ontology/helpers/index.ts +14 -0
- package/src/domains/ontology/helpers/queryClasses.ts +32 -16
- package/src/domains/ontology/helpers/queryProperties.ts +39 -6
- package/src/domains/ontology/helpers/queryTboxFacts.ts +160 -0
- package/src/domains/ontology/mcp/specs.ts +7 -84
- package/src/domains/ontology/operations/listOntologies.test.ts +80 -3
- package/src/domains/ontology/operations/listOntologies.ts +126 -30
- package/src/domains/ontology/operations/showOntology.test.ts +131 -12
- package/src/domains/ontology/operations/showOntology.ts +289 -7
- package/src/domains/ontology/operations/showOntologyRaw.test.ts +4 -2
- package/src/domains/ontology/stories.test.ts +36 -0
- package/src/domains/ontology/stories.ts +153 -0
- package/src/domains/refs/operations/updateRefs.ts +2 -38
- package/src/domains/setup/commands/index.ts +1 -0
- package/src/domains/setup/commands/setup.ts +70 -0
- 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/index.ts +7 -3
- package/src/domains/setup/operations/setupLsp.test.ts +3 -2
- package/src/domains/setup/operations/setupLsp.ts +7 -2
- package/src/domains/setup/operations/setupMcp.test.ts +6 -1
- package/src/domains/shared/bootStore.bareCore.test.ts +63 -0
- package/src/domains/shared/bootStore.test.ts +82 -0
- package/src/domains/shared/bootStore.ts +57 -18
- 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 +11 -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 +23 -26
- package/src/domains/shared/extractLocalName.test.ts +3 -3
- package/src/domains/shared/formatters.ts +23 -2
- package/src/domains/shared/listTiers.ts +40 -0
- package/src/domains/shared/loaders/bundledLoader.test.ts +248 -0
- package/src/domains/shared/loaders/bundledLoader.ts +158 -12
- package/src/domains/shared/loaders/gitLoader.ts +1 -2
- package/src/domains/shared/loaders/index.ts +4 -1
- package/src/domains/shared/loaders/localLoader.ts +2 -4
- package/src/domains/shared/loaders/readPackageDir.test.ts +58 -0
- package/src/domains/shared/loaders/readPackageDir.ts +82 -9
- 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 +135 -0
- package/src/domains/shared/lookupMany.ts +50 -2
- package/src/domains/shared/mergeAndParseRefs.test.ts +89 -0
- package/src/domains/shared/mergeAndParseRefs.ts +44 -0
- package/src/domains/shared/namespaces.ts +13 -5
- package/src/domains/shared/packages.ts +10 -17
- package/src/domains/shared/parseSampleCount.test.ts +47 -0
- package/src/domains/shared/parseSampleCount.ts +45 -0
- package/src/domains/shared/prefixes.test.ts +211 -0
- package/src/domains/shared/prefixes.ts +182 -15
- package/src/domains/shared/renderers.ts +5 -5
- package/src/domains/shared/resolveConfiguredGraphs.test.ts +27 -0
- package/src/domains/shared/resolveConfiguredGraphs.ts +41 -0
- package/src/domains/shared/resolveLookupExitCode.test.ts +48 -0
- package/src/domains/shared/resolveLookupExitCode.ts +42 -0
- package/src/domains/shared/runtime.ts +4 -63
- package/src/domains/shared/semanticPackage.test.ts +89 -0
- package/src/domains/shared/semanticPackage.ts +34 -3
- package/src/domains/shared/stories/compileLookupCommand.test.ts +145 -0
- package/src/domains/shared/stories/compileLookupCommand.ts +102 -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 +151 -0
- package/src/domains/shared/stories/pack/applyPackFilters.ts +111 -0
- package/src/domains/shared/stories/pack/applyPackSearch.test.ts +57 -0
- package/src/domains/shared/stories/pack/applyPackSearch.ts +41 -0
- package/src/domains/shared/stories/pack/buildLookupQuery.test.ts +81 -0
- package/src/domains/shared/stories/pack/buildLookupQuery.ts +154 -0
- package/src/domains/shared/stories/pack/bundled/index.ts +23 -0
- package/src/domains/shared/stories/pack/bundled/standardPack.ts +164 -0
- package/src/domains/shared/stories/pack/bundled/tierPack.ts +50 -0
- package/src/domains/shared/stories/pack/collectPackStories.test.ts +406 -0
- package/src/domains/shared/stories/pack/collectPackStories.ts +158 -0
- package/src/domains/shared/stories/pack/compilePackCommands.ts +50 -0
- package/src/domains/shared/stories/pack/compilePackStories.test.ts +751 -0
- package/src/domains/shared/stories/pack/compilePackStories.ts +724 -0
- package/src/domains/shared/stories/pack/compilePackToolSpecs.ts +55 -0
- package/src/domains/shared/stories/pack/index.ts +42 -0
- package/src/domains/shared/stories/pack/reservedVerbs.test.ts +213 -0
- package/src/domains/shared/stories/pack/reservedVerbs.ts +170 -0
- package/src/domains/shared/stories/pack/runSelectQuery.ts +31 -0
- package/src/domains/shared/stories/pack/standardParity.test.ts +381 -0
- package/src/domains/shared/stories/pack/types.ts +224 -0
- package/src/domains/shared/stories/pack/validateStoryPackDefinition.test.ts +742 -0
- package/src/domains/shared/stories/pack/validateStoryPackDefinition.ts +859 -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 +179 -0
- package/src/domains/shared/suggestions/expandGlob.ts +1 -0
- package/src/domains/shared/suggestions/suggestNames.ts +43 -10
- package/src/domains/shared/types/index.ts +5 -9
- package/src/domains/shared/types/ontology.ts +119 -24
- package/src/domains/shared/types/standard.ts +9 -52
- 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 +0 -1
- 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/token/commands/lookup.test.ts +8 -0
- package/src/domains/token/commands/lookup.ts +12 -0
- package/src/domains/token/commands/sample.ts +2 -1
- package/src/domains/token/featureFlag.ts +17 -0
- package/src/domains/token/index.ts +5 -0
- package/src/domains/token/mcp/specs.ts +18 -2
- package/src/domains/token/orchestration/resolveTokenLookup.ts +2 -1
- package/src/domains/trace/commands/resolveTraceLimit.test.ts +31 -0
- package/src/domains/trace/commands/show.ts +30 -4
- package/src/domains/trace/tracePlugin.test.ts +1 -1
- package/src/index.ts +1 -13
- package/src/mcp/registerResources.test.ts +382 -74
- package/src/mcp/registerResources.ts +5 -348
- 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 +22 -5
- package/src/mcp/tools/registerTools.test.ts +167 -34
- package/src/mcp/types.ts +4 -0
- package/src/pipeline/collectCommands.test.ts +151 -1
- package/src/pipeline/collectCommands.ts +35 -13
- package/src/pipeline/createProgram.test.ts +5 -1
- package/src/pipeline/createProgram.ts +2 -2
- package/src/pipeline/firstRun.test.ts +80 -0
- package/src/pipeline/firstRun.ts +99 -0
- package/src/pipeline/parseGlobalFlags.test.ts +102 -1
- package/src/pipeline/parseGlobalFlags.ts +98 -9
- package/src/pipeline/resolveCommandKind.test.ts +12 -0
- package/src/pipeline/resolveCommandKind.ts +4 -0
- package/src/pipeline/rootHelp.test.ts +87 -0
- package/src/pipeline/rootHelp.ts +265 -0
- package/src/pipeline/runCli.orchestration.test.ts +28 -12
- package/src/pipeline/runCli.test.ts +17 -4
- package/src/pipeline/runCli.ts +202 -25
- package/src/testing/cli.ts +30 -2
- package/src/testing/createTestMcpClient.ts +4 -1
- package/src/testing/dsFixtures.ts +21 -4
- package/src/testing/index.ts +7 -0
- package/src/testing/integration/__snapshots__/executor-golden.test.ts.snap +1207 -0
- package/src/testing/integration/cli-user-stories.test.ts +63 -0
- package/src/testing/integration/cross-binary-byte-equality.test.ts +129 -0
- package/src/testing/integration/edge-cases.test.ts +62 -50
- package/src/testing/integration/executor-execution.test.ts +103 -0
- package/src/testing/integration/executor-golden.test.ts +145 -0
- package/src/testing/integration/mcp-surface.test.ts +40 -15
- package/src/testing/integration/parity.test.ts +136 -82
- package/src/testing/regression/0001-skill-discovery-granularity.test.ts +71 -0
- package/src/testing/setupXdgIsolation.ts +26 -0
- package/src/testing/standardParityFixtures.ts +35 -0
- package/src/testing/store.ts +4 -4
- package/src/testing/storyFixtures.ts +63 -0
- package/src/domains/create/commands/component.test.ts +0 -166
- package/src/domains/create/commands/component.ts +0 -123
- package/src/domains/create/commands/index.ts +0 -3
- package/src/domains/create/commands/package.test.ts +0 -35
- package/src/domains/create/commands/package.ts +0 -21
- package/src/domains/create/generators.ts +0 -8
- package/src/domains/standard/commands/categories.test.ts +0 -70
- package/src/domains/standard/commands/categories.ts +0 -48
- package/src/domains/standard/commands/index.ts +0 -6
- package/src/domains/standard/commands/list.test.ts +0 -105
- package/src/domains/standard/commands/list.ts +0 -90
- package/src/domains/standard/commands/lookup.test.ts +0 -135
- package/src/domains/standard/commands/lookup.ts +0 -99
- package/src/domains/standard/commands/sample.ts +0 -57
- package/src/domains/standard/formatters/categories.test.ts +0 -44
- package/src/domains/standard/formatters/categories.ts +0 -38
- package/src/domains/standard/formatters/index.ts +0 -10
- package/src/domains/standard/formatters/list.test.ts +0 -169
- package/src/domains/standard/formatters/list.ts +0 -184
- package/src/domains/standard/formatters/lookup.test.ts +0 -95
- package/src/domains/standard/formatters/lookup.ts +0 -101
- package/src/domains/standard/formatters/sample.ts +0 -15
- package/src/domains/standard/formatters/types.ts +0 -31
- package/src/domains/standard/index.ts +0 -40
- package/src/domains/standard/mcp/index.ts +0 -2
- package/src/domains/standard/mcp/specs.ts +0 -244
- package/src/domains/standard/operations/categories.test.ts +0 -61
- package/src/domains/standard/operations/categories.ts +0 -38
- package/src/domains/standard/operations/index.ts +0 -6
- package/src/domains/standard/operations/list.test.ts +0 -75
- package/src/domains/standard/operations/list.ts +0 -64
- package/src/domains/standard/operations/lookup.test.ts +0 -58
- package/src/domains/standard/operations/lookup.ts +0 -151
- package/src/domains/standard/operations/sample.ts +0 -35
- package/src/domains/standard/orchestration/buildStandardFilters.ts +0 -11
- package/src/domains/standard/orchestration/index.ts +0 -4
- package/src/domains/standard/orchestration/resolveStandardList.ts +0 -45
- package/src/domains/standard/orchestration/resolveStandardLookup.ts +0 -32
- package/src/domains/standard/orchestration/standardEmptyError.test.ts +0 -33
- package/src/domains/standard/orchestration/standardEmptyError.ts +0 -29
- package/src/domains/standard/standardConfig.ts +0 -42
- package/src/domains/standard/types.ts +0 -15
- package/src/domains/tier/commands/index.ts +0 -3
- package/src/domains/tier/commands/list.test.ts +0 -67
- package/src/domains/tier/commands/list.ts +0 -59
- package/src/domains/tier/formatters/index.ts +0 -3
- package/src/domains/tier/formatters/list.test.ts +0 -33
- package/src/domains/tier/formatters/list.ts +0 -45
- package/src/domains/tier/index.ts +0 -17
- package/src/domains/tier/mcp/index.ts +0 -2
- package/src/domains/tier/mcp/specs.ts +0 -38
- package/src/domains/tier/operations/index.ts +0 -3
- package/src/domains/tier/operations/list.test.ts +0 -32
- package/src/domains/tier/operations/list.ts +0 -33
- package/src/pipeline/runInteractiveCommand.ts +0 -198
|
@@ -1,201 +1,26 @@
|
|
|
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
10
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} 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";
|
|
14
17
|
import { sampleBlocks } from "../operations/index.js";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
resolveBlockList,
|
|
18
|
-
resolveBlockLookup,
|
|
19
|
-
} from "../orchestration/index.js";
|
|
18
|
+
import { buildBlockFilters } from "../orchestration/index.js";
|
|
19
|
+
import { blockListStory, blockLookupStory } from "../stories.js";
|
|
20
20
|
|
|
21
21
|
const specs: readonly ToolSpec[] = [
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
description:
|
|
25
|
-
"List design system blocks visible under current tier and channel configuration.",
|
|
26
|
-
params: {
|
|
27
|
-
allTiers: {
|
|
28
|
-
type: "boolean",
|
|
29
|
-
description: "Show blocks from all tiers, ignoring tier filter",
|
|
30
|
-
optional: true,
|
|
31
|
-
},
|
|
32
|
-
digest: {
|
|
33
|
-
type: "boolean",
|
|
34
|
-
description: "Include implementations per block",
|
|
35
|
-
optional: true,
|
|
36
|
-
},
|
|
37
|
-
detailed: {
|
|
38
|
-
type: "boolean",
|
|
39
|
-
description: "Include full details per block",
|
|
40
|
-
optional: true,
|
|
41
|
-
},
|
|
42
|
-
condensed: {
|
|
43
|
-
type: "boolean",
|
|
44
|
-
description: "Token-optimized output",
|
|
45
|
-
optional: true,
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
readOnly: true,
|
|
49
|
-
async execute(rt, { allTiers, digest, detailed, condensed }) {
|
|
50
|
-
const contract = await resolveBlockList(rt, {
|
|
51
|
-
allTiers: allTiers === true,
|
|
52
|
-
digest: digest === true,
|
|
53
|
-
detailed: detailed === true,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
if (condensed) {
|
|
57
|
-
const text = blockListFmt.llm(contract.result.items);
|
|
58
|
-
return {
|
|
59
|
-
condensed: true,
|
|
60
|
-
text,
|
|
61
|
-
tokens: `~${Math.ceil(text.length / 4)}`,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (contract.result.disclosure.level === "detailed") {
|
|
66
|
-
return {
|
|
67
|
-
data: contract.result.items,
|
|
68
|
-
meta: {
|
|
69
|
-
count: contract.result.items.length,
|
|
70
|
-
disclosure: "detailed",
|
|
71
|
-
filters: contract.result.filters,
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (contract.result.disclosure.level === "digest") {
|
|
77
|
-
return {
|
|
78
|
-
data: contract.result.items,
|
|
79
|
-
meta: {
|
|
80
|
-
count: contract.result.items.length,
|
|
81
|
-
disclosure: "digest",
|
|
82
|
-
filters: contract.result.filters,
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
data: contract.result.items,
|
|
89
|
-
meta: {
|
|
90
|
-
count: contract.result.items.length,
|
|
91
|
-
filters: contract.result.filters,
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
{
|
|
98
|
-
name: "block_lookup",
|
|
99
|
-
description:
|
|
100
|
-
"Get detailed information about one or more design system blocks including anatomy, modifiers, tokens, and applicable standards.",
|
|
101
|
-
params: {
|
|
102
|
-
names: {
|
|
103
|
-
type: "string[]",
|
|
104
|
-
description:
|
|
105
|
-
"Block names or IRIs to look up (e.g. ['Button', 'ds:global.component.card'])",
|
|
106
|
-
optional: false,
|
|
107
|
-
},
|
|
108
|
-
detailed: {
|
|
109
|
-
type: "boolean",
|
|
110
|
-
description: "Return full details (default: true for MCP)",
|
|
111
|
-
optional: true,
|
|
112
|
-
},
|
|
113
|
-
condensed: {
|
|
114
|
-
type: "boolean",
|
|
115
|
-
description: "Token-optimized output",
|
|
116
|
-
optional: true,
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
readOnly: true,
|
|
120
|
-
async execute(rt, { names, detailed, condensed }) {
|
|
121
|
-
const queries = names as string[];
|
|
122
|
-
const showDetailed = (detailed as boolean | undefined) ?? true;
|
|
123
|
-
const contract = await resolveBlockLookup(
|
|
124
|
-
rt.store,
|
|
125
|
-
queries,
|
|
126
|
-
buildBlockFilters(rt),
|
|
127
|
-
);
|
|
128
|
-
const result = contract.result;
|
|
129
|
-
|
|
130
|
-
if (condensed) {
|
|
131
|
-
const textParts = result.results.map((block) =>
|
|
132
|
-
blockLookupFmt.llm({
|
|
133
|
-
block,
|
|
134
|
-
detailed: showDetailed,
|
|
135
|
-
aspects: {
|
|
136
|
-
anatomy: true,
|
|
137
|
-
modifiers: true,
|
|
138
|
-
tokens: true,
|
|
139
|
-
implementations: true,
|
|
140
|
-
},
|
|
141
|
-
}),
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
if (result.errors.length > 0) {
|
|
145
|
-
textParts.push(
|
|
146
|
-
[
|
|
147
|
-
"### Errors",
|
|
148
|
-
...result.errors.map(
|
|
149
|
-
(error) => `- ${error.query}: ${error.message}`,
|
|
150
|
-
),
|
|
151
|
-
].join("\n"),
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return {
|
|
156
|
-
condensed: true,
|
|
157
|
-
text: textParts.join("\n\n"),
|
|
158
|
-
tokens: `~${Math.ceil(textParts.join("\n\n").length / 4)}`,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (!showDetailed) {
|
|
163
|
-
const summaries = result.results.map(
|
|
164
|
-
({
|
|
165
|
-
uri,
|
|
166
|
-
name,
|
|
167
|
-
type,
|
|
168
|
-
tier,
|
|
169
|
-
modifiers,
|
|
170
|
-
implementations,
|
|
171
|
-
nodeCount,
|
|
172
|
-
tokenCount,
|
|
173
|
-
summary,
|
|
174
|
-
}) => ({
|
|
175
|
-
uri,
|
|
176
|
-
name,
|
|
177
|
-
type,
|
|
178
|
-
tier,
|
|
179
|
-
modifiers,
|
|
180
|
-
implementations,
|
|
181
|
-
nodeCount,
|
|
182
|
-
tokenCount,
|
|
183
|
-
summary,
|
|
184
|
-
}),
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
return {
|
|
188
|
-
data: {
|
|
189
|
-
results: summaries,
|
|
190
|
-
errors: result.errors,
|
|
191
|
-
},
|
|
192
|
-
meta: { count: summaries.length },
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return { data: result, meta: { count: result.results.length } };
|
|
197
|
-
},
|
|
198
|
-
},
|
|
22
|
+
compileReadTool(blockListStory),
|
|
23
|
+
compileLookupTool(blockLookupStory),
|
|
199
24
|
{
|
|
200
25
|
name: "block_sample",
|
|
201
26
|
description:
|
|
@@ -224,12 +49,7 @@ const specs: readonly ToolSpec[] = [
|
|
|
224
49
|
];
|
|
225
50
|
|
|
226
51
|
if (condensed) {
|
|
227
|
-
|
|
228
|
-
return {
|
|
229
|
-
condensed: true,
|
|
230
|
-
text,
|
|
231
|
-
tokens: `~${Math.ceil(text.length / 4)}`,
|
|
232
|
-
};
|
|
52
|
+
return condense(blockSampleFmt.llm({ ...result, nextSteps }));
|
|
233
53
|
}
|
|
234
54
|
|
|
235
55
|
return {
|
|
@@ -14,12 +14,15 @@ export default async function enrichBlocks(
|
|
|
14
14
|
filters: FilterConfig,
|
|
15
15
|
disclosure: Disclosure,
|
|
16
16
|
): Promise<readonly (BlockListDigest | BlockDetailed)[]> {
|
|
17
|
+
// Look up by each summary's stable unique URI, not its display name: names
|
|
18
|
+
// recur across tiers/packages, so a by-name lookup returns every same-named
|
|
19
|
+
// block and taking the first match collapses distinct blocks onto one.
|
|
17
20
|
const nested = await Promise.all(
|
|
18
|
-
summaries.map((summary) => lookupBlock(store, summary.
|
|
21
|
+
summaries.map((summary) => lookupBlock(store, summary.uri, filters)),
|
|
19
22
|
);
|
|
20
|
-
// lookupBlock returns BlockDetailed[] —
|
|
23
|
+
// lookupBlock returns BlockDetailed[] — the URI resolves to exactly one match
|
|
21
24
|
const details: BlockDetailed[] = nested.flatMap((matches) =>
|
|
22
|
-
matches
|
|
25
|
+
matches.at(0) ? [matches[0] as BlockDetailed] : [],
|
|
23
26
|
);
|
|
24
27
|
|
|
25
28
|
if (disclosure.level === "detailed") {
|
|
@@ -19,12 +19,13 @@ export default async function resolveBlockLookup(
|
|
|
19
19
|
const nested: LookupResult<BlockDetailed[]> =
|
|
20
20
|
names.length > 0
|
|
21
21
|
? await lookupMany(names, (query) => lookupBlock(store, query, filters))
|
|
22
|
-
: { results: [], errors: [] };
|
|
22
|
+
: { results: [], errors: [], meta: { internalErrorCount: 0 } };
|
|
23
23
|
|
|
24
24
|
// lookupBlock returns BlockDetailed[] (multiple matches per name) — flatten
|
|
25
25
|
const result: LookupResult<BlockDetailed> = {
|
|
26
26
|
results: nested.results.flat(),
|
|
27
27
|
errors: [...nested.errors, ...globErrors],
|
|
28
|
+
meta: nested.meta ?? { internalErrorCount: 0 },
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
return {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { blockListStory, blockLookupStory } from "./stories.js";
|
|
3
|
+
|
|
4
|
+
describe("blockListStory", () => {
|
|
5
|
+
it("renders the ink list view", () => {
|
|
6
|
+
const view = blockListStory.renderInk?.([]);
|
|
7
|
+
expect(typeof view).toBe("string");
|
|
8
|
+
expect(view).toContain("Blocks");
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe("blockLookupStory", () => {
|
|
13
|
+
it("renders the ink lookup view", () => {
|
|
14
|
+
const view = blockLookupStory.renderInk?.(
|
|
15
|
+
{ results: [], errors: [] },
|
|
16
|
+
{ surface: "cli", detailed: false, params: {} },
|
|
17
|
+
);
|
|
18
|
+
expect(typeof view).toBe("string");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("implies detail from aspect flags on the CLI only", () => {
|
|
22
|
+
const resolveDetailed = blockLookupStory.resolveDetailed;
|
|
23
|
+
expect(resolveDetailed?.("cli", { anatomy: true })).toBe(true);
|
|
24
|
+
expect(resolveDetailed?.("cli", {})).toBe(false);
|
|
25
|
+
expect(resolveDetailed?.("mcp", {})).toBe(true);
|
|
26
|
+
expect(resolveDetailed?.("mcp", { detailed: false })).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Block read stories — the single declaration of `block list` and
|
|
3
|
+
* `block lookup` for both surfaces.
|
|
4
|
+
*
|
|
5
|
+
* The story kernel compiles these into the CLI commands and MCP tools,
|
|
6
|
+
* so descriptions, parameters, resolution, and rendering live here once.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { PragmaError } from "#error";
|
|
10
|
+
import { createListView, createLookupView } from "#tui";
|
|
11
|
+
import type { ColumnDef } from "../shared/contracts.js";
|
|
12
|
+
import {
|
|
13
|
+
type LookupStory,
|
|
14
|
+
type LookupStoryView,
|
|
15
|
+
type ReadStory,
|
|
16
|
+
requirePragmaContext,
|
|
17
|
+
} from "../shared/stories/index.js";
|
|
18
|
+
import type { BlockDetailed } from "../shared/types/index.js";
|
|
19
|
+
import { blockConfig } from "./blockConfig.js";
|
|
20
|
+
import {
|
|
21
|
+
createLookupOptions,
|
|
22
|
+
listFormatters,
|
|
23
|
+
lookupFormatters,
|
|
24
|
+
} from "./formatters/index.js";
|
|
25
|
+
import type { BlockLookupInput } from "./formatters/types.js";
|
|
26
|
+
import { resolveAspects } from "./helpers/index.js";
|
|
27
|
+
import { listBlocks } from "./operations/index.js";
|
|
28
|
+
import {
|
|
29
|
+
buildBlockFilters,
|
|
30
|
+
resolveBlockList,
|
|
31
|
+
resolveBlockLookup,
|
|
32
|
+
} from "./orchestration/index.js";
|
|
33
|
+
import type { AspectFlags, BlockListContract } from "./types.js";
|
|
34
|
+
|
|
35
|
+
type BlockListItems = BlockListContract["result"]["items"];
|
|
36
|
+
|
|
37
|
+
const LIST_COLUMN_ORDER = ["name", "type", "tier", "modifiers", "uri"] as const;
|
|
38
|
+
|
|
39
|
+
/** The `block list` / `block_list` read story. */
|
|
40
|
+
export const blockListStory: ReadStory<BlockListContract, BlockListItems> = {
|
|
41
|
+
noun: "block",
|
|
42
|
+
verb: "list",
|
|
43
|
+
description: "List blocks in the design system",
|
|
44
|
+
toolDescription:
|
|
45
|
+
"List design system blocks visible under current tier and channel configuration.",
|
|
46
|
+
params: [
|
|
47
|
+
{
|
|
48
|
+
name: "allTiers",
|
|
49
|
+
type: "boolean",
|
|
50
|
+
description: "Show blocks from all tiers",
|
|
51
|
+
toolDescription: "Show blocks from all tiers, ignoring tier filter",
|
|
52
|
+
default: false,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: "digest",
|
|
56
|
+
type: "boolean",
|
|
57
|
+
description: "Show enriched summary with implementations",
|
|
58
|
+
toolDescription: "Include implementations per block",
|
|
59
|
+
default: false,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "detailed",
|
|
63
|
+
type: "boolean",
|
|
64
|
+
description: "Show full details for each block",
|
|
65
|
+
toolDescription: "Include full details per block",
|
|
66
|
+
default: false,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
examples: [
|
|
70
|
+
"pragma block list",
|
|
71
|
+
"pragma block list --all-tiers",
|
|
72
|
+
"pragma block list --digest",
|
|
73
|
+
"pragma block list --detailed",
|
|
74
|
+
"pragma block list --llm",
|
|
75
|
+
"pragma block list --format json",
|
|
76
|
+
],
|
|
77
|
+
resolve: (rt, params) =>
|
|
78
|
+
resolveBlockList(rt, {
|
|
79
|
+
allTiers: params.allTiers === true,
|
|
80
|
+
digest: params.digest === true,
|
|
81
|
+
detailed: params.detailed === true,
|
|
82
|
+
}),
|
|
83
|
+
toOutput: (contract) => contract.result.items,
|
|
84
|
+
formatters: listFormatters,
|
|
85
|
+
toEnvelope: (contract) => {
|
|
86
|
+
const { items, disclosure, filters } = contract.result;
|
|
87
|
+
if (disclosure.level === "summary") {
|
|
88
|
+
return { data: items, meta: { count: items.length, filters } };
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
data: items,
|
|
92
|
+
meta: { count: items.length, disclosure: disclosure.level, filters },
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
renderInk: (items) =>
|
|
96
|
+
createListView({
|
|
97
|
+
heading: "Blocks",
|
|
98
|
+
domain: "block",
|
|
99
|
+
items,
|
|
100
|
+
columns: reorderColumns(blockConfig.listColumns, LIST_COLUMN_ORDER),
|
|
101
|
+
}),
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/** The `block lookup` / `block_lookup` read story. */
|
|
105
|
+
export const blockLookupStory: LookupStory<BlockDetailed, BlockLookupInput> = {
|
|
106
|
+
noun: "block",
|
|
107
|
+
description: "Look up block details",
|
|
108
|
+
toolDescription:
|
|
109
|
+
"Get detailed information about one or more design system blocks including anatomy, modifiers, tokens, and applicable standards.",
|
|
110
|
+
namesDescription: "Block names or IRIs",
|
|
111
|
+
namesToolDescription:
|
|
112
|
+
"Block names or IRIs to look up (e.g. ['Button', 'ds:global.component.card'])",
|
|
113
|
+
complete: async (partial, cmdCtx) => {
|
|
114
|
+
const ctx = requirePragmaContext(cmdCtx);
|
|
115
|
+
const all = await listBlocks(ctx.store, ctx.config);
|
|
116
|
+
const lower = partial.toLowerCase();
|
|
117
|
+
// Block names recur across tiers/packages; dedupe so completion offers each
|
|
118
|
+
// name once.
|
|
119
|
+
const unique = new Set(
|
|
120
|
+
all
|
|
121
|
+
.map((block) => block.name)
|
|
122
|
+
.filter((name) => name.toLowerCase().startsWith(lower)),
|
|
123
|
+
);
|
|
124
|
+
return [...unique];
|
|
125
|
+
},
|
|
126
|
+
detailedParam: {
|
|
127
|
+
description:
|
|
128
|
+
"Show full details including anatomy, modifiers, tokens, and implementations",
|
|
129
|
+
toolDescription: "Return full details (default: true for MCP)",
|
|
130
|
+
},
|
|
131
|
+
params: [
|
|
132
|
+
{
|
|
133
|
+
name: "anatomy",
|
|
134
|
+
type: "boolean",
|
|
135
|
+
description: "Show anatomy tree",
|
|
136
|
+
default: false,
|
|
137
|
+
surfaces: "cli",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "modifiers",
|
|
141
|
+
type: "boolean",
|
|
142
|
+
description: "Show modifier values",
|
|
143
|
+
default: false,
|
|
144
|
+
surfaces: "cli",
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "tokens",
|
|
148
|
+
type: "boolean",
|
|
149
|
+
description: "Show token references",
|
|
150
|
+
default: false,
|
|
151
|
+
surfaces: "cli",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "implementations",
|
|
155
|
+
type: "boolean",
|
|
156
|
+
description: "Show implementation paths",
|
|
157
|
+
default: false,
|
|
158
|
+
surfaces: "cli",
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
parameterGroups: {
|
|
162
|
+
"Aspect filters": ["anatomy", "modifiers", "tokens", "implementations"],
|
|
163
|
+
},
|
|
164
|
+
examples: [
|
|
165
|
+
"pragma block lookup Button",
|
|
166
|
+
"pragma block lookup Button Card",
|
|
167
|
+
"pragma block lookup Button --detailed",
|
|
168
|
+
"pragma block lookup Button --anatomy --modifiers",
|
|
169
|
+
"pragma block lookup Button --detailed --llm",
|
|
170
|
+
"pragma block lookup ds:global.component.button",
|
|
171
|
+
],
|
|
172
|
+
resolve: async (rt, names) => {
|
|
173
|
+
const contract = await resolveBlockLookup(
|
|
174
|
+
rt.store,
|
|
175
|
+
names,
|
|
176
|
+
buildBlockFilters(rt),
|
|
177
|
+
);
|
|
178
|
+
return contract.result;
|
|
179
|
+
},
|
|
180
|
+
resolveDetailed: (surface, params) => {
|
|
181
|
+
if (surface === "mcp") {
|
|
182
|
+
return ((params.detailed as boolean | undefined) ?? true) === true;
|
|
183
|
+
}
|
|
184
|
+
return params.detailed === true || isAspectSelected(params);
|
|
185
|
+
},
|
|
186
|
+
toFmtInput: (block, view) => ({
|
|
187
|
+
block,
|
|
188
|
+
detailed: view.detailed,
|
|
189
|
+
aspects: resolveViewAspects(view),
|
|
190
|
+
}),
|
|
191
|
+
formatters: lookupFormatters,
|
|
192
|
+
project: (block) => {
|
|
193
|
+
const {
|
|
194
|
+
uri,
|
|
195
|
+
name,
|
|
196
|
+
type,
|
|
197
|
+
tier,
|
|
198
|
+
modifiers,
|
|
199
|
+
implementations,
|
|
200
|
+
nodeCount,
|
|
201
|
+
tokenCount,
|
|
202
|
+
summary,
|
|
203
|
+
} = block;
|
|
204
|
+
return {
|
|
205
|
+
uri,
|
|
206
|
+
name,
|
|
207
|
+
type,
|
|
208
|
+
tier,
|
|
209
|
+
modifiers,
|
|
210
|
+
implementations,
|
|
211
|
+
nodeCount,
|
|
212
|
+
tokenCount,
|
|
213
|
+
summary,
|
|
214
|
+
};
|
|
215
|
+
},
|
|
216
|
+
emptyNamesError: () =>
|
|
217
|
+
PragmaError.invalidInput("names", "(empty)", {
|
|
218
|
+
recovery: {
|
|
219
|
+
message: "List available blocks.",
|
|
220
|
+
cli: "pragma block list",
|
|
221
|
+
mcp: { tool: "block_list" },
|
|
222
|
+
},
|
|
223
|
+
}),
|
|
224
|
+
renderInk: (result, view) =>
|
|
225
|
+
createLookupView({
|
|
226
|
+
results: result.results,
|
|
227
|
+
errors: result.errors,
|
|
228
|
+
domain: "block",
|
|
229
|
+
options: createLookupOptions(view.detailed, resolveViewAspects(view)),
|
|
230
|
+
}),
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
function isAspectSelected(params: Record<string, unknown>): boolean {
|
|
234
|
+
return (
|
|
235
|
+
params.anatomy === true ||
|
|
236
|
+
params.modifiers === true ||
|
|
237
|
+
params.tokens === true ||
|
|
238
|
+
params.implementations === true
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function resolveViewAspects(view: LookupStoryView): AspectFlags {
|
|
243
|
+
return resolveAspects({
|
|
244
|
+
anatomy: view.params.anatomy === true,
|
|
245
|
+
modifiers: view.params.modifiers === true,
|
|
246
|
+
tokens: view.params.tokens === true,
|
|
247
|
+
implementations: view.params.implementations === true,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function reorderColumns<T>(
|
|
252
|
+
columns: readonly ColumnDef<T>[],
|
|
253
|
+
order: readonly string[],
|
|
254
|
+
): readonly ColumnDef<T>[] {
|
|
255
|
+
const byKey = new Map(columns.map((col) => [col.key, col]));
|
|
256
|
+
return order.flatMap((key) => {
|
|
257
|
+
const col = byKey.get(key as keyof T & string);
|
|
258
|
+
return col ? [col] : [];
|
|
259
|
+
});
|
|
260
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import type { Store } from "@canonical/ke";
|
|
@@ -18,13 +18,24 @@ function makeCtx(cwd: string): PragmaContext {
|
|
|
18
18
|
|
|
19
19
|
describe("config channel command", () => {
|
|
20
20
|
let dir: string;
|
|
21
|
+
let xdgDir: string;
|
|
22
|
+
let originalXdg: string | undefined;
|
|
21
23
|
|
|
22
24
|
beforeEach(() => {
|
|
23
25
|
dir = mkdtempSync(join(tmpdir(), "pragma-cmd-channel-"));
|
|
26
|
+
// Bound the config walk at the fixture root, seed an empty project
|
|
27
|
+
// file so writes stay local, and isolate the global XDG layer.
|
|
28
|
+
mkdirSync(join(dir, ".git"));
|
|
29
|
+
writeFileSync(join(dir, "pragma.config.json"), "{}");
|
|
30
|
+
originalXdg = process.env.XDG_CONFIG_HOME;
|
|
31
|
+
xdgDir = mkdtempSync(join(tmpdir(), "pragma-cmd-channel-xdg-"));
|
|
32
|
+
process.env.XDG_CONFIG_HOME = xdgDir;
|
|
24
33
|
});
|
|
25
34
|
|
|
26
35
|
afterEach(() => {
|
|
36
|
+
process.env.XDG_CONFIG_HOME = originalXdg;
|
|
27
37
|
rmSync(dir, { recursive: true, force: true });
|
|
38
|
+
rmSync(xdgDir, { recursive: true, force: true });
|
|
28
39
|
});
|
|
29
40
|
|
|
30
41
|
it("sets channel to experimental", async () => {
|
|
@@ -45,10 +56,26 @@ describe("config channel command", () => {
|
|
|
45
56
|
expect(result.tag).toBe("output");
|
|
46
57
|
if (result.tag === "output") {
|
|
47
58
|
const text = result.render.plain(result.value);
|
|
48
|
-
expect(text).
|
|
59
|
+
expect(text).toContain('Set channel to "prerelease".');
|
|
49
60
|
}
|
|
50
61
|
});
|
|
51
62
|
|
|
63
|
+
it("rejects a value combined with --reset", async () => {
|
|
64
|
+
const ctx = makeCtx(dir);
|
|
65
|
+
const cmd = buildChannelCommand(ctx);
|
|
66
|
+
await expect(
|
|
67
|
+
cmd.execute({ value: "experimental", reset: true }, ctx),
|
|
68
|
+
).rejects.toMatchObject({ code: "INVALID_INPUT" });
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("rejects an explicit empty-string value", async () => {
|
|
72
|
+
const ctx = makeCtx(dir);
|
|
73
|
+
const cmd = buildChannelCommand(ctx);
|
|
74
|
+
await expect(cmd.execute({ value: "" }, ctx)).rejects.toMatchObject({
|
|
75
|
+
code: "INVALID_INPUT",
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
52
79
|
it("resets channel via --reset flag", async () => {
|
|
53
80
|
writeFileSync(
|
|
54
81
|
join(dir, "pragma.config.json"),
|
|
@@ -72,7 +99,7 @@ describe("config channel command", () => {
|
|
|
72
99
|
expect(result.tag).toBe("output");
|
|
73
100
|
if (result.tag === "output") {
|
|
74
101
|
const text = result.render.plain(result.value);
|
|
75
|
-
expect(text).
|
|
102
|
+
expect(text).toContain("Reset channel to default.");
|
|
76
103
|
}
|
|
77
104
|
});
|
|
78
105
|
|
|
@@ -3,13 +3,15 @@ import {
|
|
|
3
3
|
type CommandResult,
|
|
4
4
|
createOutputResult,
|
|
5
5
|
} from "@canonical/cli-core";
|
|
6
|
-
import { runTask } from "@canonical/task";
|
|
6
|
+
import { runTask } from "@canonical/task/node";
|
|
7
7
|
import { readConfig } from "#config";
|
|
8
|
+
import { PragmaError } from "#error";
|
|
8
9
|
import type { PragmaContext } from "../../shared/context.js";
|
|
9
10
|
import { selectFormatter } from "../../shared/formatters.js";
|
|
10
11
|
import { channelFormatters } from "../formatters/index.js";
|
|
11
12
|
import { validateChannel } from "../operations/index.js";
|
|
12
13
|
import { setChannelTask } from "../tasks/index.js";
|
|
14
|
+
import { resolveConfigScope, SCOPE_PARAMETERS } from "./configScope.js";
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* Build the `pragma config channel` command definition.
|
|
@@ -40,6 +42,7 @@ export default function buildChannelCommand(
|
|
|
40
42
|
type: "boolean",
|
|
41
43
|
default: false,
|
|
42
44
|
},
|
|
45
|
+
...SCOPE_PARAMETERS,
|
|
43
46
|
],
|
|
44
47
|
meta: {
|
|
45
48
|
examples: [
|
|
@@ -50,18 +53,32 @@ export default function buildChannelCommand(
|
|
|
50
53
|
execute: async (
|
|
51
54
|
params: Record<string, unknown>,
|
|
52
55
|
): Promise<CommandResult> => {
|
|
56
|
+
const scope = resolveConfigScope(params);
|
|
53
57
|
const reset = params.reset === true;
|
|
54
58
|
const value = params.value as string | undefined;
|
|
55
59
|
|
|
60
|
+
// Contradictory input: a value AND --reset. Reject rather than silently
|
|
61
|
+
// letting one win.
|
|
62
|
+
if (reset && value !== undefined) {
|
|
63
|
+
throw PragmaError.invalidInput("channel", value, {
|
|
64
|
+
recovery: {
|
|
65
|
+
message: "Pass either a channel value or --reset, not both.",
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
56
70
|
if (reset) {
|
|
57
|
-
await runTask(setChannelTask(ctx.cwd, undefined));
|
|
71
|
+
const result = await runTask(setChannelTask(ctx.cwd, undefined, scope));
|
|
58
72
|
const format = selectFormatter(ctx, channelFormatters.reset);
|
|
59
|
-
return createOutputResult(
|
|
60
|
-
|
|
61
|
-
|
|
73
|
+
return createOutputResult(
|
|
74
|
+
{ field: "channel", path: result.path },
|
|
75
|
+
{ plain: format },
|
|
76
|
+
);
|
|
62
77
|
}
|
|
63
78
|
|
|
64
|
-
|
|
79
|
+
// No value at all → query the current channel. An explicit empty string
|
|
80
|
+
// is invalid input, not a query.
|
|
81
|
+
if (value === undefined) {
|
|
65
82
|
const config = readConfig(ctx.cwd);
|
|
66
83
|
const format = selectFormatter(ctx, channelFormatters.query);
|
|
67
84
|
return createOutputResult(config.channel, {
|
|
@@ -71,10 +88,10 @@ export default function buildChannelCommand(
|
|
|
71
88
|
|
|
72
89
|
const channel = validateChannel(value);
|
|
73
90
|
|
|
74
|
-
await runTask(setChannelTask(ctx.cwd, channel));
|
|
91
|
+
const result = await runTask(setChannelTask(ctx.cwd, channel, scope));
|
|
75
92
|
const format = selectFormatter(ctx, channelFormatters.set);
|
|
76
93
|
return createOutputResult(
|
|
77
|
-
{ field: "channel", value: channel },
|
|
94
|
+
{ field: "channel", value: channel, path: result.path },
|
|
78
95
|
{ plain: format },
|
|
79
96
|
);
|
|
80
97
|
},
|