@canonical/pragma-cli 0.18.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 +377 -0
- package/package.json +78 -0
- package/src/bin.test.ts +52 -0
- package/src/bin.ts +19 -0
- package/src/compile-validation.runner.ts +137 -0
- package/src/compile-validation.ts +192 -0
- package/src/completions/computeSocketPath.test.ts +26 -0
- package/src/completions/computeSocketPath.ts +16 -0
- package/src/completions/constants.ts +18 -0
- package/src/completions/handleQuery.test.ts +93 -0
- package/src/completions/handleQuery.ts +30 -0
- package/src/completions/index.ts +14 -0
- package/src/completions/queryCompletions.test.ts +100 -0
- package/src/completions/queryCompletions.ts +61 -0
- package/src/completions/querySocket.test.ts +70 -0
- package/src/completions/querySocket.ts +44 -0
- package/src/completions/startCompletionsServer.test.ts +74 -0
- package/src/completions/startCompletionsServer.ts +75 -0
- package/src/completions/startCompletionsServer.unit.test.ts +131 -0
- package/src/completions/waitForSocket.test.ts +27 -0
- package/src/completions/waitForSocket.ts +27 -0
- package/src/config/configExists.ts +14 -0
- package/src/config/index.ts +6 -0
- package/src/config/readConfig.test.ts +152 -0
- package/src/config/readConfig.ts +64 -0
- package/src/config/resolveConfigPath.test.ts +20 -0
- package/src/config/resolveConfigPath.ts +11 -0
- package/src/config/types.ts +26 -0
- package/src/config/writeConfig.ts +49 -0
- package/src/constants.ts +78 -0
- package/src/domains/block/blockConfig.ts +53 -0
- package/src/domains/block/commands/index.ts +4 -0
- package/src/domains/block/commands/list.test.ts +111 -0
- package/src/domains/block/commands/list.ts +69 -0
- package/src/domains/block/commands/lookup.test.ts +187 -0
- package/src/domains/block/commands/lookup.ts +199 -0
- package/src/domains/block/formatters/index.ts +4 -0
- package/src/domains/block/formatters/list.test.ts +107 -0
- package/src/domains/block/formatters/list.ts +64 -0
- package/src/domains/block/formatters/lookup.test.ts +317 -0
- package/src/domains/block/formatters/lookup.ts +354 -0
- package/src/domains/block/formatters/types.ts +16 -0
- package/src/domains/block/helpers/index.ts +4 -0
- package/src/domains/block/helpers/resolveAspects.test.ts +64 -0
- package/src/domains/block/helpers/resolveAspects.ts +35 -0
- package/src/domains/block/index.ts +25 -0
- package/src/domains/block/mcp/index.ts +2 -0
- package/src/domains/block/mcp/specs.ts +199 -0
- package/src/domains/block/operations/index.ts +4 -0
- package/src/domains/block/operations/list.test.ts +80 -0
- package/src/domains/block/operations/list.ts +72 -0
- package/src/domains/block/operations/lookup.test.ts +108 -0
- package/src/domains/block/operations/lookup.ts +359 -0
- package/src/domains/block/orchestration/blockEmptyError.ts +19 -0
- package/src/domains/block/orchestration/buildBlockFilters.ts +12 -0
- package/src/domains/block/orchestration/enrichBlocks.ts +37 -0
- package/src/domains/block/orchestration/index.ts +5 -0
- package/src/domains/block/orchestration/resolveBlockList.ts +39 -0
- package/src/domains/block/orchestration/resolveBlockLookup.ts +21 -0
- package/src/domains/block/types.ts +30 -0
- package/src/domains/config/commands/channel.test.ts +101 -0
- package/src/domains/config/commands/channel.ts +80 -0
- package/src/domains/config/commands/index.ts +4 -0
- package/src/domains/config/commands/show.test.ts +61 -0
- package/src/domains/config/commands/show.ts +51 -0
- package/src/domains/config/commands/tier.test.ts +84 -0
- package/src/domains/config/commands/tier.ts +78 -0
- package/src/domains/config/formatters/channel.test.ts +56 -0
- package/src/domains/config/formatters/channel.ts +34 -0
- package/src/domains/config/formatters/index.ts +4 -0
- package/src/domains/config/formatters/show.test.ts +126 -0
- package/src/domains/config/formatters/show.ts +66 -0
- package/src/domains/config/formatters/tier.test.ts +70 -0
- package/src/domains/config/formatters/tier.ts +40 -0
- package/src/domains/config/index.ts +23 -0
- package/src/domains/config/mcp/index.ts +2 -0
- package/src/domains/config/mcp/specs.ts +108 -0
- package/src/domains/config/operations/index.ts +5 -0
- package/src/domains/config/operations/show.test.ts +60 -0
- package/src/domains/config/operations/show.ts +42 -0
- package/src/domains/config/operations/types.ts +13 -0
- package/src/domains/config/operations/validateChannel.test.ts +36 -0
- package/src/domains/config/operations/validateChannel.ts +24 -0
- package/src/domains/config/operations/validateTier.test.ts +56 -0
- package/src/domains/config/operations/validateTier.ts +35 -0
- package/src/domains/create/commands/component.test.ts +166 -0
- package/src/domains/create/commands/component.ts +129 -0
- package/src/domains/create/commands/index.ts +3 -0
- package/src/domains/create/commands/package.test.ts +35 -0
- package/src/domains/create/commands/package.ts +21 -0
- package/src/domains/create/index.ts +15 -0
- package/src/domains/create/mcp/index.ts +2 -0
- package/src/domains/create/mcp/specs.ts +174 -0
- package/src/domains/doctor/commands/doctor.test.ts +75 -0
- package/src/domains/doctor/commands/doctor.ts +43 -0
- package/src/domains/doctor/commands/index.ts +2 -0
- package/src/domains/doctor/formatters/doctor.test.ts +117 -0
- package/src/domains/doctor/formatters/doctor.ts +84 -0
- package/src/domains/doctor/formatters/index.ts +2 -0
- package/src/domains/doctor/index.ts +9 -0
- package/src/domains/doctor/mcp/index.ts +2 -0
- package/src/domains/doctor/mcp/specs.ts +88 -0
- package/src/domains/doctor/operations/checks/checkConfigFile.ts +28 -0
- package/src/domains/doctor/operations/checks/checkKeStore.ts +38 -0
- package/src/domains/doctor/operations/checks/checkMcpConfigured.ts +65 -0
- package/src/domains/doctor/operations/checks/checkNodeVersion.ts +25 -0
- package/src/domains/doctor/operations/checks/checkPragmaVersion.ts +20 -0
- package/src/domains/doctor/operations/checks/checkShellCompletions.ts +42 -0
- package/src/domains/doctor/operations/checks/checkSkillsSymlinked.ts +64 -0
- package/src/domains/doctor/operations/checks/index.ts +8 -0
- package/src/domains/doctor/operations/checks.test.ts +151 -0
- package/src/domains/doctor/operations/index.ts +3 -0
- package/src/domains/doctor/operations/runChecks.test.ts +89 -0
- package/src/domains/doctor/operations/runChecks.ts +38 -0
- package/src/domains/doctor/operations/types.ts +20 -0
- package/src/domains/graph/commands/index.ts +4 -0
- package/src/domains/graph/commands/inspect.test.ts +94 -0
- package/src/domains/graph/commands/inspect.ts +63 -0
- package/src/domains/graph/commands/query.test.ts +92 -0
- package/src/domains/graph/commands/query.ts +60 -0
- package/src/domains/graph/formatters/index.ts +4 -0
- package/src/domains/graph/formatters/inspect.ts +45 -0
- package/src/domains/graph/formatters/query.ts +37 -0
- package/src/domains/graph/helpers/index.ts +3 -0
- package/src/domains/graph/helpers/resolveUri.ts +70 -0
- package/src/domains/graph/index.ts +22 -0
- package/src/domains/graph/mcp/index.ts +2 -0
- package/src/domains/graph/mcp/specs.ts +82 -0
- package/src/domains/graph/operations/executeQuery.test.ts +68 -0
- package/src/domains/graph/operations/executeQuery.ts +32 -0
- package/src/domains/graph/operations/index.ts +4 -0
- package/src/domains/graph/operations/inspectUri.test.ts +101 -0
- package/src/domains/graph/operations/inspectUri.ts +61 -0
- package/src/domains/info/commands/index.ts +4 -0
- package/src/domains/info/commands/info.test.ts +88 -0
- package/src/domains/info/commands/info.ts +47 -0
- package/src/domains/info/commands/upgrade.test.ts +183 -0
- package/src/domains/info/commands/upgrade.ts +150 -0
- package/src/domains/info/constants.test.ts +22 -0
- package/src/domains/info/constants.ts +15 -0
- package/src/domains/info/formatters/index.ts +8 -0
- package/src/domains/info/formatters/info.test.ts +173 -0
- package/src/domains/info/formatters/info.ts +116 -0
- package/src/domains/info/formatters/upgrade.test.ts +133 -0
- package/src/domains/info/formatters/upgrade.ts +68 -0
- package/src/domains/info/index.ts +7 -0
- package/src/domains/info/operations/checkRegistryVersion.test.ts +124 -0
- package/src/domains/info/operations/checkRegistryVersion.ts +45 -0
- package/src/domains/info/operations/collectInfo.test.ts +111 -0
- package/src/domains/info/operations/collectInfo.ts +68 -0
- package/src/domains/info/operations/collectStoreSummary.test.ts +61 -0
- package/src/domains/info/operations/collectStoreSummary.ts +42 -0
- package/src/domains/info/operations/index.ts +5 -0
- package/src/domains/info/types.test-d.ts +35 -0
- package/src/domains/info/types.ts +46 -0
- package/src/domains/llm/commands/index.ts +3 -0
- package/src/domains/llm/commands/llm.ts +37 -0
- package/src/domains/llm/data/commandReference.ts +25 -0
- package/src/domains/llm/data/decisionTrees.ts +46 -0
- package/src/domains/llm/data/index.ts +4 -0
- package/src/domains/llm/formatters/index.ts +3 -0
- package/src/domains/llm/formatters/orientation.ts +53 -0
- package/src/domains/llm/index.ts +8 -0
- package/src/domains/llm/llmCommand.test.ts +93 -0
- package/src/domains/llm/mcp/index.ts +2 -0
- package/src/domains/llm/mcp/specs.ts +87 -0
- package/src/domains/llm/operations/collectContext.ts +47 -0
- package/src/domains/llm/operations/index.ts +3 -0
- package/src/domains/llm/types.ts +32 -0
- package/src/domains/modifier/commands/index.ts +4 -0
- package/src/domains/modifier/commands/list.test.ts +57 -0
- package/src/domains/modifier/commands/list.ts +33 -0
- package/src/domains/modifier/commands/lookup.test.ts +91 -0
- package/src/domains/modifier/commands/lookup.ts +105 -0
- package/src/domains/modifier/formatters/index.ts +4 -0
- package/src/domains/modifier/formatters/list.test.ts +38 -0
- package/src/domains/modifier/formatters/list.ts +35 -0
- package/src/domains/modifier/formatters/lookup.test.ts +33 -0
- package/src/domains/modifier/formatters/lookup.ts +38 -0
- package/src/domains/modifier/index.ts +22 -0
- package/src/domains/modifier/mcp/index.ts +2 -0
- package/src/domains/modifier/mcp/specs.ts +97 -0
- package/src/domains/modifier/operations/index.ts +4 -0
- package/src/domains/modifier/operations/list.test.ts +39 -0
- package/src/domains/modifier/operations/list.ts +41 -0
- package/src/domains/modifier/operations/lookup.test.ts +37 -0
- package/src/domains/modifier/operations/lookup.ts +57 -0
- package/src/domains/modifier/orchestration/index.ts +3 -0
- package/src/domains/modifier/orchestration/modifierEmptyError.ts +10 -0
- package/src/domains/modifier/orchestration/resolveModifierList.ts +16 -0
- package/src/domains/modifier/orchestration/resolveModifierLookup.ts +20 -0
- package/src/domains/modifier/types.ts +5 -0
- package/src/domains/ontology/commands/index.ts +4 -0
- package/src/domains/ontology/commands/list.test.ts +82 -0
- package/src/domains/ontology/commands/list.ts +46 -0
- package/src/domains/ontology/commands/show.test.ts +103 -0
- package/src/domains/ontology/commands/show.ts +66 -0
- package/src/domains/ontology/formatters/index.ts +4 -0
- package/src/domains/ontology/formatters/list.ts +37 -0
- package/src/domains/ontology/formatters/show.ts +74 -0
- package/src/domains/ontology/helpers/findNamespace.ts +23 -0
- package/src/domains/ontology/helpers/index.ts +7 -0
- package/src/domains/ontology/helpers/queryClasses.ts +50 -0
- package/src/domains/ontology/helpers/queryProperties.ts +57 -0
- package/src/domains/ontology/helpers/resolvePrefix.ts +45 -0
- package/src/domains/ontology/index.ts +26 -0
- package/src/domains/ontology/mcp/index.ts +2 -0
- package/src/domains/ontology/mcp/specs.ts +93 -0
- package/src/domains/ontology/operations/index.ts +5 -0
- package/src/domains/ontology/operations/listOntologies.test.ts +45 -0
- package/src/domains/ontology/operations/listOntologies.ts +101 -0
- package/src/domains/ontology/operations/showOntology.test.ts +65 -0
- package/src/domains/ontology/operations/showOntology.ts +41 -0
- package/src/domains/ontology/operations/showOntologyRaw.test.ts +39 -0
- package/src/domains/ontology/operations/showOntologyRaw.ts +50 -0
- package/src/domains/setup/commands/all.ts +58 -0
- package/src/domains/setup/commands/completions.ts +85 -0
- package/src/domains/setup/commands/entrypoints.test.ts +170 -0
- package/src/domains/setup/commands/index.ts +6 -0
- package/src/domains/setup/commands/lsp.ts +49 -0
- package/src/domains/setup/commands/mcp.ts +119 -0
- package/src/domains/setup/commands/skills.test.ts +64 -0
- package/src/domains/setup/commands/skills.ts +106 -0
- package/src/domains/setup/formatters/index.ts +2 -0
- package/src/domains/setup/formatters/skills.test.ts +103 -0
- package/src/domains/setup/formatters/skills.ts +112 -0
- package/src/domains/setup/formatters/types.ts +7 -0
- package/src/domains/setup/helpers/completionScripts.test.ts +58 -0
- package/src/domains/setup/helpers/completionScripts.ts +92 -0
- package/src/domains/setup/helpers/constants.ts +2 -0
- package/src/domains/setup/helpers/detectShell.test.ts +48 -0
- package/src/domains/setup/helpers/detectShell.ts +20 -0
- package/src/domains/setup/helpers/index.ts +12 -0
- package/src/domains/setup/helpers/runSetupTask.test.ts +279 -0
- package/src/domains/setup/helpers/runSetupTask.ts +229 -0
- package/src/domains/setup/index.ts +33 -0
- package/src/domains/setup/operations/index.ts +6 -0
- package/src/domains/setup/operations/setupAll.test.ts +48 -0
- package/src/domains/setup/operations/setupAll.ts +41 -0
- package/src/domains/setup/operations/setupCompletions.test.ts +94 -0
- package/src/domains/setup/operations/setupCompletions.ts +54 -0
- package/src/domains/setup/operations/setupLsp.test.ts +29 -0
- package/src/domains/setup/operations/setupLsp.ts +17 -0
- package/src/domains/setup/operations/setupMcp.test.ts +115 -0
- package/src/domains/setup/operations/setupMcp.ts +108 -0
- package/src/domains/setup/operations/setupSkills.test.ts +191 -0
- package/src/domains/setup/operations/setupSkills.ts +160 -0
- package/src/domains/setup/types.ts +18 -0
- package/src/domains/shared/ToolSpec.ts +49 -0
- package/src/domains/shared/bootStore.ts +77 -0
- package/src/domains/shared/buildQuery.ts +18 -0
- package/src/domains/shared/compactUri.test.ts +21 -0
- package/src/domains/shared/compactUri.ts +16 -0
- package/src/domains/shared/context.ts +15 -0
- package/src/domains/shared/contracts.ts +113 -0
- package/src/domains/shared/extractLocalName.test.ts +21 -0
- package/src/domains/shared/extractLocalName.ts +14 -0
- package/src/domains/shared/filters/buildChannelFilter.test.ts +52 -0
- package/src/domains/shared/filters/buildChannelFilter.ts +41 -0
- package/src/domains/shared/filters/buildFilterConfig.ts +16 -0
- package/src/domains/shared/filters/buildFilters.test.ts +33 -0
- package/src/domains/shared/filters/buildFilters.ts +30 -0
- package/src/domains/shared/filters/buildTierFilter.test.ts +78 -0
- package/src/domains/shared/filters/buildTierFilter.ts +69 -0
- package/src/domains/shared/filters/describeFilters.ts +14 -0
- package/src/domains/shared/filters/index.ts +10 -0
- package/src/domains/shared/formatters.ts +35 -0
- package/src/domains/shared/lookupMany.ts +45 -0
- package/src/domains/shared/namespaces.ts +18 -0
- package/src/domains/shared/packages.ts +76 -0
- package/src/domains/shared/prefixes.ts +37 -0
- package/src/domains/shared/runtime.ts +62 -0
- package/src/domains/shared/types.test-d.ts +127 -0
- package/src/domains/shared/types.ts +348 -0
- package/src/domains/skill/commands/index.ts +2 -0
- package/src/domains/skill/commands/list.test.ts +111 -0
- package/src/domains/skill/commands/list.ts +69 -0
- package/src/domains/skill/formatters/index.ts +2 -0
- package/src/domains/skill/formatters/list.test.ts +140 -0
- package/src/domains/skill/formatters/list.ts +119 -0
- package/src/domains/skill/formatters/types.ts +8 -0
- package/src/domains/skill/helpers/index.ts +6 -0
- package/src/domains/skill/helpers/parseFrontmatter.test.ts +122 -0
- package/src/domains/skill/helpers/parseFrontmatter.ts +112 -0
- package/src/domains/skill/helpers/resolveSkillSources.ts +34 -0
- package/src/domains/skill/index.ts +19 -0
- package/src/domains/skill/mcp/index.ts +2 -0
- package/src/domains/skill/mcp/specs.ts +38 -0
- package/src/domains/skill/operations/discover.test.ts +145 -0
- package/src/domains/skill/operations/discover.ts +68 -0
- package/src/domains/skill/operations/index.ts +4 -0
- package/src/domains/skill/operations/list.test.ts +68 -0
- package/src/domains/skill/operations/list.ts +47 -0
- package/src/domains/skill/types.ts +25 -0
- package/src/domains/standard/commands/categories.test.ts +70 -0
- package/src/domains/standard/commands/categories.ts +48 -0
- package/src/domains/standard/commands/index.ts +5 -0
- package/src/domains/standard/commands/list.test.ts +105 -0
- package/src/domains/standard/commands/list.ts +81 -0
- package/src/domains/standard/commands/lookup.test.ts +135 -0
- package/src/domains/standard/commands/lookup.ts +127 -0
- package/src/domains/standard/formatters/categories.test.ts +44 -0
- package/src/domains/standard/formatters/categories.ts +38 -0
- package/src/domains/standard/formatters/index.ts +6 -0
- package/src/domains/standard/formatters/list.test.ts +166 -0
- package/src/domains/standard/formatters/list.ts +156 -0
- package/src/domains/standard/formatters/lookup.test.ts +95 -0
- package/src/domains/standard/formatters/lookup.ts +86 -0
- package/src/domains/standard/formatters/types.ts +31 -0
- package/src/domains/standard/index.ts +32 -0
- package/src/domains/standard/mcp/index.ts +2 -0
- package/src/domains/standard/mcp/specs.ts +197 -0
- package/src/domains/standard/operations/categories.test.ts +61 -0
- package/src/domains/standard/operations/categories.ts +38 -0
- package/src/domains/standard/operations/index.ts +5 -0
- package/src/domains/standard/operations/list.test.ts +75 -0
- package/src/domains/standard/operations/list.ts +64 -0
- package/src/domains/standard/operations/lookup.test.ts +58 -0
- package/src/domains/standard/operations/lookup.ts +142 -0
- package/src/domains/standard/orchestration/buildStandardFilters.ts +11 -0
- package/src/domains/standard/orchestration/index.ts +4 -0
- package/src/domains/standard/orchestration/resolveStandardList.ts +42 -0
- package/src/domains/standard/orchestration/resolveStandardLookup.ts +20 -0
- package/src/domains/standard/orchestration/standardEmptyError.ts +19 -0
- package/src/domains/standard/types.ts +15 -0
- package/src/domains/tier/commands/index.ts +3 -0
- package/src/domains/tier/commands/list.test.ts +67 -0
- package/src/domains/tier/commands/list.ts +43 -0
- package/src/domains/tier/formatters/index.ts +3 -0
- package/src/domains/tier/formatters/list.test.ts +33 -0
- package/src/domains/tier/formatters/list.ts +40 -0
- package/src/domains/tier/index.ts +17 -0
- package/src/domains/tier/mcp/index.ts +2 -0
- package/src/domains/tier/mcp/specs.ts +38 -0
- package/src/domains/tier/operations/index.ts +3 -0
- package/src/domains/tier/operations/list.test.ts +32 -0
- package/src/domains/tier/operations/list.ts +33 -0
- package/src/domains/token/commands/add-config.test.ts +68 -0
- package/src/domains/token/commands/add-config.ts +62 -0
- package/src/domains/token/commands/index.ts +5 -0
- package/src/domains/token/commands/list.test.ts +82 -0
- package/src/domains/token/commands/list.ts +45 -0
- package/src/domains/token/commands/lookup.test.ts +125 -0
- package/src/domains/token/commands/lookup.ts +121 -0
- package/src/domains/token/formatters/index.ts +4 -0
- package/src/domains/token/formatters/list.test.ts +37 -0
- package/src/domains/token/formatters/list.ts +37 -0
- package/src/domains/token/formatters/lookup.test.ts +61 -0
- package/src/domains/token/formatters/lookup.ts +72 -0
- package/src/domains/token/index.ts +32 -0
- package/src/domains/token/mcp/index.ts +2 -0
- package/src/domains/token/mcp/specs.ts +145 -0
- package/src/domains/token/operations/add-config.test.ts +68 -0
- package/src/domains/token/operations/add-config.ts +61 -0
- package/src/domains/token/operations/index.ts +7 -0
- package/src/domains/token/operations/list.test.ts +50 -0
- package/src/domains/token/operations/list.ts +52 -0
- package/src/domains/token/operations/lookup.test.ts +42 -0
- package/src/domains/token/operations/lookup.ts +66 -0
- package/src/domains/token/orchestration/index.ts +3 -0
- package/src/domains/token/orchestration/resolveTokenList.ts +17 -0
- package/src/domains/token/orchestration/resolveTokenLookup.ts +20 -0
- package/src/domains/token/orchestration/tokenEmptyError.ts +17 -0
- package/src/domains/token/types.ts +6 -0
- package/src/error/PragmaError.test.ts +121 -0
- package/src/error/PragmaError.ts +164 -0
- package/src/error/constants.ts +12 -0
- package/src/error/index.ts +4 -0
- package/src/error/types.ts +41 -0
- package/src/index.ts +141 -0
- package/src/mcp/createMcpServer.test.ts +41 -0
- package/src/mcp/createMcpServer.ts +53 -0
- package/src/mcp/error/buildRecovery.test.ts +37 -0
- package/src/mcp/error/buildRecovery.ts +17 -0
- package/src/mcp/error/index.ts +12 -0
- package/src/mcp/error/serializeError.test.ts +121 -0
- package/src/mcp/error/serializeError.ts +31 -0
- package/src/mcp/error/serializeErrorPayload.test.ts +38 -0
- package/src/mcp/error/serializeErrorPayload.ts +27 -0
- package/src/mcp/error/types.ts +51 -0
- package/src/mcp/index.ts +15 -0
- package/src/mcp/registerResources.test.ts +236 -0
- package/src/mcp/registerResources.ts +303 -0
- package/src/mcp/runMcpServer.test.ts +66 -0
- package/src/mcp/runMcpServer.ts +24 -0
- package/src/mcp/tools/index.ts +55 -0
- package/src/mcp/tools/registerFromSpec.ts +97 -0
- package/src/mcp/tools/registerTools.test.ts +1124 -0
- package/src/mcp/types.ts +62 -0
- package/src/mcp/utils/estimateTokens.test.ts +14 -0
- package/src/mcp/utils/estimateTokens.ts +9 -0
- package/src/mcp/utils/index.ts +11 -0
- package/src/mcp/utils/wrapTool.test.ts +108 -0
- package/src/mcp/utils/wrapTool.ts +81 -0
- package/src/package-manager/constants.ts +29 -0
- package/src/package-manager/detectInstallSource.test.ts +23 -0
- package/src/package-manager/detectInstallSource.ts +111 -0
- package/src/package-manager/detectLocalInstall.test.ts +16 -0
- package/src/package-manager/detectLocalInstall.ts +43 -0
- package/src/package-manager/detectPackageManager.test.ts +81 -0
- package/src/package-manager/detectPackageManager.ts +30 -0
- package/src/package-manager/index.ts +6 -0
- package/src/package-manager/types.ts +12 -0
- package/src/pipeline/collectCommands.test.ts +37 -0
- package/src/pipeline/collectCommands.ts +47 -0
- package/src/pipeline/constants.ts +14 -0
- package/src/pipeline/createProgram.test.ts +112 -0
- package/src/pipeline/createProgram.ts +70 -0
- package/src/pipeline/formatTerminal.test.ts +43 -0
- package/src/pipeline/formatTerminal.ts +53 -0
- package/src/pipeline/index.ts +19 -0
- package/src/pipeline/mapExitCode.test.ts +41 -0
- package/src/pipeline/mapExitCode.ts +12 -0
- package/src/pipeline/parseGlobalFlags.ts +21 -0
- package/src/pipeline/renderError.test.ts +151 -0
- package/src/pipeline/renderError.ts +114 -0
- package/src/pipeline/resolveCommandKind.test.ts +68 -0
- package/src/pipeline/resolveCommandKind.ts +71 -0
- package/src/pipeline/runCli.orchestration.test.ts +418 -0
- package/src/pipeline/runCli.test.ts +70 -0
- package/src/pipeline/runCli.ts +215 -0
- package/src/pipeline/types.ts +17 -0
- package/src/testing/cli.ts +43 -0
- package/src/testing/createTestMcpClient.ts +64 -0
- package/src/testing/dsFixtures.ts +506 -0
- package/src/testing/fixtures/canonical-config.json +4 -0
- package/src/testing/fixtures/canonical.ttl +437 -0
- package/src/testing/fixtures/filtered-config.json +4 -0
- package/src/testing/fixtures.ts +34 -0
- package/src/testing/helpers/assertParity.ts +28 -0
- package/src/testing/helpers/createTestMcpClient.ts +40 -0
- package/src/testing/helpers/createTestRuntime.ts +67 -0
- package/src/testing/index.ts +8 -0
- package/src/testing/integration/agent-session.test.ts +148 -0
- package/src/testing/integration/boot.test.ts +67 -0
- package/src/testing/integration/mcp-surface.test.ts +574 -0
- package/src/testing/integration/parity.test.ts +192 -0
- package/src/testing/store.ts +39 -0
- package/src/testing/types.ts +20 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Store } from "@canonical/ke";
|
|
2
|
+
import { PragmaError } from "#error";
|
|
3
|
+
import type { TierEntry } from "../../shared/types.js";
|
|
4
|
+
import { listTiers } from "../../tier/operations/index.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Validate a tier path against the ke store ontology.
|
|
8
|
+
*
|
|
9
|
+
* @param store - The booted ke store.
|
|
10
|
+
* @param tierPath - The tier path string to validate.
|
|
11
|
+
* @returns The matching TierEntry.
|
|
12
|
+
* @throws PragmaError.invalidInput if the tier path does not exist in the ontology.
|
|
13
|
+
* @note Queries ke store
|
|
14
|
+
*/
|
|
15
|
+
export default async function validateTier(
|
|
16
|
+
store: Store,
|
|
17
|
+
tierPath: string,
|
|
18
|
+
): Promise<TierEntry> {
|
|
19
|
+
const tiers = await listTiers(store);
|
|
20
|
+
const match = tiers.find((t) => t.path === tierPath);
|
|
21
|
+
|
|
22
|
+
if (!match) {
|
|
23
|
+
const validPaths = tiers.map((t) => t.path);
|
|
24
|
+
throw PragmaError.invalidInput("tier", tierPath, {
|
|
25
|
+
validOptions: validPaths,
|
|
26
|
+
recovery: {
|
|
27
|
+
message: "Reset tier configuration.",
|
|
28
|
+
cli: "pragma config tier --reset",
|
|
29
|
+
mcp: { tool: "config_tier", params: { reset: true } },
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return match;
|
|
35
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { CommandContext, CommandDefinition } from "@canonical/cli-core";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { PragmaError } from "#error";
|
|
4
|
+
import buildComponentCommand from "./component.js";
|
|
5
|
+
|
|
6
|
+
const ctx: CommandContext = {
|
|
7
|
+
cwd: "/tmp",
|
|
8
|
+
globalFlags: { llm: false, format: "text" as const, verbose: false },
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const llmCtx: CommandContext = {
|
|
12
|
+
cwd: "/tmp",
|
|
13
|
+
globalFlags: { llm: true, format: "text" as const, verbose: false },
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const jsonCtx: CommandContext = {
|
|
17
|
+
cwd: "/tmp",
|
|
18
|
+
globalFlags: { llm: false, format: "json" as const, verbose: false },
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
async function executeOutput(
|
|
22
|
+
cmd: CommandDefinition,
|
|
23
|
+
params: Record<string, unknown>,
|
|
24
|
+
context: CommandContext,
|
|
25
|
+
): Promise<{ value: unknown; text: string }> {
|
|
26
|
+
const result = await cmd.execute(params, context);
|
|
27
|
+
expect(result.tag).toBe("output");
|
|
28
|
+
if (result.tag !== "output") throw new Error("Expected output result");
|
|
29
|
+
const text = result.render.plain(result.value);
|
|
30
|
+
return { value: result.value, text };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe("buildComponentCommand", () => {
|
|
34
|
+
it("has correct path", () => {
|
|
35
|
+
const cmd = buildComponentCommand();
|
|
36
|
+
expect(cmd.path).toEqual(["create", "component"]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("includes framework as positional required select parameter", () => {
|
|
40
|
+
const cmd = buildComponentCommand();
|
|
41
|
+
const framework = cmd.parameters.find((p) => p.name === "framework");
|
|
42
|
+
expect(framework).toBeDefined();
|
|
43
|
+
expect(framework?.positional).toBe(true);
|
|
44
|
+
expect(framework?.required).toBe(true);
|
|
45
|
+
expect(framework?.type).toBe("select");
|
|
46
|
+
expect(framework?.choices?.map((c) => c.value)).toEqual([
|
|
47
|
+
"react",
|
|
48
|
+
"svelte",
|
|
49
|
+
"lit",
|
|
50
|
+
]);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("includes prompt-derived parameters", () => {
|
|
54
|
+
const cmd = buildComponentCommand();
|
|
55
|
+
const names = cmd.parameters.map((p) => p.name);
|
|
56
|
+
expect(names).toContain("componentPath");
|
|
57
|
+
expect(names).toContain("withStyles");
|
|
58
|
+
expect(names).toContain("withStories");
|
|
59
|
+
expect(names).toContain("withSsrTests");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("includes execution-mode parameters", () => {
|
|
63
|
+
const cmd = buildComponentCommand();
|
|
64
|
+
const names = cmd.parameters.map((p) => p.name);
|
|
65
|
+
expect(names).toContain("dryRun");
|
|
66
|
+
expect(names).toContain("yes");
|
|
67
|
+
expect(names).toContain("showFiles");
|
|
68
|
+
expect(names).toContain("preview");
|
|
69
|
+
expect(names).toContain("generatedStamp");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("dry-run with react returns output with file paths", async () => {
|
|
73
|
+
const cmd = buildComponentCommand();
|
|
74
|
+
const { text } = await executeOutput(
|
|
75
|
+
cmd,
|
|
76
|
+
{
|
|
77
|
+
framework: "react",
|
|
78
|
+
componentPath: "src/components/Button",
|
|
79
|
+
dryRun: true,
|
|
80
|
+
yes: true,
|
|
81
|
+
},
|
|
82
|
+
ctx,
|
|
83
|
+
);
|
|
84
|
+
expect(text).toContain("Button");
|
|
85
|
+
expect(text).toContain("src/components/Button");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("dry-run with svelte returns output with svelte files", async () => {
|
|
89
|
+
const cmd = buildComponentCommand();
|
|
90
|
+
const { text } = await executeOutput(
|
|
91
|
+
cmd,
|
|
92
|
+
{
|
|
93
|
+
framework: "svelte",
|
|
94
|
+
componentPath: "src/lib/components/Toggle",
|
|
95
|
+
dryRun: true,
|
|
96
|
+
yes: true,
|
|
97
|
+
},
|
|
98
|
+
ctx,
|
|
99
|
+
);
|
|
100
|
+
expect(text).toContain("Toggle");
|
|
101
|
+
expect(text).toContain("src/lib/components/Toggle");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("LLM mode returns markdown", async () => {
|
|
105
|
+
const cmd = buildComponentCommand();
|
|
106
|
+
const { text } = await executeOutput(
|
|
107
|
+
cmd,
|
|
108
|
+
{
|
|
109
|
+
framework: "react",
|
|
110
|
+
componentPath: "src/components/Card",
|
|
111
|
+
},
|
|
112
|
+
llmCtx,
|
|
113
|
+
);
|
|
114
|
+
// LLM markdown output includes generator name header
|
|
115
|
+
expect(text).toContain("component/react");
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("JSON mode returns parseable JSON", async () => {
|
|
119
|
+
const cmd = buildComponentCommand();
|
|
120
|
+
const { text } = await executeOutput(
|
|
121
|
+
cmd,
|
|
122
|
+
{
|
|
123
|
+
framework: "react",
|
|
124
|
+
componentPath: "src/components/Card",
|
|
125
|
+
},
|
|
126
|
+
jsonCtx,
|
|
127
|
+
);
|
|
128
|
+
const data = JSON.parse(text);
|
|
129
|
+
expect(data.generator.name).toBe("component/react");
|
|
130
|
+
expect(Array.isArray(data.plan)).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("throws PragmaError for invalid framework", async () => {
|
|
134
|
+
const cmd = buildComponentCommand();
|
|
135
|
+
await expect(cmd.execute({ framework: "angular" }, ctx)).rejects.toThrow(
|
|
136
|
+
PragmaError,
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("throws PragmaError when framework is missing", async () => {
|
|
141
|
+
const cmd = buildComponentCommand();
|
|
142
|
+
await expect(cmd.execute({}, ctx)).rejects.toThrow(PragmaError);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("returns interactive result when required answers are missing", async () => {
|
|
146
|
+
const cmd = buildComponentCommand();
|
|
147
|
+
// framework provided but componentPath has a default, so it should NOT
|
|
148
|
+
// trigger interactive mode — all prompts have defaults
|
|
149
|
+
const result = await cmd.execute({ framework: "lit", dryRun: true }, ctx);
|
|
150
|
+
// componentPath has a default, so executeGenerator applies it and proceeds
|
|
151
|
+
expect(result.tag).toBe("output");
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("has parameter groups", () => {
|
|
155
|
+
const cmd = buildComponentCommand();
|
|
156
|
+
expect(cmd.parameterGroups).toEqual({
|
|
157
|
+
Component: ["componentPath"],
|
|
158
|
+
Options: ["withStyles", "withStories", "withSsrTests"],
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("has examples in meta", () => {
|
|
163
|
+
const cmd = buildComponentCommand();
|
|
164
|
+
expect(cmd.meta?.examples?.length).toBeGreaterThan(0);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CommandDefinition,
|
|
3
|
+
executeGenerator,
|
|
4
|
+
type ParameterDefinition,
|
|
5
|
+
promptToParameter,
|
|
6
|
+
} from "@canonical/cli-core";
|
|
7
|
+
import { generators } from "@canonical/summon-component";
|
|
8
|
+
import type { AnyGenerator } from "@canonical/summon-core";
|
|
9
|
+
import { PragmaError } from "#error";
|
|
10
|
+
|
|
11
|
+
const FRAMEWORK_CHOICES = [
|
|
12
|
+
{ label: "react", value: "react" },
|
|
13
|
+
{ label: "svelte", value: "svelte" },
|
|
14
|
+
{ label: "lit", value: "lit" },
|
|
15
|
+
] as const;
|
|
16
|
+
|
|
17
|
+
const GENERATOR_MAP: Record<string, AnyGenerator> = {
|
|
18
|
+
react: generators["component/react"],
|
|
19
|
+
svelte: generators["component/svelte"],
|
|
20
|
+
lit: generators["component/lit"],
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/** Reference generator used to derive shared prompt parameters. */
|
|
24
|
+
const referenceGenerator = generators["component/react"];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Build the `pragma create component` command definition.
|
|
28
|
+
*
|
|
29
|
+
* Uses a dispatch pattern: `framework` is a required positional select
|
|
30
|
+
* parameter. The execute function looks up the matching generator and
|
|
31
|
+
* delegates to `executeGenerator` from cli-core.
|
|
32
|
+
*
|
|
33
|
+
* @returns The command definition for `pragma create component`.
|
|
34
|
+
* @note Impure
|
|
35
|
+
*/
|
|
36
|
+
export default function buildComponentCommand(): CommandDefinition {
|
|
37
|
+
const frameworkParam: ParameterDefinition = {
|
|
38
|
+
name: "framework",
|
|
39
|
+
description: "Component framework (react, svelte, lit)",
|
|
40
|
+
type: "select",
|
|
41
|
+
choices: [...FRAMEWORK_CHOICES],
|
|
42
|
+
positional: true,
|
|
43
|
+
required: true,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Derive prompt parameters from the reference generator
|
|
47
|
+
const promptParams = referenceGenerator.prompts.map(promptToParameter);
|
|
48
|
+
|
|
49
|
+
// Execution-mode parameters (same as generatorToCommand appends)
|
|
50
|
+
const execParams: ParameterDefinition[] = [
|
|
51
|
+
{
|
|
52
|
+
name: "dryRun",
|
|
53
|
+
description: "Preview without writing files",
|
|
54
|
+
type: "boolean",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "undo",
|
|
58
|
+
description: "Reverse a previously generated component",
|
|
59
|
+
type: "boolean",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "yes",
|
|
63
|
+
description: "Skip confirmation prompts",
|
|
64
|
+
type: "boolean",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "showFiles",
|
|
68
|
+
description: "Show file contents in dry-run",
|
|
69
|
+
type: "boolean",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "preview",
|
|
73
|
+
description: "Show file preview before writing",
|
|
74
|
+
type: "boolean",
|
|
75
|
+
default: true,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: "generatedStamp",
|
|
79
|
+
description: "Add generated file stamps",
|
|
80
|
+
type: "boolean",
|
|
81
|
+
default: true,
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
const parameters = [frameworkParam, ...promptParams, ...execParams];
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
path: ["create", "component"],
|
|
89
|
+
description:
|
|
90
|
+
"Generate a component with TypeScript, tests, stories, and styles",
|
|
91
|
+
parameters,
|
|
92
|
+
execute: async (params, ctx) => {
|
|
93
|
+
const framework = params.framework as string | undefined;
|
|
94
|
+
if (!framework) {
|
|
95
|
+
throw PragmaError.invalidInput("framework", "(missing)", {
|
|
96
|
+
validOptions: ["react", "svelte", "lit"],
|
|
97
|
+
recovery: {
|
|
98
|
+
message: "Provide a framework for component generation.",
|
|
99
|
+
cli: "pragma create component react --component-path src/components/Button",
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const gen = GENERATOR_MAP[framework];
|
|
105
|
+
if (!gen) {
|
|
106
|
+
throw PragmaError.invalidInput("framework", framework, {
|
|
107
|
+
validOptions: Object.keys(GENERATOR_MAP),
|
|
108
|
+
recovery: {
|
|
109
|
+
message: `Valid frameworks: ${Object.keys(GENERATOR_MAP).join(", ")}`,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return executeGenerator(gen, params, ctx);
|
|
115
|
+
},
|
|
116
|
+
meta: {
|
|
117
|
+
examples: [
|
|
118
|
+
"pragma create component react --component-path src/components/Button",
|
|
119
|
+
"pragma create component svelte --component-path src/lib/components/Toggle",
|
|
120
|
+
"pragma create component lit --component-path src/lib/Accordion",
|
|
121
|
+
"pragma create component react --component-path src/components/Button --dry-run",
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
parameterGroups: {
|
|
125
|
+
Component: ["componentPath"],
|
|
126
|
+
Options: ["withStyles", "withStories", "withSsrTests"],
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { CommandContext } from "@canonical/cli-core";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import buildPackageCommand from "./package.js";
|
|
4
|
+
|
|
5
|
+
const ctx: CommandContext = {
|
|
6
|
+
cwd: "/tmp",
|
|
7
|
+
globalFlags: { llm: false, format: "text" as const, verbose: false },
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
describe("buildPackageCommand", () => {
|
|
11
|
+
it("has correct path", () => {
|
|
12
|
+
const cmd = buildPackageCommand();
|
|
13
|
+
expect(cmd.path).toEqual(["create", "package"]);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("dry-run with all params returns output", async () => {
|
|
17
|
+
const cmd = buildPackageCommand();
|
|
18
|
+
const result = await cmd.execute(
|
|
19
|
+
{
|
|
20
|
+
name: "@canonical/test-pkg",
|
|
21
|
+
type: "tool-ts",
|
|
22
|
+
dryRun: true,
|
|
23
|
+
yes: true,
|
|
24
|
+
},
|
|
25
|
+
ctx,
|
|
26
|
+
);
|
|
27
|
+
expect(result.tag).toBe("output");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("with missing required params returns interactive", async () => {
|
|
31
|
+
const cmd = buildPackageCommand();
|
|
32
|
+
const result = await cmd.execute({}, ctx);
|
|
33
|
+
expect(result.tag).toBe("interactive");
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CommandDefinition,
|
|
3
|
+
generatorToCommand,
|
|
4
|
+
} from "@canonical/cli-core";
|
|
5
|
+
import { generators as packageGenerators } from "@canonical/summon-package";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Build the `pragma create package` command definition by bridging
|
|
9
|
+
* the package generator via `generatorToCommand`.
|
|
10
|
+
*
|
|
11
|
+
* @returns The command definition for `pragma create package`.
|
|
12
|
+
* @throws Error if the package generator is not found.
|
|
13
|
+
* @note Impure
|
|
14
|
+
*/
|
|
15
|
+
export default function buildPackageCommand(): CommandDefinition {
|
|
16
|
+
const gen = packageGenerators.package;
|
|
17
|
+
if (!gen) {
|
|
18
|
+
throw new Error("Package generator not found in @canonical/summon-package");
|
|
19
|
+
}
|
|
20
|
+
return generatorToCommand(["create", "package"], gen);
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** @module Create domain -- generator commands for `pragma create` (component and package). */
|
|
2
|
+
|
|
3
|
+
import type { CommandDefinition } from "@canonical/cli-core";
|
|
4
|
+
import { componentCommand, packageCommand } from "./commands/index.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Return all create command definitions.
|
|
8
|
+
*
|
|
9
|
+
* @returns An array of CommandDefinitions for component and package generators.
|
|
10
|
+
*/
|
|
11
|
+
export function commands(): CommandDefinition[] {
|
|
12
|
+
return [componentCommand(), packageCommand()];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { specs as mcpSpecs } from "./mcp/index.js";
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool specs for create domain — create_component, create_package.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { executeGenerator } from "@canonical/cli-core";
|
|
6
|
+
import { generators as componentGenerators } from "@canonical/summon-component";
|
|
7
|
+
import type { AnyGenerator } from "@canonical/summon-core";
|
|
8
|
+
import { generators as packageGenerators } from "@canonical/summon-package";
|
|
9
|
+
import { PragmaError } from "#error";
|
|
10
|
+
import type { ToolSpec } from "../../shared/ToolSpec.js";
|
|
11
|
+
|
|
12
|
+
const componentGeneratorMap: Record<string, AnyGenerator> = {
|
|
13
|
+
react: componentGenerators["component/react"],
|
|
14
|
+
svelte: componentGenerators["component/svelte"],
|
|
15
|
+
lit: componentGenerators["component/lit"],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const specs: readonly ToolSpec[] = [
|
|
19
|
+
{
|
|
20
|
+
name: "create_component",
|
|
21
|
+
description:
|
|
22
|
+
"Generate a design system component with TypeScript, tests, stories, and styles. Returns a JSON generation plan (dry-run).",
|
|
23
|
+
params: {
|
|
24
|
+
framework: {
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "Component framework",
|
|
27
|
+
optional: false,
|
|
28
|
+
enum: ["react", "svelte", "lit"],
|
|
29
|
+
},
|
|
30
|
+
componentPath: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description:
|
|
33
|
+
"Path for the component directory (e.g. 'src/components/Button')",
|
|
34
|
+
optional: false,
|
|
35
|
+
},
|
|
36
|
+
withStyles: {
|
|
37
|
+
type: "boolean",
|
|
38
|
+
description: "Include CSS styles (default: true)",
|
|
39
|
+
optional: true,
|
|
40
|
+
},
|
|
41
|
+
withStories: {
|
|
42
|
+
type: "boolean",
|
|
43
|
+
description: "Include Storybook stories (default: true)",
|
|
44
|
+
optional: true,
|
|
45
|
+
},
|
|
46
|
+
withSsrTests: {
|
|
47
|
+
type: "boolean",
|
|
48
|
+
description: "Include SSR tests (default: true)",
|
|
49
|
+
optional: true,
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
readOnly: false,
|
|
53
|
+
destructive: false,
|
|
54
|
+
async execute(rt, params) {
|
|
55
|
+
const batchCtx = {
|
|
56
|
+
cwd: rt.cwd,
|
|
57
|
+
globalFlags: {
|
|
58
|
+
llm: false,
|
|
59
|
+
format: "json" as const,
|
|
60
|
+
verbose: false,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const framework = params.framework as string;
|
|
65
|
+
const gen = componentGeneratorMap[framework];
|
|
66
|
+
if (!gen) {
|
|
67
|
+
throw PragmaError.invalidInput("framework", framework, {
|
|
68
|
+
validOptions: Object.keys(componentGeneratorMap),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const genParams: Record<string, unknown> = {
|
|
73
|
+
componentPath: params.componentPath,
|
|
74
|
+
...(params.withStyles !== undefined && {
|
|
75
|
+
withStyles: params.withStyles,
|
|
76
|
+
}),
|
|
77
|
+
...(params.withStories !== undefined && {
|
|
78
|
+
withStories: params.withStories,
|
|
79
|
+
}),
|
|
80
|
+
...(params.withSsrTests !== undefined && {
|
|
81
|
+
withSsrTests: params.withSsrTests,
|
|
82
|
+
}),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const result = await executeGenerator(gen, genParams, batchCtx);
|
|
86
|
+
if (result.tag === "output") {
|
|
87
|
+
const text = result.render.plain(result.value);
|
|
88
|
+
return { data: JSON.parse(text) };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
throw PragmaError.invalidInput(
|
|
92
|
+
"componentPath",
|
|
93
|
+
String(params.componentPath),
|
|
94
|
+
);
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "create_package",
|
|
99
|
+
description:
|
|
100
|
+
"Generate a new npm package with proper configuration. Returns a JSON generation plan (dry-run).",
|
|
101
|
+
params: {
|
|
102
|
+
name: {
|
|
103
|
+
type: "string",
|
|
104
|
+
description: "Full package name (e.g. '@canonical/my-package')",
|
|
105
|
+
optional: false,
|
|
106
|
+
},
|
|
107
|
+
type: {
|
|
108
|
+
type: "string",
|
|
109
|
+
description: "Package type",
|
|
110
|
+
optional: false,
|
|
111
|
+
enum: ["tool-ts", "library", "css"],
|
|
112
|
+
},
|
|
113
|
+
description: {
|
|
114
|
+
type: "string",
|
|
115
|
+
description: "Package description",
|
|
116
|
+
optional: true,
|
|
117
|
+
},
|
|
118
|
+
withReact: {
|
|
119
|
+
type: "boolean",
|
|
120
|
+
description: "Add React dependencies (default: false)",
|
|
121
|
+
optional: true,
|
|
122
|
+
},
|
|
123
|
+
withStorybook: {
|
|
124
|
+
type: "boolean",
|
|
125
|
+
description: "Add Storybook config (default: false)",
|
|
126
|
+
optional: true,
|
|
127
|
+
},
|
|
128
|
+
withCli: {
|
|
129
|
+
type: "boolean",
|
|
130
|
+
description: "Add CLI entry point (default: false)",
|
|
131
|
+
optional: true,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
readOnly: false,
|
|
135
|
+
destructive: false,
|
|
136
|
+
async execute(rt, params) {
|
|
137
|
+
const batchCtx = {
|
|
138
|
+
cwd: rt.cwd,
|
|
139
|
+
globalFlags: {
|
|
140
|
+
llm: false,
|
|
141
|
+
format: "json" as const,
|
|
142
|
+
verbose: false,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const gen = packageGenerators.package as AnyGenerator | undefined;
|
|
147
|
+
if (!gen) throw PragmaError.internalError("Package generator not found");
|
|
148
|
+
|
|
149
|
+
const genParams: Record<string, unknown> = {
|
|
150
|
+
name: params.name,
|
|
151
|
+
type: params.type,
|
|
152
|
+
...(params.description !== undefined && {
|
|
153
|
+
description: params.description,
|
|
154
|
+
}),
|
|
155
|
+
...(params.withReact !== undefined && { withReact: params.withReact }),
|
|
156
|
+
...(params.withStorybook !== undefined && {
|
|
157
|
+
withStorybook: params.withStorybook,
|
|
158
|
+
}),
|
|
159
|
+
...(params.withCli !== undefined && { withCli: params.withCli }),
|
|
160
|
+
runInstall: false,
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const result = await executeGenerator(gen, genParams, batchCtx);
|
|
164
|
+
if (result.tag === "output") {
|
|
165
|
+
const text = result.render.plain(result.value);
|
|
166
|
+
return { data: JSON.parse(text) };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
throw PragmaError.invalidInput("name", String(params.name));
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
export default specs;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
const { selectFormatterMock, runChecksMock } = vi.hoisted(() => ({
|
|
4
|
+
selectFormatterMock: vi.fn(
|
|
5
|
+
() => (data: { passed: number }) => `passed=${data.passed}`,
|
|
6
|
+
),
|
|
7
|
+
runChecksMock: vi.fn(),
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
vi.mock("../../shared/formatters.js", () => ({
|
|
11
|
+
selectFormatter: selectFormatterMock,
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
vi.mock("../operations/index.js", () => ({
|
|
15
|
+
runChecks: runChecksMock,
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
import doctorCommand from "./doctor.js";
|
|
19
|
+
|
|
20
|
+
describe("doctorCommand", () => {
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
vi.clearAllMocks();
|
|
23
|
+
process.exitCode = undefined;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("has path ['doctor']", () => {
|
|
27
|
+
expect(doctorCommand.path).toEqual(["doctor"]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("has a description", () => {
|
|
31
|
+
expect(doctorCommand.description).toBeTruthy();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("has no parameters", () => {
|
|
35
|
+
expect(doctorCommand.parameters).toEqual([]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("has an execute function", () => {
|
|
39
|
+
expect(typeof doctorCommand.execute).toBe("function");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("returns formatted output without setting an error exit code when checks pass", async () => {
|
|
43
|
+
runChecksMock.mockResolvedValue({ checks: [], passed: 2, failed: 0 });
|
|
44
|
+
|
|
45
|
+
const result = await doctorCommand.execute(
|
|
46
|
+
{},
|
|
47
|
+
{
|
|
48
|
+
cwd: "/workspace",
|
|
49
|
+
globalFlags: { llm: false, format: "text", verbose: false },
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
expect(runChecksMock).toHaveBeenCalledWith({ cwd: "/workspace" });
|
|
54
|
+
expect(result.tag).toBe("output");
|
|
55
|
+
if (result.tag === "output") {
|
|
56
|
+
expect(result.render.plain(result.value)).toBe("passed=2");
|
|
57
|
+
}
|
|
58
|
+
expect(process.exitCode).toBeUndefined();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("sets exitCode when checks fail", async () => {
|
|
62
|
+
runChecksMock.mockResolvedValue({ checks: [], passed: 1, failed: 1 });
|
|
63
|
+
|
|
64
|
+
await doctorCommand.execute(
|
|
65
|
+
{},
|
|
66
|
+
{
|
|
67
|
+
cwd: "/workspace",
|
|
68
|
+
globalFlags: { llm: true, format: "json", verbose: false },
|
|
69
|
+
},
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
expect(selectFormatterMock).toHaveBeenCalled();
|
|
73
|
+
expect(process.exitCode).toBe(1);
|
|
74
|
+
});
|
|
75
|
+
});
|