@fragments-sdk/cli 0.7.0 → 0.7.2
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/LICENSE +77 -14
- package/dist/bin.js +247 -247
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-CVXKXVOY.js → chunk-3T6QL7IY.js} +47 -29
- package/dist/chunk-3T6QL7IY.js.map +1 -0
- package/dist/{chunk-7OPWMLOE.js → chunk-7KUSBMI4.js} +114 -112
- package/dist/chunk-7KUSBMI4.js.map +1 -0
- package/dist/{chunk-XHUDJNN3.js → chunk-DH4ETVSM.js} +18 -18
- package/dist/chunk-DH4ETVSM.js.map +1 -0
- package/dist/{chunk-RVRTRESS.js → chunk-DQHWLAUV.js} +29 -29
- package/dist/chunk-DQHWLAUV.js.map +1 -0
- package/dist/{chunk-6JBGU74P.js → chunk-GHYYFAQN.js} +23 -23
- package/dist/chunk-GHYYFAQN.js.map +1 -0
- package/dist/{chunk-NWQ4CJOQ.js → chunk-GKX2HPZ6.js} +40 -40
- package/dist/chunk-GKX2HPZ6.js.map +1 -0
- package/dist/{chunk-TJ34N7C7.js → chunk-OOGTG5FM.js} +34 -33
- package/dist/chunk-OOGTG5FM.js.map +1 -0
- package/dist/{core-W2HYIQW6.js → core-UQXZTBFZ.js} +24 -26
- package/dist/{generate-LMTISDIJ.js → generate-GP6ZLAQB.js} +5 -5
- package/dist/generate-GP6ZLAQB.js.map +1 -0
- package/dist/index.d.ts +23 -27
- package/dist/index.js +10 -10
- package/dist/{init-7CHRKQ7P.js → init-W72WBSU2.js} +5 -5
- package/dist/{init-7CHRKQ7P.js.map → init-W72WBSU2.js.map} +1 -1
- package/dist/mcp-bin.js +73 -73
- package/dist/mcp-bin.js.map +1 -1
- package/dist/scan-V54HWRDY.js +12 -0
- package/dist/{service-T2L7VLTE.js → service-PVGTYUKX.js} +6 -6
- package/dist/{static-viewer-GBR7YNF3.js → static-viewer-KILKIVN7.js} +4 -4
- package/dist/{test-OJRXNDO2.js → test-3YRYQRGV.js} +19 -19
- package/dist/test-3YRYQRGV.js.map +1 -0
- package/dist/{tokens-3BWDESVM.js → tokens-IXSQHPQK.js} +5 -5
- package/dist/{viewer-SUFOISZM.js → viewer-K42REJU2.js} +199 -199
- package/dist/viewer-K42REJU2.js.map +1 -0
- package/package.json +13 -2
- package/src/ai.ts +5 -5
- package/src/analyze.ts +11 -11
- package/src/bin.ts +1 -1
- package/src/build.ts +37 -35
- package/src/commands/a11y.ts +6 -6
- package/src/commands/add.ts +11 -11
- package/src/commands/audit.ts +4 -4
- package/src/commands/baseline.ts +3 -3
- package/src/commands/build.ts +8 -8
- package/src/commands/compare.ts +20 -20
- package/src/commands/context.ts +16 -16
- package/src/commands/enhance.ts +36 -36
- package/src/commands/generate.ts +1 -1
- package/src/commands/graph.ts +5 -5
- package/src/commands/init.ts +1 -1
- package/src/commands/link/figma.ts +82 -82
- package/src/commands/link/index.ts +3 -3
- package/src/commands/link/storybook.ts +9 -9
- package/src/commands/list.ts +2 -2
- package/src/commands/reset.ts +15 -15
- package/src/commands/scan.ts +27 -27
- package/src/commands/storygen.ts +24 -24
- package/src/commands/validate.ts +2 -2
- package/src/commands/verify.ts +8 -8
- package/src/core/auto-props.ts +4 -4
- package/src/core/composition.test.ts +36 -36
- package/src/core/composition.ts +19 -19
- package/src/core/config.ts +6 -6
- package/src/core/{defineSegment.ts → defineFragment.ts} +16 -22
- package/src/core/discovery.ts +6 -6
- package/src/core/figma.ts +2 -2
- package/src/core/graph-extractor.test.ts +77 -77
- package/src/core/graph-extractor.ts +32 -32
- package/src/core/importAnalyzer.ts +1 -1
- package/src/core/index.ts +22 -23
- package/src/core/loader.ts +21 -24
- package/src/core/node.ts +5 -5
- package/src/core/parser.ts +71 -31
- package/src/core/previewLoader.ts +1 -1
- package/src/core/schema.ts +16 -16
- package/src/core/storyAdapter.test.ts +87 -87
- package/src/core/storyAdapter.ts +16 -16
- package/src/core/token-parser.ts +9 -1
- package/src/core/types.ts +21 -26
- package/src/diff.ts +22 -22
- package/src/index.ts +2 -2
- package/src/mcp/server.ts +80 -80
- package/src/migrate/__tests__/utils/utils.test.ts +3 -3
- package/src/migrate/bin.ts +4 -4
- package/src/migrate/converter.ts +16 -16
- package/src/migrate/index.ts +3 -3
- package/src/migrate/migrate.ts +3 -3
- package/src/migrate/parser.ts +8 -8
- package/src/migrate/report.ts +2 -2
- package/src/migrate/types.ts +4 -4
- package/src/screenshot.ts +22 -22
- package/src/service/__tests__/props-extractor.test.ts +15 -15
- package/src/service/analytics.ts +39 -39
- package/src/service/enhance/codebase-scanner.ts +1 -1
- package/src/service/enhance/index.ts +1 -1
- package/src/service/enhance/props-extractor.ts +2 -2
- package/src/service/enhance/types.ts +2 -2
- package/src/service/index.ts +2 -2
- package/src/service/metrics-store.ts +1 -1
- package/src/service/patch-generator.ts +1 -1
- package/src/setup.ts +52 -52
- package/src/shared/dev-server-client.ts +7 -7
- package/src/shared/fragment-loader.ts +59 -0
- package/src/shared/index.ts +1 -1
- package/src/shared/types.ts +4 -4
- package/src/static-viewer.ts +35 -35
- package/src/test/discovery.ts +6 -6
- package/src/test/index.ts +5 -5
- package/src/test/reporters/console.ts +1 -1
- package/src/test/reporters/junit.ts +1 -1
- package/src/test/runner.ts +7 -7
- package/src/test/types.ts +3 -3
- package/src/test/watch.ts +9 -9
- package/src/validators.ts +26 -26
- package/src/viewer/__tests__/render-utils.test.ts +28 -28
- package/src/viewer/__tests__/viewer-integration.test.ts +4 -4
- package/src/viewer/cli/health.ts +26 -26
- package/src/viewer/components/App.tsx +79 -79
- package/src/viewer/components/BottomPanel.tsx +17 -17
- package/src/viewer/components/CodePanel.tsx +3 -3
- package/src/viewer/components/CommandPalette.tsx +11 -11
- package/src/viewer/components/ComponentGraph.tsx +28 -28
- package/src/viewer/components/ComponentHeader.tsx +2 -2
- package/src/viewer/components/ContractPanel.tsx +6 -6
- package/src/viewer/components/FigmaEmbed.tsx +9 -9
- package/src/viewer/components/HealthDashboard.tsx +17 -17
- package/src/viewer/components/InteractionsPanel.tsx +2 -2
- package/src/viewer/components/IsolatedPreviewFrame.tsx +6 -6
- package/src/viewer/components/IsolatedRender.tsx +10 -10
- package/src/viewer/components/LeftSidebar.tsx +28 -28
- package/src/viewer/components/MultiViewportPreview.tsx +14 -14
- package/src/viewer/components/PreviewArea.tsx +11 -11
- package/src/viewer/components/PreviewFrameHost.tsx +51 -51
- package/src/viewer/components/RightSidebar.tsx +9 -9
- package/src/viewer/components/Sidebar.tsx +17 -17
- package/src/viewer/components/StoryRenderer.tsx +2 -2
- package/src/viewer/components/TokenStylePanel.tsx +1 -1
- package/src/viewer/components/UsageSection.tsx +2 -2
- package/src/viewer/components/VariantMatrix.tsx +11 -11
- package/src/viewer/components/VariantRenderer.tsx +3 -3
- package/src/viewer/components/VariantTabs.tsx +2 -2
- package/src/viewer/components/_future/CreatePage.tsx +6 -6
- package/src/viewer/composition-renderer.ts +11 -11
- package/src/viewer/entry.tsx +40 -40
- package/src/viewer/hooks/useFigmaIntegration.ts +1 -1
- package/src/viewer/hooks/usePreviewBridge.ts +5 -5
- package/src/viewer/hooks/useUrlState.ts +6 -6
- package/src/viewer/index.ts +2 -2
- package/src/viewer/intelligence/healthReport.ts +17 -17
- package/src/viewer/intelligence/styleDrift.ts +1 -1
- package/src/viewer/intelligence/usageScanner.ts +1 -1
- package/src/viewer/render-template.html +1 -1
- package/src/viewer/render-utils.ts +21 -21
- package/src/viewer/server.ts +18 -18
- package/src/viewer/utils/detectRelationships.ts +22 -22
- package/src/viewer/vite-plugin.ts +213 -213
- package/dist/chunk-6JBGU74P.js.map +0 -1
- package/dist/chunk-7OPWMLOE.js.map +0 -1
- package/dist/chunk-CVXKXVOY.js.map +0 -1
- package/dist/chunk-NWQ4CJOQ.js.map +0 -1
- package/dist/chunk-RVRTRESS.js.map +0 -1
- package/dist/chunk-TJ34N7C7.js.map +0 -1
- package/dist/chunk-XHUDJNN3.js.map +0 -1
- package/dist/generate-LMTISDIJ.js.map +0 -1
- package/dist/scan-WY23TJCP.js +0 -12
- package/dist/test-OJRXNDO2.js.map +0 -1
- package/dist/viewer-SUFOISZM.js.map +0 -1
- package/src/shared/segment-loader.ts +0 -59
- /package/dist/{core-W2HYIQW6.js.map → core-UQXZTBFZ.js.map} +0 -0
- /package/dist/{scan-WY23TJCP.js.map → scan-V54HWRDY.js.map} +0 -0
- /package/dist/{service-T2L7VLTE.js.map → service-PVGTYUKX.js.map} +0 -0
- /package/dist/{static-viewer-GBR7YNF3.js.map → static-viewer-KILKIVN7.js.map} +0 -0
- /package/dist/{tokens-3BWDESVM.js.map → tokens-IXSQHPQK.js.map} +0 -0
package/dist/mcp-bin.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
generateContext
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-OOGTG5FM.js";
|
|
6
6
|
import {
|
|
7
7
|
BRAND,
|
|
8
8
|
DEFAULTS
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-GHYYFAQN.js";
|
|
10
10
|
|
|
11
11
|
// src/mcp/server.ts
|
|
12
12
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -58,7 +58,7 @@ var _service = null;
|
|
|
58
58
|
async function getService() {
|
|
59
59
|
if (!_service) {
|
|
60
60
|
try {
|
|
61
|
-
_service = await import("./service-
|
|
61
|
+
_service = await import("./service-PVGTYUKX.js");
|
|
62
62
|
} catch {
|
|
63
63
|
throw new Error(
|
|
64
64
|
"Visual tools require playwright. Install it with: npm install playwright"
|
|
@@ -230,16 +230,16 @@ function createMcpServer(config) {
|
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
232
|
);
|
|
233
|
-
let
|
|
234
|
-
const
|
|
233
|
+
let fragmentsData = null;
|
|
234
|
+
const fragmentPackageMap = /* @__PURE__ */ new Map();
|
|
235
235
|
let defaultPackageName = null;
|
|
236
236
|
let browserPool = null;
|
|
237
237
|
let storageManager = null;
|
|
238
238
|
let diffEngine = null;
|
|
239
239
|
let isPoolWarming = false;
|
|
240
|
-
async function
|
|
241
|
-
if (
|
|
242
|
-
return
|
|
240
|
+
async function loadFragments() {
|
|
241
|
+
if (fragmentsData) {
|
|
242
|
+
return fragmentsData;
|
|
243
243
|
}
|
|
244
244
|
const paths = findFragmentsJson(config.projectRoot);
|
|
245
245
|
if (paths.length === 0) {
|
|
@@ -248,41 +248,41 @@ function createMcpServer(config) {
|
|
|
248
248
|
);
|
|
249
249
|
}
|
|
250
250
|
const content = await readFile(paths[0], "utf-8");
|
|
251
|
-
|
|
252
|
-
if (!
|
|
253
|
-
|
|
251
|
+
fragmentsData = JSON.parse(content);
|
|
252
|
+
if (!fragmentsData.blocks && fragmentsData.recipes) {
|
|
253
|
+
fragmentsData.blocks = fragmentsData.recipes;
|
|
254
254
|
}
|
|
255
|
-
if (
|
|
256
|
-
for (const name of Object.keys(
|
|
257
|
-
|
|
255
|
+
if (fragmentsData.packageName) {
|
|
256
|
+
for (const name of Object.keys(fragmentsData.fragments)) {
|
|
257
|
+
fragmentPackageMap.set(name, fragmentsData.packageName);
|
|
258
258
|
}
|
|
259
259
|
}
|
|
260
260
|
for (let i = 1; i < paths.length; i++) {
|
|
261
261
|
const extra = JSON.parse(await readFile(paths[i], "utf-8"));
|
|
262
262
|
if (extra.packageName) {
|
|
263
|
-
for (const name of Object.keys(extra.
|
|
264
|
-
|
|
263
|
+
for (const name of Object.keys(extra.fragments)) {
|
|
264
|
+
fragmentPackageMap.set(name, extra.packageName);
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
|
-
Object.assign(
|
|
267
|
+
Object.assign(fragmentsData.fragments, extra.fragments);
|
|
268
268
|
const extraBlocks = extra.blocks ?? extra.recipes;
|
|
269
269
|
if (extraBlocks) {
|
|
270
|
-
|
|
270
|
+
fragmentsData.blocks = { ...fragmentsData.blocks, ...extraBlocks };
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
|
-
return
|
|
273
|
+
return fragmentsData;
|
|
274
274
|
}
|
|
275
|
-
async function getPackageName(
|
|
276
|
-
await
|
|
277
|
-
if (
|
|
278
|
-
const segPkg =
|
|
275
|
+
async function getPackageName(fragmentName) {
|
|
276
|
+
await loadFragments();
|
|
277
|
+
if (fragmentName) {
|
|
278
|
+
const segPkg = fragmentPackageMap.get(fragmentName);
|
|
279
279
|
if (segPkg) return segPkg;
|
|
280
280
|
}
|
|
281
281
|
if (defaultPackageName) {
|
|
282
282
|
return defaultPackageName;
|
|
283
283
|
}
|
|
284
|
-
if (
|
|
285
|
-
defaultPackageName =
|
|
284
|
+
if (fragmentsData?.packageName) {
|
|
285
|
+
defaultPackageName = fragmentsData.packageName;
|
|
286
286
|
return defaultPackageName;
|
|
287
287
|
}
|
|
288
288
|
const packageJsonPath = join(config.projectRoot, "package.json");
|
|
@@ -356,7 +356,7 @@ function createMcpServer(config) {
|
|
|
356
356
|
// DISCOVER — list, suggest, context, alternatives
|
|
357
357
|
// ================================================================
|
|
358
358
|
case TOOL_NAMES.discover: {
|
|
359
|
-
const data = await
|
|
359
|
+
const data = await loadFragments();
|
|
360
360
|
const useCase = args2?.useCase ?? void 0;
|
|
361
361
|
const componentForAlts = args2?.component ?? void 0;
|
|
362
362
|
const category = args2?.category ?? void 0;
|
|
@@ -367,9 +367,9 @@ function createMcpServer(config) {
|
|
|
367
367
|
const includeCode = args2?.includeCode ?? false;
|
|
368
368
|
const includeRelations = args2?.includeRelations ?? false;
|
|
369
369
|
if (compact || args2?.format && !useCase && !componentForAlts && !category && !search && !status) {
|
|
370
|
-
const
|
|
370
|
+
const fragments2 = Object.values(data.fragments);
|
|
371
371
|
const allBlocks = Object.values(data.blocks ?? data.recipes ?? {});
|
|
372
|
-
const { content: ctxContent, tokenEstimate } = generateContext(
|
|
372
|
+
const { content: ctxContent, tokenEstimate } = generateContext(fragments2, {
|
|
373
373
|
format,
|
|
374
374
|
compact,
|
|
375
375
|
include: {
|
|
@@ -411,7 +411,7 @@ function createMcpServer(config) {
|
|
|
411
411
|
synonyms.forEach((syn) => expandedTerms.add(syn));
|
|
412
412
|
}
|
|
413
413
|
});
|
|
414
|
-
const scored = Object.values(data.
|
|
414
|
+
const scored = Object.values(data.fragments).map((s) => {
|
|
415
415
|
let score = 0;
|
|
416
416
|
const reasons = [];
|
|
417
417
|
const nameLower = s.meta.name.toLowerCase();
|
|
@@ -535,14 +535,14 @@ function createMcpServer(config) {
|
|
|
535
535
|
};
|
|
536
536
|
}
|
|
537
537
|
if (componentForAlts) {
|
|
538
|
-
const
|
|
538
|
+
const fragment = Object.values(data.fragments).find(
|
|
539
539
|
(s) => s.meta.name.toLowerCase() === componentForAlts.toLowerCase()
|
|
540
540
|
);
|
|
541
|
-
if (!
|
|
541
|
+
if (!fragment) {
|
|
542
542
|
throw new Error(`Component "${componentForAlts}" not found. Use fragments_discover to see available components.`);
|
|
543
543
|
}
|
|
544
|
-
const relations =
|
|
545
|
-
const referencedBy = Object.values(data.
|
|
544
|
+
const relations = fragment.relations ?? [];
|
|
545
|
+
const referencedBy = Object.values(data.fragments).filter(
|
|
546
546
|
(s) => s.relations?.some((r) => r.component.toLowerCase() === componentForAlts.toLowerCase())
|
|
547
547
|
).map((s) => ({
|
|
548
548
|
component: s.meta.name,
|
|
@@ -553,8 +553,8 @@ function createMcpServer(config) {
|
|
|
553
553
|
(r) => r.component.toLowerCase() === componentForAlts.toLowerCase()
|
|
554
554
|
)?.note
|
|
555
555
|
}));
|
|
556
|
-
const sameCategory = Object.values(data.
|
|
557
|
-
(s) => s.meta.category ===
|
|
556
|
+
const sameCategory = Object.values(data.fragments).filter(
|
|
557
|
+
(s) => s.meta.category === fragment.meta.category && s.meta.name.toLowerCase() !== componentForAlts.toLowerCase()
|
|
558
558
|
).map((s) => ({
|
|
559
559
|
component: s.meta.name,
|
|
560
560
|
description: s.meta.description
|
|
@@ -563,8 +563,8 @@ function createMcpServer(config) {
|
|
|
563
563
|
content: [{
|
|
564
564
|
type: "text",
|
|
565
565
|
text: JSON.stringify({
|
|
566
|
-
component:
|
|
567
|
-
category:
|
|
566
|
+
component: fragment.meta.name,
|
|
567
|
+
category: fragment.meta.category,
|
|
568
568
|
directRelations: relations,
|
|
569
569
|
referencedBy,
|
|
570
570
|
sameCategory,
|
|
@@ -573,7 +573,7 @@ function createMcpServer(config) {
|
|
|
573
573
|
}]
|
|
574
574
|
};
|
|
575
575
|
}
|
|
576
|
-
const
|
|
576
|
+
const fragments = Object.values(data.fragments).filter((s) => {
|
|
577
577
|
if (category && s.meta.category !== category) return false;
|
|
578
578
|
if (status && (s.meta.status ?? "stable") !== status) return false;
|
|
579
579
|
if (search) {
|
|
@@ -595,10 +595,10 @@ function createMcpServer(config) {
|
|
|
595
595
|
content: [{
|
|
596
596
|
type: "text",
|
|
597
597
|
text: JSON.stringify({
|
|
598
|
-
total:
|
|
599
|
-
|
|
600
|
-
categories: [...new Set(
|
|
601
|
-
hint:
|
|
598
|
+
total: fragments.length,
|
|
599
|
+
fragments,
|
|
600
|
+
categories: [...new Set(fragments.map((s) => s.category))],
|
|
601
|
+
hint: fragments.length === 0 ? "No components found. Try broader search terms or check available categories." : fragments.length > 5 ? "Use fragments_discover with useCase for recommendations, or fragments_inspect for details on a specific component." : void 0
|
|
602
602
|
}, null, 2)
|
|
603
603
|
}]
|
|
604
604
|
};
|
|
@@ -607,7 +607,7 @@ function createMcpServer(config) {
|
|
|
607
607
|
// INSPECT — get + guidelines + example in one call
|
|
608
608
|
// ================================================================
|
|
609
609
|
case TOOL_NAMES.inspect: {
|
|
610
|
-
const data = await
|
|
610
|
+
const data = await loadFragments();
|
|
611
611
|
const componentName = args2?.component;
|
|
612
612
|
const fields = args2?.fields;
|
|
613
613
|
const variantName = args2?.variant ?? void 0;
|
|
@@ -616,14 +616,14 @@ function createMcpServer(config) {
|
|
|
616
616
|
if (!componentName) {
|
|
617
617
|
throw new Error("component is required");
|
|
618
618
|
}
|
|
619
|
-
const
|
|
619
|
+
const fragment = Object.values(data.fragments).find(
|
|
620
620
|
(s) => s.meta.name.toLowerCase() === componentName.toLowerCase()
|
|
621
621
|
);
|
|
622
|
-
if (!
|
|
622
|
+
if (!fragment) {
|
|
623
623
|
throw new Error(`Component "${componentName}" not found. Use fragments_discover to see available components.`);
|
|
624
624
|
}
|
|
625
|
-
const pkgName = await getPackageName(
|
|
626
|
-
let variants =
|
|
625
|
+
const pkgName = await getPackageName(fragment.meta.name);
|
|
626
|
+
let variants = fragment.variants;
|
|
627
627
|
if (variantName) {
|
|
628
628
|
const query = variantName.toLowerCase();
|
|
629
629
|
let filtered = variants.filter(
|
|
@@ -643,7 +643,7 @@ function createMcpServer(config) {
|
|
|
643
643
|
variants = filtered;
|
|
644
644
|
} else {
|
|
645
645
|
throw new Error(
|
|
646
|
-
`Variant "${variantName}" not found for ${componentName}. Available: ${
|
|
646
|
+
`Variant "${variantName}" not found for ${componentName}. Available: ${fragment.variants.map((v) => v.name).join(", ")}`
|
|
647
647
|
);
|
|
648
648
|
}
|
|
649
649
|
}
|
|
@@ -667,44 +667,44 @@ function createMcpServer(config) {
|
|
|
667
667
|
return {
|
|
668
668
|
variant: variant.name,
|
|
669
669
|
description: variant.description,
|
|
670
|
-
code: `<${
|
|
670
|
+
code: `<${fragment.meta.name} />`,
|
|
671
671
|
note: "No code example provided in fragment. Refer to props for customization."
|
|
672
672
|
};
|
|
673
673
|
});
|
|
674
|
-
const propsReference = Object.entries(
|
|
674
|
+
const propsReference = Object.entries(fragment.props ?? {}).map(([propName, prop]) => ({
|
|
675
675
|
name: propName,
|
|
676
676
|
type: prop.type,
|
|
677
677
|
required: prop.required,
|
|
678
678
|
default: prop.default,
|
|
679
679
|
description: prop.description
|
|
680
680
|
}));
|
|
681
|
-
const propConstraints = Object.entries(
|
|
681
|
+
const propConstraints = Object.entries(fragment.props ?? {}).filter(([, prop]) => prop.constraints && prop.constraints.length > 0).map(([pName, prop]) => ({
|
|
682
682
|
prop: pName,
|
|
683
683
|
constraints: prop.constraints
|
|
684
684
|
}));
|
|
685
685
|
const fullResult = {
|
|
686
686
|
// Component data (from old "get")
|
|
687
|
-
meta:
|
|
688
|
-
props:
|
|
689
|
-
variants:
|
|
690
|
-
relations:
|
|
691
|
-
contract:
|
|
692
|
-
generated:
|
|
687
|
+
meta: fragment.meta,
|
|
688
|
+
props: fragment.props,
|
|
689
|
+
variants: fragment.variants,
|
|
690
|
+
relations: fragment.relations,
|
|
691
|
+
contract: fragment.contract,
|
|
692
|
+
generated: fragment._generated,
|
|
693
693
|
// Guidelines (from old "guidelines")
|
|
694
694
|
guidelines: {
|
|
695
|
-
when: filterPlaceholders(
|
|
696
|
-
whenNot: filterPlaceholders(
|
|
697
|
-
guidelines:
|
|
698
|
-
accessibility:
|
|
695
|
+
when: filterPlaceholders(fragment.usage?.when),
|
|
696
|
+
whenNot: filterPlaceholders(fragment.usage?.whenNot),
|
|
697
|
+
guidelines: fragment.usage?.guidelines ?? [],
|
|
698
|
+
accessibility: fragment.usage?.accessibility ?? [],
|
|
699
699
|
propConstraints,
|
|
700
|
-
alternatives:
|
|
700
|
+
alternatives: fragment.relations?.filter((r) => r.relationship === "alternative").map((r) => ({
|
|
701
701
|
component: r.component,
|
|
702
702
|
note: r.note
|
|
703
703
|
})) ?? []
|
|
704
704
|
},
|
|
705
705
|
// Examples (from old "example")
|
|
706
706
|
examples: {
|
|
707
|
-
import: `import { ${
|
|
707
|
+
import: `import { ${fragment.meta.name} } from '${pkgName}';`,
|
|
708
708
|
code: examples,
|
|
709
709
|
propsReference
|
|
710
710
|
}
|
|
@@ -721,7 +721,7 @@ function createMcpServer(config) {
|
|
|
721
721
|
// BLOCKS — composition patterns
|
|
722
722
|
// ================================================================
|
|
723
723
|
case TOOL_NAMES.blocks: {
|
|
724
|
-
const data = await
|
|
724
|
+
const data = await loadFragments();
|
|
725
725
|
const blockName = args2?.name;
|
|
726
726
|
const search = args2?.search?.toLowerCase() ?? void 0;
|
|
727
727
|
const component = args2?.component?.toLowerCase() ?? void 0;
|
|
@@ -781,7 +781,7 @@ function createMcpServer(config) {
|
|
|
781
781
|
// TOKENS — list CSS custom properties by category
|
|
782
782
|
// ================================================================
|
|
783
783
|
case TOOL_NAMES.tokens: {
|
|
784
|
-
const data = await
|
|
784
|
+
const data = await loadFragments();
|
|
785
785
|
const category = args2?.category?.toLowerCase() ?? void 0;
|
|
786
786
|
const search = args2?.search?.toLowerCase() ?? void 0;
|
|
787
787
|
const tokenData = data.tokens;
|
|
@@ -841,7 +841,7 @@ function createMcpServer(config) {
|
|
|
841
841
|
// IMPLEMENT — one-shot discover + inspect + blocks + tokens
|
|
842
842
|
// ================================================================
|
|
843
843
|
case TOOL_NAMES.implement: {
|
|
844
|
-
const data = await
|
|
844
|
+
const data = await loadFragments();
|
|
845
845
|
const useCase = args2?.useCase;
|
|
846
846
|
if (!useCase) {
|
|
847
847
|
throw new Error("useCase is required");
|
|
@@ -866,7 +866,7 @@ function createMcpServer(config) {
|
|
|
866
866
|
const synonyms = synonymMap[term];
|
|
867
867
|
if (synonyms) synonyms.forEach((syn) => expandedTerms.add(syn));
|
|
868
868
|
});
|
|
869
|
-
const scored = Object.values(data.
|
|
869
|
+
const scored = Object.values(data.fragments).map((s) => {
|
|
870
870
|
let score = 0;
|
|
871
871
|
const nameLower = s.meta.name.toLowerCase();
|
|
872
872
|
if (searchTerms.some((t) => nameLower.includes(t))) score += 15;
|
|
@@ -881,11 +881,11 @@ function createMcpServer(config) {
|
|
|
881
881
|
if (s.meta.category && searchTerms.some((t) => s.meta.category.toLowerCase().includes(t))) score += 8;
|
|
882
882
|
if (s.meta.status === "stable") score += 5;
|
|
883
883
|
if (s.meta.status === "deprecated") score -= 25;
|
|
884
|
-
return {
|
|
884
|
+
return { fragment: s, score };
|
|
885
885
|
});
|
|
886
886
|
const topMatches = scored.filter((s) => s.score >= 8).sort((a, b) => b.score - a.score).slice(0, 3);
|
|
887
887
|
const components = await Promise.all(
|
|
888
|
-
topMatches.map(async ({
|
|
888
|
+
topMatches.map(async ({ fragment: s, score }) => {
|
|
889
889
|
const pkgName = await getPackageName(s.meta.name);
|
|
890
890
|
const examples = s.variants.slice(0, 2).map((v) => ({
|
|
891
891
|
variant: v.name,
|
|
@@ -910,7 +910,7 @@ function createMcpServer(config) {
|
|
|
910
910
|
const allBlocks = Object.values(data.blocks ?? data.recipes ?? {});
|
|
911
911
|
const matchingBlocks = allBlocks.filter((b) => {
|
|
912
912
|
const haystack = [b.name, b.description, ...b.tags ?? [], ...b.components, b.category].join(" ").toLowerCase();
|
|
913
|
-
return searchTerms.some((t) => haystack.includes(t)) || topMatches.some(({
|
|
913
|
+
return searchTerms.some((t) => haystack.includes(t)) || topMatches.some(({ fragment }) => b.components.some((c) => c.toLowerCase() === fragment.meta.name.toLowerCase()));
|
|
914
914
|
}).slice(0, 2).map((b) => ({ name: b.name, description: b.description, components: b.components, code: b.code }));
|
|
915
915
|
const tokenData = data.tokens;
|
|
916
916
|
let relevantTokens;
|
|
@@ -1147,17 +1147,17 @@ Suggestion: ${result.suggestion}` : ""}`
|
|
|
1147
1147
|
// FIX — unchanged
|
|
1148
1148
|
// ================================================================
|
|
1149
1149
|
case TOOL_NAMES.fix: {
|
|
1150
|
-
const data = await
|
|
1150
|
+
const data = await loadFragments();
|
|
1151
1151
|
const componentName = args2?.component;
|
|
1152
1152
|
const variantName = args2?.variant ?? void 0;
|
|
1153
1153
|
const fixType = args2?.fixType ?? "all";
|
|
1154
1154
|
if (!componentName) {
|
|
1155
1155
|
throw new Error("component is required");
|
|
1156
1156
|
}
|
|
1157
|
-
const
|
|
1157
|
+
const fragment = Object.values(data.fragments).find(
|
|
1158
1158
|
(s) => s.meta.name.toLowerCase() === componentName.toLowerCase()
|
|
1159
1159
|
);
|
|
1160
|
-
if (!
|
|
1160
|
+
if (!fragment) {
|
|
1161
1161
|
throw new Error(`Component "${componentName}" not found. Use fragments_discover to see available components.`);
|
|
1162
1162
|
}
|
|
1163
1163
|
const baseUrl = config.viewerUrl ?? "http://localhost:6006";
|