@canonical/pragma-cli 0.20.0 → 0.21.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/dist/pragma +0 -0
- package/package.json +30 -18
- package/src/constants.ts +1 -1
- package/src/domains/block/blockConfig.ts +47 -3
- package/src/domains/block/commands/list.test.ts +1 -1
- package/src/domains/block/commands/list.ts +27 -0
- package/src/domains/block/commands/lookup.ts +26 -52
- package/src/domains/block/formatters/index.ts +1 -1
- package/src/domains/block/formatters/list.test.ts +1 -1
- package/src/domains/block/formatters/list.ts +28 -42
- package/src/domains/block/formatters/lookup.test.ts +3 -2
- package/src/domains/block/formatters/lookup.ts +91 -296
- package/src/domains/block/formatters/types.ts +1 -1
- package/src/domains/block/operations/list.test.ts +1 -1
- package/src/domains/block/operations/list.ts +1 -1
- package/src/domains/block/operations/lookup.test.ts +29 -8
- package/src/domains/block/operations/lookup.ts +94 -16
- package/src/domains/block/orchestration/blockEmptyError.ts +1 -1
- package/src/domains/block/orchestration/buildBlockFilters.ts +1 -1
- package/src/domains/block/orchestration/enrichBlocks.ts +6 -2
- package/src/domains/block/orchestration/resolveBlockList.ts +1 -1
- package/src/domains/block/orchestration/resolveBlockLookup.ts +8 -2
- package/src/domains/block/types.ts +1 -1
- package/src/domains/config/commands/channel.ts +6 -4
- package/src/domains/config/commands/tier.ts +6 -4
- package/src/domains/config/mcp/specs.ts +18 -6
- package/src/domains/config/operations/validateTier.ts +1 -1
- package/src/domains/config/tasks/index.ts +3 -0
- package/src/domains/config/tasks/setChannel.ts +30 -0
- package/src/domains/config/tasks/setTier.ts +33 -0
- package/src/domains/create/commands/package.test.ts +2 -2
- package/src/domains/doctor/mcp/index.ts +1 -1
- package/src/domains/doctor/mcp/specs.ts +2 -49
- package/src/domains/graph/commands/inspect.test.ts +1 -1
- package/src/domains/graph/formatters/inspect.ts +12 -7
- package/src/domains/graph/operations/inspectUri.ts +4 -1
- package/src/domains/info/commands/upgrade.ts +6 -3
- package/src/domains/info/index.ts +3 -1
- package/src/domains/info/mcp/index.ts +2 -0
- package/src/domains/info/mcp/specs.ts +65 -0
- package/src/domains/llm/data/commandReference.ts +4 -4
- package/src/domains/llm/data/decisionTrees.ts +14 -12
- package/src/domains/llm/operations/collectContext.ts +1 -1
- package/src/domains/modifier/commands/list.ts +9 -0
- package/src/domains/modifier/commands/lookup.ts +22 -42
- package/src/domains/modifier/formatters/index.ts +4 -1
- package/src/domains/modifier/formatters/list.test.ts +1 -1
- package/src/domains/modifier/formatters/list.ts +13 -26
- package/src/domains/modifier/formatters/lookup.test.ts +1 -1
- package/src/domains/modifier/formatters/lookup.ts +41 -29
- package/src/domains/modifier/index.ts +1 -0
- package/src/domains/modifier/modifierConfig.ts +36 -0
- package/src/domains/modifier/operations/list.ts +1 -1
- package/src/domains/modifier/operations/lookup.ts +4 -3
- package/src/domains/modifier/orchestration/resolveModifierLookup.ts +1 -1
- package/src/domains/modifier/types.ts +1 -1
- package/src/domains/ontology/commands/list.test.ts +1 -1
- package/src/domains/ontology/commands/list.ts +18 -0
- package/src/domains/ontology/commands/show.test.ts +1 -1
- package/src/domains/ontology/formatters/list.ts +5 -3
- package/src/domains/ontology/formatters/show.ts +38 -13
- package/src/domains/ontology/helpers/queryClasses.ts +1 -1
- package/src/domains/ontology/helpers/queryProperties.ts +1 -1
- package/src/domains/ontology/operations/listOntologies.ts +1 -1
- package/src/domains/ontology/operations/showOntology.ts +1 -1
- package/src/domains/setup/helpers/completionScripts.test.ts +3 -3
- package/src/domains/setup/helpers/completionScripts.ts +4 -4
- package/src/domains/shared/ToolSpec.ts +1 -1
- package/src/domains/shared/context.ts +3 -2
- package/src/domains/shared/contracts.ts +40 -1
- package/src/domains/shared/filters/buildFilterConfig.ts +1 -2
- package/src/domains/shared/filters/buildFilters.ts +1 -1
- package/src/domains/shared/filters/describeFilters.ts +1 -1
- package/src/domains/shared/formatters.ts +47 -0
- package/src/domains/shared/renderers.ts +410 -0
- package/src/domains/shared/runtime.ts +7 -22
- package/src/domains/shared/types/block.ts +107 -0
- package/src/domains/shared/types/common.ts +33 -0
- package/src/domains/shared/types/graph.ts +17 -0
- package/src/domains/shared/types/index.ts +49 -0
- package/src/domains/shared/types/modifier.ts +22 -0
- package/src/domains/shared/types/ontology.ts +50 -0
- package/src/domains/shared/types/runtime.ts +21 -0
- package/src/domains/shared/types/standard.ts +64 -0
- package/src/domains/shared/types/tier.ts +15 -0
- package/src/domains/shared/types/token.ts +30 -0
- package/src/domains/standard/commands/list.ts +9 -0
- package/src/domains/standard/commands/lookup.ts +22 -50
- package/src/domains/standard/formatters/categories.test.ts +1 -1
- package/src/domains/standard/formatters/categories.ts +1 -1
- package/src/domains/standard/formatters/index.ts +4 -1
- package/src/domains/standard/formatters/list.test.ts +4 -1
- package/src/domains/standard/formatters/list.ts +112 -84
- package/src/domains/standard/formatters/lookup.test.ts +1 -1
- package/src/domains/standard/formatters/lookup.ts +85 -70
- package/src/domains/standard/formatters/types.ts +1 -1
- package/src/domains/standard/index.ts +1 -0
- package/src/domains/standard/operations/categories.ts +1 -1
- package/src/domains/standard/operations/list.ts +1 -1
- package/src/domains/standard/operations/lookup.ts +1 -1
- package/src/domains/standard/orchestration/buildStandardFilters.ts +1 -1
- package/src/domains/standard/orchestration/resolveStandardList.ts +4 -1
- package/src/domains/standard/orchestration/resolveStandardLookup.ts +1 -1
- package/src/domains/standard/orchestration/standardEmptyError.ts +1 -1
- package/src/domains/standard/standardConfig.ts +42 -0
- package/src/domains/standard/types.ts +1 -1
- package/src/domains/tier/commands/list.ts +16 -0
- package/src/domains/tier/formatters/list.test.ts +1 -1
- package/src/domains/tier/formatters/list.ts +11 -6
- package/src/domains/tier/operations/list.ts +1 -1
- package/src/domains/token/commands/list.ts +9 -0
- package/src/domains/token/commands/lookup.ts +22 -48
- package/src/domains/token/formatters/index.ts +4 -1
- package/src/domains/token/formatters/list.test.ts +1 -1
- package/src/domains/token/formatters/list.ts +15 -28
- package/src/domains/token/formatters/lookup.test.ts +2 -2
- package/src/domains/token/formatters/lookup.ts +80 -45
- package/src/domains/token/index.ts +1 -0
- package/src/domains/token/operations/list.ts +1 -1
- package/src/domains/token/operations/lookup.ts +1 -1
- package/src/domains/token/orchestration/resolveTokenLookup.ts +1 -1
- package/src/domains/token/tokenConfig.ts +38 -0
- package/src/domains/token/types.ts +1 -1
- package/src/index.ts +1 -1
- package/src/mcp/runMcpServer.test.ts +2 -2
- package/src/mcp/tools/index.ts +2 -0
- package/src/mcp/tools/registerTools.test.ts +8 -3
- package/src/package-manager/types.ts +1 -3
- package/src/pipeline/createProgram.ts +20 -1
- package/src/pipeline/index.ts +4 -1
- package/src/pipeline/parseGlobalFlags.test.ts +92 -0
- package/src/pipeline/parseGlobalFlags.ts +25 -0
- package/src/pipeline/runCli.orchestration.test.ts +1 -0
- package/src/pipeline/runCli.ts +11 -4
- package/src/pipeline/runInteractiveCommand.ts +198 -0
- package/src/testing/cli.ts +2 -2
- package/src/testing/fixtures.ts +2 -2
- package/src/testing/integration/boot.test.ts +2 -2
- package/src/testing/integration/cli-user-stories.test.ts +198 -0
- package/src/testing/integration/edge-cases.test.ts +263 -0
- package/src/testing/integration/parity.test.ts +377 -27
- package/src/testing/store.ts +1 -1
- package/src/tui/components/BulletList/BulletList.tsx +46 -0
- package/src/tui/components/BulletList/index.ts +2 -0
- package/src/tui/components/BulletList/types.ts +6 -0
- package/src/tui/components/Card/Card.tsx +73 -0
- package/src/tui/components/Card/index.ts +1 -0
- package/src/tui/components/Card/types.ts +12 -0
- package/src/tui/components/CodeBlock/CodeBlock.tsx +37 -0
- package/src/tui/components/CodeBlock/index.ts +2 -0
- package/src/tui/components/CodeBlock/types.ts +6 -0
- package/src/tui/components/DataRow/DataRow.tsx +80 -0
- package/src/tui/components/DataRow/index.ts +2 -0
- package/src/tui/components/DataRow/types.ts +14 -0
- package/src/tui/components/FieldRow/FieldRow.tsx +24 -0
- package/src/tui/components/FieldRow/index.ts +2 -0
- package/src/tui/components/FieldRow/types.ts +10 -0
- package/src/tui/components/HeaderRow/HeaderRow.tsx +32 -0
- package/src/tui/components/HeaderRow/index.ts +2 -0
- package/src/tui/components/HeaderRow/types.ts +8 -0
- package/src/tui/components/MarkdownText/MarkdownText.tsx +19 -0
- package/src/tui/components/MarkdownText/index.ts +2 -0
- package/src/tui/components/MarkdownText/types.ts +4 -0
- package/src/tui/components/MiniTable/MiniTable.tsx +82 -0
- package/src/tui/components/MiniTable/index.ts +2 -0
- package/src/tui/components/MiniTable/types.ts +6 -0
- package/src/tui/components/SectionRenderer/SectionRenderer.tsx +91 -0
- package/src/tui/components/SectionRenderer/index.ts +2 -0
- package/src/tui/components/SectionRenderer/types.ts +15 -0
- package/src/tui/components/TreeView/TreeView.tsx +84 -0
- package/src/tui/components/TreeView/index.ts +2 -0
- package/src/tui/components/TreeView/types.ts +6 -0
- package/src/tui/components/index.ts +19 -0
- package/src/tui/constants.ts +39 -0
- package/src/tui/createListView.ts +23 -0
- package/src/tui/createLookupView.ts +26 -0
- package/src/tui/helpers/computeWidths.ts +53 -0
- package/src/tui/helpers/fitColumns.ts +33 -0
- package/src/tui/helpers/formatMarkdown.ts +19 -0
- package/src/tui/helpers/getTerminalSize.ts +16 -0
- package/src/tui/helpers/index.ts +6 -0
- package/src/tui/helpers/syntaxColor.ts +67 -0
- package/src/tui/helpers/truncateText.ts +12 -0
- package/src/tui/hooks/index.ts +3 -0
- package/src/tui/hooks/types.ts +7 -0
- package/src/tui/hooks/useAutoExit.ts +17 -0
- package/src/tui/hooks/useTerminalSize.ts +19 -0
- package/src/tui/index.ts +15 -0
- package/src/tui/renderInk.tsx +18 -0
- package/src/tui/types.ts +12 -0
- package/src/tui/views/ListView/ListView.tsx +104 -0
- package/src/tui/views/ListView/index.ts +2 -0
- package/src/tui/views/ListView/types.ts +14 -0
- package/src/tui/views/LookupView/LookupView.tsx +244 -0
- package/src/tui/views/LookupView/index.ts +2 -0
- package/src/tui/views/LookupView/types.ts +16 -0
- package/src/tui/views/index.ts +4 -0
- package/src/domains/shared/types.test-d.ts +0 -127
- package/src/domains/shared/types.ts +0 -348
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool spec for the info domain.
|
|
3
|
+
*
|
|
4
|
+
* Uses shared operations (collectStoreSummary, resolveTierChain) instead of
|
|
5
|
+
* inlining data assembly. Skips the npm registry check to avoid network
|
|
6
|
+
* latency in MCP tool calls — sets `updateSkipped: true`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { VERSION } from "#constants";
|
|
10
|
+
import { detectInstallSource } from "#package-manager";
|
|
11
|
+
import { CHANNEL_RELEASES } from "../../shared/filters/buildChannelFilter.js";
|
|
12
|
+
import { resolveTierChain } from "../../shared/filters/buildTierFilter.js";
|
|
13
|
+
import type { ToolSpec } from "../../shared/ToolSpec.js";
|
|
14
|
+
import { renderInfoLlm } from "../formatters/index.js";
|
|
15
|
+
import { collectStoreSummary } from "../operations/index.js";
|
|
16
|
+
import type { InfoData } from "../types.js";
|
|
17
|
+
|
|
18
|
+
const specs: readonly ToolSpec[] = [
|
|
19
|
+
{
|
|
20
|
+
name: "info",
|
|
21
|
+
description: "Show pragma version, configuration, and store summary.",
|
|
22
|
+
params: {
|
|
23
|
+
condensed: {
|
|
24
|
+
type: "boolean",
|
|
25
|
+
description: "Token-optimized output",
|
|
26
|
+
optional: true,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
readOnly: true,
|
|
30
|
+
async execute(rt, params) {
|
|
31
|
+
const install = detectInstallSource();
|
|
32
|
+
const tierChain =
|
|
33
|
+
rt.config.tier !== undefined ? resolveTierChain(rt.config.tier) : [];
|
|
34
|
+
const channelReleases = CHANNEL_RELEASES[rt.config.channel];
|
|
35
|
+
const storeSummary = await collectStoreSummary(rt.store);
|
|
36
|
+
|
|
37
|
+
const data: InfoData = {
|
|
38
|
+
version: VERSION,
|
|
39
|
+
pm: install.packageManager,
|
|
40
|
+
installSource: install.label,
|
|
41
|
+
configPath: "pragma.config.json",
|
|
42
|
+
tier: rt.config.tier,
|
|
43
|
+
tierChain,
|
|
44
|
+
channel: rt.config.channel,
|
|
45
|
+
channelReleases: [...channelReleases],
|
|
46
|
+
update: undefined,
|
|
47
|
+
updateSkipped: true,
|
|
48
|
+
store: storeSummary,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
if (params.condensed) {
|
|
52
|
+
const text = renderInfoLlm(data);
|
|
53
|
+
return {
|
|
54
|
+
condensed: true,
|
|
55
|
+
text,
|
|
56
|
+
tokens: `~${Math.ceil(text.length / 4)}`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return { data };
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
export default specs;
|
|
@@ -7,14 +7,14 @@ import type { CommandRefEntry } from "../types.js";
|
|
|
7
7
|
*/
|
|
8
8
|
export const COMMAND_REFERENCE: readonly CommandRefEntry[] = [
|
|
9
9
|
{ command: "block list", tokens: "~200" },
|
|
10
|
-
{ command: "block lookup <name
|
|
10
|
+
{ command: "block lookup <name-or-iri...> --detailed", tokens: "~500" },
|
|
11
11
|
{ command: "standard list --category <cat>", tokens: "~100" },
|
|
12
|
-
{ command: "standard lookup <name
|
|
12
|
+
{ command: "standard lookup <name-or-iri...> --detailed", tokens: "~400" },
|
|
13
13
|
{ command: "standard categories", tokens: "~50" },
|
|
14
14
|
{ command: "modifier list", tokens: "~100" },
|
|
15
|
-
{ command: "modifier lookup <name
|
|
15
|
+
{ command: "modifier lookup <name-or-iri...>", tokens: "~80" },
|
|
16
16
|
{ command: "token list", tokens: "~400" },
|
|
17
|
-
{ command: "token lookup <name
|
|
17
|
+
{ command: "token lookup <name-or-iri...> --detailed", tokens: "~150" },
|
|
18
18
|
{ command: "tier list", tokens: "~50" },
|
|
19
19
|
{ command: "ontology list", tokens: "~80" },
|
|
20
20
|
{ command: "ontology show <prefix>", tokens: "~300" },
|
|
@@ -9,31 +9,33 @@ import type { DecisionTree } from "../types.js";
|
|
|
9
9
|
export const DECISION_TREES: readonly DecisionTree[] = [
|
|
10
10
|
{
|
|
11
11
|
intent: "Build a block",
|
|
12
|
-
tree: `? Know name?
|
|
13
|
-
yes → block lookup <name
|
|
14
|
-
|
|
12
|
+
tree: `? Know IRI or name?
|
|
13
|
+
yes → block lookup <name-or-iri...> --detailed [~500]
|
|
14
|
+
e.g. block lookup ds:global.component.button
|
|
15
|
+
no → block list [~200] → pick compact IRI → lookup`,
|
|
15
16
|
},
|
|
16
17
|
{
|
|
17
18
|
intent: "Audit standards",
|
|
18
|
-
tree: `? Know standard?
|
|
19
|
-
yes → standard lookup <name
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
tree: `? Know standard IRI or name?
|
|
20
|
+
yes → standard lookup <name-or-iri...> --detailed [~400]
|
|
21
|
+
e.g. standard lookup react/component/props
|
|
22
|
+
no → ? Know block IRI or name?
|
|
23
|
+
yes → block lookup <name-or-iri...> --detailed [~500]
|
|
22
24
|
→ inspect related guidance manually Σ500
|
|
23
25
|
no → standard list --category <cat> [~100]
|
|
24
|
-
→ standard lookup <std
|
|
26
|
+
→ standard lookup <std-iri...> --detailed [~400] Σ500`,
|
|
25
27
|
},
|
|
26
28
|
{
|
|
27
29
|
intent: "Find a token",
|
|
28
|
-
tree: `? Know name?
|
|
29
|
-
yes → token lookup <name
|
|
30
|
+
tree: `? Know token IRI or name?
|
|
31
|
+
yes → token lookup <name-or-iri...> --detailed [~150]
|
|
30
32
|
no → token list --category <cat> [~100]
|
|
31
|
-
→ token lookup <name
|
|
33
|
+
→ token lookup <name-or-iri...> --detailed [~150] Σ250`,
|
|
32
34
|
},
|
|
33
35
|
{
|
|
34
36
|
intent: "Explore the design system",
|
|
35
37
|
tree: `high-level → ontology list [~80] → ontology show <ns> [~300]
|
|
36
|
-
modifiers → modifier list [~100] → modifier lookup <name
|
|
38
|
+
modifiers → modifier list [~100] → modifier lookup <name-or-iri...> [~80]
|
|
37
39
|
tiers → tier list [~50]
|
|
38
40
|
raw → graph query "SELECT ..." → graph inspect <uri> [~200]`,
|
|
39
41
|
},
|
|
@@ -3,7 +3,7 @@ import { listBlocks } from "../../block/operations/index.js";
|
|
|
3
3
|
import { listModifiers } from "../../modifier/operations/index.js";
|
|
4
4
|
import { listOntologies } from "../../ontology/operations/index.js";
|
|
5
5
|
import { resolveTierChain } from "../../shared/filters/buildTierFilter.js";
|
|
6
|
-
import type { FilterConfig } from "../../shared/types.js";
|
|
6
|
+
import type { FilterConfig } from "../../shared/types/index.js";
|
|
7
7
|
import { listStandards } from "../../standard/operations/index.js";
|
|
8
8
|
import { listTokens } from "../../token/operations/index.js";
|
|
9
9
|
import type { LlmContext } from "../types.js";
|
|
@@ -9,9 +9,11 @@ import {
|
|
|
9
9
|
type CommandDefinition,
|
|
10
10
|
createOutputResult,
|
|
11
11
|
} from "@canonical/cli-core";
|
|
12
|
+
import { createListView } from "#tui";
|
|
12
13
|
import type { PragmaContext } from "../../shared/context.js";
|
|
13
14
|
import { selectFormatter } from "../../shared/formatters.js";
|
|
14
15
|
import { listFormatters } from "../formatters/index.js";
|
|
16
|
+
import { modifierConfig } from "../modifierConfig.js";
|
|
15
17
|
import { resolveModifierList } from "../orchestration/index.js";
|
|
16
18
|
|
|
17
19
|
export default function listCommand(ctx: PragmaContext): CommandDefinition {
|
|
@@ -27,6 +29,13 @@ export default function listCommand(ctx: PragmaContext): CommandDefinition {
|
|
|
27
29
|
|
|
28
30
|
return createOutputResult([...resolution.items], {
|
|
29
31
|
plain: selectFormatter(ctx, listFormatters),
|
|
32
|
+
ink: (data) =>
|
|
33
|
+
createListView({
|
|
34
|
+
heading: "Modifiers",
|
|
35
|
+
domain: "modifier",
|
|
36
|
+
items: data,
|
|
37
|
+
columns: modifierConfig.listColumns,
|
|
38
|
+
}),
|
|
30
39
|
});
|
|
31
40
|
},
|
|
32
41
|
};
|
|
@@ -8,9 +8,14 @@ import {
|
|
|
8
8
|
type CommandDefinition,
|
|
9
9
|
createOutputResult,
|
|
10
10
|
} from "@canonical/cli-core";
|
|
11
|
+
import { createLookupView } from "#tui";
|
|
11
12
|
import type { PragmaContext } from "../../shared/context.js";
|
|
12
13
|
import type { LookupResult } from "../../shared/contracts.js";
|
|
13
|
-
import {
|
|
14
|
+
import { renderLookupResults } from "../../shared/formatters.js";
|
|
15
|
+
import {
|
|
16
|
+
createInkLookupOptions,
|
|
17
|
+
lookupFormatters,
|
|
18
|
+
} from "../formatters/index.js";
|
|
14
19
|
import type { lookupModifier } from "../operations/index.js";
|
|
15
20
|
import { resolveModifierLookup } from "../orchestration/index.js";
|
|
16
21
|
|
|
@@ -46,7 +51,22 @@ export default function buildLookupCommand(
|
|
|
46
51
|
|
|
47
52
|
return createOutputResult<ModifierLookupOutput>(
|
|
48
53
|
{ result: contract.result },
|
|
49
|
-
{
|
|
54
|
+
{
|
|
55
|
+
plain: ({ result }) =>
|
|
56
|
+
renderLookupResults({
|
|
57
|
+
ctx,
|
|
58
|
+
result,
|
|
59
|
+
formatters: lookupFormatters,
|
|
60
|
+
mapResult: (family) => family,
|
|
61
|
+
}),
|
|
62
|
+
ink: ({ result }) =>
|
|
63
|
+
createLookupView({
|
|
64
|
+
results: result.results,
|
|
65
|
+
errors: result.errors,
|
|
66
|
+
domain: "modifier",
|
|
67
|
+
options: createInkLookupOptions(),
|
|
68
|
+
}),
|
|
69
|
+
},
|
|
50
70
|
);
|
|
51
71
|
},
|
|
52
72
|
};
|
|
@@ -63,43 +83,3 @@ function normalizeNames(names: unknown, legacyName?: unknown): string[] {
|
|
|
63
83
|
}
|
|
64
84
|
return [];
|
|
65
85
|
}
|
|
66
|
-
|
|
67
|
-
function renderModifierLookupOutput(
|
|
68
|
-
ctx: PragmaContext,
|
|
69
|
-
): (data: ModifierLookupOutput) => string {
|
|
70
|
-
return ({ result }) => {
|
|
71
|
-
const formatOne =
|
|
72
|
-
ctx.globalFlags.format === "json"
|
|
73
|
-
? lookupFormatters.json
|
|
74
|
-
: ctx.globalFlags.llm
|
|
75
|
-
? lookupFormatters.llm
|
|
76
|
-
: lookupFormatters.plain;
|
|
77
|
-
|
|
78
|
-
if (ctx.globalFlags.format === "json") {
|
|
79
|
-
if (result.results.length === 1 && result.errors.length === 0) {
|
|
80
|
-
const only = result.results[0];
|
|
81
|
-
return only
|
|
82
|
-
? lookupFormatters.json(only)
|
|
83
|
-
: JSON.stringify({ results: [], errors: result.errors }, null, 2);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return JSON.stringify(
|
|
87
|
-
{ results: result.results, errors: result.errors },
|
|
88
|
-
null,
|
|
89
|
-
2,
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const parts = result.results.map((family) => formatOne(family));
|
|
94
|
-
if (result.errors.length > 0) {
|
|
95
|
-
parts.push(
|
|
96
|
-
[
|
|
97
|
-
"Errors:",
|
|
98
|
-
...result.errors.map((error) => `- ${error.query}: ${error.message}`),
|
|
99
|
-
].join("\n"),
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return parts.join("\n\n");
|
|
104
|
-
};
|
|
105
|
-
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
/** @module Re-exports modifier formatters (`lookupFormatters`, `listFormatters`). */
|
|
2
2
|
|
|
3
3
|
export { default as listFormatters } from "./list.js";
|
|
4
|
-
export {
|
|
4
|
+
export {
|
|
5
|
+
createInkLookupOptions,
|
|
6
|
+
default as lookupFormatters,
|
|
7
|
+
} from "./lookup.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { URI } from "@canonical/ke";
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
-
import type { ModifierFamily } from "../../shared/types.js";
|
|
3
|
+
import type { ModifierFamily } from "../../shared/types/index.js";
|
|
4
4
|
import formatters from "./list.js";
|
|
5
5
|
|
|
6
6
|
const FAMILIES: ModifierFamily[] = [
|
|
@@ -1,33 +1,20 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Three-mode formatter for `pragma modifier list` output.
|
|
3
|
-
*
|
|
4
|
-
* - **plain** — one line per family showing name and comma-separated values.
|
|
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
1
|
import type { Formatters } from "../../shared/formatters.js";
|
|
11
|
-
import
|
|
2
|
+
import { renderListLlm } from "../../shared/renderers.js";
|
|
3
|
+
import type { ModifierFamily } from "../../shared/types/index.js";
|
|
4
|
+
import { modifierConfig } from "../modifierConfig.js";
|
|
12
5
|
|
|
6
|
+
/** Three-mode formatter for `pragma modifier list` output. */
|
|
13
7
|
const formatters: Formatters<ModifierFamily[]> = {
|
|
14
|
-
plain: (families) =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
return lines.join("\n");
|
|
20
|
-
},
|
|
8
|
+
plain: (families) =>
|
|
9
|
+
families
|
|
10
|
+
.map((family) => `${family.name}: ${family.values.join(", ")}`)
|
|
11
|
+
.join("\n"),
|
|
21
12
|
|
|
22
|
-
llm: (families) =>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
lines.push(`- **${f.name}**: ${f.values.join(", ")}`);
|
|
28
|
-
}
|
|
29
|
-
return lines.join("\n");
|
|
30
|
-
},
|
|
13
|
+
llm: (families) =>
|
|
14
|
+
renderListLlm(families, {
|
|
15
|
+
heading: "Modifier Families",
|
|
16
|
+
columns: modifierConfig.listColumns,
|
|
17
|
+
}),
|
|
31
18
|
|
|
32
19
|
json: (families) => JSON.stringify(families, null, 2),
|
|
33
20
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { URI } from "@canonical/ke";
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
-
import type { ModifierFamily } from "../../shared/types.js";
|
|
3
|
+
import type { ModifierFamily } from "../../shared/types/index.js";
|
|
4
4
|
import formatters from "./lookup.js";
|
|
5
5
|
|
|
6
6
|
const FAMILY: ModifierFamily = {
|
|
@@ -1,38 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
* Three-mode formatter for `pragma modifier lookup` output.
|
|
3
|
-
*
|
|
4
|
-
* - **plain** — terminal text showing the family name and its values.
|
|
5
|
-
* - **llm** — condensed Markdown consumed by LLM agents and reused
|
|
6
|
-
* by the MCP adapter when `condensed: true`.
|
|
7
|
-
* - **json** — structured JSON for programmatic consumption.
|
|
8
|
-
*/
|
|
9
|
-
|
|
1
|
+
import type { RenderLookupOptions } from "../../shared/contracts.js";
|
|
10
2
|
import type { Formatters } from "../../shared/formatters.js";
|
|
11
|
-
import
|
|
3
|
+
import { renderLookupLlm, renderLookupPlain } from "../../shared/renderers.js";
|
|
4
|
+
import type {
|
|
5
|
+
ModifierDetailed,
|
|
6
|
+
ModifierFamily,
|
|
7
|
+
} from "../../shared/types/index.js";
|
|
8
|
+
import { modifierConfig } from "../modifierConfig.js";
|
|
12
9
|
|
|
10
|
+
/** Three-mode formatter for `pragma modifier lookup` output. */
|
|
13
11
|
const formatters: Formatters<ModifierFamily> = {
|
|
14
|
-
plain: (family) =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
12
|
+
plain: (family) =>
|
|
13
|
+
renderLookupPlain(family, {
|
|
14
|
+
title: (entry) => entry.name,
|
|
15
|
+
fields: [{ label: "IRI", value: (entry) => entry.uri }],
|
|
16
|
+
sections: modifierConfig.lookupSections,
|
|
17
|
+
sectionOverrides: {
|
|
18
|
+
values: {
|
|
19
|
+
plain: (entry) =>
|
|
20
|
+
entry.values.length > 0
|
|
21
|
+
? entry.values.map((value) => ` ${value}`).join("\n")
|
|
22
|
+
: null,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
24
26
|
|
|
25
|
-
llm: (family) =>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
return lines.join("\n");
|
|
33
|
-
},
|
|
27
|
+
llm: (family) =>
|
|
28
|
+
renderLookupLlm(family, {
|
|
29
|
+
title: (entry) => entry.name,
|
|
30
|
+
fields: [{ label: "IRI", value: (entry) => entry.uri }],
|
|
31
|
+
sections: modifierConfig.lookupSections,
|
|
32
|
+
}),
|
|
34
33
|
|
|
35
34
|
json: (family) => JSON.stringify(family, null, 2),
|
|
36
35
|
};
|
|
37
36
|
|
|
38
37
|
export default formatters;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Build lookup rendering options for the Ink TUI view.
|
|
41
|
+
*
|
|
42
|
+
* @returns Options compatible with the LookupView component.
|
|
43
|
+
*/
|
|
44
|
+
export function createInkLookupOptions(): RenderLookupOptions<ModifierDetailed> {
|
|
45
|
+
return {
|
|
46
|
+
title: (entry) => entry.name,
|
|
47
|
+
fields: [{ label: "IRI", value: (entry) => entry.uri }],
|
|
48
|
+
sections: modifierConfig.lookupSections,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -14,6 +14,7 @@ export function commands(ctx: PragmaContext): CommandDefinition[] {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export { specs as mcpSpecs } from "./mcp/index.js";
|
|
17
|
+
export { modifierConfig } from "./modifierConfig.js";
|
|
17
18
|
export { listModifiers, lookupModifier } from "./operations/index.js";
|
|
18
19
|
export {
|
|
19
20
|
modifierEmptyError,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { EntityDisplayConfig } from "../shared/contracts.js";
|
|
2
|
+
import { P } from "../shared/prefixes.js";
|
|
3
|
+
import type {
|
|
4
|
+
FilterConfig,
|
|
5
|
+
ModifierDetailed,
|
|
6
|
+
ModifierDigest,
|
|
7
|
+
ModifierSummary,
|
|
8
|
+
} from "../shared/types/index.js";
|
|
9
|
+
|
|
10
|
+
/** Display-contract configuration for modifier-family entities. */
|
|
11
|
+
export const modifierConfig: EntityDisplayConfig<
|
|
12
|
+
ModifierSummary,
|
|
13
|
+
ModifierDigest,
|
|
14
|
+
ModifierDetailed
|
|
15
|
+
> = {
|
|
16
|
+
domain: "modifier",
|
|
17
|
+
entityName: "modifier",
|
|
18
|
+
rdfTypes: [`${P.ds}ModifierFamily`],
|
|
19
|
+
listColumns: [
|
|
20
|
+
{ key: "uri", label: "IRI" },
|
|
21
|
+
{ key: "name", label: "Name" },
|
|
22
|
+
{ key: "values", label: "Values", showWhenEmpty: false },
|
|
23
|
+
],
|
|
24
|
+
digestColumns: [],
|
|
25
|
+
lookupSections: [{ key: "values", heading: "Values", kind: "list" }],
|
|
26
|
+
emptyRecovery: (_filters: FilterConfig) => ({
|
|
27
|
+
message: "List available modifier families.",
|
|
28
|
+
cli: "pragma modifier list",
|
|
29
|
+
mcp: { tool: "modifier_list" },
|
|
30
|
+
}),
|
|
31
|
+
notFoundRecovery: (_query: string) => ({
|
|
32
|
+
message: "List available modifier families.",
|
|
33
|
+
cli: "pragma modifier list",
|
|
34
|
+
mcp: { tool: "modifier_list" },
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import type { Store, URI } from "@canonical/ke";
|
|
10
10
|
import { buildQuery } from "../../shared/buildQuery.js";
|
|
11
11
|
import { P } from "../../shared/prefixes.js";
|
|
12
|
-
import type { ModifierFamily } from "../../shared/types.js";
|
|
12
|
+
import type { ModifierFamily } from "../../shared/types/index.js";
|
|
13
13
|
|
|
14
14
|
export default async function listModifiers(
|
|
15
15
|
store: Store,
|
|
@@ -13,20 +13,21 @@ import { escapeSparqlValue } from "@canonical/ke";
|
|
|
13
13
|
import { PragmaError } from "#error";
|
|
14
14
|
import { buildQuery } from "../../shared/buildQuery.js";
|
|
15
15
|
import { P } from "../../shared/prefixes.js";
|
|
16
|
-
import type { ModifierFamily } from "../../shared/types.js";
|
|
16
|
+
import type { ModifierFamily } from "../../shared/types/index.js";
|
|
17
17
|
|
|
18
18
|
export default async function lookupModifier(
|
|
19
19
|
store: Store,
|
|
20
20
|
name: string,
|
|
21
21
|
): Promise<ModifierFamily> {
|
|
22
|
-
const escaped = escapeSparqlValue(name);
|
|
22
|
+
const escaped = escapeSparqlValue(name.toLowerCase());
|
|
23
23
|
|
|
24
24
|
const result = await store.query(
|
|
25
25
|
buildQuery(`
|
|
26
26
|
SELECT ?family (GROUP_CONCAT(DISTINCT ?valueName; separator="|") AS ?values)
|
|
27
27
|
WHERE {
|
|
28
28
|
?family a ${P.ds}ModifierFamily ;
|
|
29
|
-
${P.ds}name
|
|
29
|
+
${P.ds}name ?familyName .
|
|
30
|
+
FILTER(LCASE(STR(?familyName)) = ${escaped})
|
|
30
31
|
OPTIONAL {
|
|
31
32
|
?mod a ${P.ds}Modifier ;
|
|
32
33
|
${P.ds}modifierFamily ?family ;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { LookupContract, LookupResult } from "../../shared/contracts.js";
|
|
2
2
|
import lookupMany from "../../shared/lookupMany.js";
|
|
3
3
|
import type { PragmaRuntime } from "../../shared/runtime.js";
|
|
4
|
-
import type { ModifierFamily } from "../../shared/types.js";
|
|
4
|
+
import type { ModifierFamily } from "../../shared/types/index.js";
|
|
5
5
|
import { lookupModifier } from "../operations/index.js";
|
|
6
6
|
|
|
7
7
|
export default async function resolveModifierLookup(
|
|
@@ -3,7 +3,7 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
|
3
3
|
import createTestRuntime from "../../../testing/helpers/createTestRuntime.js";
|
|
4
4
|
import type { PragmaContext } from "../../shared/context.js";
|
|
5
5
|
import type { PragmaRuntime } from "../../shared/runtime.js";
|
|
6
|
-
import type { OntologySummary } from "../../shared/types.js";
|
|
6
|
+
import type { OntologySummary } from "../../shared/types/index.js";
|
|
7
7
|
import buildListCommand from "./list.js";
|
|
8
8
|
|
|
9
9
|
let runtime: PragmaRuntime;
|
|
@@ -4,11 +4,22 @@ import {
|
|
|
4
4
|
createOutputResult,
|
|
5
5
|
} from "@canonical/cli-core";
|
|
6
6
|
import { PragmaError } from "#error";
|
|
7
|
+
import { createListView } from "#tui";
|
|
7
8
|
import type { PragmaContext } from "../../shared/context.js";
|
|
9
|
+
import type { ColumnDef } from "../../shared/contracts.js";
|
|
8
10
|
import { selectFormatter } from "../../shared/formatters.js";
|
|
11
|
+
import type { OntologySummary } from "../../shared/types/ontology.js";
|
|
9
12
|
import { listFormatters } from "../formatters/index.js";
|
|
10
13
|
import { listOntologies } from "../operations/index.js";
|
|
11
14
|
|
|
15
|
+
const ontologyListColumns: readonly ColumnDef<OntologySummary>[] = [
|
|
16
|
+
{ key: "prefix", label: "Prefix" },
|
|
17
|
+
{ key: "namespace", label: "Namespace" },
|
|
18
|
+
{ key: "classCount", label: "Classes" },
|
|
19
|
+
{ key: "propertyCount", label: "Properties" },
|
|
20
|
+
{ key: "anatomyCount", label: "Anatomies" },
|
|
21
|
+
];
|
|
22
|
+
|
|
12
23
|
/**
|
|
13
24
|
* Builds the `pragma ontology list` command definition.
|
|
14
25
|
*
|
|
@@ -40,6 +51,13 @@ export default function buildListCommand(
|
|
|
40
51
|
|
|
41
52
|
return createOutputResult(ontologies, {
|
|
42
53
|
plain: selectFormatter(ctx, listFormatters),
|
|
54
|
+
ink: (data) =>
|
|
55
|
+
createListView({
|
|
56
|
+
heading: "Ontologies",
|
|
57
|
+
domain: "ontology",
|
|
58
|
+
items: data,
|
|
59
|
+
columns: ontologyListColumns,
|
|
60
|
+
}),
|
|
43
61
|
});
|
|
44
62
|
},
|
|
45
63
|
};
|
|
@@ -3,7 +3,7 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
|
3
3
|
import createTestRuntime from "../../../testing/helpers/createTestRuntime.js";
|
|
4
4
|
import type { PragmaContext } from "../../shared/context.js";
|
|
5
5
|
import type { PragmaRuntime } from "../../shared/runtime.js";
|
|
6
|
-
import type { OntologyDetailed } from "../../shared/types.js";
|
|
6
|
+
import type { OntologyDetailed } from "../../shared/types/index.js";
|
|
7
7
|
import buildShowCommand from "./show.js";
|
|
8
8
|
|
|
9
9
|
let runtime: PragmaRuntime;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
+
import compactUri from "../../shared/compactUri.js";
|
|
2
3
|
import type { Formatters } from "../../shared/formatters.js";
|
|
3
|
-
import
|
|
4
|
+
import { PREFIX_MAP } from "../../shared/prefixes.js";
|
|
5
|
+
import type { OntologySummary } from "../../shared/types/index.js";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Formatters for `pragma ontology list` output.
|
|
@@ -14,7 +16,7 @@ const formatters: Formatters<readonly OntologySummary[]> = {
|
|
|
14
16
|
return ontologies
|
|
15
17
|
.map(
|
|
16
18
|
(o) =>
|
|
17
|
-
`${chalk.bold(o.prefix)} ${
|
|
19
|
+
`${chalk.bold(`${o.prefix}:`)} ${compactUri(o.namespace, PREFIX_MAP)} classes: ${o.classCount} properties: ${o.propertyCount} anatomy: ${o.anatomyCount}`,
|
|
18
20
|
)
|
|
19
21
|
.join("\n");
|
|
20
22
|
},
|
|
@@ -23,7 +25,7 @@ const formatters: Formatters<readonly OntologySummary[]> = {
|
|
|
23
25
|
const lines = ["## Ontologies", ""];
|
|
24
26
|
for (const o of ontologies) {
|
|
25
27
|
lines.push(
|
|
26
|
-
`- **${o.prefix}:** (
|
|
28
|
+
`- **${o.prefix}:** \`${compactUri(o.namespace, PREFIX_MAP)}\` | classes: ${o.classCount} | properties: ${o.propertyCount} | anatomy: ${o.anatomyCount}`,
|
|
27
29
|
);
|
|
28
30
|
}
|
|
29
31
|
return lines.join("\n");
|