@taocompany/magic-grid-mcp 0.0.0-stage → 0.14.1

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.
Files changed (40) hide show
  1. package/bin/magic-grid-mcp.js +7 -0
  2. package/bin/mgc.js +2 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +43 -0
  6. package/dist/index.d.ts +8 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +5 -0
  9. package/dist/mcpServer.d.ts +7 -0
  10. package/dist/mcpServer.d.ts.map +1 -0
  11. package/dist/mcpServer.js +105 -0
  12. package/dist/packageVersion.d.ts +3 -0
  13. package/dist/packageVersion.d.ts.map +1 -0
  14. package/dist/packageVersion.js +10 -0
  15. package/dist/resolveManifest.d.ts +25 -0
  16. package/dist/resolveManifest.d.ts.map +1 -0
  17. package/dist/resolveManifest.js +169 -0
  18. package/dist/scan/collectSourceFiles.d.ts +2 -0
  19. package/dist/scan/collectSourceFiles.d.ts.map +1 -0
  20. package/dist/scan/collectSourceFiles.js +30 -0
  21. package/dist/scan/parseMagicGrid.d.ts +18 -0
  22. package/dist/scan/parseMagicGrid.d.ts.map +1 -0
  23. package/dist/scan/parseMagicGrid.js +85 -0
  24. package/dist/tools/findRecipes.d.ts +19 -0
  25. package/dist/tools/findRecipes.d.ts.map +1 -0
  26. package/dist/tools/findRecipes.js +104 -0
  27. package/dist/tools/getComponentApi.d.ts +33 -0
  28. package/dist/tools/getComponentApi.d.ts.map +1 -0
  29. package/dist/tools/getComponentApi.js +138 -0
  30. package/dist/types.d.ts +110 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/types.js +1 -0
  33. package/dist/validate/propTypeLiteral.d.ts +4 -0
  34. package/dist/validate/propTypeLiteral.d.ts.map +1 -0
  35. package/dist/validate/propTypeLiteral.js +48 -0
  36. package/dist/validate/validateUsage.d.ts +9 -0
  37. package/dist/validate/validateUsage.d.ts.map +1 -0
  38. package/dist/validate/validateUsage.js +342 -0
  39. package/package.json +52 -4
  40. package/README.md +0 -3
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { runMcpServer } from '../dist/mcpServer.js'
3
+
4
+ runMcpServer().catch((error) => {
5
+ console.error(error instanceof Error ? error.message : error)
6
+ process.exit(1)
7
+ })
package/bin/mgc.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/cli.js'
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,43 @@
1
+ import { resolveManifest, runDoctor } from './resolveManifest.js';
2
+ import { validateMagicGridUsage } from './validate/validateUsage.js';
3
+ function printUsage() {
4
+ console.log(`@taocompany/magic-grid-mcp · mgc
5
+
6
+ 用法:
7
+ mgc check [paths...] 静态校验 MagicGrid 用法(默认 ./src)
8
+ mgc doctor 检查已安装的 magic-grid 与 manifest 解析
9
+
10
+ 示例:
11
+ npx @taocompany/magic-grid-mcp check ./src
12
+ npx @taocompany/magic-grid-mcp doctor
13
+ `);
14
+ }
15
+ async function main() {
16
+ const [, , command, ...rest] = process.argv;
17
+ if (!command || command === '--help' || command === '-h') {
18
+ printUsage();
19
+ process.exit(0);
20
+ }
21
+ if (command === 'doctor') {
22
+ const report = runDoctor();
23
+ console.log(JSON.stringify(report, null, 2));
24
+ process.exit(report.manifestExists || report.source === 'package-parse' ? 0 : 1);
25
+ }
26
+ if (command === 'check') {
27
+ const paths = rest.length > 0 ? rest : ['./src'];
28
+ try {
29
+ const resolved = resolveManifest();
30
+ const result = validateMagicGridUsage(resolved, { paths, cwd: process.cwd() });
31
+ console.log(JSON.stringify(result, null, 2));
32
+ process.exit(result.score === 'fail' ? 1 : 0);
33
+ }
34
+ catch (error) {
35
+ console.error(error instanceof Error ? error.message : error);
36
+ process.exit(2);
37
+ }
38
+ }
39
+ console.error(`未知命令: ${command}`);
40
+ printUsage();
41
+ process.exit(2);
42
+ }
43
+ main();
@@ -0,0 +1,8 @@
1
+ export { resolveManifest, runDoctor, findMagicGridPackageRoot, type ResolveManifestResult, } from './resolveManifest.js';
2
+ export { getComponentApi } from './tools/getComponentApi.js';
3
+ export { findRecipes } from './tools/findRecipes.js';
4
+ export { createMcpServer, runMcpServer, MCP_TOOL_NAMES } from './mcpServer.js';
5
+ export type { McpToolName } from './mcpServer.js';
6
+ export { validateMagicGridUsage } from './validate/validateUsage.js';
7
+ export type { ApiManifest, ValidateUsageResult, ValidationIssue, UncheckedItem, } from './types.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,SAAS,EACT,wBAAwB,EACxB,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC9E,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACpE,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,aAAa,GACd,MAAM,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { resolveManifest, runDoctor, findMagicGridPackageRoot, } from './resolveManifest.js';
2
+ export { getComponentApi } from './tools/getComponentApi.js';
3
+ export { findRecipes } from './tools/findRecipes.js';
4
+ export { createMcpServer, runMcpServer, MCP_TOOL_NAMES } from './mcpServer.js';
5
+ export { validateMagicGridUsage } from './validate/validateUsage.js';
@@ -0,0 +1,7 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ /** P1 DoD:stdio 暴露的三个 tool(与四家客户端配置文档一致) */
3
+ export declare const MCP_TOOL_NAMES: readonly ["get_component_api", "find_recipes", "validate_magic_grid_usage"];
4
+ export type McpToolName = (typeof MCP_TOOL_NAMES)[number];
5
+ export declare function createMcpServer(cwd?: string): McpServer;
6
+ export declare function runMcpServer(cwd?: string): Promise<void>;
7
+ //# sourceMappingURL=mcpServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpServer.d.ts","sourceRoot":"","sources":["../src/mcpServer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAgBnE,4CAA4C;AAC5C,eAAO,MAAM,cAAc,6EAIjB,CAAA;AAEV,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;AAgCzD,wBAAgB,eAAe,CAAC,GAAG,SAAgB,GAAG,SAAS,CAwF9D;AAED,wBAAsB,YAAY,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAIrE"}
@@ -0,0 +1,105 @@
1
+ // MCP SDK + Zod tool schemas trigger TS2589 in strict mode; runtime types are validated by Zod.
2
+ // @ts-nocheck
3
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
+ import { z } from 'zod';
6
+ import { resolveManifest } from './resolveManifest.js';
7
+ import { getComponentApi, } from './tools/getComponentApi.js';
8
+ import { findRecipes } from './tools/findRecipes.js';
9
+ import { readMcpPackageVersion } from './packageVersion.js';
10
+ import { validateMagicGridUsage } from './validate/validateUsage.js';
11
+ const SERVER_VERSION = readMcpPackageVersion();
12
+ /** P1 DoD:stdio 暴露的三个 tool(与四家客户端配置文档一致) */
13
+ export const MCP_TOOL_NAMES = [
14
+ 'get_component_api',
15
+ 'find_recipes',
16
+ 'validate_magic_grid_usage',
17
+ ];
18
+ const API_SECTIONS = [
19
+ 'props',
20
+ 'emits',
21
+ 'slots',
22
+ 'api',
23
+ 'expose',
24
+ 'types',
25
+ 'columnDef',
26
+ ];
27
+ function jsonText(value) {
28
+ return {
29
+ content: [{ type: 'text', text: JSON.stringify(value, null, 2) }],
30
+ };
31
+ }
32
+ function parseGetComponentApiInput(raw) {
33
+ const input = {};
34
+ if (typeof raw.section === 'string' && API_SECTIONS.includes(raw.section)) {
35
+ input.section = raw.section;
36
+ }
37
+ if (Array.isArray(raw.names)) {
38
+ input.names = raw.names.filter((n) => typeof n === 'string');
39
+ }
40
+ if (typeof raw.query === 'string') {
41
+ input.query = raw.query;
42
+ }
43
+ return input;
44
+ }
45
+ export function createMcpServer(cwd = process.cwd()) {
46
+ const resolved = resolveManifest(cwd);
47
+ const { manifest, source } = resolved;
48
+ const server = new McpServer({ name: '@taocompany/magic-grid-mcp', version: SERVER_VERSION }, { capabilities: { resources: {} } });
49
+ server.resource('version', 'magic-grid://version', {
50
+ description: 'Installed magic-grid version and manifest resolution source',
51
+ }, async () => ({
52
+ contents: [
53
+ {
54
+ uri: 'magic-grid://version',
55
+ mimeType: 'application/json',
56
+ text: JSON.stringify({
57
+ mcpPackageVersion: SERVER_VERSION,
58
+ libraryVersion: manifest.libraryVersion,
59
+ manifestVersion: manifest.manifestVersion,
60
+ source,
61
+ manifestPath: resolved.manifestPath,
62
+ packageRoot: resolved.packageRoot,
63
+ }, null, 2),
64
+ },
65
+ ],
66
+ }));
67
+ server.registerTool('get_component_api', {
68
+ description: 'Subset of MagicGrid API from api-manifest.json. section=api → full GridApi methods (getData, setData, applyTransaction, addRows, stopEditing, …). section=expose → ref shortcuts only (use api for row CRUD). section=types → RowTransaction / AddRowsOptions shapes. Use names or query to filter.',
69
+ inputSchema: {
70
+ section: z.string().optional(),
71
+ names: z.array(z.string()).optional(),
72
+ query: z.string().optional(),
73
+ },
74
+ }, async (args) => jsonText(getComponentApi(resolved, parseGetComponentApiInput(args))));
75
+ server.registerTool('find_recipes', {
76
+ description: 'Find 1–3 copy-pasteable Vue SFC recipes by intent keywords (e.g. 新增行 / applyTransaction / 树形). Recipes ship in api-manifest.json from docs/ai/recipes.',
77
+ inputSchema: {
78
+ intent: z.string(),
79
+ limit: z.number().int().min(1).max(5).optional(),
80
+ },
81
+ }, async (args) => {
82
+ const intent = typeof args.intent === 'string' ? args.intent : '';
83
+ const limit = typeof args.limit === 'number' ? args.limit : undefined;
84
+ return jsonText(findRecipes(manifest, { intent, limit }));
85
+ });
86
+ server.registerTool('validate_magic_grid_usage', {
87
+ description: 'Statically validate MagicGrid usage in Vue/TS sources. Always returns unchecked for non-literal bindings.',
88
+ inputSchema: {
89
+ paths: z.array(z.string()).optional(),
90
+ },
91
+ }, async (args) => {
92
+ const rawPaths = Array.isArray(args.paths)
93
+ ? args.paths.filter((p) => typeof p === 'string')
94
+ : undefined;
95
+ const paths = rawPaths?.length ? rawPaths : ['./src'];
96
+ const result = validateMagicGridUsage(resolved, { paths, cwd });
97
+ return jsonText(result);
98
+ });
99
+ return server;
100
+ }
101
+ export async function runMcpServer(cwd = process.cwd()) {
102
+ const server = createMcpServer(cwd);
103
+ const transport = new StdioServerTransport();
104
+ await server.connect(transport);
105
+ }
@@ -0,0 +1,3 @@
1
+ /** MCP 包 semver(与 @taocompany/magic-grid 同号发布) */
2
+ export declare function readMcpPackageVersion(): string;
3
+ //# sourceMappingURL=packageVersion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAIA,kDAAkD;AAClD,wBAAgB,qBAAqB,IAAI,MAAM,CAK9C"}
@@ -0,0 +1,10 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ /** MCP 包 semver(与 @taocompany/magic-grid 同号发布) */
5
+ export function readMcpPackageVersion() {
6
+ const here = path.dirname(fileURLToPath(import.meta.url));
7
+ const pkgPath = path.join(here, '../package.json');
8
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
9
+ return pkg.version ?? '0.0.0';
10
+ }
@@ -0,0 +1,25 @@
1
+ import type { ApiManifest } from './types.js';
2
+ export interface ResolveManifestResult {
3
+ manifest: ApiManifest;
4
+ source: 'manifest' | 'package-parse';
5
+ manifestPath: string;
6
+ packageRoot: string;
7
+ }
8
+ /** 从 startDir 向上查找已安装的 magic-grid(workspace 根或 node_modules) */
9
+ export declare function findMagicGridPackageRoot(startDir: string): string | null;
10
+ export declare function resolveManifest(cwd?: string): ResolveManifestResult;
11
+ export interface DoctorReport {
12
+ mcpVersion: string;
13
+ libraryVersion: string;
14
+ versionsAligned: boolean;
15
+ source: 'manifest' | 'package-parse';
16
+ manifestPath: string;
17
+ packageRoot: string;
18
+ props: number;
19
+ emits: number;
20
+ slots: number;
21
+ rules: number;
22
+ manifestExists: boolean;
23
+ }
24
+ export declare function runDoctor(cwd?: string): DoctorReport;
25
+ //# sourceMappingURL=resolveManifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveManifest.d.ts","sourceRoot":"","sources":["../src/resolveManifest.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAI7C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,WAAW,CAAA;IACrB,MAAM,EAAE,UAAU,GAAG,eAAe,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;CACpB;AAMD,gEAAgE;AAChE,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsBxE;AAED,wBAAgB,eAAe,CAAC,GAAG,SAAgB,GAAG,qBAAqB,CA4D1E;AA0ED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,OAAO,CAAA;IACxB,MAAM,EAAE,UAAU,GAAG,eAAe,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,OAAO,CAAA;CACxB;AAED,wBAAgB,SAAS,CAAC,GAAG,SAAgB,GAAG,YAAY,CAiB3D"}
@@ -0,0 +1,169 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { readMcpPackageVersion } from './packageVersion.js';
5
+ const PACKAGE_NAME = '@taocompany/magic-grid';
6
+ function readJson(filePath) {
7
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
8
+ }
9
+ /** 从 startDir 向上查找已安装的 magic-grid(workspace 根或 node_modules) */
10
+ export function findMagicGridPackageRoot(startDir) {
11
+ let dir = path.resolve(startDir);
12
+ for (;;) {
13
+ const pkgPath = path.join(dir, 'package.json');
14
+ if (fs.existsSync(pkgPath)) {
15
+ const pkg = readJson(pkgPath);
16
+ if (pkg.name === PACKAGE_NAME) {
17
+ return dir;
18
+ }
19
+ }
20
+ const candidate = path.join(dir, 'node_modules', PACKAGE_NAME);
21
+ if (fs.existsSync(path.join(candidate, 'package.json'))) {
22
+ return candidate;
23
+ }
24
+ const parent = path.dirname(dir);
25
+ if (parent === dir) {
26
+ return null;
27
+ }
28
+ dir = parent;
29
+ }
30
+ }
31
+ export function resolveManifest(cwd = process.cwd()) {
32
+ const here = path.dirname(fileURLToPath(import.meta.url));
33
+ const packageRoot = findMagicGridPackageRoot(cwd) ??
34
+ findMagicGridPackageRoot(path.resolve(here, '../..')) ??
35
+ findMagicGridPackageRoot(path.resolve(here, '../../..'));
36
+ if (!packageRoot) {
37
+ throw new Error(`未找到 ${PACKAGE_NAME}。请在项目中安装:pnpm add ${PACKAGE_NAME}`);
38
+ }
39
+ const manifestPath = path.join(packageRoot, 'dist', 'api-manifest.json');
40
+ if (fs.existsSync(manifestPath)) {
41
+ return {
42
+ manifest: readJson(manifestPath),
43
+ source: 'manifest',
44
+ manifestPath,
45
+ packageRoot,
46
+ };
47
+ }
48
+ const pkg = readJson(path.join(packageRoot, 'package.json'));
49
+ const propsDtsPath = path.join(packageRoot, 'dist/components/MagicGrid/magicGridProps.d.ts');
50
+ const propsDts = fs.readFileSync(propsDtsPath, 'utf8');
51
+ const magicGridTypesPath = path.join(packageRoot, 'dist/types/magic-grid.d.ts');
52
+ const magicGridDts = fs.existsSync(magicGridTypesPath)
53
+ ? fs.readFileSync(magicGridTypesPath, 'utf8')
54
+ : '';
55
+ const props = parseRuntimePropNames(propsDts);
56
+ const fallback = {
57
+ manifestVersion: 0,
58
+ libraryVersion: pkg.version,
59
+ props: props.map((name) => ({ name })),
60
+ emits: parseEmitNamesFromPropsDts(propsDts),
61
+ slots: [],
62
+ expose: [],
63
+ gridApi: [],
64
+ columnDef: parseColumnDefFieldsFromMagicGridDts(magicGridDts),
65
+ recipes: [],
66
+ rules: [],
67
+ commonMistakes: [
68
+ { wrong: 'columnDefs', right: 'columns', kind: 'prop' },
69
+ { wrong: 'rowData', right: 'data', kind: 'prop' },
70
+ { wrong: 'field', right: 'prop', kind: 'columnDef' },
71
+ { wrong: 'headerName', right: 'label', kind: 'columnDef' },
72
+ { wrong: 'colId', right: 'key', kind: 'columnDef' },
73
+ ],
74
+ };
75
+ return {
76
+ manifest: fallback,
77
+ source: 'package-parse',
78
+ manifestPath,
79
+ packageRoot,
80
+ };
81
+ }
82
+ function parseRuntimePropNames(dts) {
83
+ const marker = 'declare const magicGridProps';
84
+ const start = dts.indexOf(marker);
85
+ if (start < 0) {
86
+ return [];
87
+ }
88
+ const braceStart = dts.indexOf('{', start);
89
+ let depth = 0;
90
+ let body = '';
91
+ for (let i = braceStart; i < dts.length; i++) {
92
+ if (dts[i] === '{')
93
+ depth++;
94
+ else if (dts[i] === '}') {
95
+ depth--;
96
+ if (depth === 0) {
97
+ body = dts.slice(braceStart + 1, i);
98
+ break;
99
+ }
100
+ }
101
+ }
102
+ if (!body) {
103
+ return [];
104
+ }
105
+ return [...body.matchAll(/\n readonly (\w+):/g)].map((m) => m[1]);
106
+ }
107
+ function extractBracedBody(dts, marker) {
108
+ const start = dts.indexOf(marker);
109
+ if (start < 0) {
110
+ return '';
111
+ }
112
+ const braceStart = dts.indexOf('{', start);
113
+ if (braceStart < 0) {
114
+ return '';
115
+ }
116
+ let depth = 0;
117
+ for (let i = braceStart; i < dts.length; i++) {
118
+ if (dts[i] === '{')
119
+ depth++;
120
+ else if (dts[i] === '}') {
121
+ depth--;
122
+ if (depth === 0) {
123
+ return dts.slice(braceStart + 1, i);
124
+ }
125
+ }
126
+ }
127
+ return '';
128
+ }
129
+ function parseColumnDefFieldsFromMagicGridDts(dts) {
130
+ const body = extractBracedBody(dts, 'export interface ColumnDef');
131
+ if (!body) {
132
+ return [];
133
+ }
134
+ const names = [...body.matchAll(/^\s+(\w+)(\?)?:/gm)].map((m) => m[1]);
135
+ return names.map((name) => ({ name }));
136
+ }
137
+ function parseEmitNamesFromPropsDts(dts) {
138
+ const body = extractBracedBody(dts, 'export type MagicGridEmits = {');
139
+ if (!body) {
140
+ return [];
141
+ }
142
+ const linePattern = /^\s+('[^']+'|\w+):\s*\[/gm;
143
+ const names = [];
144
+ let match;
145
+ while ((match = linePattern.exec(body)) !== null) {
146
+ const rawName = match[1];
147
+ const name = rawName.startsWith("'") ? rawName.slice(1, -1) : rawName;
148
+ names.push({ name });
149
+ }
150
+ return names;
151
+ }
152
+ export function runDoctor(cwd = process.cwd()) {
153
+ const resolved = resolveManifest(cwd);
154
+ const { manifest, source, manifestPath, packageRoot } = resolved;
155
+ const mcpVersion = readMcpPackageVersion();
156
+ return {
157
+ mcpVersion,
158
+ libraryVersion: manifest.libraryVersion,
159
+ versionsAligned: mcpVersion === manifest.libraryVersion,
160
+ source,
161
+ manifestPath,
162
+ packageRoot,
163
+ props: manifest.props.length,
164
+ emits: manifest.emits?.length ?? 0,
165
+ slots: manifest.slots?.length ?? 0,
166
+ rules: manifest.rules.length,
167
+ manifestExists: fs.existsSync(manifestPath),
168
+ };
169
+ }
@@ -0,0 +1,2 @@
1
+ export declare function collectSourceFiles(targetPath: string): string[];
2
+ //# sourceMappingURL=collectSourceFiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collectSourceFiles.d.ts","sourceRoot":"","sources":["../../src/scan/collectSourceFiles.ts"],"names":[],"mappings":"AAKA,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAc/D"}
@@ -0,0 +1,30 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ const SOURCE_EXT = new Set(['.vue', '.ts', '.tsx', '.js', '.jsx']);
4
+ export function collectSourceFiles(targetPath) {
5
+ const abs = path.resolve(targetPath);
6
+ if (!fs.existsSync(abs)) {
7
+ return [];
8
+ }
9
+ const stat = fs.statSync(abs);
10
+ if (stat.isFile()) {
11
+ return SOURCE_EXT.has(path.extname(abs)) ? [abs] : [];
12
+ }
13
+ const out = [];
14
+ walkDir(abs, out);
15
+ return out;
16
+ }
17
+ function walkDir(dir, out) {
18
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
19
+ if (entry.name === 'node_modules' || entry.name === 'dist') {
20
+ continue;
21
+ }
22
+ const full = path.join(dir, entry.name);
23
+ if (entry.isDirectory()) {
24
+ walkDir(full, out);
25
+ }
26
+ else if (SOURCE_EXT.has(path.extname(entry.name))) {
27
+ out.push(full);
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,18 @@
1
+ export interface ParsedAttr {
2
+ name: string;
3
+ line: number;
4
+ /** 字面量字符串/数字/boolean;绑定为 null */
5
+ literalValue: string | boolean | null;
6
+ raw: string;
7
+ isBinding: boolean;
8
+ }
9
+ export interface MagicGridBlock {
10
+ line: number;
11
+ attrs: ParsedAttr[];
12
+ }
13
+ export declare function findMagicGridBlocks(filePath: string, source: string): MagicGridBlock[];
14
+ export declare function findStyleImports(source: string): Array<{
15
+ path: string;
16
+ line: number;
17
+ }>;
18
+ //# sourceMappingURL=parseMagicGrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseMagicGrid.d.ts","sourceRoot":"","sources":["../../src/scan/parseMagicGrid.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,iCAAiC;IACjC,YAAY,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAA;IACrC,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,UAAU,EAAE,CAAA;CACpB;AAKD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,EAAE,CAgBtF;AAiED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAYtF"}
@@ -0,0 +1,85 @@
1
+ import { parse as parseSfc } from '@vue/compiler-sfc';
2
+ /** 结束于首个 `>` / `/>`(勿用 `(?<!\s)>`,否则会吞掉换行后的 ` >` 并误解析子节点) */
3
+ const GRID_TAG = /<(?:MagicGrid|magic-grid)\b([\s\S]*?)\/?>/g;
4
+ export function findMagicGridBlocks(filePath, source) {
5
+ if (!filePath.endsWith('.vue')) {
6
+ return findMagicGridBlocksInFragment(source, 1);
7
+ }
8
+ const { descriptor, errors } = parseSfc(source, { filename: filePath });
9
+ if (errors.length) {
10
+ return findMagicGridBlocksInFragment(source, 1);
11
+ }
12
+ const blocks = [];
13
+ if (descriptor.template?.content) {
14
+ const offset = descriptor.template.loc.start.line;
15
+ blocks.push(...findMagicGridBlocksInFragment(descriptor.template.content, offset));
16
+ }
17
+ return blocks;
18
+ }
19
+ function findMagicGridBlocksInFragment(fragment, lineOffset) {
20
+ const blocks = [];
21
+ let match;
22
+ while ((match = GRID_TAG.exec(fragment)) !== null) {
23
+ const attrSource = match[1] ?? '';
24
+ const before = fragment.slice(0, match.index);
25
+ const line = lineOffset + before.split('\n').length - 1;
26
+ blocks.push({
27
+ line,
28
+ attrs: parseAttrs(attrSource, line),
29
+ });
30
+ }
31
+ return blocks;
32
+ }
33
+ function parseAttrs(attrSource, baseLine) {
34
+ const attrs = [];
35
+ const eventPattern = /(?:^|\s)@([\w-]+)(?==|\s|\/|>)/g;
36
+ let eventMatch;
37
+ while ((eventMatch = eventPattern.exec(attrSource)) !== null) {
38
+ const name = `@${eventMatch[1]}`;
39
+ const raw = eventMatch[0].trim();
40
+ const line = baseLine + attrSource.slice(0, eventMatch.index).split('\n').length - 1;
41
+ attrs.push({
42
+ name,
43
+ line,
44
+ literalValue: null,
45
+ raw,
46
+ isBinding: false,
47
+ });
48
+ }
49
+ const attrPattern = /(?:^|\s)(:?)([\w-]+)(?:=(["'])([\s\S]*?)\3)?/g;
50
+ let match;
51
+ while ((match = attrPattern.exec(attrSource)) !== null) {
52
+ const isBinding = match[1] === ':';
53
+ const name = match[2];
54
+ const raw = match[0].trim();
55
+ const line = baseLine + attrSource.slice(0, match.index).split('\n').length - 1;
56
+ if (!match[4] && !match[3]) {
57
+ attrs.push({ name, line, literalValue: true, raw, isBinding: false });
58
+ continue;
59
+ }
60
+ if (isBinding) {
61
+ attrs.push({ name, line, literalValue: null, raw, isBinding: true });
62
+ continue;
63
+ }
64
+ attrs.push({
65
+ name,
66
+ line,
67
+ literalValue: match[4] ?? '',
68
+ raw,
69
+ isBinding: false,
70
+ });
71
+ }
72
+ return attrs;
73
+ }
74
+ export function findStyleImports(source) {
75
+ const imports = [];
76
+ const lines = source.split('\n');
77
+ const importRe = /import\s+['"](@taocompany\/magic-grid\/(?:tokens|style)\.css)['"]/g;
78
+ lines.forEach((line, index) => {
79
+ let m;
80
+ while ((m = importRe.exec(line)) !== null) {
81
+ imports.push({ path: m[1], line: index + 1 });
82
+ }
83
+ });
84
+ return imports;
85
+ }
@@ -0,0 +1,19 @@
1
+ import type { ApiManifest } from '../types.js';
2
+ export interface FindRecipesInput {
3
+ intent: string;
4
+ limit?: number;
5
+ }
6
+ export interface FindRecipesMatch {
7
+ id: string;
8
+ intent: string;
9
+ score: number;
10
+ code: string;
11
+ propsUsed: string[];
12
+ }
13
+ export interface FindRecipesResult {
14
+ libraryVersion: string;
15
+ matches: FindRecipesMatch[];
16
+ warn?: string;
17
+ }
18
+ export declare function findRecipes(manifest: ApiManifest, input: FindRecipesInput): FindRecipesResult;
19
+ //# sourceMappingURL=findRecipes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findRecipes.d.ts","sourceRoot":"","sources":["../../src/tools/findRecipes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,aAAa,CAAA;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AA4DD,wBAAgB,WAAW,CACzB,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,gBAAgB,GACtB,iBAAiB,CAqDnB"}