@dryui/mcp 0.1.4 → 0.2.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/architecture.d.ts +0 -1
- package/dist/architecture.js +0 -3
- package/dist/architecture.json +12 -8
- package/dist/composition-search.d.ts +15 -0
- package/dist/composition-search.js +202 -0
- package/dist/contract.v1.json +29 -11
- package/dist/index.js +619 -269
- package/dist/spec.json +29 -11
- package/dist/toon.d.ts +43 -0
- package/dist/toon.js +480 -0
- package/package.json +15 -2
package/dist/spec.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.7",
|
|
3
3
|
"package": "@dryui/ui",
|
|
4
4
|
"themeImports": {
|
|
5
5
|
"default": "@dryui/ui/themes/default.css",
|
|
@@ -10818,6 +10818,26 @@
|
|
|
10818
10818
|
"type": "number",
|
|
10819
10819
|
"required": false,
|
|
10820
10820
|
"description": "Step interval used when incrementing numeric values."
|
|
10821
|
+
},
|
|
10822
|
+
"size": {
|
|
10823
|
+
"type": "'sm' | 'md' | 'lg'",
|
|
10824
|
+
"required": false,
|
|
10825
|
+
"acceptedValues": [
|
|
10826
|
+
"sm",
|
|
10827
|
+
"md",
|
|
10828
|
+
"lg"
|
|
10829
|
+
],
|
|
10830
|
+
"description": "Size preset affecting density, spacing, or typography.",
|
|
10831
|
+
"default": "'md'"
|
|
10832
|
+
},
|
|
10833
|
+
"name": {
|
|
10834
|
+
"type": "string",
|
|
10835
|
+
"required": false,
|
|
10836
|
+
"description": "Field name used during native form submission."
|
|
10837
|
+
},
|
|
10838
|
+
"class": {
|
|
10839
|
+
"type": "string",
|
|
10840
|
+
"required": false
|
|
10821
10841
|
}
|
|
10822
10842
|
},
|
|
10823
10843
|
"forwardedProps": {
|
|
@@ -10831,25 +10851,23 @@
|
|
|
10831
10851
|
],
|
|
10832
10852
|
"note": "Forwards <input> attributes via rest props."
|
|
10833
10853
|
},
|
|
10834
|
-
"cssVars": {
|
|
10835
|
-
"--dry-time-input-bg": "Input Bg",
|
|
10836
|
-
"--dry-time-input-border": "Input Border",
|
|
10837
|
-
"--dry-time-input-color": "Input Color",
|
|
10838
|
-
"--dry-time-input-font-size": "Input Font Size",
|
|
10839
|
-
"--dry-time-input-padding-x": "Input Padding X",
|
|
10840
|
-
"--dry-time-input-padding-y": "Input Padding Y",
|
|
10841
|
-
"--dry-time-input-radius": "Input Radius"
|
|
10842
|
-
},
|
|
10854
|
+
"cssVars": {},
|
|
10843
10855
|
"dataAttributes": [
|
|
10844
10856
|
{
|
|
10845
10857
|
"name": "data-disabled",
|
|
10846
10858
|
"description": "Present when the component or part is disabled."
|
|
10847
10859
|
},
|
|
10848
10860
|
{
|
|
10849
|
-
"name": "data-
|
|
10861
|
+
"name": "data-placeholder"
|
|
10862
|
+
},
|
|
10863
|
+
{
|
|
10864
|
+
"name": "data-time-display"
|
|
10850
10865
|
},
|
|
10851
10866
|
{
|
|
10852
10867
|
"name": "data-time-input-wrapper"
|
|
10868
|
+
},
|
|
10869
|
+
{
|
|
10870
|
+
"name": "data-time-separator"
|
|
10853
10871
|
}
|
|
10854
10872
|
],
|
|
10855
10873
|
"example": "<TimeInput>Content</TimeInput>"
|
package/dist/toon.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ComponentDef, CompositionComponentDef, CompositionRecipeDef } from './spec-types.js';
|
|
2
|
+
import type { ReviewResult } from './reviewer.js';
|
|
3
|
+
import type { DiagnoseResult } from './theme-checker.js';
|
|
4
|
+
import type { WorkspaceReport } from './workspace-audit.js';
|
|
5
|
+
import type { ProjectDetection, InstallPlan, AddPlan } from './project-planner.js';
|
|
6
|
+
export type HelpCommand = 'info' | 'list' | 'compose' | 'review' | 'diagnose' | 'doctor' | 'lint' | 'detect' | 'install';
|
|
7
|
+
export type HelpContext = {
|
|
8
|
+
command: HelpCommand;
|
|
9
|
+
hasErrors?: boolean;
|
|
10
|
+
hasFindings?: boolean;
|
|
11
|
+
isEmpty?: boolean;
|
|
12
|
+
componentName?: string;
|
|
13
|
+
query?: string;
|
|
14
|
+
status?: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Build context-aware next-step suggestions.
|
|
18
|
+
* Returns 1-3 help lines for agents to copy-paste.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildContextualHelp(ctx: HelpContext): string[];
|
|
21
|
+
/** Format help hints as plain next-step suggestions. */
|
|
22
|
+
export declare function formatHelp(hints: string[]): string;
|
|
23
|
+
export declare function toonComponent(name: string, def: ComponentDef, opts?: {
|
|
24
|
+
full?: boolean | undefined;
|
|
25
|
+
}): string;
|
|
26
|
+
export declare function toonComponentList(components: Record<string, ComponentDef>, category?: string): string;
|
|
27
|
+
export declare function toonComposition(results: {
|
|
28
|
+
componentMatches: readonly CompositionComponentDef[];
|
|
29
|
+
recipeMatches: readonly CompositionRecipeDef[];
|
|
30
|
+
}, opts?: {
|
|
31
|
+
full?: boolean | undefined;
|
|
32
|
+
}): string;
|
|
33
|
+
export declare function toonReviewResult(result: ReviewResult): string;
|
|
34
|
+
export declare function toonDiagnoseResult(result: DiagnoseResult): string;
|
|
35
|
+
export declare function toonWorkspaceReport(report: WorkspaceReport, opts?: {
|
|
36
|
+
title?: string | undefined;
|
|
37
|
+
command?: 'doctor' | 'lint' | undefined;
|
|
38
|
+
full?: boolean | undefined;
|
|
39
|
+
}): string;
|
|
40
|
+
export declare function toonProjectDetection(detection: ProjectDetection): string;
|
|
41
|
+
export declare function toonInstallPlan(plan: InstallPlan): string;
|
|
42
|
+
export declare function toonAddPlan(plan: AddPlan): string;
|
|
43
|
+
export declare function toonError(code: string, message: string, suggestions?: string[]): string;
|
package/dist/toon.js
ADDED
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
function __accessProp(key) {
|
|
7
|
+
return this[key];
|
|
8
|
+
}
|
|
9
|
+
var __toESMCache_node;
|
|
10
|
+
var __toESMCache_esm;
|
|
11
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
12
|
+
var canCache = mod != null && typeof mod === "object";
|
|
13
|
+
if (canCache) {
|
|
14
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
15
|
+
var cached = cache.get(mod);
|
|
16
|
+
if (cached)
|
|
17
|
+
return cached;
|
|
18
|
+
}
|
|
19
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
20
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
21
|
+
for (let key of __getOwnPropNames(mod))
|
|
22
|
+
if (!__hasOwnProp.call(to, key))
|
|
23
|
+
__defProp(to, key, {
|
|
24
|
+
get: __accessProp.bind(mod, key),
|
|
25
|
+
enumerable: true
|
|
26
|
+
});
|
|
27
|
+
if (canCache)
|
|
28
|
+
cache.set(mod, to);
|
|
29
|
+
return to;
|
|
30
|
+
};
|
|
31
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
32
|
+
var __returnValue = (v) => v;
|
|
33
|
+
function __exportSetter(name, newValue) {
|
|
34
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
35
|
+
}
|
|
36
|
+
var __export = (target, all) => {
|
|
37
|
+
for (var name in all)
|
|
38
|
+
__defProp(target, name, {
|
|
39
|
+
get: all[name],
|
|
40
|
+
enumerable: true,
|
|
41
|
+
configurable: true,
|
|
42
|
+
set: __exportSetter.bind(all, name)
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// src/toon.ts
|
|
47
|
+
function esc(value) {
|
|
48
|
+
if (value.includes(",") || value.includes(`
|
|
49
|
+
`)) {
|
|
50
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
function header(resource, count, fields) {
|
|
55
|
+
return `${resource}[${count}]{${fields.join(",")}}:`;
|
|
56
|
+
}
|
|
57
|
+
function row(...values) {
|
|
58
|
+
return " " + values.map((v) => esc(String(v))).join(",");
|
|
59
|
+
}
|
|
60
|
+
function truncate(text, maxLen, hint) {
|
|
61
|
+
if (text.length <= maxLen)
|
|
62
|
+
return text;
|
|
63
|
+
return `(truncated, ${text.length} chars -- ${hint})`;
|
|
64
|
+
}
|
|
65
|
+
function buildContextualHelp(ctx) {
|
|
66
|
+
const hints = [];
|
|
67
|
+
switch (ctx.command) {
|
|
68
|
+
case "info":
|
|
69
|
+
if (ctx.componentName) {
|
|
70
|
+
hints.push(`compose "${ctx.componentName.toLowerCase()}" -- see composition patterns`);
|
|
71
|
+
hints.push(`add ${ctx.componentName} -- get starter snippet`);
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
case "list":
|
|
75
|
+
hints.push("info <Component> -- see full API reference");
|
|
76
|
+
break;
|
|
77
|
+
case "compose":
|
|
78
|
+
if (ctx.componentName) {
|
|
79
|
+
hints.push(`info ${ctx.componentName} -- full API reference`);
|
|
80
|
+
hints.push(`add ${ctx.componentName} -- starter snippet`);
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
case "review":
|
|
84
|
+
if (ctx.hasErrors) {
|
|
85
|
+
hints.push("info <Component> -- check API for errored component");
|
|
86
|
+
hints.push("diagnose <file.css> -- check theme if theme warnings present");
|
|
87
|
+
} else if (ctx.isEmpty) {
|
|
88
|
+
hints.push("lint . -- check entire workspace");
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
case "diagnose":
|
|
92
|
+
if (ctx.hasErrors) {
|
|
93
|
+
hints.push('compose "app shell" -- get correct theme setup');
|
|
94
|
+
} else if (ctx.isEmpty) {
|
|
95
|
+
hints.push("review <file.svelte> -- validate component usage");
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
case "doctor":
|
|
99
|
+
case "lint":
|
|
100
|
+
if (ctx.hasFindings) {
|
|
101
|
+
hints.push("lint --max-severity error -- focus on errors only");
|
|
102
|
+
hints.push("review <file.svelte> -- check specific file");
|
|
103
|
+
} else if (ctx.isEmpty) {
|
|
104
|
+
hints.push("detect -- verify project setup");
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
case "detect":
|
|
108
|
+
if (ctx.status === "partial" || ctx.status === "unsupported") {
|
|
109
|
+
hints.push("install -- see step-by-step setup plan");
|
|
110
|
+
} else if (ctx.status === "ready") {
|
|
111
|
+
hints.push("list -- see available components");
|
|
112
|
+
hints.push('compose "app shell" -- get root layout template');
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
case "install":
|
|
116
|
+
hints.push("detect -- verify project after completing steps");
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
return hints;
|
|
120
|
+
}
|
|
121
|
+
function formatHelp(hints) {
|
|
122
|
+
if (hints.length === 0)
|
|
123
|
+
return "";
|
|
124
|
+
const lines = [`next[${hints.length}]:`];
|
|
125
|
+
for (const hint of hints) {
|
|
126
|
+
lines.push(" " + hint);
|
|
127
|
+
}
|
|
128
|
+
return lines.join(`
|
|
129
|
+
`);
|
|
130
|
+
}
|
|
131
|
+
function toonComponent(name, def, opts) {
|
|
132
|
+
const full = opts?.full ?? false;
|
|
133
|
+
const lines = [];
|
|
134
|
+
lines.push(`${name} -- ${def.description}`, `category: ${def.category} | tags: ${def.tags.join(",")}`, `import: import { ${name} } from '${def.import}'`, `compound: ${def.compound}`);
|
|
135
|
+
if (def.compound && def.structure?.tree.length) {
|
|
136
|
+
lines.push("", header("structure", def.structure.tree.length, ["node"]));
|
|
137
|
+
for (const node of def.structure.tree) {
|
|
138
|
+
lines.push(" " + node);
|
|
139
|
+
}
|
|
140
|
+
if (def.structure.note)
|
|
141
|
+
lines.push(` note: ${def.structure.note}`);
|
|
142
|
+
}
|
|
143
|
+
if (def.compound && def.parts) {
|
|
144
|
+
const partEntries = Object.entries(def.parts);
|
|
145
|
+
lines.push("", header("parts", partEntries.length, ["part"]));
|
|
146
|
+
for (const [partName, partDef] of partEntries) {
|
|
147
|
+
lines.push(` ${name}.${partName}`);
|
|
148
|
+
const props = Object.entries(partDef.props ?? {});
|
|
149
|
+
if (props.length > 0) {
|
|
150
|
+
for (const [propName, propDef] of props) {
|
|
151
|
+
const flags = [propDef.type];
|
|
152
|
+
if (propDef.required)
|
|
153
|
+
flags.push("required");
|
|
154
|
+
if (propDef.default !== undefined)
|
|
155
|
+
flags.push(`default:${propDef.default}`);
|
|
156
|
+
if (propDef.acceptedValues?.length)
|
|
157
|
+
flags.push(`values:${propDef.acceptedValues.join("|")}`);
|
|
158
|
+
lines.push(` ${propName}: ${flags.join(" | ")}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
} else if (def.props) {
|
|
163
|
+
const propEntries = Object.entries(def.props);
|
|
164
|
+
if (propEntries.length > 0) {
|
|
165
|
+
lines.push("", header("props", propEntries.length, ["name", "type", "required", "default"]));
|
|
166
|
+
for (const [propName, propDef] of propEntries) {
|
|
167
|
+
lines.push(row(propName, propDef.type, propDef.required ? "yes" : "no", propDef.default ?? "-"));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const cssEntries = Object.entries(def.cssVars);
|
|
172
|
+
if (cssEntries.length > 0) {
|
|
173
|
+
lines.push("", header("css-vars", cssEntries.length, ["name", "description"]));
|
|
174
|
+
for (const [varName, desc] of cssEntries) {
|
|
175
|
+
lines.push(row(varName, desc));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (def.dataAttributes.length > 0) {
|
|
179
|
+
lines.push("", header("data-attrs", def.dataAttributes.length, ["name", "values"]));
|
|
180
|
+
for (const attr of def.dataAttributes) {
|
|
181
|
+
lines.push(row(attr.name, attr.values?.join("|") ?? "-"));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (def.example) {
|
|
185
|
+
const example = full ? def.example : truncate(def.example, 400, `use add ${name} for full snippet`);
|
|
186
|
+
lines.push("", "example:", example);
|
|
187
|
+
}
|
|
188
|
+
const help = buildContextualHelp({ command: "info", componentName: name });
|
|
189
|
+
if (help.length > 0) {
|
|
190
|
+
lines.push("", formatHelp(help));
|
|
191
|
+
}
|
|
192
|
+
return lines.join(`
|
|
193
|
+
`);
|
|
194
|
+
}
|
|
195
|
+
function toonComponentList(components, category) {
|
|
196
|
+
const entries = Object.entries(components);
|
|
197
|
+
const filtered = category ? entries.filter(([, def]) => def.category.toLowerCase() === category.toLowerCase()) : entries;
|
|
198
|
+
if (filtered.length === 0) {
|
|
199
|
+
const cats = [...new Set(entries.map(([, d]) => d.category))].sort();
|
|
200
|
+
return `components[0]: no matches
|
|
201
|
+
available categories: ${cats.join(", ")}`;
|
|
202
|
+
}
|
|
203
|
+
const groups = {};
|
|
204
|
+
for (const entry of filtered) {
|
|
205
|
+
const cat = entry[1].category;
|
|
206
|
+
(groups[cat] ??= []).push(entry);
|
|
207
|
+
}
|
|
208
|
+
const lines = [header("components", filtered.length, ["name", "category", "compound", "description"])];
|
|
209
|
+
const sortedCats = Object.keys(groups).sort();
|
|
210
|
+
for (const cat of sortedCats) {
|
|
211
|
+
const items = groups[cat] ?? [];
|
|
212
|
+
for (const [name, def] of items) {
|
|
213
|
+
lines.push(row(name, cat, def.compound, def.description));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const help = buildContextualHelp({ command: "list" });
|
|
217
|
+
if (help.length > 0) {
|
|
218
|
+
lines.push("", formatHelp(help));
|
|
219
|
+
}
|
|
220
|
+
return lines.join(`
|
|
221
|
+
`);
|
|
222
|
+
}
|
|
223
|
+
function toonComposition(results, opts) {
|
|
224
|
+
const full = opts?.full ?? false;
|
|
225
|
+
const lines = [];
|
|
226
|
+
const totalMatches = results.componentMatches.length + results.recipeMatches.length;
|
|
227
|
+
if (totalMatches === 0) {
|
|
228
|
+
return "matches[0]: none";
|
|
229
|
+
}
|
|
230
|
+
for (const comp of results.componentMatches) {
|
|
231
|
+
lines.push(`-- ${comp.component}: ${comp.useWhen}`);
|
|
232
|
+
for (const alt of comp.alternatives) {
|
|
233
|
+
const snippet = full ? alt.snippet : truncate(alt.snippet, 500, `use info ${alt.component} for full snippet`);
|
|
234
|
+
lines.push(` ${alt.rank}. ${alt.component} (${alt.useWhen})`);
|
|
235
|
+
lines.push(snippet.split(`
|
|
236
|
+
`).map((l) => " " + l).join(`
|
|
237
|
+
`));
|
|
238
|
+
}
|
|
239
|
+
for (const ap of comp.antiPatterns) {
|
|
240
|
+
lines.push(` anti-pattern: ${ap.pattern}`);
|
|
241
|
+
lines.push(` reason: ${ap.reason} | fix: ${ap.fix}`);
|
|
242
|
+
}
|
|
243
|
+
if (comp.combinesWith.length) {
|
|
244
|
+
lines.push(` combines-with: ${comp.combinesWith.join(",")}`);
|
|
245
|
+
}
|
|
246
|
+
lines.push("");
|
|
247
|
+
}
|
|
248
|
+
for (const recipe of results.recipeMatches) {
|
|
249
|
+
const snippet = full ? recipe.snippet : truncate(recipe.snippet, 500, `use compose "${recipe.name}" --full for complete code`);
|
|
250
|
+
lines.push(`-- recipe: ${recipe.name}`);
|
|
251
|
+
lines.push(` ${recipe.description}`);
|
|
252
|
+
lines.push(` components: ${recipe.components.join(",")}`);
|
|
253
|
+
lines.push(" code:");
|
|
254
|
+
lines.push(snippet.split(`
|
|
255
|
+
`).map((l) => " " + l).join(`
|
|
256
|
+
`));
|
|
257
|
+
lines.push("");
|
|
258
|
+
}
|
|
259
|
+
const firstComponent = results.componentMatches[0]?.alternatives[0]?.component ?? results.recipeMatches[0]?.components[0] ?? undefined;
|
|
260
|
+
const ctx = { command: "compose" };
|
|
261
|
+
if (firstComponent)
|
|
262
|
+
ctx.componentName = firstComponent;
|
|
263
|
+
const help = buildContextualHelp(ctx);
|
|
264
|
+
if (help.length > 0) {
|
|
265
|
+
lines.push(formatHelp(help));
|
|
266
|
+
}
|
|
267
|
+
return lines.join(`
|
|
268
|
+
`).trimEnd();
|
|
269
|
+
}
|
|
270
|
+
function toonReviewResult(result) {
|
|
271
|
+
const lines = [];
|
|
272
|
+
const hasBlockers = result.issues.some((i) => i.severity === "error");
|
|
273
|
+
const autoFixable = result.issues.filter((i) => i.fix !== null).length;
|
|
274
|
+
if (result.issues.length === 0) {
|
|
275
|
+
lines.push("issues[0]: clean");
|
|
276
|
+
lines.push(`hasBlockers: false | autoFixable: 0`);
|
|
277
|
+
} else {
|
|
278
|
+
lines.push(header("issues", result.issues.length, ["severity", "line", "code", "message"]));
|
|
279
|
+
for (const issue of result.issues) {
|
|
280
|
+
lines.push(row(issue.severity, issue.line, issue.code, issue.message));
|
|
281
|
+
if (issue.fix) {
|
|
282
|
+
lines.push(` fix: ${issue.fix}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
lines.push(`hasBlockers: ${hasBlockers} | autoFixable: ${autoFixable}`);
|
|
286
|
+
}
|
|
287
|
+
lines.push(result.summary);
|
|
288
|
+
const help = buildContextualHelp({
|
|
289
|
+
command: "review",
|
|
290
|
+
hasErrors: hasBlockers,
|
|
291
|
+
isEmpty: result.issues.length === 0
|
|
292
|
+
});
|
|
293
|
+
if (help.length > 0) {
|
|
294
|
+
lines.push("", formatHelp(help));
|
|
295
|
+
}
|
|
296
|
+
return lines.join(`
|
|
297
|
+
`);
|
|
298
|
+
}
|
|
299
|
+
function toonDiagnoseResult(result) {
|
|
300
|
+
const lines = [];
|
|
301
|
+
const { variables } = result;
|
|
302
|
+
const missingCount = result.issues.filter((i) => i.code === "missing-token").length;
|
|
303
|
+
const totalRequired = variables.required + missingCount;
|
|
304
|
+
const coverage = totalRequired > 0 ? Math.round(variables.required / totalRequired * 100) : 100;
|
|
305
|
+
lines.push(`tokens: ${variables.found} found, ${variables.required} required, ${variables.extra} extra | coverage: ${coverage}%`);
|
|
306
|
+
if (result.issues.length === 0) {
|
|
307
|
+
lines.push("issues[0]: clean");
|
|
308
|
+
} else {
|
|
309
|
+
lines.push(header("issues", result.issues.length, ["severity", "code", "variable", "message"]));
|
|
310
|
+
for (const issue of result.issues) {
|
|
311
|
+
lines.push(row(issue.severity, issue.code, issue.variable, issue.message));
|
|
312
|
+
if (issue.fix) {
|
|
313
|
+
lines.push(` fix: ${issue.fix}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
lines.push(result.summary);
|
|
318
|
+
const hasErrors = result.issues.some((i) => i.severity === "error");
|
|
319
|
+
const help = buildContextualHelp({
|
|
320
|
+
command: "diagnose",
|
|
321
|
+
hasErrors,
|
|
322
|
+
isEmpty: result.issues.length === 0
|
|
323
|
+
});
|
|
324
|
+
if (help.length > 0) {
|
|
325
|
+
lines.push("", formatHelp(help));
|
|
326
|
+
}
|
|
327
|
+
return lines.join(`
|
|
328
|
+
`);
|
|
329
|
+
}
|
|
330
|
+
var MAX_FINDINGS_DEFAULT = 50;
|
|
331
|
+
function toonWorkspaceReport(report, opts) {
|
|
332
|
+
const full = opts?.full ?? false;
|
|
333
|
+
const title = opts?.title ?? "workspace";
|
|
334
|
+
const command = opts?.command ?? (title.includes("lint") ? "lint" : "doctor");
|
|
335
|
+
const lines = [];
|
|
336
|
+
lines.push(`${title} | root: ${report.root}`);
|
|
337
|
+
lines.push(`scanned: ${report.scannedFiles} files | errors: ${report.summary.error} | warnings: ${report.summary.warning} | info: ${report.summary.info}`);
|
|
338
|
+
if (report.summary.byRule && Object.keys(report.summary.byRule).length > 0) {
|
|
339
|
+
const sorted = Object.entries(report.summary.byRule).sort(([, a], [, b]) => b - a);
|
|
340
|
+
const topRule = sorted[0];
|
|
341
|
+
if (topRule) {
|
|
342
|
+
lines.push(`top-rule: ${topRule[0]} (${topRule[1]} occurrences)`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (report.findings.length === 0) {
|
|
346
|
+
lines.push("findings[0]: clean");
|
|
347
|
+
} else {
|
|
348
|
+
const findings = full ? report.findings : report.findings.slice(0, MAX_FINDINGS_DEFAULT);
|
|
349
|
+
const truncated = !full && report.findings.length > MAX_FINDINGS_DEFAULT;
|
|
350
|
+
lines.push(header("findings", findings.length, ["severity", "rule", "file", "line", "message"]));
|
|
351
|
+
for (const f of findings) {
|
|
352
|
+
lines.push(row(f.severity, f.ruleId, f.file, f.line ?? "-", f.message));
|
|
353
|
+
if (f.suggestedFixes.length > 0) {
|
|
354
|
+
for (const fix of f.suggestedFixes) {
|
|
355
|
+
lines.push(` fix: ${fix.description}${fix.replacement ? ` -> ${fix.replacement}` : ""}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
if (truncated) {
|
|
360
|
+
lines.push(` (showing ${MAX_FINDINGS_DEFAULT} of ${report.findings.length} -- use --full to see all)`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
if (report.warnings.length > 0) {
|
|
364
|
+
lines.push("", header("warnings", report.warnings.length, ["message"]));
|
|
365
|
+
for (const w of report.warnings) {
|
|
366
|
+
lines.push(" " + w);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
const help = buildContextualHelp({
|
|
370
|
+
command,
|
|
371
|
+
hasFindings: report.findings.length > 0,
|
|
372
|
+
isEmpty: report.findings.length === 0
|
|
373
|
+
});
|
|
374
|
+
if (help.length > 0) {
|
|
375
|
+
lines.push("", formatHelp(help));
|
|
376
|
+
}
|
|
377
|
+
return lines.join(`
|
|
378
|
+
`);
|
|
379
|
+
}
|
|
380
|
+
function toonProjectDetection(detection) {
|
|
381
|
+
const lines = [];
|
|
382
|
+
lines.push(`project: ${detection.status} | framework: ${detection.framework} | pkg-manager: ${detection.packageManager}`);
|
|
383
|
+
lines.push(`root: ${detection.root ?? "(not found)"}`);
|
|
384
|
+
lines.push(`deps: ui=${detection.dependencies.ui}, primitives=${detection.dependencies.primitives}`);
|
|
385
|
+
lines.push(`theme: default=${detection.theme.defaultImported}, dark=${detection.theme.darkImported}, auto=${detection.theme.themeAuto}`);
|
|
386
|
+
if (detection.warnings.length > 0) {
|
|
387
|
+
lines.push(header("warnings", detection.warnings.length, ["message"]));
|
|
388
|
+
for (const w of detection.warnings) {
|
|
389
|
+
lines.push(" " + w);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
const help = buildContextualHelp({ command: "detect", status: detection.status });
|
|
393
|
+
if (help.length > 0) {
|
|
394
|
+
lines.push("", formatHelp(help));
|
|
395
|
+
}
|
|
396
|
+
return lines.join(`
|
|
397
|
+
`);
|
|
398
|
+
}
|
|
399
|
+
function toonStep(step, index) {
|
|
400
|
+
const parts = [`${index + 1}. [${step.status}] ${step.title}: ${step.description}`];
|
|
401
|
+
if (step.command)
|
|
402
|
+
parts.push(` cmd: ${step.command}`);
|
|
403
|
+
if (step.path)
|
|
404
|
+
parts.push(` file: ${step.path}`);
|
|
405
|
+
return parts.join(`
|
|
406
|
+
`);
|
|
407
|
+
}
|
|
408
|
+
function toonInstallPlan(plan) {
|
|
409
|
+
const lines = [];
|
|
410
|
+
lines.push(toonProjectDetection(plan.detection));
|
|
411
|
+
lines.push("");
|
|
412
|
+
if (plan.steps.length === 0) {
|
|
413
|
+
lines.push("steps[0]: none needed");
|
|
414
|
+
} else {
|
|
415
|
+
lines.push(header("steps", plan.steps.length, ["status", "title", "description"]));
|
|
416
|
+
for (const [i, step] of plan.steps.entries()) {
|
|
417
|
+
lines.push(toonStep(step, i));
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
const help = buildContextualHelp({ command: "install" });
|
|
421
|
+
if (help.length > 0) {
|
|
422
|
+
lines.push("", formatHelp(help));
|
|
423
|
+
}
|
|
424
|
+
return lines.join(`
|
|
425
|
+
`);
|
|
426
|
+
}
|
|
427
|
+
function toonAddPlan(plan) {
|
|
428
|
+
const lines = [];
|
|
429
|
+
lines.push(`add: ${plan.name} | target: ${plan.target ?? "(choose)"}`);
|
|
430
|
+
if (plan.importStatement) {
|
|
431
|
+
lines.push(`import: ${plan.importStatement}`);
|
|
432
|
+
}
|
|
433
|
+
lines.push("");
|
|
434
|
+
if (plan.installPlan.steps.length > 0) {
|
|
435
|
+
lines.push(header("install-steps", plan.installPlan.steps.length, ["status", "title"]));
|
|
436
|
+
for (const [i, step] of plan.installPlan.steps.entries()) {
|
|
437
|
+
lines.push(toonStep(step, i));
|
|
438
|
+
}
|
|
439
|
+
lines.push("");
|
|
440
|
+
}
|
|
441
|
+
if (plan.steps.length > 0) {
|
|
442
|
+
lines.push(header("add-steps", plan.steps.length, ["status", "title"]));
|
|
443
|
+
for (const [i, step] of plan.steps.entries()) {
|
|
444
|
+
lines.push(toonStep(step, i));
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
if (plan.warnings.length > 0) {
|
|
448
|
+
lines.push("", header("warnings", plan.warnings.length, ["message"]));
|
|
449
|
+
for (const w of plan.warnings) {
|
|
450
|
+
lines.push(" " + w);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return lines.join(`
|
|
454
|
+
`);
|
|
455
|
+
}
|
|
456
|
+
function toonError(code, message, suggestions) {
|
|
457
|
+
const lines = [`error[1]{code,message}: ${esc(code)},${esc(message)}`];
|
|
458
|
+
if (suggestions?.length) {
|
|
459
|
+
lines.push(header("suggestions", suggestions.length, ["value"]));
|
|
460
|
+
for (const s of suggestions) {
|
|
461
|
+
lines.push(" " + s);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return lines.join(`
|
|
465
|
+
`);
|
|
466
|
+
}
|
|
467
|
+
export {
|
|
468
|
+
toonWorkspaceReport,
|
|
469
|
+
toonReviewResult,
|
|
470
|
+
toonProjectDetection,
|
|
471
|
+
toonInstallPlan,
|
|
472
|
+
toonError,
|
|
473
|
+
toonDiagnoseResult,
|
|
474
|
+
toonComposition,
|
|
475
|
+
toonComponentList,
|
|
476
|
+
toonComponent,
|
|
477
|
+
toonAddPlan,
|
|
478
|
+
formatHelp,
|
|
479
|
+
buildContextualHelp
|
|
480
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dryui/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"author": "Rob Balfre",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -66,11 +66,24 @@
|
|
|
66
66
|
"bun": "./src/spec-formatters.ts",
|
|
67
67
|
"types": "./dist/spec-formatters.d.ts",
|
|
68
68
|
"default": "./dist/spec-formatters.js"
|
|
69
|
+
},
|
|
70
|
+
"./toon": {
|
|
71
|
+
"bun": "./src/toon.ts",
|
|
72
|
+
"types": "./dist/toon.d.ts",
|
|
73
|
+
"default": "./dist/toon.js"
|
|
74
|
+
},
|
|
75
|
+
"./composition-search": {
|
|
76
|
+
"bun": "./src/composition-search.ts",
|
|
77
|
+
"types": "./dist/composition-search.d.ts",
|
|
78
|
+
"default": "./dist/composition-search.js"
|
|
69
79
|
}
|
|
70
80
|
},
|
|
71
81
|
"files": [
|
|
72
82
|
"dist"
|
|
73
83
|
],
|
|
84
|
+
"publishConfig": {
|
|
85
|
+
"access": "public"
|
|
86
|
+
},
|
|
74
87
|
"scripts": {
|
|
75
88
|
"generate-spec": "bun src/generate-spec.ts",
|
|
76
89
|
"generate-architecture": "bun src/generate-architecture.ts",
|
|
@@ -78,7 +91,7 @@
|
|
|
78
91
|
"generate-llms": "bun src/generate-llms-txt.ts",
|
|
79
92
|
"check:contract": "bun src/check-contract.ts",
|
|
80
93
|
"check": "bun run check:contract",
|
|
81
|
-
"build": "bun run generate-spec && bun run generate-architecture && bun run generate-contract && bun run generate-llms && mkdir -p dist && cp src/spec.json dist/spec.json && cp src/architecture.json dist/architecture.json && cp src/contract.v1.json dist/contract.v1.json && cp src/contract.v1.schema.json dist/contract.v1.schema.json && bun build src/index.ts src/architecture.ts src/reviewer.ts src/theme-checker.ts src/utils.ts src/project-planner.ts src/workspace-audit.ts src/spec-types.ts src/spec-formatters.ts src/composition-data.ts --outdir dist --root src --target node && printf '#!/usr/bin/env node\n' | cat - dist/index.js > dist/index.tmp && mv dist/index.tmp dist/index.js && bunx tsc -p tsconfig.build.json"
|
|
94
|
+
"build": "bun run generate-spec && bun run generate-architecture && bun run generate-contract && bun run generate-llms && mkdir -p dist && cp src/spec.json dist/spec.json && cp src/architecture.json dist/architecture.json && cp src/contract.v1.json dist/contract.v1.json && cp src/contract.v1.schema.json dist/contract.v1.schema.json && bun build src/index.ts src/architecture.ts src/reviewer.ts src/theme-checker.ts src/utils.ts src/project-planner.ts src/workspace-audit.ts src/spec-types.ts src/spec-formatters.ts src/composition-data.ts src/toon.ts src/composition-search.ts --outdir dist --root src --target node && printf '#!/usr/bin/env node\n' | cat - dist/index.js > dist/index.tmp && mv dist/index.tmp dist/index.js && bunx tsc -p tsconfig.build.json"
|
|
82
95
|
},
|
|
83
96
|
"dependencies": {
|
|
84
97
|
"@modelcontextprotocol/sdk": "^1.29.0",
|