@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
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import projectCliParameters from "./projectCliParameters.js";
|
|
3
|
+
import type { StoryParam } from "./types.js";
|
|
4
|
+
|
|
5
|
+
describe("projectCliParameters", () => {
|
|
6
|
+
it("drops MCP-only parameters", () => {
|
|
7
|
+
const params: StoryParam[] = [
|
|
8
|
+
{ name: "a", type: "boolean", description: "a" },
|
|
9
|
+
{ name: "b", type: "boolean", description: "b", surfaces: "mcp" },
|
|
10
|
+
{ name: "c", type: "boolean", description: "c", surfaces: "cli" },
|
|
11
|
+
];
|
|
12
|
+
expect(projectCliParameters(params).map((p) => p.name)).toEqual(["a", "c"]);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("maps string[] to multiselect and enum strings to select with choices", () => {
|
|
16
|
+
const params: StoryParam[] = [
|
|
17
|
+
{ name: "names", type: "string[]", description: "names" },
|
|
18
|
+
{
|
|
19
|
+
name: "mode",
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "mode",
|
|
22
|
+
enum: ["fast", "slow"],
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
const projected = projectCliParameters(params);
|
|
26
|
+
expect(projected.at(0)?.type).toBe("multiselect");
|
|
27
|
+
expect(projected.at(1)?.type).toBe("select");
|
|
28
|
+
expect(projected.at(1)?.choices).toEqual([
|
|
29
|
+
{ label: "fast", value: "fast" },
|
|
30
|
+
{ label: "slow", value: "slow" },
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("carries defaults, positionals, required, and completion through", async () => {
|
|
35
|
+
const complete = async () => ["x"];
|
|
36
|
+
const params: StoryParam[] = [
|
|
37
|
+
{
|
|
38
|
+
name: "prefix",
|
|
39
|
+
type: "string",
|
|
40
|
+
description: "prefix",
|
|
41
|
+
positional: true,
|
|
42
|
+
required: true,
|
|
43
|
+
default: "ds",
|
|
44
|
+
complete,
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
const projected = projectCliParameters(params);
|
|
48
|
+
const first = projected.at(0);
|
|
49
|
+
expect(first?.positional).toBe(true);
|
|
50
|
+
expect(first?.required).toBe(true);
|
|
51
|
+
expect(first?.default).toBe("ds");
|
|
52
|
+
await expect(
|
|
53
|
+
first?.complete?.("d", {
|
|
54
|
+
cwd: "/",
|
|
55
|
+
globalFlags: { llm: false, format: "text", verbose: false },
|
|
56
|
+
}),
|
|
57
|
+
).resolves.toEqual(["x"]);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { ParameterDefinition } from "@canonical/cli-core";
|
|
2
|
+
import type { StoryParam } from "./types.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Project story parameters onto cli-core `ParameterDefinition`s.
|
|
6
|
+
*
|
|
7
|
+
* MCP-only parameters are dropped; `string[]` becomes a multiselect;
|
|
8
|
+
* an `enum` on a string parameter becomes a select with choices.
|
|
9
|
+
*/
|
|
10
|
+
export default function projectCliParameters(
|
|
11
|
+
params: readonly StoryParam[],
|
|
12
|
+
): ParameterDefinition[] {
|
|
13
|
+
return params
|
|
14
|
+
.filter((param) => (param.surfaces ?? "both") !== "mcp")
|
|
15
|
+
.map((param) => toParameterDefinition(param));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function toParameterDefinition(param: StoryParam): ParameterDefinition {
|
|
19
|
+
const definition: {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
type: ParameterDefinition["type"];
|
|
23
|
+
choices?: ParameterDefinition["choices"];
|
|
24
|
+
default?: unknown;
|
|
25
|
+
positional?: boolean;
|
|
26
|
+
required?: boolean;
|
|
27
|
+
complete?: ParameterDefinition["complete"];
|
|
28
|
+
} = {
|
|
29
|
+
name: param.name,
|
|
30
|
+
description: param.description,
|
|
31
|
+
type: resolveCliType(param),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
if (param.enum) {
|
|
35
|
+
definition.choices = param.enum.map((value) => ({ label: value, value }));
|
|
36
|
+
}
|
|
37
|
+
if (param.default !== undefined) {
|
|
38
|
+
definition.default = param.default;
|
|
39
|
+
}
|
|
40
|
+
if (param.positional === true) {
|
|
41
|
+
definition.positional = true;
|
|
42
|
+
}
|
|
43
|
+
if (param.required === true) {
|
|
44
|
+
definition.required = true;
|
|
45
|
+
}
|
|
46
|
+
if (param.complete) {
|
|
47
|
+
definition.complete = param.complete;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return definition;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function resolveCliType(param: StoryParam): ParameterDefinition["type"] {
|
|
54
|
+
if (param.type === "string[]") return "multiselect";
|
|
55
|
+
if (param.type === "string" && param.enum) return "select";
|
|
56
|
+
return param.type;
|
|
57
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import projectToolParams from "./projectToolParams.js";
|
|
3
|
+
import type { StoryParam } from "./types.js";
|
|
4
|
+
|
|
5
|
+
describe("projectToolParams", () => {
|
|
6
|
+
it("drops CLI-only parameters", () => {
|
|
7
|
+
const params: StoryParam[] = [
|
|
8
|
+
{ name: "a", type: "boolean", description: "a" },
|
|
9
|
+
{ name: "b", type: "boolean", description: "b", surfaces: "cli" },
|
|
10
|
+
{ name: "c", type: "boolean", description: "c", surfaces: "mcp" },
|
|
11
|
+
];
|
|
12
|
+
expect(Object.keys(projectToolParams(params))).toEqual(["a", "c"]);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("prefers the tool description and sets optional from required", () => {
|
|
16
|
+
const params: StoryParam[] = [
|
|
17
|
+
{
|
|
18
|
+
name: "names",
|
|
19
|
+
type: "string[]",
|
|
20
|
+
description: "cli text",
|
|
21
|
+
toolDescription: "mcp text",
|
|
22
|
+
required: true,
|
|
23
|
+
},
|
|
24
|
+
{ name: "flag", type: "boolean", description: "shared text" },
|
|
25
|
+
];
|
|
26
|
+
const projected = projectToolParams(params);
|
|
27
|
+
expect(projected.names).toEqual({
|
|
28
|
+
type: "string[]",
|
|
29
|
+
description: "mcp text",
|
|
30
|
+
optional: false,
|
|
31
|
+
});
|
|
32
|
+
expect(projected.flag).toEqual({
|
|
33
|
+
type: "boolean",
|
|
34
|
+
description: "shared text",
|
|
35
|
+
optional: true,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("carries enums through", () => {
|
|
40
|
+
const params: StoryParam[] = [
|
|
41
|
+
{
|
|
42
|
+
name: "mode",
|
|
43
|
+
type: "string",
|
|
44
|
+
description: "mode",
|
|
45
|
+
enum: ["fast", "slow"],
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
expect(projectToolParams(params).mode?.enum).toEqual(["fast", "slow"]);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ToolParamDef } from "../ToolSpec.js";
|
|
2
|
+
import type { StoryParam } from "./types.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Project story parameters onto MCP `ToolParamDef`s.
|
|
6
|
+
*
|
|
7
|
+
* CLI-only parameters are dropped, along with CLI-only attributes
|
|
8
|
+
* (defaults, positionals, completion). Required parameters set
|
|
9
|
+
* `optional: false` explicitly — the MCP adapter treats anything
|
|
10
|
+
* else as optional.
|
|
11
|
+
*/
|
|
12
|
+
export default function projectToolParams(
|
|
13
|
+
params: readonly StoryParam[],
|
|
14
|
+
): Record<string, ToolParamDef> {
|
|
15
|
+
const projected: Record<string, ToolParamDef> = {};
|
|
16
|
+
|
|
17
|
+
for (const param of params) {
|
|
18
|
+
if ((param.surfaces ?? "both") === "cli") continue;
|
|
19
|
+
projected[param.name] = toToolParamDef(param);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return projected;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function toToolParamDef(param: StoryParam): ToolParamDef {
|
|
26
|
+
return {
|
|
27
|
+
type: param.type,
|
|
28
|
+
description: param.toolDescription ?? param.description,
|
|
29
|
+
optional: param.required !== true,
|
|
30
|
+
...(param.enum && { enum: param.enum }),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { PragmaError } from "#error";
|
|
3
|
+
import type { PragmaContext } from "../context.js";
|
|
4
|
+
import requirePragmaContext from "./requirePragmaContext.js";
|
|
5
|
+
|
|
6
|
+
describe("requirePragmaContext", () => {
|
|
7
|
+
it("returns a context that carries the pragma runtime", () => {
|
|
8
|
+
const ctx = {
|
|
9
|
+
cwd: "/",
|
|
10
|
+
globalFlags: { llm: false, format: "text", verbose: false },
|
|
11
|
+
store: {},
|
|
12
|
+
} as unknown as PragmaContext;
|
|
13
|
+
expect(requirePragmaContext(ctx)).toBe(ctx);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("throws for a context without the runtime", () => {
|
|
17
|
+
const bare = {
|
|
18
|
+
cwd: "/",
|
|
19
|
+
globalFlags: { llm: false, format: "text" as const, verbose: false },
|
|
20
|
+
};
|
|
21
|
+
expect(() => requirePragmaContext(bare)).toThrow(PragmaError);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CommandContext } from "@canonical/cli-core";
|
|
2
|
+
import { PragmaError } from "#error";
|
|
3
|
+
import type { PragmaContext } from "../context.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Narrow a cli-core `CommandContext` to the pragma context.
|
|
7
|
+
*
|
|
8
|
+
* Story completion callbacks receive the cli-core context type, but every
|
|
9
|
+
* context the pragma pipeline constructs is a `PragmaContext` (it carries
|
|
10
|
+
* the ke store and config). This asserts that invariant at runtime instead
|
|
11
|
+
* of casting silently, failing fast if a foreign context ever appears.
|
|
12
|
+
*/
|
|
13
|
+
export default function requirePragmaContext(
|
|
14
|
+
ctx: CommandContext,
|
|
15
|
+
): PragmaContext {
|
|
16
|
+
if (!("store" in ctx)) {
|
|
17
|
+
throw PragmaError.internalError(
|
|
18
|
+
"completion context is missing the pragma runtime",
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
// Proven one line up: a context carrying `store` is a PragmaContext.
|
|
22
|
+
return ctx as PragmaContext;
|
|
23
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import resolveLookupDetailed from "./resolveLookupDetailed.js";
|
|
3
|
+
import type { LookupStory } from "./types.js";
|
|
4
|
+
|
|
5
|
+
type AnyLookupStory = LookupStory<unknown, unknown>;
|
|
6
|
+
|
|
7
|
+
const baseStory: Pick<
|
|
8
|
+
AnyLookupStory,
|
|
9
|
+
"noun" | "description" | "toolDescription" | "namesDescription"
|
|
10
|
+
> = {
|
|
11
|
+
noun: "thing",
|
|
12
|
+
description: "d",
|
|
13
|
+
toolDescription: "td",
|
|
14
|
+
namesDescription: "names",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function makeStory(overrides: Partial<AnyLookupStory>): AnyLookupStory {
|
|
18
|
+
return {
|
|
19
|
+
...baseStory,
|
|
20
|
+
examples: [],
|
|
21
|
+
resolve: async () => ({ results: [], errors: [] }),
|
|
22
|
+
toFmtInput: (entity) => entity,
|
|
23
|
+
formatters: {
|
|
24
|
+
plain: () => "",
|
|
25
|
+
llm: () => "",
|
|
26
|
+
json: () => "",
|
|
27
|
+
},
|
|
28
|
+
...overrides,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe("resolveLookupDetailed", () => {
|
|
33
|
+
it("is never detailed when the story has no detailed param", () => {
|
|
34
|
+
const story = makeStory({});
|
|
35
|
+
expect(resolveLookupDetailed(story, "cli", { detailed: true })).toBe(false);
|
|
36
|
+
expect(resolveLookupDetailed(story, "mcp", {})).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("defaults detailed to true on MCP and false on CLI", () => {
|
|
40
|
+
const story = makeStory({ detailedParam: { description: "d" } });
|
|
41
|
+
expect(resolveLookupDetailed(story, "mcp", {})).toBe(true);
|
|
42
|
+
expect(resolveLookupDetailed(story, "mcp", { detailed: false })).toBe(
|
|
43
|
+
false,
|
|
44
|
+
);
|
|
45
|
+
expect(resolveLookupDetailed(story, "cli", {})).toBe(false);
|
|
46
|
+
expect(resolveLookupDetailed(story, "cli", { detailed: true })).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("lets a story override the surface defaults", () => {
|
|
50
|
+
const story = makeStory({
|
|
51
|
+
detailedParam: { description: "d" },
|
|
52
|
+
resolveDetailed: (surface) => surface === "cli",
|
|
53
|
+
});
|
|
54
|
+
expect(resolveLookupDetailed(story, "cli", {})).toBe(true);
|
|
55
|
+
expect(resolveLookupDetailed(story, "mcp", {})).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { LookupStory } from "./types.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the effective `detailed` flag for a lookup story on a surface.
|
|
5
|
+
*
|
|
6
|
+
* Defaults follow the ratified surface contract: the CLI opts in
|
|
7
|
+
* (`detailed` is false unless set) while MCP opts out (`detailed` is true
|
|
8
|
+
* unless set, since agents want full data by default). Stories without a
|
|
9
|
+
* `detailed` parameter are never detailed. A story's `resolveDetailed`
|
|
10
|
+
* override wins — block uses it to let aspect flags imply detail.
|
|
11
|
+
*/
|
|
12
|
+
export default function resolveLookupDetailed<TDetailed, TFmtInput>(
|
|
13
|
+
story: LookupStory<TDetailed, TFmtInput>,
|
|
14
|
+
surface: "cli" | "mcp",
|
|
15
|
+
params: Record<string, unknown>,
|
|
16
|
+
): boolean {
|
|
17
|
+
if (story.resolveDetailed) {
|
|
18
|
+
return story.resolveDetailed(surface, params);
|
|
19
|
+
}
|
|
20
|
+
if (!story.detailedParam) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
if (surface === "mcp") {
|
|
24
|
+
return ((params.detailed as boolean | undefined) ?? true) === true;
|
|
25
|
+
}
|
|
26
|
+
return params.detailed === true;
|
|
27
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-story spec types — one declaration per read story, many projections.
|
|
3
|
+
*
|
|
4
|
+
* A read story (list, show, or lookup) is declared once per domain and
|
|
5
|
+
* compiled into both surfaces: a cli-core `CommandDefinition` and a
|
|
6
|
+
* declarative MCP `ToolSpec`. The compilers in this folder own the shared
|
|
7
|
+
* execute skeletons — parameter projection, condensed rendering with token
|
|
8
|
+
* estimates, empty-result guards, and summary projection — so a domain
|
|
9
|
+
* supplies only its facts: descriptions, parameters, resolve function,
|
|
10
|
+
* formatters, and envelope mapping. This kills the per-domain duplication
|
|
11
|
+
* between `commands/*.ts` and `mcp/specs.ts` for read verbs and makes
|
|
12
|
+
* CLI/MCP parity structural instead of conventional.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { CommandContext } from "@canonical/cli-core";
|
|
16
|
+
import type { PragmaError } from "#error";
|
|
17
|
+
import type { LookupResult } from "../contracts.js";
|
|
18
|
+
import type { Formatters } from "../formatters.js";
|
|
19
|
+
import type { PragmaRuntime } from "../types/index.js";
|
|
20
|
+
|
|
21
|
+
/** Surfaces a story parameter is projected to (default: "both"). */
|
|
22
|
+
export type StorySurface = "both" | "cli" | "mcp";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Neutral parameter definition projected to a CLI flag and an MCP tool
|
|
26
|
+
* parameter. `string[]` becomes a CLI multiselect and an MCP string array.
|
|
27
|
+
*/
|
|
28
|
+
export interface StoryParam {
|
|
29
|
+
readonly name: string;
|
|
30
|
+
readonly type: "string" | "boolean" | "string[]";
|
|
31
|
+
/** CLI help text; also the MCP description unless `toolDescription` is set. */
|
|
32
|
+
readonly description: string;
|
|
33
|
+
/** MCP-specific description override. */
|
|
34
|
+
readonly toolDescription?: string;
|
|
35
|
+
readonly required?: boolean;
|
|
36
|
+
/** CLI default value — MCP parameters carry no defaults. */
|
|
37
|
+
readonly default?: unknown;
|
|
38
|
+
/** Allowed values; projects to CLI select choices and an MCP enum. */
|
|
39
|
+
readonly enum?: readonly string[];
|
|
40
|
+
/** If true, the CLI accepts this parameter as a positional argument. */
|
|
41
|
+
readonly positional?: boolean;
|
|
42
|
+
/** Surfaces this parameter appears on (default: "both"). */
|
|
43
|
+
readonly surfaces?: StorySurface;
|
|
44
|
+
/** CLI tab-completion for this parameter's argument. */
|
|
45
|
+
readonly complete?: (
|
|
46
|
+
partial: string,
|
|
47
|
+
ctx: CommandContext,
|
|
48
|
+
) => Promise<string[]>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** MCP envelope fragment produced by a story's `toEnvelope`. */
|
|
52
|
+
export interface StoryEnvelope {
|
|
53
|
+
readonly data: unknown;
|
|
54
|
+
readonly meta?: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* A collection-or-singleton read story (`<noun> list`, `<noun> show`).
|
|
59
|
+
*
|
|
60
|
+
* `TData` is the domain's resolved payload; `TOutput` is the formatter and
|
|
61
|
+
* renderer input derived from it via `toOutput`.
|
|
62
|
+
*/
|
|
63
|
+
export interface ReadStory<TData, TOutput> {
|
|
64
|
+
readonly noun: string;
|
|
65
|
+
/** Read verb this story projects to (e.g. "list", "show"). */
|
|
66
|
+
readonly verb: string;
|
|
67
|
+
/** CLI one-line help description. */
|
|
68
|
+
readonly description: string;
|
|
69
|
+
/** MCP tool description. */
|
|
70
|
+
readonly toolDescription: string;
|
|
71
|
+
readonly params: readonly StoryParam[];
|
|
72
|
+
/** Usage examples shown in CLI help. */
|
|
73
|
+
readonly examples: readonly string[];
|
|
74
|
+
/** Fetch the story's data. Shared verbatim by both surfaces. */
|
|
75
|
+
readonly resolve: (
|
|
76
|
+
rt: PragmaRuntime,
|
|
77
|
+
params: Record<string, unknown>,
|
|
78
|
+
) => Promise<TData>;
|
|
79
|
+
/** Map resolved data to the formatter/renderer input. */
|
|
80
|
+
readonly toOutput: (data: TData, params: Record<string, unknown>) => TOutput;
|
|
81
|
+
readonly formatters: Formatters<TOutput>;
|
|
82
|
+
/** Map resolved data to the MCP `{ data, meta }` envelope. */
|
|
83
|
+
readonly toEnvelope: (data: TData) => StoryEnvelope;
|
|
84
|
+
/**
|
|
85
|
+
* CLI-only pre-resolve guard: return an error to reject invalid
|
|
86
|
+
* parameters (e.g. an empty required positional).
|
|
87
|
+
*/
|
|
88
|
+
readonly guardParams?: (
|
|
89
|
+
params: Record<string, unknown>,
|
|
90
|
+
) => PragmaError | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* CLI-only post-resolve guard: return an error to reject an empty
|
|
93
|
+
* result set with a recovery hint.
|
|
94
|
+
*/
|
|
95
|
+
readonly emptyError?: (
|
|
96
|
+
data: TData,
|
|
97
|
+
params: Record<string, unknown>,
|
|
98
|
+
) => PragmaError | undefined;
|
|
99
|
+
/** Optional interactive (ink) renderer for the CLI. */
|
|
100
|
+
readonly renderInk?: (output: TOutput) => unknown;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Per-invocation view state passed to lookup story hooks. */
|
|
104
|
+
export interface LookupStoryView {
|
|
105
|
+
readonly surface: "cli" | "mcp";
|
|
106
|
+
/** Effective detail level after surface defaults and flag implications. */
|
|
107
|
+
readonly detailed: boolean;
|
|
108
|
+
readonly params: Record<string, unknown>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* A batch retrieval story (`<noun> lookup <names...>`).
|
|
113
|
+
*
|
|
114
|
+
* `TDetailed` is the looked-up entity; `TFmtInput` is the per-entity
|
|
115
|
+
* formatter input derived via `toFmtInput` (some domains pair the entity
|
|
116
|
+
* with view flags such as `detailed` or aspect selections).
|
|
117
|
+
*/
|
|
118
|
+
export interface LookupStory<TDetailed, TFmtInput> {
|
|
119
|
+
readonly noun: string;
|
|
120
|
+
readonly description: string;
|
|
121
|
+
readonly toolDescription: string;
|
|
122
|
+
/** CLI description of the `names` positional parameter. */
|
|
123
|
+
readonly namesDescription: string;
|
|
124
|
+
/** MCP-specific `names` description override. */
|
|
125
|
+
readonly namesToolDescription?: string;
|
|
126
|
+
/** CLI tab-completion for names. */
|
|
127
|
+
readonly complete?: (
|
|
128
|
+
partial: string,
|
|
129
|
+
ctx: CommandContext,
|
|
130
|
+
) => Promise<string[]>;
|
|
131
|
+
/**
|
|
132
|
+
* The `detailed` toggle, when the story supports one. MCP defaults
|
|
133
|
+
* `detailed` to true; the CLI defaults it to false.
|
|
134
|
+
*/
|
|
135
|
+
readonly detailedParam?: {
|
|
136
|
+
readonly description: string;
|
|
137
|
+
readonly toolDescription?: string;
|
|
138
|
+
};
|
|
139
|
+
/** Additional story parameters beyond `names` and `detailed`. */
|
|
140
|
+
readonly params?: readonly StoryParam[];
|
|
141
|
+
/** Named groups for organizing CLI parameters in help output. */
|
|
142
|
+
readonly parameterGroups?: Readonly<Record<string, readonly string[]>>;
|
|
143
|
+
readonly examples: readonly string[];
|
|
144
|
+
/**
|
|
145
|
+
* Resolve all queries, collecting per-query failures.
|
|
146
|
+
*
|
|
147
|
+
* The compilers pass the per-invocation `view` so surface-sensitive
|
|
148
|
+
* resolution (e.g. pack disclosure defaults, which differ between the
|
|
149
|
+
* CLI and MCP per the ratified surface contract) can see which surface
|
|
150
|
+
* is calling; most stories ignore it.
|
|
151
|
+
*/
|
|
152
|
+
readonly resolve: (
|
|
153
|
+
rt: PragmaRuntime,
|
|
154
|
+
names: readonly string[],
|
|
155
|
+
params: Record<string, unknown>,
|
|
156
|
+
view?: LookupStoryView,
|
|
157
|
+
) => Promise<LookupResult<TDetailed>>;
|
|
158
|
+
/**
|
|
159
|
+
* Effective `detailed` for a surface. Defaults to the plain flag value
|
|
160
|
+
* (CLI: false unless set; MCP: true unless set). Domains override this
|
|
161
|
+
* when other flags imply detail (e.g. block aspect filters).
|
|
162
|
+
*/
|
|
163
|
+
readonly resolveDetailed?: (
|
|
164
|
+
surface: "cli" | "mcp",
|
|
165
|
+
params: Record<string, unknown>,
|
|
166
|
+
) => boolean;
|
|
167
|
+
/** Map an entity to the per-entity formatter input. */
|
|
168
|
+
readonly toFmtInput: (entity: TDetailed, view: LookupStoryView) => TFmtInput;
|
|
169
|
+
readonly formatters: Formatters<TFmtInput>;
|
|
170
|
+
/** MCP summary projection applied when `detailed` is false. */
|
|
171
|
+
readonly project?: (entity: TDetailed) => unknown;
|
|
172
|
+
/** CLI-only error thrown when no names are supplied. */
|
|
173
|
+
readonly emptyNamesError?: () => PragmaError;
|
|
174
|
+
/** Optional interactive (ink) renderer for the CLI. */
|
|
175
|
+
readonly renderInk?: (
|
|
176
|
+
result: LookupResult<TDetailed>,
|
|
177
|
+
view: LookupStoryView,
|
|
178
|
+
) => unknown;
|
|
179
|
+
}
|
|
@@ -41,6 +41,7 @@ function globToRegex(glob: string): RegExp {
|
|
|
41
41
|
for (const char of glob) {
|
|
42
42
|
if (char === "*") {
|
|
43
43
|
pattern += ".*";
|
|
44
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: regex meta-characters to escape, not a JS template
|
|
44
45
|
} else if (".+^${}()|[]\\".includes(char)) {
|
|
45
46
|
pattern += `\\${char}`;
|
|
46
47
|
} else {
|
|
@@ -63,35 +63,68 @@ function damerauLevenshtein(a: string, b: string): number {
|
|
|
63
63
|
if (lenA === 0) return lenB;
|
|
64
64
|
if (lenB === 0) return lenA;
|
|
65
65
|
|
|
66
|
+
// Fully allocated (lenA + 1) × (lenB + 1) grid: every row/column index in
|
|
67
|
+
// [0, lenA] × [0, lenB] below is provably in bounds, so `row.at(j)` never
|
|
68
|
+
// yields undefined for the indices we read.
|
|
66
69
|
const matrix: number[][] = Array.from({ length: lenA + 1 }, () =>
|
|
67
70
|
Array.from<number>({ length: lenB + 1 }).fill(0),
|
|
68
71
|
);
|
|
69
72
|
|
|
70
73
|
for (let i = 0; i <= lenA; i++) {
|
|
71
|
-
matrix
|
|
74
|
+
getRow(matrix, i)[0] = i;
|
|
72
75
|
}
|
|
76
|
+
const firstRow = getRow(matrix, 0);
|
|
73
77
|
for (let j = 0; j <= lenB; j++) {
|
|
74
|
-
|
|
78
|
+
firstRow[j] = j;
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
for (let i = 1; i <= lenA; i++) {
|
|
82
|
+
const prevRow = getRow(matrix, i - 1);
|
|
83
|
+
const row = getRow(matrix, i);
|
|
78
84
|
for (let j = 1; j <= lenB; j++) {
|
|
79
85
|
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
80
86
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
row[j] = Math.min(
|
|
88
|
+
getCell(prevRow, j) + 1, // deletion
|
|
89
|
+
getCell(row, j - 1) + 1, // insertion
|
|
90
|
+
getCell(prevRow, j - 1) + cost, // substitution
|
|
85
91
|
);
|
|
86
92
|
|
|
87
93
|
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
88
|
-
matrix
|
|
89
|
-
|
|
90
|
-
|
|
94
|
+
const prevPrevRow = getRow(matrix, i - 2);
|
|
95
|
+
row[j] = Math.min(
|
|
96
|
+
getCell(row, j),
|
|
97
|
+
getCell(prevPrevRow, j - 2) + cost, // transposition
|
|
91
98
|
);
|
|
92
99
|
}
|
|
93
100
|
}
|
|
94
101
|
}
|
|
95
102
|
|
|
96
|
-
return matrix
|
|
103
|
+
return getCell(getRow(matrix, lenA), lenB);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Read a matrix row that is structurally guaranteed to exist.
|
|
108
|
+
*
|
|
109
|
+
* @throws if the row is missing, signalling a broken allocation invariant.
|
|
110
|
+
*/
|
|
111
|
+
function getRow(matrix: number[][], index: number): number[] {
|
|
112
|
+
const row = matrix.at(index);
|
|
113
|
+
if (row === undefined) {
|
|
114
|
+
throw new Error(`matrix row ${index} is out of bounds`);
|
|
115
|
+
}
|
|
116
|
+
return row;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Read a matrix cell that is structurally guaranteed to exist.
|
|
121
|
+
*
|
|
122
|
+
* @throws if the cell is missing, signalling a broken allocation invariant.
|
|
123
|
+
*/
|
|
124
|
+
function getCell(row: number[], index: number): number {
|
|
125
|
+
const cell = row.at(index);
|
|
126
|
+
if (cell === undefined) {
|
|
127
|
+
throw new Error(`matrix cell ${index} is out of bounds`);
|
|
128
|
+
}
|
|
129
|
+
return cell;
|
|
97
130
|
}
|
|
@@ -26,21 +26,17 @@ export type {
|
|
|
26
26
|
} from "./modifier.js";
|
|
27
27
|
export type {
|
|
28
28
|
OntologyClass,
|
|
29
|
+
OntologyClassFocus,
|
|
30
|
+
OntologyConstraint,
|
|
29
31
|
OntologyDetailed,
|
|
32
|
+
OntologyMeta,
|
|
30
33
|
OntologyProperty,
|
|
34
|
+
OntologyQueryHint,
|
|
31
35
|
OntologySummary,
|
|
32
36
|
} from "./ontology.js";
|
|
33
37
|
export type { PragmaRuntime } from "./runtime.js";
|
|
34
38
|
export type { SampleOutput, SampleResult } from "./sample.js";
|
|
35
|
-
export type {
|
|
36
|
-
CategorySummary,
|
|
37
|
-
CodeBlock,
|
|
38
|
-
StandardDetailed,
|
|
39
|
-
StandardDigest,
|
|
40
|
-
StandardListFilters,
|
|
41
|
-
StandardRef,
|
|
42
|
-
StandardSummary,
|
|
43
|
-
} from "./standard.js";
|
|
39
|
+
export type { StandardRef } from "./standard.js";
|
|
44
40
|
export type { TierEntry } from "./tier.js";
|
|
45
41
|
export type {
|
|
46
42
|
TokenDetailed,
|