@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,68 @@
|
|
|
1
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import type { CommandContext } from "@canonical/cli-core";
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
import { PragmaError } from "#error";
|
|
7
|
+
import addConfigCommand from "./add-config.js";
|
|
8
|
+
|
|
9
|
+
function makeCtx(cwd: string): CommandContext {
|
|
10
|
+
return {
|
|
11
|
+
cwd,
|
|
12
|
+
globalFlags: {
|
|
13
|
+
llm: false,
|
|
14
|
+
format: "text",
|
|
15
|
+
verbose: false,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe("tokens add-config command", () => {
|
|
21
|
+
it("writes config file to cwd", async () => {
|
|
22
|
+
const cwd = mkdtempSync(join(tmpdir(), "pragma-test-"));
|
|
23
|
+
try {
|
|
24
|
+
const cmd = addConfigCommand();
|
|
25
|
+
const result = await cmd.execute({}, makeCtx(cwd));
|
|
26
|
+
expect(result.tag).toBe("output");
|
|
27
|
+
|
|
28
|
+
const content = readFileSync(join(cwd, "tokens.config.mjs"), "utf-8");
|
|
29
|
+
expect(content).toContain("defineConfig");
|
|
30
|
+
} finally {
|
|
31
|
+
rmSync(cwd, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("throws INVALID_INPUT when file already exists", async () => {
|
|
36
|
+
const cwd = mkdtempSync(join(tmpdir(), "pragma-test-"));
|
|
37
|
+
try {
|
|
38
|
+
writeFileSync(join(cwd, "tokens.config.mjs"), "// existing", "utf-8");
|
|
39
|
+
|
|
40
|
+
const cmd = addConfigCommand();
|
|
41
|
+
try {
|
|
42
|
+
await cmd.execute({}, makeCtx(cwd));
|
|
43
|
+
expect.fail("Should have thrown");
|
|
44
|
+
} catch (e) {
|
|
45
|
+
expect(e).toBeInstanceOf(PragmaError);
|
|
46
|
+
expect((e as PragmaError).code).toBe("INVALID_INPUT");
|
|
47
|
+
}
|
|
48
|
+
} finally {
|
|
49
|
+
rmSync(cwd, { recursive: true });
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("overwrites with --force", async () => {
|
|
54
|
+
const cwd = mkdtempSync(join(tmpdir(), "pragma-test-"));
|
|
55
|
+
try {
|
|
56
|
+
writeFileSync(join(cwd, "tokens.config.mjs"), "// old", "utf-8");
|
|
57
|
+
|
|
58
|
+
const cmd = addConfigCommand();
|
|
59
|
+
await cmd.execute({ force: true }, makeCtx(cwd));
|
|
60
|
+
|
|
61
|
+
const content = readFileSync(join(cwd, "tokens.config.mjs"), "utf-8");
|
|
62
|
+
expect(content).toContain("defineConfig");
|
|
63
|
+
expect(content).not.toContain("// old");
|
|
64
|
+
} finally {
|
|
65
|
+
rmSync(cwd, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wires the `pragma tokens add-config` CLI command.
|
|
3
|
+
*
|
|
4
|
+
* Generates a `tokens.config.mjs` file for the terrazzo token pipeline.
|
|
5
|
+
* Refuses to overwrite an existing config unless `--force` is passed.
|
|
6
|
+
*
|
|
7
|
+
* @note Impure
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { writeFileSync } from "node:fs";
|
|
11
|
+
import {
|
|
12
|
+
type CommandContext,
|
|
13
|
+
type CommandDefinition,
|
|
14
|
+
createOutputResult,
|
|
15
|
+
} from "@canonical/cli-core";
|
|
16
|
+
import { PragmaError } from "#error";
|
|
17
|
+
import { resolveAddConfig } from "../operations/index.js";
|
|
18
|
+
|
|
19
|
+
export default function addConfigCommand(): CommandDefinition {
|
|
20
|
+
return {
|
|
21
|
+
path: ["tokens", "add-config"],
|
|
22
|
+
description: "Generate a tokens.config.mjs for terrazzo",
|
|
23
|
+
parameters: [
|
|
24
|
+
{
|
|
25
|
+
name: "force",
|
|
26
|
+
description: "Overwrite existing config file",
|
|
27
|
+
type: "boolean",
|
|
28
|
+
default: false,
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
meta: {
|
|
32
|
+
examples: ["pragma tokens add-config"],
|
|
33
|
+
},
|
|
34
|
+
async execute(params: Record<string, unknown>, ctx: CommandContext) {
|
|
35
|
+
const force = (params.force as boolean) ?? false;
|
|
36
|
+
const result = resolveAddConfig(ctx.cwd);
|
|
37
|
+
|
|
38
|
+
if (result.alreadyExists && !force) {
|
|
39
|
+
throw PragmaError.invalidInput("tokens.config.mjs", "already exists", {
|
|
40
|
+
recovery: {
|
|
41
|
+
message: "Overwrite existing config file.",
|
|
42
|
+
cli: "pragma tokens add-config --force",
|
|
43
|
+
mcp: { tool: "tokens_add_config", params: { force: true } },
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
writeFileSync(result.configPath, result.configContent, "utf-8");
|
|
49
|
+
|
|
50
|
+
const lines: string[] = [];
|
|
51
|
+
lines.push(`Created ${result.configPath}`);
|
|
52
|
+
if (result.installHint) {
|
|
53
|
+
lines.push(result.installHint);
|
|
54
|
+
}
|
|
55
|
+
const message = lines.join("\n");
|
|
56
|
+
|
|
57
|
+
return createOutputResult(message, {
|
|
58
|
+
plain: () => message,
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { CommandOutputResult } from "@canonical/cli-core";
|
|
2
|
+
import type { Store } from "@canonical/ke";
|
|
3
|
+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
4
|
+
import { PragmaError } from "#error";
|
|
5
|
+
import { createTestStore, DS_ALL_TTL } from "#testing";
|
|
6
|
+
import type { PragmaContext } from "../../shared/context.js";
|
|
7
|
+
import listCommand from "./list.js";
|
|
8
|
+
|
|
9
|
+
let store: Store;
|
|
10
|
+
let cleanup: () => void;
|
|
11
|
+
|
|
12
|
+
beforeAll(async () => {
|
|
13
|
+
const result = await createTestStore({ ttl: DS_ALL_TTL });
|
|
14
|
+
store = result.store;
|
|
15
|
+
cleanup = result.cleanup;
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterAll(() => cleanup());
|
|
19
|
+
|
|
20
|
+
function makeCtx(
|
|
21
|
+
overrides?: Partial<PragmaContext["globalFlags"]>,
|
|
22
|
+
): PragmaContext {
|
|
23
|
+
return {
|
|
24
|
+
cwd: "/tmp",
|
|
25
|
+
store,
|
|
26
|
+
config: { tier: undefined, channel: "normal" },
|
|
27
|
+
globalFlags: {
|
|
28
|
+
llm: false,
|
|
29
|
+
format: "text",
|
|
30
|
+
verbose: false,
|
|
31
|
+
...overrides,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe("token list command", () => {
|
|
37
|
+
it("returns output result with all tokens", async () => {
|
|
38
|
+
const ctx = makeCtx();
|
|
39
|
+
const cmd = listCommand(ctx);
|
|
40
|
+
const result = await cmd.execute({}, ctx);
|
|
41
|
+
expect(result.tag).toBe("output");
|
|
42
|
+
|
|
43
|
+
const output = result as CommandOutputResult;
|
|
44
|
+
const text = output.render.plain(output.value);
|
|
45
|
+
expect(text).toContain("color.primary");
|
|
46
|
+
expect(text).toContain("spacing.sm");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("filters by --category", async () => {
|
|
50
|
+
const ctx = makeCtx();
|
|
51
|
+
const cmd = listCommand(ctx);
|
|
52
|
+
const result = await cmd.execute({ category: "Color" }, ctx);
|
|
53
|
+
expect(result.tag).toBe("output");
|
|
54
|
+
|
|
55
|
+
const output = result as CommandOutputResult;
|
|
56
|
+
const text = output.render.plain(output.value);
|
|
57
|
+
expect(text).toContain("color.primary");
|
|
58
|
+
expect(text).not.toContain("spacing.sm");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("throws EMPTY_RESULTS for non-matching category", async () => {
|
|
62
|
+
const ctx = makeCtx();
|
|
63
|
+
const cmd = listCommand(ctx);
|
|
64
|
+
try {
|
|
65
|
+
await cmd.execute({ category: "nonexistent" }, ctx);
|
|
66
|
+
expect.fail("Should have thrown");
|
|
67
|
+
} catch (e) {
|
|
68
|
+
expect(e).toBeInstanceOf(PragmaError);
|
|
69
|
+
expect((e as PragmaError).code).toBe("EMPTY_RESULTS");
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("renders LLM format with --llm", async () => {
|
|
74
|
+
const ctx = makeCtx({ llm: true });
|
|
75
|
+
const cmd = listCommand(ctx);
|
|
76
|
+
const result = await cmd.execute({}, ctx);
|
|
77
|
+
const output = result as CommandOutputResult;
|
|
78
|
+
const text = output.render.plain(output.value);
|
|
79
|
+
expect(text).toContain("## Design Tokens");
|
|
80
|
+
expect(text).toContain("**color.primary**");
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wires the `pragma token list` CLI command.
|
|
3
|
+
*
|
|
4
|
+
* Lists all design tokens with an optional `--category` filter.
|
|
5
|
+
* Throws a structured recovery error when no tokens match.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
type CommandDefinition,
|
|
10
|
+
createOutputResult,
|
|
11
|
+
} from "@canonical/cli-core";
|
|
12
|
+
import type { PragmaContext } from "../../shared/context.js";
|
|
13
|
+
import { selectFormatter } from "../../shared/formatters.js";
|
|
14
|
+
import { listFormatters } from "../formatters/index.js";
|
|
15
|
+
import { resolveTokenList } from "../orchestration/index.js";
|
|
16
|
+
|
|
17
|
+
export default function listCommand(ctx: PragmaContext): CommandDefinition {
|
|
18
|
+
return {
|
|
19
|
+
path: ["token", "list"],
|
|
20
|
+
description: "List all design tokens",
|
|
21
|
+
parameters: [
|
|
22
|
+
{
|
|
23
|
+
name: "category",
|
|
24
|
+
description: "Filter by token type (e.g., Color, Dimension)",
|
|
25
|
+
type: "string",
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
meta: {
|
|
29
|
+
examples: [
|
|
30
|
+
"pragma token list",
|
|
31
|
+
"pragma token list --category color",
|
|
32
|
+
"pragma token list --llm",
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
async execute(params: Record<string, unknown>) {
|
|
36
|
+
const resolution = await resolveTokenList(ctx, {
|
|
37
|
+
category: params.category as string | undefined,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return createOutputResult([...resolution.items], {
|
|
41
|
+
plain: selectFormatter(ctx, listFormatters),
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { CommandOutputResult } from "@canonical/cli-core";
|
|
2
|
+
import type { Store } from "@canonical/ke";
|
|
3
|
+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
4
|
+
import { createTestStore, DS_ALL_TTL } from "#testing";
|
|
5
|
+
import type { PragmaContext } from "../../shared/context.js";
|
|
6
|
+
import lookupCommand from "./lookup.js";
|
|
7
|
+
|
|
8
|
+
let store: Store;
|
|
9
|
+
let cleanup: () => void;
|
|
10
|
+
|
|
11
|
+
beforeAll(async () => {
|
|
12
|
+
const result = await createTestStore({ ttl: DS_ALL_TTL });
|
|
13
|
+
store = result.store;
|
|
14
|
+
cleanup = result.cleanup;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterAll(() => cleanup());
|
|
18
|
+
|
|
19
|
+
function makeCtx(
|
|
20
|
+
overrides?: Partial<PragmaContext["globalFlags"]>,
|
|
21
|
+
): PragmaContext {
|
|
22
|
+
return {
|
|
23
|
+
cwd: "/tmp",
|
|
24
|
+
store,
|
|
25
|
+
config: { tier: undefined, channel: "normal" },
|
|
26
|
+
globalFlags: {
|
|
27
|
+
llm: false,
|
|
28
|
+
format: "text",
|
|
29
|
+
verbose: false,
|
|
30
|
+
...overrides,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe("token lookup command", () => {
|
|
36
|
+
it("returns summary by default", async () => {
|
|
37
|
+
const ctx = makeCtx();
|
|
38
|
+
const cmd = lookupCommand(ctx);
|
|
39
|
+
const result = await cmd.execute({ names: ["color.primary"] }, ctx);
|
|
40
|
+
expect(result.tag).toBe("output");
|
|
41
|
+
|
|
42
|
+
const output = result as CommandOutputResult;
|
|
43
|
+
const text = output.render.plain(output.value);
|
|
44
|
+
expect(text).toContain("color.primary");
|
|
45
|
+
expect(text).toContain("Category: Color");
|
|
46
|
+
expect(text).not.toContain("Values:");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("returns values with --detailed", async () => {
|
|
50
|
+
const ctx = makeCtx();
|
|
51
|
+
const cmd = lookupCommand(ctx);
|
|
52
|
+
const result = await cmd.execute(
|
|
53
|
+
{ names: ["color.primary"], detailed: true },
|
|
54
|
+
ctx,
|
|
55
|
+
);
|
|
56
|
+
const output = result as CommandOutputResult;
|
|
57
|
+
const text = output.render.plain(output.value);
|
|
58
|
+
expect(text).toContain("Values:");
|
|
59
|
+
expect(text).toContain("light: #0066cc");
|
|
60
|
+
expect(text).toContain("dark: #4d9aff");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("throws ENTITY_NOT_FOUND for unknown token", async () => {
|
|
64
|
+
const ctx = makeCtx();
|
|
65
|
+
const cmd = lookupCommand(ctx);
|
|
66
|
+
const result = await cmd.execute({ names: ["nonexistent"] }, ctx);
|
|
67
|
+
expect(result.tag).toBe("output");
|
|
68
|
+
if (result.tag !== "output") {
|
|
69
|
+
expect.fail("Expected output result");
|
|
70
|
+
}
|
|
71
|
+
expect(result.render.plain(result.value)).toContain("Errors:");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("renders LLM format with --llm --detailed", async () => {
|
|
75
|
+
const ctx = makeCtx({ llm: true });
|
|
76
|
+
const cmd = lookupCommand(ctx);
|
|
77
|
+
const result = await cmd.execute(
|
|
78
|
+
{ names: ["color.primary"], detailed: true },
|
|
79
|
+
ctx,
|
|
80
|
+
);
|
|
81
|
+
const output = result as CommandOutputResult;
|
|
82
|
+
const text = output.render.plain(output.value);
|
|
83
|
+
expect(text).toContain("## color.primary");
|
|
84
|
+
expect(text).toContain("### Values");
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("renders JSON with --detailed", async () => {
|
|
88
|
+
const ctx = makeCtx({ format: "json" });
|
|
89
|
+
const cmd = lookupCommand(ctx);
|
|
90
|
+
const result = await cmd.execute(
|
|
91
|
+
{ names: ["color.primary"], detailed: true },
|
|
92
|
+
ctx,
|
|
93
|
+
);
|
|
94
|
+
const output = result as CommandOutputResult;
|
|
95
|
+
const text = output.render.plain(output.value);
|
|
96
|
+
const parsed = JSON.parse(text);
|
|
97
|
+
expect(parsed.name).toBe("color.primary");
|
|
98
|
+
expect(parsed.values).toHaveLength(2);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("renders JSON without --detailed (omits values)", async () => {
|
|
102
|
+
const ctx = makeCtx({ format: "json" });
|
|
103
|
+
const cmd = lookupCommand(ctx);
|
|
104
|
+
const result = await cmd.execute({ names: ["color.primary"] }, ctx);
|
|
105
|
+
const output = result as CommandOutputResult;
|
|
106
|
+
const text = output.render.plain(output.value);
|
|
107
|
+
const parsed = JSON.parse(text);
|
|
108
|
+
expect(parsed.name).toBe("color.primary");
|
|
109
|
+
expect(parsed.values).toBeUndefined();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("renders multiple tokens together", async () => {
|
|
113
|
+
const ctx = makeCtx();
|
|
114
|
+
const cmd = lookupCommand(ctx);
|
|
115
|
+
const result = await cmd.execute(
|
|
116
|
+
{ names: ["color.primary", "spacing.sm"] },
|
|
117
|
+
ctx,
|
|
118
|
+
);
|
|
119
|
+
expect(result.tag).toBe("output");
|
|
120
|
+
const output = result as CommandOutputResult;
|
|
121
|
+
const text = output.render.plain(output.value);
|
|
122
|
+
expect(text).toContain("color.primary");
|
|
123
|
+
expect(text).toContain("spacing.sm");
|
|
124
|
+
});
|
|
125
|
+
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wires the `pragma token lookup <name...>` CLI command.
|
|
3
|
+
*
|
|
4
|
+
* Retrieves detailed information for a single design token, including
|
|
5
|
+
* per-theme values when `--detailed` is passed.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
type CommandDefinition,
|
|
10
|
+
createOutputResult,
|
|
11
|
+
} from "@canonical/cli-core";
|
|
12
|
+
import type { PragmaContext } from "../../shared/context.js";
|
|
13
|
+
import type { LookupResult } from "../../shared/contracts.js";
|
|
14
|
+
import { createLookupFormatters } from "../formatters/index.js";
|
|
15
|
+
import type { lookupToken } from "../operations/index.js";
|
|
16
|
+
import { resolveTokenLookup } from "../orchestration/index.js";
|
|
17
|
+
|
|
18
|
+
interface TokenLookupOutput {
|
|
19
|
+
readonly result: LookupResult<Awaited<ReturnType<typeof lookupToken>>>;
|
|
20
|
+
readonly detailed: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default function buildLookupCommand(
|
|
24
|
+
ctx: PragmaContext,
|
|
25
|
+
): CommandDefinition {
|
|
26
|
+
return {
|
|
27
|
+
path: ["token", "lookup"],
|
|
28
|
+
description: "Look up detailed information for a design token",
|
|
29
|
+
parameters: [
|
|
30
|
+
{
|
|
31
|
+
name: "names",
|
|
32
|
+
description: "Token names or IRIs",
|
|
33
|
+
type: "multiselect",
|
|
34
|
+
positional: true,
|
|
35
|
+
required: true,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "detailed",
|
|
39
|
+
description: "Include values per theme",
|
|
40
|
+
type: "boolean",
|
|
41
|
+
default: false,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
meta: {
|
|
45
|
+
examples: [
|
|
46
|
+
"pragma token lookup color.primary",
|
|
47
|
+
"pragma token lookup color.primary spacing.sm",
|
|
48
|
+
"pragma token lookup color.primary --detailed",
|
|
49
|
+
"pragma token lookup color.primary --llm",
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
async execute(params: Record<string, unknown>) {
|
|
53
|
+
const names = normalizeNames(params.names, params.name);
|
|
54
|
+
const detailed = (params.detailed as boolean) ?? false;
|
|
55
|
+
const contract = await resolveTokenLookup(ctx.store, names);
|
|
56
|
+
|
|
57
|
+
return createOutputResult<TokenLookupOutput>(
|
|
58
|
+
{ result: contract.result, detailed },
|
|
59
|
+
{ plain: renderTokenLookupOutput(ctx) },
|
|
60
|
+
);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function normalizeNames(names: unknown, legacyName?: unknown): string[] {
|
|
66
|
+
if (Array.isArray(names)) {
|
|
67
|
+
return names.filter(
|
|
68
|
+
(name): name is string => typeof name === "string" && name.length > 0,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
if (typeof legacyName === "string" && legacyName.length > 0) {
|
|
72
|
+
return [legacyName];
|
|
73
|
+
}
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function renderTokenLookupOutput(
|
|
78
|
+
ctx: PragmaContext,
|
|
79
|
+
): (data: TokenLookupOutput) => string {
|
|
80
|
+
return ({ result, detailed }) => {
|
|
81
|
+
const formatters = createLookupFormatters({ detailed });
|
|
82
|
+
const formatOne =
|
|
83
|
+
ctx.globalFlags.format === "json"
|
|
84
|
+
? formatters.json
|
|
85
|
+
: ctx.globalFlags.llm
|
|
86
|
+
? formatters.llm
|
|
87
|
+
: formatters.plain;
|
|
88
|
+
|
|
89
|
+
if (ctx.globalFlags.format === "json") {
|
|
90
|
+
if (result.results.length === 1 && result.errors.length === 0) {
|
|
91
|
+
const only = result.results[0];
|
|
92
|
+
return only
|
|
93
|
+
? formatters.json(only)
|
|
94
|
+
: JSON.stringify({ results: [], errors: result.errors }, null, 2);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return JSON.stringify(
|
|
98
|
+
{
|
|
99
|
+
results: result.results.map((token) =>
|
|
100
|
+
JSON.parse(formatters.json(token)),
|
|
101
|
+
),
|
|
102
|
+
errors: result.errors,
|
|
103
|
+
},
|
|
104
|
+
null,
|
|
105
|
+
2,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const parts = result.results.map((token) => formatOne(token));
|
|
110
|
+
if (result.errors.length > 0) {
|
|
111
|
+
parts.push(
|
|
112
|
+
[
|
|
113
|
+
"Errors:",
|
|
114
|
+
...result.errors.map((error) => `- ${error.query}: ${error.message}`),
|
|
115
|
+
].join("\n"),
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return parts.join("\n\n");
|
|
120
|
+
};
|
|
121
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { URI } from "@canonical/ke";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import type { TokenSummary } from "../../shared/types.js";
|
|
4
|
+
import formatters from "./list.js";
|
|
5
|
+
|
|
6
|
+
const TOKENS: TokenSummary[] = [
|
|
7
|
+
{
|
|
8
|
+
uri: "http://example.com/t1" as URI,
|
|
9
|
+
name: "color.primary",
|
|
10
|
+
category: "Color",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
uri: "http://example.com/t2" as URI,
|
|
14
|
+
name: "spacing.sm",
|
|
15
|
+
category: "Dimension",
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
describe("token list formatters", () => {
|
|
20
|
+
it("plain renders name with category in brackets", () => {
|
|
21
|
+
const text = formatters.plain(TOKENS);
|
|
22
|
+
expect(text).toContain("color.primary [Color]");
|
|
23
|
+
expect(text).toContain("spacing.sm [Dimension]");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("plain omits brackets when category is empty", () => {
|
|
27
|
+
const text = formatters.plain([{ ...TOKENS[0], category: "" }]);
|
|
28
|
+
expect(text).not.toContain("[");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("llm renders markdown heading and bold names", () => {
|
|
32
|
+
const text = formatters.llm(TOKENS);
|
|
33
|
+
expect(text).toContain("## Design Tokens");
|
|
34
|
+
expect(text).toContain("**color.primary**");
|
|
35
|
+
expect(text).toContain("**spacing.sm**");
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Three-mode formatter for `pragma token list` output.
|
|
3
|
+
*
|
|
4
|
+
* - **plain** — one line per token showing name and optional category.
|
|
5
|
+
* - **llm** — condensed Markdown consumed by LLM agents and reused
|
|
6
|
+
* by the MCP adapter when `condensed: true`.
|
|
7
|
+
* - **json** — structured JSON array for programmatic consumption.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Formatters } from "../../shared/formatters.js";
|
|
11
|
+
import type { TokenSummary } from "../../shared/types.js";
|
|
12
|
+
|
|
13
|
+
const formatters: Formatters<TokenSummary[]> = {
|
|
14
|
+
plain: (tokens) => {
|
|
15
|
+
const lines: string[] = [];
|
|
16
|
+
for (const t of tokens) {
|
|
17
|
+
const cat = t.category ? ` [${t.category}]` : "";
|
|
18
|
+
lines.push(`${t.name}${cat}`);
|
|
19
|
+
}
|
|
20
|
+
return lines.join("\n");
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
llm: (tokens) => {
|
|
24
|
+
const lines: string[] = [];
|
|
25
|
+
lines.push("## Design Tokens");
|
|
26
|
+
lines.push("");
|
|
27
|
+
for (const t of tokens) {
|
|
28
|
+
const cat = t.category ? ` [${t.category}]` : "";
|
|
29
|
+
lines.push(`- **${t.name}**${cat}`);
|
|
30
|
+
}
|
|
31
|
+
return lines.join("\n");
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
json: (tokens) => JSON.stringify(tokens, null, 2),
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default formatters;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { URI } from "@canonical/ke";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import type { TokenDetailed } from "../../shared/types.js";
|
|
4
|
+
import { createLookupFormatters } from "./lookup.js";
|
|
5
|
+
|
|
6
|
+
const DETAILED: TokenDetailed = {
|
|
7
|
+
uri: "http://example.com/t1" as URI,
|
|
8
|
+
name: "color.primary",
|
|
9
|
+
category: "Color",
|
|
10
|
+
values: [
|
|
11
|
+
{ theme: "light", value: "#0066cc" },
|
|
12
|
+
{ theme: "dark", value: "#4d9aff" },
|
|
13
|
+
],
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
describe("token lookup formatters", () => {
|
|
17
|
+
describe("detailed: false", () => {
|
|
18
|
+
const fmt = createLookupFormatters({ detailed: false });
|
|
19
|
+
|
|
20
|
+
it("plain renders summary without values", () => {
|
|
21
|
+
const text = fmt.plain(DETAILED);
|
|
22
|
+
expect(text).toContain("color.primary");
|
|
23
|
+
expect(text).toContain("Category: Color");
|
|
24
|
+
expect(text).not.toContain("Values:");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("json omits values", () => {
|
|
28
|
+
const parsed = JSON.parse(fmt.json(DETAILED));
|
|
29
|
+
expect(parsed.name).toBe("color.primary");
|
|
30
|
+
expect(parsed.values).toBeUndefined();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("detailed: true", () => {
|
|
35
|
+
const fmt = createLookupFormatters({ detailed: true });
|
|
36
|
+
|
|
37
|
+
it("plain renders values", () => {
|
|
38
|
+
const text = fmt.plain(DETAILED);
|
|
39
|
+
expect(text).toContain("Values:");
|
|
40
|
+
expect(text).toContain(" light: #0066cc");
|
|
41
|
+
expect(text).toContain(" dark: #4d9aff");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("llm renders values section", () => {
|
|
45
|
+
const text = fmt.llm(DETAILED);
|
|
46
|
+
expect(text).toContain("### Values");
|
|
47
|
+
expect(text).toContain("- light: `#0066cc`");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("json includes values", () => {
|
|
51
|
+
const parsed = JSON.parse(fmt.json(DETAILED));
|
|
52
|
+
expect(parsed.values).toHaveLength(2);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("plain renders dash for empty category", () => {
|
|
57
|
+
const fmt = createLookupFormatters({ detailed: false });
|
|
58
|
+
const text = fmt.plain({ ...DETAILED, category: "" });
|
|
59
|
+
expect(text).toContain("Category: —");
|
|
60
|
+
});
|
|
61
|
+
});
|