speccore 6.83.0 → 6.90.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.
Files changed (134) hide show
  1. package/dist/cli.js +15 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/analyze.d.ts.map +1 -1
  4. package/dist/commands/analyze.js +32 -7
  5. package/dist/commands/analyze.js.map +1 -1
  6. package/dist/commands/change.d.ts.map +1 -1
  7. package/dist/commands/change.js +39 -1
  8. package/dist/commands/change.js.map +1 -1
  9. package/dist/commands/code-index.d.ts +1 -0
  10. package/dist/commands/code-index.d.ts.map +1 -1
  11. package/dist/commands/code-index.js +10 -0
  12. package/dist/commands/code-index.js.map +1 -1
  13. package/dist/commands/init.d.ts.map +1 -1
  14. package/dist/commands/init.js +118 -0
  15. package/dist/commands/init.js.map +1 -1
  16. package/dist/commands/knowledge.d.ts +12 -0
  17. package/dist/commands/knowledge.d.ts.map +1 -1
  18. package/dist/commands/knowledge.js +80 -0
  19. package/dist/commands/knowledge.js.map +1 -1
  20. package/dist/commands/pr.d.ts.map +1 -1
  21. package/dist/commands/pr.js +75 -38
  22. package/dist/commands/pr.js.map +1 -1
  23. package/dist/core/agents/defaults/_INDEX.md +68 -0
  24. package/dist/core/agents/defaults/_TEMPLATE.md +34 -0
  25. package/dist/core/agents/defaults/code-reviewer.md +49 -0
  26. package/dist/core/agents/defaults/compiler.md +25 -0
  27. package/dist/core/agents/defaults/compliance-checker.md +38 -0
  28. package/dist/core/agents/defaults/dependency-analyst.md +42 -0
  29. package/dist/core/agents/defaults/doc-sync-agent.md +25 -0
  30. package/dist/core/agents/defaults/impact-analyst.md +37 -0
  31. package/dist/core/agents/defaults/interaction-designer.md +73 -0
  32. package/dist/core/agents/defaults/performance-expert.md +35 -0
  33. package/dist/core/agents/defaults/product-analyst-backend.md +68 -0
  34. package/dist/core/agents/defaults/product-analyst-frontend.md +72 -0
  35. package/dist/core/agents/defaults/product-analyst.md +48 -0
  36. package/dist/core/agents/defaults/regression-tester.md +36 -0
  37. package/dist/core/agents/defaults/risk-assessor.md +38 -0
  38. package/dist/core/agents/defaults/schedule-planner.md +37 -0
  39. package/dist/core/agents/defaults/security-reviewer-finance.md +67 -0
  40. package/dist/core/agents/defaults/security-reviewer.md +43 -0
  41. package/dist/core/agents/defaults/task-decomposer.md +33 -0
  42. package/dist/core/agents/defaults/test-engineer.md +25 -0
  43. package/dist/core/agents/defaults/test-reviewer.md +48 -0
  44. package/dist/core/agents/engine/agent-executor.d.ts +50 -0
  45. package/dist/core/agents/engine/agent-executor.d.ts.map +1 -0
  46. package/dist/core/agents/engine/agent-executor.js +225 -0
  47. package/dist/core/agents/engine/agent-executor.js.map +1 -0
  48. package/dist/core/agents/engine/agent-loader.d.ts +58 -0
  49. package/dist/core/agents/engine/agent-loader.d.ts.map +1 -0
  50. package/dist/core/agents/engine/agent-loader.js +377 -0
  51. package/dist/core/agents/engine/agent-loader.js.map +1 -0
  52. package/dist/core/agents/engine/types.d.ts +71 -0
  53. package/dist/core/agents/engine/types.d.ts.map +1 -0
  54. package/dist/core/agents/engine/types.js +8 -0
  55. package/dist/core/agents/engine/types.js.map +1 -0
  56. package/dist/core/agents/index.d.ts +4 -0
  57. package/dist/core/agents/index.d.ts.map +1 -1
  58. package/dist/core/agents/index.js +17 -1
  59. package/dist/core/agents/index.js.map +1 -1
  60. package/dist/core/code-graph/builder.d.ts +6 -0
  61. package/dist/core/code-graph/builder.d.ts.map +1 -0
  62. package/dist/core/code-graph/builder.js +155 -0
  63. package/dist/core/code-graph/builder.js.map +1 -0
  64. package/dist/core/code-graph/index.d.ts +25 -0
  65. package/dist/core/code-graph/index.d.ts.map +1 -0
  66. package/dist/core/code-graph/index.js +125 -0
  67. package/dist/core/code-graph/index.js.map +1 -0
  68. package/dist/core/code-graph/parser.d.ts +10 -0
  69. package/dist/core/code-graph/parser.d.ts.map +1 -0
  70. package/dist/core/code-graph/parser.js +314 -0
  71. package/dist/core/code-graph/parser.js.map +1 -0
  72. package/dist/core/code-graph/query.d.ts +14 -0
  73. package/dist/core/code-graph/query.d.ts.map +1 -0
  74. package/dist/core/code-graph/query.js +112 -0
  75. package/dist/core/code-graph/query.js.map +1 -0
  76. package/dist/core/code-graph/reporter.d.ts +7 -0
  77. package/dist/core/code-graph/reporter.d.ts.map +1 -0
  78. package/dist/core/code-graph/reporter.js +97 -0
  79. package/dist/core/code-graph/reporter.js.map +1 -0
  80. package/dist/core/code-graph/types.d.ts +60 -0
  81. package/dist/core/code-graph/types.d.ts.map +1 -0
  82. package/dist/core/code-graph/types.js +7 -0
  83. package/dist/core/code-graph/types.js.map +1 -0
  84. package/dist/core/code-graph/visualizer.d.ts +9 -0
  85. package/dist/core/code-graph/visualizer.d.ts.map +1 -0
  86. package/dist/core/code-graph/visualizer.js +97 -0
  87. package/dist/core/code-graph/visualizer.js.map +1 -0
  88. package/dist/core/command-loader.d.ts +31 -0
  89. package/dist/core/command-loader.d.ts.map +1 -0
  90. package/dist/core/command-loader.js +76 -0
  91. package/dist/core/command-loader.js.map +1 -0
  92. package/dist/core/commands/defaults/change-impact.md +40 -0
  93. package/dist/core/commands/defaults/pr-review.md +42 -0
  94. package/dist/core/commands/defaults/refactor.md +37 -0
  95. package/dist/core/context-injector.d.ts +56 -0
  96. package/dist/core/context-injector.d.ts.map +1 -0
  97. package/dist/core/context-injector.js +122 -0
  98. package/dist/core/context-injector.js.map +1 -0
  99. package/dist/core/hook-runner.d.ts +36 -0
  100. package/dist/core/hook-runner.d.ts.map +1 -0
  101. package/dist/core/hook-runner.js +93 -0
  102. package/dist/core/hook-runner.js.map +1 -0
  103. package/dist/core/hooks/defaults/post-execute.md +22 -0
  104. package/dist/core/hooks/defaults/pre-execute.md +18 -0
  105. package/dist/core/prompt-builder.d.ts +1 -0
  106. package/dist/core/prompt-builder.d.ts.map +1 -1
  107. package/dist/core/prompt-builder.js +60 -1
  108. package/dist/core/prompt-builder.js.map +1 -1
  109. package/dist/core/rule-loader.d.ts +38 -0
  110. package/dist/core/rule-loader.d.ts.map +1 -0
  111. package/dist/core/rule-loader.js +156 -0
  112. package/dist/core/rule-loader.js.map +1 -0
  113. package/dist/core/rules/defaults/_INDEX.md +16 -0
  114. package/dist/core/rules/defaults/api-design.md +44 -0
  115. package/dist/core/rules/defaults/database.md +37 -0
  116. package/dist/core/rules/defaults/frontend-common.md +38 -0
  117. package/dist/core/rules/defaults/nodejs.md +38 -0
  118. package/dist/core/rules/defaults/react.md +34 -0
  119. package/dist/core/rules/defaults/security.md +31 -0
  120. package/dist/core/rules/defaults/testing.md +35 -0
  121. package/dist/core/rules/defaults/typescript.md +36 -0
  122. package/dist/core/skill-loader.d.ts +28 -0
  123. package/dist/core/skill-loader.d.ts.map +1 -0
  124. package/dist/core/skill-loader.js +102 -0
  125. package/dist/core/skill-loader.js.map +1 -0
  126. package/dist/core/skills/defaults/caching.md +33 -0
  127. package/dist/core/skills/defaults/db-migration.md +46 -0
  128. package/dist/core/skills/defaults/deployment.md +50 -0
  129. package/dist/core/skills/defaults/logging.md +38 -0
  130. package/dist/core/verify-engine.d.ts +7 -0
  131. package/dist/core/verify-engine.d.ts.map +1 -1
  132. package/dist/core/verify-engine.js +27 -1
  133. package/dist/core/verify-engine.js.map +1 -1
  134. package/package.json +2 -2
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildCodeGraph = buildCodeGraph;
4
+ /**
5
+ * Code Knowledge Graph — 图谱构建器
6
+ * v6.90.0
7
+ */
8
+ const path_1 = require("path");
9
+ /**
10
+ * 计算节点度数、识别 god nodes、构建完整图谱
11
+ */
12
+ function buildCodeGraph(nodes, edges, projectName, projectRoot, scannedFiles) {
13
+ // 0. 构建 name → id 映射,修复跨文件引用的裸名
14
+ const idSet = new Set(nodes.map(n => n.id));
15
+ const nameToIds = new Map();
16
+ for (const n of nodes) {
17
+ if (!nameToIds.has(n.name))
18
+ nameToIds.set(n.name, []);
19
+ nameToIds.get(n.name).push(n.id);
20
+ }
21
+ for (const e of edges) {
22
+ if (!idSet.has(e.source) && nameToIds.has(e.source)) {
23
+ e.source = nameToIds.get(e.source)[0];
24
+ }
25
+ if (!idSet.has(e.target) && nameToIds.has(e.target)) {
26
+ e.target = nameToIds.get(e.target)[0];
27
+ }
28
+ }
29
+ // 1. 计算每个节点的度数
30
+ const degreeMap = new Map();
31
+ for (const n of nodes) {
32
+ degreeMap.set(n.id, 0);
33
+ }
34
+ for (const e of edges) {
35
+ if (idSet.has(e.source))
36
+ degreeMap.set(e.source, (degreeMap.get(e.source) || 0) + 1);
37
+ if (idSet.has(e.target))
38
+ degreeMap.set(e.target, (degreeMap.get(e.target) || 0) + 1);
39
+ }
40
+ // 2. 按度数排序,识别 god nodes(前10%)
41
+ const sortedByDegree = Array.from(degreeMap.entries())
42
+ .sort((a, b) => b[1] - a[1]);
43
+ const godNodeThreshold = Math.max(1, Math.floor(nodes.length * 0.1));
44
+ const godNodes = sortedByDegree.slice(0, godNodeThreshold).map(([id]) => id);
45
+ // 3. 给节点附加度数
46
+ const enrichedNodes = nodes.map(n => ({
47
+ ...n,
48
+ degree: degreeMap.get(n.id) || 0,
49
+ }));
50
+ // 4. 社区检测(基于目录路径 + 连通分量)
51
+ const communities = detectCommunities(enrichedNodes, edges);
52
+ // 5. 统计
53
+ const extractedEdges = edges.filter(e => e.confidence === 'EXTRACTED').length;
54
+ const inferredEdges = edges.filter(e => e.confidence === 'INFERRED').length;
55
+ return {
56
+ nodes: enrichedNodes,
57
+ edges,
58
+ communities,
59
+ godNodes,
60
+ metadata: {
61
+ projectName,
62
+ projectRoot,
63
+ scannedFiles,
64
+ totalNodes: nodes.length,
65
+ totalEdges: edges.length,
66
+ extractedEdges,
67
+ inferredEdges,
68
+ generatedAt: new Date().toISOString(),
69
+ },
70
+ };
71
+ }
72
+ /**
73
+ * 社区检测:基于目录结构 + 简单连通分量
74
+ */
75
+ function detectCommunities(nodes, edges) {
76
+ // Step 1: 按目录路径初步分组
77
+ const dirGroups = new Map();
78
+ for (const n of nodes) {
79
+ const dir = (0, path_1.dirname)(n.filePath);
80
+ if (!dirGroups.has(dir))
81
+ dirGroups.set(dir, []);
82
+ dirGroups.get(dir).push(n.id);
83
+ }
84
+ // Step 2: 用 Union-Find 合并有边连接的组
85
+ const uf = new UnionFind(nodes.map(n => n.id));
86
+ for (const e of edges) {
87
+ uf.union(e.source, e.target);
88
+ }
89
+ // Step 3: 按连通分量 + 目录信息生成社区
90
+ const componentMap = new Map();
91
+ for (const n of nodes) {
92
+ const root = uf.find(n.id);
93
+ if (!componentMap.has(root))
94
+ componentMap.set(root, []);
95
+ componentMap.get(root).push(n.id);
96
+ }
97
+ const communities = [];
98
+ let commId = 0;
99
+ for (const [, members] of componentMap) {
100
+ if (members.length < 2)
101
+ continue; // 忽略孤立节点
102
+ // 找社区标签:取成员最多的目录名
103
+ const dirCounts = new Map();
104
+ for (const id of members) {
105
+ const node = nodes.find(n => n.id === id);
106
+ if (node) {
107
+ const dir = (0, path_1.dirname)(node.filePath);
108
+ dirCounts.set(dir, (dirCounts.get(dir) || 0) + 1);
109
+ }
110
+ }
111
+ const label = Array.from(dirCounts.entries()).sort((a, b) => b[1] - a[1])[0]?.[0] || 'unknown';
112
+ // 计算密度:内部边 / 总边
113
+ const memberSet = new Set(members);
114
+ const internalEdges = edges.filter(e => memberSet.has(e.source) && memberSet.has(e.target)).length;
115
+ const totalPossible = members.length * (members.length - 1) / 2;
116
+ const density = totalPossible > 0 ? internalEdges / totalPossible : 0;
117
+ communities.push({
118
+ id: commId++,
119
+ label,
120
+ nodes: members,
121
+ density: Math.min(1, density),
122
+ });
123
+ }
124
+ // 给节点附加社区 ID
125
+ for (const comm of communities) {
126
+ for (const id of comm.nodes) {
127
+ const node = nodes.find(n => n.id === id);
128
+ if (node)
129
+ node.community = comm.id;
130
+ }
131
+ }
132
+ return communities.sort((a, b) => b.nodes.length - a.nodes.length);
133
+ }
134
+ class UnionFind {
135
+ constructor(ids) {
136
+ this.parent = new Map();
137
+ for (const id of ids)
138
+ this.parent.set(id, id);
139
+ }
140
+ find(x) {
141
+ const p = this.parent.get(x);
142
+ if (!p || p === x)
143
+ return x;
144
+ const root = this.find(p);
145
+ this.parent.set(x, root);
146
+ return root;
147
+ }
148
+ union(a, b) {
149
+ const ra = this.find(a);
150
+ const rb = this.find(b);
151
+ if (ra !== rb)
152
+ this.parent.set(ra, rb);
153
+ }
154
+ }
155
+ //# sourceMappingURL=builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../../src/core/code-graph/builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Code Knowledge Graph — 统一导出
3
+ * v6.90.0
4
+ */
5
+ export * from './types';
6
+ export { parseProject } from './parser';
7
+ export { buildCodeGraph } from './builder';
8
+ export { explainNode, findPath, queryGraph } from './query';
9
+ export { generateGraphReport } from './reporter';
10
+ export { buildCodeGraphHtml } from './visualizer';
11
+ import type { CodeGraph } from './types';
12
+ export interface BuildGraphOptions {
13
+ scope?: string;
14
+ projectRoot?: string;
15
+ projectName?: string;
16
+ }
17
+ /**
18
+ * 一键构建代码知识图谱,输出三产物
19
+ */
20
+ export declare function buildCodeKnowledgeGraph(options?: BuildGraphOptions): Promise<CodeGraph>;
21
+ /**
22
+ * 加载已存在的 graph.json
23
+ */
24
+ export declare function loadCodeGraph(projectRoot?: string): Promise<CodeGraph | null>;
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/code-graph/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAUlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIzC,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,SAAS,CAAC,CA8CjG;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAWnF"}
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
+ };
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.buildCodeGraphHtml = exports.generateGraphReport = exports.queryGraph = exports.findPath = exports.explainNode = exports.buildCodeGraph = exports.parseProject = void 0;
40
+ exports.buildCodeKnowledgeGraph = buildCodeKnowledgeGraph;
41
+ exports.loadCodeGraph = loadCodeGraph;
42
+ /**
43
+ * Code Knowledge Graph — 统一导出
44
+ * v6.90.0
45
+ */
46
+ __exportStar(require("./types"), exports);
47
+ var parser_1 = require("./parser");
48
+ Object.defineProperty(exports, "parseProject", { enumerable: true, get: function () { return parser_1.parseProject; } });
49
+ var builder_1 = require("./builder");
50
+ Object.defineProperty(exports, "buildCodeGraph", { enumerable: true, get: function () { return builder_1.buildCodeGraph; } });
51
+ var query_1 = require("./query");
52
+ Object.defineProperty(exports, "explainNode", { enumerable: true, get: function () { return query_1.explainNode; } });
53
+ Object.defineProperty(exports, "findPath", { enumerable: true, get: function () { return query_1.findPath; } });
54
+ Object.defineProperty(exports, "queryGraph", { enumerable: true, get: function () { return query_1.queryGraph; } });
55
+ var reporter_1 = require("./reporter");
56
+ Object.defineProperty(exports, "generateGraphReport", { enumerable: true, get: function () { return reporter_1.generateGraphReport; } });
57
+ var visualizer_1 = require("./visualizer");
58
+ Object.defineProperty(exports, "buildCodeGraphHtml", { enumerable: true, get: function () { return visualizer_1.buildCodeGraphHtml; } });
59
+ const path_1 = require("path");
60
+ const fs_extra_1 = require("fs-extra");
61
+ const glob_1 = require("glob");
62
+ const logger_1 = require("../../utils/logger");
63
+ const parser_2 = require("./parser");
64
+ const builder_2 = require("./builder");
65
+ const reporter_2 = require("./reporter");
66
+ const visualizer_2 = require("./visualizer");
67
+ const GRAPH_DIR = '.speccore/code-graph';
68
+ /**
69
+ * 一键构建代码知识图谱,输出三产物
70
+ */
71
+ async function buildCodeKnowledgeGraph(options = {}) {
72
+ const projectRoot = options.projectRoot || process.cwd();
73
+ const projectName = options.projectName || 'Project';
74
+ const scope = options.scope || 'src';
75
+ const scopePath = (0, path_1.join)(projectRoot, scope);
76
+ // 1. 扫描文件
77
+ logger_1.logger.info(`🔍 扫描代码文件: ${scope}`);
78
+ const pattern = (0, path_1.join)(scopePath, '**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}');
79
+ const files = await (0, glob_1.glob)(pattern, { absolute: true });
80
+ logger_1.logger.info(` 发现 ${files.length} 个文件`);
81
+ // 2. AST 解析
82
+ logger_1.logger.info(`🌳 AST 解析中...`);
83
+ const { nodes, edges, fileCount } = await (0, parser_2.parseProject)(files, projectRoot);
84
+ logger_1.logger.info(` 提取 ${nodes.length} 个节点, ${edges.length} 条边`);
85
+ // 3. 构建图谱
86
+ const graph = (0, builder_2.buildCodeGraph)(nodes, edges, projectName, projectRoot, fileCount);
87
+ logger_1.logger.info(` 社区: ${graph.communities.length} 个 | God nodes: ${graph.godNodes.length} 个`);
88
+ // 4. 输出产物
89
+ const outDir = (0, path_1.join)(projectRoot, GRAPH_DIR);
90
+ await (0, fs_extra_1.ensureDir)(outDir);
91
+ // graph.json
92
+ const jsonPath = (0, path_1.join)(outDir, 'graph.json');
93
+ await (0, fs_extra_1.writeFile)(jsonPath, JSON.stringify(graph, null, 2));
94
+ logger_1.logger.info(` ✅ graph.json`);
95
+ // GRAPH_REPORT.md
96
+ const reportPath = (0, path_1.join)(outDir, 'GRAPH_REPORT.md');
97
+ await (0, fs_extra_1.writeFile)(reportPath, (0, reporter_2.generateGraphReport)(graph));
98
+ logger_1.logger.info(` ✅ GRAPH_REPORT.md`);
99
+ // graph.html
100
+ const htmlPath = (0, path_1.join)(outDir, 'graph.html');
101
+ await (0, fs_extra_1.writeFile)(htmlPath, (0, visualizer_2.buildCodeGraphHtml)(graph));
102
+ logger_1.logger.info(` ✅ graph.html`);
103
+ logger_1.logger.info('');
104
+ logger_1.logger.info(`📊 代码知识图谱已生成: ${outDir}`);
105
+ logger_1.logger.info(` 打开 ${(0, path_1.join)(GRAPH_DIR, 'graph.html')} 查看可视化`);
106
+ return graph;
107
+ }
108
+ /**
109
+ * 加载已存在的 graph.json
110
+ */
111
+ async function loadCodeGraph(projectRoot) {
112
+ const root = projectRoot || process.cwd();
113
+ const jsonPath = (0, path_1.join)(root, GRAPH_DIR, 'graph.json');
114
+ if (!(await (0, fs_extra_1.pathExists)(jsonPath)))
115
+ return null;
116
+ try {
117
+ const { readFile } = await Promise.resolve().then(() => __importStar(require('fs-extra')));
118
+ const raw = await readFile(jsonPath, 'utf-8');
119
+ return JSON.parse(raw);
120
+ }
121
+ catch {
122
+ return null;
123
+ }
124
+ }
125
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/code-graph/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,0DA8CC;AAKD,sCAWC;AA9FD;;;GAGG;AACH,0CAAwB;AACxB,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AACrB,qCAA2C;AAAlC,yGAAA,cAAc,OAAA;AACvB,iCAA4D;AAAnD,oGAAA,WAAW,OAAA;AAAE,iGAAA,QAAQ,OAAA;AAAE,mGAAA,UAAU,OAAA;AAC1C,uCAAiD;AAAxC,+GAAA,mBAAmB,OAAA;AAC5B,2CAAkD;AAAzC,gHAAA,kBAAkB,OAAA;AAE3B,+BAA4B;AAC5B,uCAA4D;AAC5D,+BAA4B;AAC5B,+CAA4C;AAC5C,qCAAwC;AACxC,uCAA2C;AAC3C,yCAAiD;AACjD,6CAAkD;AAGlD,MAAM,SAAS,GAAG,sBAAsB,CAAC;AAQzC;;GAEG;AACI,KAAK,UAAU,uBAAuB,CAAC,UAA6B,EAAE;IAC3E,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,SAAS,CAAC;IACrD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;IAErC,MAAM,SAAS,GAAG,IAAA,WAAI,EAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAE3C,UAAU;IACV,eAAM,CAAC,IAAI,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,sCAAsC,CAAC,CAAC;IACxE,MAAM,KAAK,GAAG,MAAM,IAAA,WAAI,EAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,eAAM,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,MAAM,CAAC,CAAC;IAEzC,YAAY;IACZ,eAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC7B,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,IAAA,qBAAY,EAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAC3E,eAAM,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,SAAS,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;IAE7D,UAAU;IACV,MAAM,KAAK,GAAG,IAAA,wBAAc,EAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAChF,eAAM,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,WAAW,CAAC,MAAM,mBAAmB,KAAK,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;IAE5F,UAAU;IACV,MAAM,MAAM,GAAG,IAAA,WAAI,EAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAC5C,MAAM,IAAA,oBAAS,EAAC,MAAM,CAAC,CAAC;IAExB,aAAa;IACb,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC5C,MAAM,IAAA,oBAAS,EAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1D,eAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAE/B,kBAAkB;IAClB,MAAM,UAAU,GAAG,IAAA,WAAI,EAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACnD,MAAM,IAAA,oBAAS,EAAC,UAAU,EAAE,IAAA,8BAAmB,EAAC,KAAK,CAAC,CAAC,CAAC;IACxD,eAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAEpC,aAAa;IACb,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC5C,MAAM,IAAA,oBAAS,EAAC,QAAQ,EAAE,IAAA,+BAAkB,EAAC,KAAK,CAAC,CAAC,CAAC;IACrD,eAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAE/B,eAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,eAAM,CAAC,IAAI,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAC;IACvC,eAAM,CAAC,IAAI,CAAC,SAAS,IAAA,WAAI,EAAC,SAAS,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;IAE5D,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,aAAa,CAAC,WAAoB;IACtD,MAAM,IAAI,GAAG,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,IAAI,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IACrD,IAAI,CAAC,CAAC,MAAM,IAAA,qBAAU,EAAC,QAAQ,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,IAAI,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,GAAG,wDAAa,UAAU,GAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { CodeNode, CodeEdge } from './types';
2
+ /**
3
+ * 扫描目录,解析所有 TS/JS 文件
4
+ */
5
+ export declare function parseProject(filePaths: string[], projectRoot: string): Promise<{
6
+ nodes: CodeNode[];
7
+ edges: CodeEdge[];
8
+ fileCount: number;
9
+ }>;
10
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/core/code-graph/parser.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAc,MAAM,SAAS,CAAC;AAoR9D;;GAEG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EAAE,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IAAC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA2BtE"}
@@ -0,0 +1,314 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseProject = parseProject;
37
+ /**
38
+ * Code Knowledge Graph — AST 解析器
39
+ * v6.90.0: 基于 TypeScript 编译器 API 的本地确定性解析
40
+ *
41
+ * 零 LLM Token 消耗,代码不出本机。
42
+ */
43
+ const ts = __importStar(require("typescript"));
44
+ const fs_1 = require("fs");
45
+ const path_1 = require("path");
46
+ const SCRIPT_TARGET = ts.ScriptTarget.ES2020;
47
+ const SCRIPT_KIND_TS = ts.ScriptKind.TS;
48
+ const SCRIPT_KIND_JS = ts.ScriptKind.JS;
49
+ function isTsOrJs(filePath) {
50
+ return /\.(ts|tsx|js|jsx|mts|cts|mjs|cjs)$/i.test(filePath);
51
+ }
52
+ function getScriptKind(filePath) {
53
+ if (/\.tsx$/i.test(filePath))
54
+ return ts.ScriptKind.TSX;
55
+ if (/\.jsx$/i.test(filePath))
56
+ return ts.ScriptKind.JSX;
57
+ if (/\.(js|mjs|cjs)$/i.test(filePath))
58
+ return SCRIPT_KIND_JS;
59
+ return SCRIPT_KIND_TS;
60
+ }
61
+ function makeNodeId(filePath, name) {
62
+ return `${filePath}::${name}`;
63
+ }
64
+ function getNodePosition(node, sourceFile) {
65
+ const pos = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
66
+ return { line: pos.line + 1, column: pos.character + 1 };
67
+ }
68
+ function getSnippet(node, sourceFile) {
69
+ const text = node.getText(sourceFile);
70
+ return text.slice(0, 200).replace(/\s+/g, ' ').trim();
71
+ }
72
+ /**
73
+ * 解析单个文件,提取节点和边
74
+ */
75
+ function parseSingleFile(filePath, projectRoot) {
76
+ if (!isTsOrJs(filePath))
77
+ return null;
78
+ let content;
79
+ try {
80
+ content = (0, fs_1.readFileSync)(filePath, 'utf-8');
81
+ }
82
+ catch {
83
+ return null;
84
+ }
85
+ const relPath = (0, path_1.relative)(projectRoot, filePath);
86
+ const sourceFile = ts.createSourceFile(filePath, content, SCRIPT_TARGET, true, getScriptKind(filePath));
87
+ const nodes = [];
88
+ const edges = [];
89
+ const exports = [];
90
+ const localNames = new Set();
91
+ // 文件级 module 节点
92
+ const moduleId = relPath;
93
+ nodes.push({
94
+ id: moduleId,
95
+ name: (0, path_1.basename)(relPath),
96
+ type: 'module',
97
+ filePath: relPath,
98
+ line: 1,
99
+ column: 1,
100
+ });
101
+ function addNode(name, type, node) {
102
+ const pos = getNodePosition(node, sourceFile);
103
+ const id = makeNodeId(relPath, name);
104
+ const n = {
105
+ id,
106
+ name,
107
+ type,
108
+ filePath: relPath,
109
+ line: pos.line,
110
+ column: pos.column,
111
+ snippet: getSnippet(node, sourceFile),
112
+ };
113
+ nodes.push(n);
114
+ localNames.add(name);
115
+ return n;
116
+ }
117
+ function addEdge(source, target, type, confidence, line) {
118
+ edges.push({ source, target, type, confidence, filePath: relPath, line });
119
+ }
120
+ function visit(node) {
121
+ // 1. Import declarations → module dependency edges
122
+ if (ts.isImportDeclaration(node)) {
123
+ const moduleName = node.moduleSpecifier?.text;
124
+ if (moduleName) {
125
+ // Named imports / namespace imports
126
+ const importClause = node.importClause;
127
+ if (importClause) {
128
+ if (importClause.namedBindings) {
129
+ if (ts.isNamedImports(importClause.namedBindings)) {
130
+ for (const elem of importClause.namedBindings.elements) {
131
+ const name = elem.name.text;
132
+ addNode(name, 'variable', elem); // imported symbol as a node
133
+ addEdge(makeNodeId(relPath, name), moduleName, 'imports', 'EXTRACTED', getNodePosition(node, sourceFile).line);
134
+ }
135
+ }
136
+ else if (ts.isNamespaceImport(importClause.namedBindings)) {
137
+ const name = importClause.namedBindings.name.text;
138
+ addNode(name, 'variable', importClause.namedBindings);
139
+ addEdge(makeNodeId(relPath, name), moduleName, 'imports', 'EXTRACTED', getNodePosition(node, sourceFile).line);
140
+ }
141
+ }
142
+ if (importClause.name) {
143
+ const name = importClause.name.text;
144
+ addNode(name, 'variable', importClause);
145
+ addEdge(makeNodeId(relPath, name), moduleName, 'imports', 'EXTRACTED', getNodePosition(node, sourceFile).line);
146
+ }
147
+ }
148
+ else {
149
+ // side-effect import: import "module"
150
+ addEdge(relPath, moduleName, 'imports', 'EXTRACTED', getNodePosition(node, sourceFile).line);
151
+ }
152
+ }
153
+ }
154
+ // 2. Export declarations
155
+ if (ts.isExportDeclaration(node) && node.exportClause && ts.isNamedExports(node.exportClause)) {
156
+ for (const elem of node.exportClause.elements) {
157
+ exports.push(elem.name.text);
158
+ }
159
+ }
160
+ if (ts.isExportAssignment(node) && !node.isExportEquals) {
161
+ // export default <expr>
162
+ const expr = node.expression;
163
+ if (ts.isIdentifier(expr)) {
164
+ exports.push(`default:${expr.text}`);
165
+ }
166
+ }
167
+ // 3. Function declarations
168
+ if (ts.isFunctionDeclaration(node) && node.name) {
169
+ addNode(node.name.text, 'function', node);
170
+ }
171
+ // 4. Class declarations
172
+ if (ts.isClassDeclaration(node) && node.name) {
173
+ const className = node.name.text;
174
+ const classId = makeNodeId(relPath, className);
175
+ addNode(className, 'class', node);
176
+ // extends
177
+ if (node.heritageClauses) {
178
+ for (const clause of node.heritageClauses) {
179
+ if (clause.token === ts.SyntaxKind.ExtendsKeyword) {
180
+ for (const type of clause.types) {
181
+ const parentName = type.expression.getText(sourceFile);
182
+ addEdge(classId, parentName, 'extends', 'EXTRACTED', getNodePosition(clause, sourceFile).line);
183
+ }
184
+ }
185
+ if (clause.token === ts.SyntaxKind.ImplementsKeyword) {
186
+ for (const type of clause.types) {
187
+ const ifaceName = type.expression.getText(sourceFile);
188
+ addEdge(classId, ifaceName, 'implements', 'EXTRACTED', getNodePosition(clause, sourceFile).line);
189
+ }
190
+ }
191
+ }
192
+ }
193
+ // methods and properties
194
+ for (const member of node.members) {
195
+ if (ts.isMethodDeclaration(member) && member.name) {
196
+ const methodName = member.name.getText(sourceFile);
197
+ const methodId = makeNodeId(relPath, `${className}.${methodName}`);
198
+ nodes.push({
199
+ id: methodId,
200
+ name: methodName,
201
+ type: 'method',
202
+ filePath: relPath,
203
+ line: getNodePosition(member, sourceFile).line,
204
+ column: getNodePosition(member, sourceFile).column,
205
+ snippet: getSnippet(member, sourceFile),
206
+ });
207
+ localNames.add(methodName);
208
+ addEdge(classId, methodId, 'contains', 'EXTRACTED', getNodePosition(member, sourceFile).line);
209
+ }
210
+ if (ts.isPropertyDeclaration(member) && member.name) {
211
+ const propName = member.name.getText(sourceFile);
212
+ const propId = makeNodeId(relPath, `${className}.${propName}`);
213
+ nodes.push({
214
+ id: propId,
215
+ name: propName,
216
+ type: 'property',
217
+ filePath: relPath,
218
+ line: getNodePosition(member, sourceFile).line,
219
+ column: getNodePosition(member, sourceFile).column,
220
+ snippet: getSnippet(member, sourceFile),
221
+ });
222
+ addEdge(classId, propId, 'contains', 'EXTRACTED', getNodePosition(member, sourceFile).line);
223
+ }
224
+ }
225
+ }
226
+ // 5. Interface declarations
227
+ if (ts.isInterfaceDeclaration(node) && node.name) {
228
+ const ifaceName = node.name.text;
229
+ const ifaceId = makeNodeId(relPath, ifaceName);
230
+ addNode(ifaceName, 'interface', node);
231
+ if (node.heritageClauses) {
232
+ for (const clause of node.heritageClauses) {
233
+ for (const type of clause.types) {
234
+ const parentName = type.expression.getText(sourceFile);
235
+ addEdge(ifaceId, parentName, 'extends', 'EXTRACTED', getNodePosition(clause, sourceFile).line);
236
+ }
237
+ }
238
+ }
239
+ }
240
+ // 6. Type alias declarations
241
+ if (ts.isTypeAliasDeclaration(node) && node.name) {
242
+ addNode(node.name.text, 'type', node);
243
+ }
244
+ // 7. Enum declarations
245
+ if (ts.isEnumDeclaration(node) && node.name) {
246
+ addNode(node.name.text, 'enum', node);
247
+ }
248
+ // 8. Variable declarations (catch arrow functions / function expressions)
249
+ if (ts.isVariableDeclaration(node) && node.name) {
250
+ const varName = node.name.getText(sourceFile);
251
+ const isFunctionLike = node.initializer &&
252
+ (ts.isArrowFunction(node.initializer) || ts.isFunctionExpression(node.initializer));
253
+ addNode(varName, isFunctionLike ? 'function' : 'variable', node);
254
+ }
255
+ // 9. Call expressions → same-file call edges
256
+ if (ts.isCallExpression(node)) {
257
+ const expr = node.expression;
258
+ let calleeName;
259
+ if (ts.isIdentifier(expr)) {
260
+ calleeName = expr.text;
261
+ }
262
+ else if (ts.isPropertyAccessExpression(expr)) {
263
+ // obj.method() or Class.method()
264
+ calleeName = expr.name.text;
265
+ // Try to get full chain like "fs.readFileSync"
266
+ const fullChain = expr.getText(sourceFile);
267
+ if (fullChain.includes('.')) {
268
+ calleeName = fullChain;
269
+ }
270
+ }
271
+ if (calleeName && localNames.has(calleeName)) {
272
+ // 简单推断:如果调用的是本文件已知的名称,标记为 EXTRACTED
273
+ const confidence = 'EXTRACTED';
274
+ addEdge(moduleId, makeNodeId(relPath, calleeName), 'calls', confidence, getNodePosition(node, sourceFile).line);
275
+ }
276
+ else if (calleeName) {
277
+ // INFERRED: could be imported or built-in
278
+ addEdge(moduleId, calleeName, 'calls', 'INFERRED', getNodePosition(node, sourceFile).line);
279
+ }
280
+ }
281
+ ts.forEachChild(node, visit);
282
+ }
283
+ visit(sourceFile);
284
+ return { filePath: relPath, nodes, edges, exports };
285
+ }
286
+ /**
287
+ * 扫描目录,解析所有 TS/JS 文件
288
+ */
289
+ async function parseProject(filePaths, projectRoot) {
290
+ const allNodes = [];
291
+ const allEdges = [];
292
+ let fileCount = 0;
293
+ for (const fp of filePaths) {
294
+ const parsed = parseSingleFile(fp, projectRoot);
295
+ if (parsed) {
296
+ allNodes.push(...parsed.nodes);
297
+ allEdges.push(...parsed.edges);
298
+ fileCount++;
299
+ }
300
+ }
301
+ // 去重节点(按 id)
302
+ const nodeMap = new Map();
303
+ for (const n of allNodes) {
304
+ if (!nodeMap.has(n.id)) {
305
+ nodeMap.set(n.id, n);
306
+ }
307
+ }
308
+ return {
309
+ nodes: Array.from(nodeMap.values()),
310
+ edges: allEdges,
311
+ fileCount,
312
+ };
313
+ }
314
+ //# sourceMappingURL=parser.js.map