@vpxa/kb 0.1.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 (275) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1140 -0
  3. package/bin/kb.mjs +10 -0
  4. package/package.json +67 -0
  5. package/packages/analyzers/dist/blast-radius-analyzer.d.ts +23 -0
  6. package/packages/analyzers/dist/blast-radius-analyzer.js +114 -0
  7. package/packages/analyzers/dist/dependency-analyzer.d.ts +29 -0
  8. package/packages/analyzers/dist/dependency-analyzer.js +425 -0
  9. package/packages/analyzers/dist/diagram-generator.d.ts +13 -0
  10. package/packages/analyzers/dist/diagram-generator.js +86 -0
  11. package/packages/analyzers/dist/entry-point-analyzer.d.ts +19 -0
  12. package/packages/analyzers/dist/entry-point-analyzer.js +239 -0
  13. package/packages/analyzers/dist/index.d.ts +14 -0
  14. package/packages/analyzers/dist/index.js +23 -0
  15. package/packages/analyzers/dist/knowledge-producer.d.ts +32 -0
  16. package/packages/analyzers/dist/knowledge-producer.js +113 -0
  17. package/packages/analyzers/dist/pattern-analyzer.d.ts +12 -0
  18. package/packages/analyzers/dist/pattern-analyzer.js +359 -0
  19. package/packages/analyzers/dist/regex-call-graph.d.ts +17 -0
  20. package/packages/analyzers/dist/regex-call-graph.js +428 -0
  21. package/packages/analyzers/dist/structure-analyzer.d.ts +11 -0
  22. package/packages/analyzers/dist/structure-analyzer.js +258 -0
  23. package/packages/analyzers/dist/symbol-analyzer.d.ts +10 -0
  24. package/packages/analyzers/dist/symbol-analyzer.js +442 -0
  25. package/packages/analyzers/dist/ts-call-graph.d.ts +27 -0
  26. package/packages/analyzers/dist/ts-call-graph.js +160 -0
  27. package/packages/analyzers/dist/types.d.ts +98 -0
  28. package/packages/analyzers/dist/types.js +1 -0
  29. package/packages/chunker/dist/call-graph-extractor.d.ts +22 -0
  30. package/packages/chunker/dist/call-graph-extractor.js +90 -0
  31. package/packages/chunker/dist/chunker-factory.d.ts +7 -0
  32. package/packages/chunker/dist/chunker-factory.js +36 -0
  33. package/packages/chunker/dist/chunker.interface.d.ts +10 -0
  34. package/packages/chunker/dist/chunker.interface.js +1 -0
  35. package/packages/chunker/dist/code-chunker.d.ts +14 -0
  36. package/packages/chunker/dist/code-chunker.js +134 -0
  37. package/packages/chunker/dist/generic-chunker.d.ts +12 -0
  38. package/packages/chunker/dist/generic-chunker.js +72 -0
  39. package/packages/chunker/dist/index.d.ts +8 -0
  40. package/packages/chunker/dist/index.js +21 -0
  41. package/packages/chunker/dist/markdown-chunker.d.ts +14 -0
  42. package/packages/chunker/dist/markdown-chunker.js +122 -0
  43. package/packages/chunker/dist/treesitter-chunker.d.ts +47 -0
  44. package/packages/chunker/dist/treesitter-chunker.js +234 -0
  45. package/packages/cli/dist/commands/analyze.d.ts +3 -0
  46. package/packages/cli/dist/commands/analyze.js +112 -0
  47. package/packages/cli/dist/commands/context-cmds.d.ts +3 -0
  48. package/packages/cli/dist/commands/context-cmds.js +155 -0
  49. package/packages/cli/dist/commands/environment.d.ts +3 -0
  50. package/packages/cli/dist/commands/environment.js +204 -0
  51. package/packages/cli/dist/commands/execution.d.ts +3 -0
  52. package/packages/cli/dist/commands/execution.js +137 -0
  53. package/packages/cli/dist/commands/graph.d.ts +3 -0
  54. package/packages/cli/dist/commands/graph.js +81 -0
  55. package/packages/cli/dist/commands/init.d.ts +8 -0
  56. package/packages/cli/dist/commands/init.js +87 -0
  57. package/packages/cli/dist/commands/knowledge.d.ts +3 -0
  58. package/packages/cli/dist/commands/knowledge.js +139 -0
  59. package/packages/cli/dist/commands/search.d.ts +3 -0
  60. package/packages/cli/dist/commands/search.js +267 -0
  61. package/packages/cli/dist/commands/system.d.ts +3 -0
  62. package/packages/cli/dist/commands/system.js +241 -0
  63. package/packages/cli/dist/commands/workspace.d.ts +3 -0
  64. package/packages/cli/dist/commands/workspace.js +388 -0
  65. package/packages/cli/dist/context.d.ts +5 -0
  66. package/packages/cli/dist/context.js +14 -0
  67. package/packages/cli/dist/helpers.d.ts +52 -0
  68. package/packages/cli/dist/helpers.js +458 -0
  69. package/packages/cli/dist/index.d.ts +8 -0
  70. package/packages/cli/dist/index.js +69 -0
  71. package/packages/cli/dist/kb-init.d.ts +57 -0
  72. package/packages/cli/dist/kb-init.js +82 -0
  73. package/packages/cli/dist/types.d.ts +7 -0
  74. package/packages/cli/dist/types.js +1 -0
  75. package/packages/core/dist/constants.d.ts +49 -0
  76. package/packages/core/dist/constants.js +43 -0
  77. package/packages/core/dist/content-detector.d.ts +9 -0
  78. package/packages/core/dist/content-detector.js +79 -0
  79. package/packages/core/dist/errors.d.ts +18 -0
  80. package/packages/core/dist/errors.js +40 -0
  81. package/packages/core/dist/index.d.ts +6 -0
  82. package/packages/core/dist/index.js +9 -0
  83. package/packages/core/dist/logger.d.ts +9 -0
  84. package/packages/core/dist/logger.js +34 -0
  85. package/packages/core/dist/types.d.ts +108 -0
  86. package/packages/core/dist/types.js +1 -0
  87. package/packages/embeddings/dist/embedder.interface.d.ts +24 -0
  88. package/packages/embeddings/dist/embedder.interface.js +1 -0
  89. package/packages/embeddings/dist/index.d.ts +3 -0
  90. package/packages/embeddings/dist/index.js +5 -0
  91. package/packages/embeddings/dist/onnx-embedder.d.ts +24 -0
  92. package/packages/embeddings/dist/onnx-embedder.js +82 -0
  93. package/packages/indexer/dist/file-hasher.d.ts +11 -0
  94. package/packages/indexer/dist/file-hasher.js +13 -0
  95. package/packages/indexer/dist/filesystem-crawler.d.ts +27 -0
  96. package/packages/indexer/dist/filesystem-crawler.js +125 -0
  97. package/packages/indexer/dist/graph-extractor.d.ts +22 -0
  98. package/packages/indexer/dist/graph-extractor.js +111 -0
  99. package/packages/indexer/dist/incremental-indexer.d.ts +47 -0
  100. package/packages/indexer/dist/incremental-indexer.js +278 -0
  101. package/packages/indexer/dist/index.d.ts +5 -0
  102. package/packages/indexer/dist/index.js +14 -0
  103. package/packages/server/dist/api.d.ts +8 -0
  104. package/packages/server/dist/api.js +9 -0
  105. package/packages/server/dist/config.d.ts +3 -0
  106. package/packages/server/dist/config.js +75 -0
  107. package/packages/server/dist/curated-manager.d.ts +86 -0
  108. package/packages/server/dist/curated-manager.js +357 -0
  109. package/packages/server/dist/index.d.ts +2 -0
  110. package/packages/server/dist/index.js +134 -0
  111. package/packages/server/dist/replay-interceptor.d.ts +11 -0
  112. package/packages/server/dist/replay-interceptor.js +38 -0
  113. package/packages/server/dist/resources/resources.d.ts +4 -0
  114. package/packages/server/dist/resources/resources.js +40 -0
  115. package/packages/server/dist/server.d.ts +21 -0
  116. package/packages/server/dist/server.js +247 -0
  117. package/packages/server/dist/tools/analyze.tools.d.ts +11 -0
  118. package/packages/server/dist/tools/analyze.tools.js +288 -0
  119. package/packages/server/dist/tools/forge.tools.d.ts +12 -0
  120. package/packages/server/dist/tools/forge.tools.js +501 -0
  121. package/packages/server/dist/tools/forget.tool.d.ts +4 -0
  122. package/packages/server/dist/tools/forget.tool.js +43 -0
  123. package/packages/server/dist/tools/graph.tool.d.ts +4 -0
  124. package/packages/server/dist/tools/graph.tool.js +110 -0
  125. package/packages/server/dist/tools/list.tool.d.ts +4 -0
  126. package/packages/server/dist/tools/list.tool.js +56 -0
  127. package/packages/server/dist/tools/lookup.tool.d.ts +4 -0
  128. package/packages/server/dist/tools/lookup.tool.js +53 -0
  129. package/packages/server/dist/tools/onboard.tool.d.ts +5 -0
  130. package/packages/server/dist/tools/onboard.tool.js +112 -0
  131. package/packages/server/dist/tools/produce.tool.d.ts +3 -0
  132. package/packages/server/dist/tools/produce.tool.js +74 -0
  133. package/packages/server/dist/tools/read.tool.d.ts +4 -0
  134. package/packages/server/dist/tools/read.tool.js +49 -0
  135. package/packages/server/dist/tools/reindex.tool.d.ts +7 -0
  136. package/packages/server/dist/tools/reindex.tool.js +70 -0
  137. package/packages/server/dist/tools/remember.tool.d.ts +4 -0
  138. package/packages/server/dist/tools/remember.tool.js +45 -0
  139. package/packages/server/dist/tools/replay.tool.d.ts +3 -0
  140. package/packages/server/dist/tools/replay.tool.js +89 -0
  141. package/packages/server/dist/tools/search.tool.d.ts +5 -0
  142. package/packages/server/dist/tools/search.tool.js +331 -0
  143. package/packages/server/dist/tools/status.tool.d.ts +4 -0
  144. package/packages/server/dist/tools/status.tool.js +68 -0
  145. package/packages/server/dist/tools/toolkit.tools.d.ts +35 -0
  146. package/packages/server/dist/tools/toolkit.tools.js +1674 -0
  147. package/packages/server/dist/tools/update.tool.d.ts +4 -0
  148. package/packages/server/dist/tools/update.tool.js +42 -0
  149. package/packages/server/dist/tools/utility.tools.d.ts +15 -0
  150. package/packages/server/dist/tools/utility.tools.js +461 -0
  151. package/packages/store/dist/graph-store.interface.d.ts +104 -0
  152. package/packages/store/dist/graph-store.interface.js +1 -0
  153. package/packages/store/dist/index.d.ts +6 -0
  154. package/packages/store/dist/index.js +9 -0
  155. package/packages/store/dist/lance-store.d.ts +32 -0
  156. package/packages/store/dist/lance-store.js +258 -0
  157. package/packages/store/dist/sqlite-graph-store.d.ts +43 -0
  158. package/packages/store/dist/sqlite-graph-store.js +374 -0
  159. package/packages/store/dist/store-factory.d.ts +9 -0
  160. package/packages/store/dist/store-factory.js +14 -0
  161. package/packages/store/dist/store.interface.d.ts +48 -0
  162. package/packages/store/dist/store.interface.js +1 -0
  163. package/packages/tools/dist/batch.d.ts +21 -0
  164. package/packages/tools/dist/batch.js +45 -0
  165. package/packages/tools/dist/changelog.d.ts +34 -0
  166. package/packages/tools/dist/changelog.js +112 -0
  167. package/packages/tools/dist/check.d.ts +26 -0
  168. package/packages/tools/dist/check.js +59 -0
  169. package/packages/tools/dist/checkpoint.d.ts +17 -0
  170. package/packages/tools/dist/checkpoint.js +43 -0
  171. package/packages/tools/dist/codemod.d.ts +37 -0
  172. package/packages/tools/dist/codemod.js +69 -0
  173. package/packages/tools/dist/compact.d.ts +41 -0
  174. package/packages/tools/dist/compact.js +60 -0
  175. package/packages/tools/dist/data-transform.d.ts +10 -0
  176. package/packages/tools/dist/data-transform.js +124 -0
  177. package/packages/tools/dist/dead-symbols.d.ts +21 -0
  178. package/packages/tools/dist/dead-symbols.js +71 -0
  179. package/packages/tools/dist/delegate.d.ts +34 -0
  180. package/packages/tools/dist/delegate.js +130 -0
  181. package/packages/tools/dist/diff-parse.d.ts +26 -0
  182. package/packages/tools/dist/diff-parse.js +153 -0
  183. package/packages/tools/dist/digest.d.ts +53 -0
  184. package/packages/tools/dist/digest.js +242 -0
  185. package/packages/tools/dist/encode.d.ts +14 -0
  186. package/packages/tools/dist/encode.js +46 -0
  187. package/packages/tools/dist/env-info.d.ts +28 -0
  188. package/packages/tools/dist/env-info.js +58 -0
  189. package/packages/tools/dist/eval.d.ts +13 -0
  190. package/packages/tools/dist/eval.js +79 -0
  191. package/packages/tools/dist/evidence-map.d.ts +79 -0
  192. package/packages/tools/dist/evidence-map.js +203 -0
  193. package/packages/tools/dist/file-summary.d.ts +32 -0
  194. package/packages/tools/dist/file-summary.js +106 -0
  195. package/packages/tools/dist/file-walk.d.ts +4 -0
  196. package/packages/tools/dist/file-walk.js +75 -0
  197. package/packages/tools/dist/find-examples.d.ts +25 -0
  198. package/packages/tools/dist/find-examples.js +48 -0
  199. package/packages/tools/dist/find.d.ts +47 -0
  200. package/packages/tools/dist/find.js +120 -0
  201. package/packages/tools/dist/forge-classify.d.ts +44 -0
  202. package/packages/tools/dist/forge-classify.js +319 -0
  203. package/packages/tools/dist/forge-ground.d.ts +64 -0
  204. package/packages/tools/dist/forge-ground.js +184 -0
  205. package/packages/tools/dist/git-context.d.ts +22 -0
  206. package/packages/tools/dist/git-context.js +46 -0
  207. package/packages/tools/dist/graph-query.d.ts +89 -0
  208. package/packages/tools/dist/graph-query.js +194 -0
  209. package/packages/tools/dist/health.d.ts +14 -0
  210. package/packages/tools/dist/health.js +118 -0
  211. package/packages/tools/dist/http-request.d.ts +23 -0
  212. package/packages/tools/dist/http-request.js +58 -0
  213. package/packages/tools/dist/index.d.ts +49 -0
  214. package/packages/tools/dist/index.js +273 -0
  215. package/packages/tools/dist/lane.d.ts +39 -0
  216. package/packages/tools/dist/lane.js +227 -0
  217. package/packages/tools/dist/measure.d.ts +38 -0
  218. package/packages/tools/dist/measure.js +119 -0
  219. package/packages/tools/dist/onboard.d.ts +41 -0
  220. package/packages/tools/dist/onboard.js +1139 -0
  221. package/packages/tools/dist/parse-output.d.ts +80 -0
  222. package/packages/tools/dist/parse-output.js +158 -0
  223. package/packages/tools/dist/process-manager.d.ts +18 -0
  224. package/packages/tools/dist/process-manager.js +69 -0
  225. package/packages/tools/dist/queue.d.ts +38 -0
  226. package/packages/tools/dist/queue.js +126 -0
  227. package/packages/tools/dist/regex-test.d.ts +31 -0
  228. package/packages/tools/dist/regex-test.js +39 -0
  229. package/packages/tools/dist/rename.d.ts +29 -0
  230. package/packages/tools/dist/rename.js +70 -0
  231. package/packages/tools/dist/replay.d.ts +56 -0
  232. package/packages/tools/dist/replay.js +108 -0
  233. package/packages/tools/dist/schema-validate.d.ts +23 -0
  234. package/packages/tools/dist/schema-validate.js +141 -0
  235. package/packages/tools/dist/scope-map.d.ts +52 -0
  236. package/packages/tools/dist/scope-map.js +72 -0
  237. package/packages/tools/dist/snippet.d.ts +34 -0
  238. package/packages/tools/dist/snippet.js +80 -0
  239. package/packages/tools/dist/stash.d.ts +12 -0
  240. package/packages/tools/dist/stash.js +60 -0
  241. package/packages/tools/dist/stratum-card.d.ts +31 -0
  242. package/packages/tools/dist/stratum-card.js +239 -0
  243. package/packages/tools/dist/symbol.d.ts +28 -0
  244. package/packages/tools/dist/symbol.js +87 -0
  245. package/packages/tools/dist/test-run.d.ts +23 -0
  246. package/packages/tools/dist/test-run.js +55 -0
  247. package/packages/tools/dist/text-utils.d.ts +16 -0
  248. package/packages/tools/dist/text-utils.js +31 -0
  249. package/packages/tools/dist/time-utils.d.ts +18 -0
  250. package/packages/tools/dist/time-utils.js +135 -0
  251. package/packages/tools/dist/trace.d.ts +24 -0
  252. package/packages/tools/dist/trace.js +114 -0
  253. package/packages/tools/dist/truncation.d.ts +22 -0
  254. package/packages/tools/dist/truncation.js +45 -0
  255. package/packages/tools/dist/watch.d.ts +30 -0
  256. package/packages/tools/dist/watch.js +61 -0
  257. package/packages/tools/dist/web-fetch.d.ts +45 -0
  258. package/packages/tools/dist/web-fetch.js +249 -0
  259. package/packages/tools/dist/web-search.d.ts +23 -0
  260. package/packages/tools/dist/web-search.js +46 -0
  261. package/packages/tools/dist/workset.d.ts +45 -0
  262. package/packages/tools/dist/workset.js +77 -0
  263. package/packages/tui/dist/App.d.ts +8 -0
  264. package/packages/tui/dist/App.js +52659 -0
  265. package/packages/tui/dist/index.d.ts +19 -0
  266. package/packages/tui/dist/index.js +54742 -0
  267. package/packages/tui/dist/panels/CuratedPanel.d.ts +8 -0
  268. package/packages/tui/dist/panels/CuratedPanel.js +34452 -0
  269. package/packages/tui/dist/panels/LogPanel.d.ts +3 -0
  270. package/packages/tui/dist/panels/LogPanel.js +51894 -0
  271. package/packages/tui/dist/panels/SearchPanel.d.ts +10 -0
  272. package/packages/tui/dist/panels/SearchPanel.js +34985 -0
  273. package/packages/tui/dist/panels/StatusPanel.d.ts +8 -0
  274. package/packages/tui/dist/panels/StatusPanel.js +34465 -0
  275. package/skills/knowledge-base/SKILL.md +316 -0
@@ -0,0 +1,428 @@
1
+ import { readdirSync, readFileSync } from "node:fs";
2
+ import { extname, join, relative } from "node:path";
3
+ const SKIP_DIRS = /* @__PURE__ */ new Set([
4
+ "node_modules",
5
+ ".git",
6
+ "dist",
7
+ "build",
8
+ "coverage",
9
+ ".turbo",
10
+ ".cache",
11
+ "cdk.out",
12
+ ".venv",
13
+ "venv",
14
+ "__pycache__",
15
+ "target",
16
+ "vendor",
17
+ "bin",
18
+ "obj"
19
+ ]);
20
+ const CODE_EXTENSIONS = /* @__PURE__ */ new Set([
21
+ ".ts",
22
+ ".tsx",
23
+ ".js",
24
+ ".jsx",
25
+ ".java",
26
+ ".py",
27
+ ".go",
28
+ ".cs",
29
+ ".kt",
30
+ ".scala",
31
+ ".rs",
32
+ ".rb",
33
+ ".php",
34
+ ".swift"
35
+ ]);
36
+ async function extractRegexCallGraph(rootPath) {
37
+ const startTime = Date.now();
38
+ const files = collectFiles(rootPath);
39
+ if (files.length === 0) return null;
40
+ const cappedFiles = files.slice(0, 800);
41
+ const fileImports = /* @__PURE__ */ new Map();
42
+ const moduleExports = /* @__PURE__ */ new Map();
43
+ for (const fullPath of cappedFiles) {
44
+ const relPath = relative(rootPath, fullPath).replace(/\\/g, "/");
45
+ const content = readFileSync(fullPath, "utf-8");
46
+ const ext = extname(fullPath).toLowerCase();
47
+ const imports = parseImports(content, ext);
48
+ fileImports.set(relPath, imports);
49
+ const exports = parseExports(content, ext);
50
+ moduleExports.set(relPath, exports);
51
+ }
52
+ const stemToFiles = buildStemLookup(cappedFiles, rootPath);
53
+ const edgeMap = /* @__PURE__ */ new Map();
54
+ for (const [callerRel, imports] of fileImports) {
55
+ if (isTestPath(callerRel)) continue;
56
+ const callerContent = readFileSync(join(rootPath, callerRel), "utf-8");
57
+ const bodyContent = stripImportLines(callerContent, extname(callerRel));
58
+ for (const imp of imports) {
59
+ if (!imp.isRelative) continue;
60
+ const targetPaths = resolveImportPath(callerRel, imp.source, stemToFiles, extname(callerRel));
61
+ if (targetPaths.length === 0) continue;
62
+ const targetRel = targetPaths[0];
63
+ if (isTestPath(targetRel)) continue;
64
+ if (callerRel === targetRel) continue;
65
+ let usedSymbols;
66
+ if (imp.symbols.length > 0) {
67
+ usedSymbols = imp.symbols.filter((sym) => {
68
+ const regex = new RegExp(`\\b${escapeRegex(sym)}\\b`);
69
+ return regex.test(bodyContent);
70
+ });
71
+ } else {
72
+ usedSymbols = ["*"];
73
+ }
74
+ if (usedSymbols.length === 0) continue;
75
+ const edgeKey = `${callerRel}|${targetRel}`;
76
+ const existing = edgeMap.get(edgeKey);
77
+ if (existing) {
78
+ for (const s of usedSymbols) existing.add(s);
79
+ } else {
80
+ edgeMap.set(edgeKey, new Set(usedSymbols));
81
+ }
82
+ }
83
+ }
84
+ const edges = [];
85
+ for (const [key, syms] of edgeMap) {
86
+ const [from, to] = key.split("|");
87
+ edges.push({ from, to, symbols: [...syms].sort().slice(0, 10) });
88
+ }
89
+ edges.sort((a, b) => b.symbols.length - a.symbols.length);
90
+ return {
91
+ edges,
92
+ fileCount: cappedFiles.length,
93
+ edgeCount: edges.length,
94
+ durationMs: Date.now() - startTime
95
+ };
96
+ }
97
+ function parseImports(content, ext) {
98
+ const imports = [];
99
+ switch (ext) {
100
+ case ".ts":
101
+ case ".tsx":
102
+ case ".js":
103
+ case ".jsx": {
104
+ const esNamed = /import\s+(?:type\s+)?\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]/g;
105
+ let m;
106
+ while ((m = esNamed.exec(content)) !== null) {
107
+ const symbols = m[1].split(",").map((s) => {
108
+ const parts = s.trim().split(/\s+as\s+/);
109
+ return (parts[parts.length - 1] || "").trim();
110
+ }).filter(Boolean);
111
+ imports.push({ source: m[2], symbols, isRelative: m[2].startsWith(".") });
112
+ }
113
+ const esDefault = /import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g;
114
+ while ((m = esDefault.exec(content)) !== null) {
115
+ if (m[1] === "type") continue;
116
+ imports.push({ source: m[2], symbols: [m[1]], isRelative: m[2].startsWith(".") });
117
+ }
118
+ const cjsNamed = /(?:const|let|var)\s+\{([^}]+)\}\s*=\s*require\(\s*['"]([^'"]+)['"]\s*\)/g;
119
+ while ((m = cjsNamed.exec(content)) !== null) {
120
+ const symbols = m[1].split(",").map((s) => s.trim().split(":")[0].trim()).filter(Boolean);
121
+ imports.push({ source: m[2], symbols, isRelative: m[2].startsWith(".") });
122
+ }
123
+ break;
124
+ }
125
+ case ".java":
126
+ case ".kt":
127
+ case ".scala": {
128
+ const javaImport = /^import\s+(?:static\s+)?([\w.]+)\s*;/gm;
129
+ let m;
130
+ while ((m = javaImport.exec(content)) !== null) {
131
+ const parts = m[1].split(".");
132
+ const lastPart = parts[parts.length - 1];
133
+ if (lastPart === "*") {
134
+ imports.push({
135
+ source: m[1],
136
+ symbols: [],
137
+ isRelative: isInternalJavaImport(m[1], content)
138
+ });
139
+ } else {
140
+ imports.push({
141
+ source: m[1],
142
+ symbols: [lastPart],
143
+ isRelative: isInternalJavaImport(m[1], content)
144
+ });
145
+ }
146
+ }
147
+ break;
148
+ }
149
+ case ".py": {
150
+ const fromImport = /^from\s+([\w.]+)\s+import\s+(.+)$/gm;
151
+ let m;
152
+ while ((m = fromImport.exec(content)) !== null) {
153
+ const symbols = m[2].split(",").map((s) => {
154
+ const parts = s.trim().split(/\s+as\s+/);
155
+ return (parts[parts.length - 1] || "").trim();
156
+ }).filter((s) => s && s !== "(");
157
+ imports.push({ source: m[1], symbols, isRelative: m[1].startsWith(".") });
158
+ }
159
+ const plainImport = /^import\s+([\w.]+)(?:\s+as\s+(\w+))?\s*$/gm;
160
+ while ((m = plainImport.exec(content)) !== null) {
161
+ const pyParts = m[1].split(".");
162
+ const alias = m[2] || pyParts[pyParts.length - 1];
163
+ imports.push({ source: m[1], symbols: [alias], isRelative: m[1].startsWith(".") });
164
+ }
165
+ break;
166
+ }
167
+ case ".go": {
168
+ const goSingle = /import\s+(?:(\w+)\s+)?[""]([^""]+)[""]/g;
169
+ let m;
170
+ while ((m = goSingle.exec(content)) !== null) {
171
+ const goParts = m[2].split("/");
172
+ const alias = m[1] || goParts[goParts.length - 1];
173
+ imports.push({
174
+ source: m[2],
175
+ symbols: [alias],
176
+ isRelative: !m[2].includes(".") && !m[2].startsWith("github.com")
177
+ });
178
+ }
179
+ const goBlock = /import\s*\(([\s\S]*?)\)/g;
180
+ while ((m = goBlock.exec(content)) !== null) {
181
+ const blockContent = m[1];
182
+ const lineRe = /(?:(\w+)\s+)?[""]([^""]+)[""]/g;
183
+ let lm;
184
+ while ((lm = lineRe.exec(blockContent)) !== null) {
185
+ const blockParts = lm[2].split("/");
186
+ const alias = lm[1] || blockParts[blockParts.length - 1];
187
+ imports.push({
188
+ source: lm[2],
189
+ symbols: [alias],
190
+ isRelative: !lm[2].includes(".") && !lm[2].startsWith("github.com")
191
+ });
192
+ }
193
+ }
194
+ break;
195
+ }
196
+ case ".cs": {
197
+ const csUsing = /^using\s+(?:static\s+)?([\w.]+)\s*;/gm;
198
+ let m;
199
+ while ((m = csUsing.exec(content)) !== null) {
200
+ const parts = m[1].split(".");
201
+ imports.push({ source: m[1], symbols: [parts[parts.length - 1]], isRelative: true });
202
+ }
203
+ break;
204
+ }
205
+ case ".rs": {
206
+ const rsUse = /^use\s+([\w:]+(?:::\w+)*)/gm;
207
+ let m;
208
+ while ((m = rsUse.exec(content)) !== null) {
209
+ const parts = m[1].split("::");
210
+ const lastPart = parts[parts.length - 1];
211
+ imports.push({
212
+ source: m[1],
213
+ symbols: lastPart === "*" ? [] : [lastPart],
214
+ isRelative: m[1].startsWith("crate") || m[1].startsWith("super")
215
+ });
216
+ }
217
+ break;
218
+ }
219
+ }
220
+ return imports;
221
+ }
222
+ function parseExports(content, ext) {
223
+ const exports = /* @__PURE__ */ new Set();
224
+ switch (ext) {
225
+ case ".ts":
226
+ case ".tsx":
227
+ case ".js":
228
+ case ".jsx": {
229
+ const exportPattern = /export\s+(?:default\s+)?(?:abstract\s+)?(?:async\s+)?(?:function|class|const|let|var|type|interface|enum)\s+(\w+)/g;
230
+ let m;
231
+ while ((m = exportPattern.exec(content)) !== null) exports.add(m[1]);
232
+ break;
233
+ }
234
+ case ".java":
235
+ case ".kt":
236
+ case ".scala": {
237
+ const javaPattern = /(?:public|protected)\s+(?:static\s+)?(?:abstract\s+)?(?:final\s+)?(?:class|interface|enum|record|@interface)\s+(\w+)/g;
238
+ let m;
239
+ while ((m = javaPattern.exec(content)) !== null) exports.add(m[1]);
240
+ const methodPattern = /(?:public|protected)\s+(?:static\s+)?(?:abstract\s+)?(?:final\s+)?\w+(?:<[^>]+>)?\s+(\w+)\s*\(/g;
241
+ while ((m = methodPattern.exec(content)) !== null) {
242
+ if (![
243
+ "if",
244
+ "for",
245
+ "while",
246
+ "switch",
247
+ "catch",
248
+ "return",
249
+ "class",
250
+ "interface",
251
+ "enum",
252
+ "new"
253
+ ].includes(m[1])) {
254
+ exports.add(m[1]);
255
+ }
256
+ }
257
+ break;
258
+ }
259
+ case ".py": {
260
+ const pyPattern = /^(?:def|class)\s+([A-Z_]\w*)/gm;
261
+ let m;
262
+ while ((m = pyPattern.exec(content)) !== null) {
263
+ if (!m[1].startsWith("_")) exports.add(m[1]);
264
+ }
265
+ break;
266
+ }
267
+ case ".go": {
268
+ const goPattern = /^(?:func|type|var|const)\s+(\(?[A-Z]\w*)/gm;
269
+ let m;
270
+ while ((m = goPattern.exec(content)) !== null) exports.add(m[1].replace("(", ""));
271
+ break;
272
+ }
273
+ }
274
+ return exports;
275
+ }
276
+ function isInternalJavaImport(importPath, fileContent) {
277
+ const pkgMatch = fileContent.match(/^package\s+([\w.]+)\s*;/m);
278
+ if (!pkgMatch) return false;
279
+ const filePkg = pkgMatch[1];
280
+ const fileParts = filePkg.split(".");
281
+ const importParts = importPath.split(".");
282
+ return fileParts.length >= 2 && importParts.length >= 2 && fileParts[0] === importParts[0] && fileParts[1] === importParts[1];
283
+ }
284
+ function escapeRegex(s) {
285
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
286
+ }
287
+ function stripImportLines(content, ext) {
288
+ switch (ext) {
289
+ case ".ts":
290
+ case ".tsx":
291
+ case ".js":
292
+ case ".jsx":
293
+ return content.replace(/^import\s+.+$/gm, "").replace(/^const\s+.+=\s*require\(.+$/gm, "");
294
+ case ".java":
295
+ case ".kt":
296
+ case ".scala":
297
+ return content.replace(/^import\s+.+;$/gm, "");
298
+ case ".py":
299
+ return content.replace(/^(?:from\s+.+import\s+.+|import\s+.+)$/gm, "");
300
+ case ".go":
301
+ return content.replace(/^import\s+.+$/gm, "").replace(/import\s*\([\s\S]*?\)/g, "");
302
+ case ".cs":
303
+ return content.replace(/^using\s+.+;$/gm, "");
304
+ case ".rs":
305
+ return content.replace(/^use\s+.+;$/gm, "");
306
+ default:
307
+ return content;
308
+ }
309
+ }
310
+ function buildStemLookup(files, rootPath) {
311
+ const lookup = /* @__PURE__ */ new Map();
312
+ for (const fullPath of files) {
313
+ const relPath = relative(rootPath, fullPath).replace(/\\/g, "/");
314
+ const withoutExt = relPath.replace(/\.[^.]+$/, "");
315
+ addToLookup(lookup, withoutExt, relPath);
316
+ const stemParts = withoutExt.split("/");
317
+ const baseName = stemParts[stemParts.length - 1];
318
+ addToLookup(lookup, baseName, relPath);
319
+ }
320
+ return lookup;
321
+ }
322
+ function addToLookup(lookup, key, value) {
323
+ const existing = lookup.get(key);
324
+ if (existing) existing.push(value);
325
+ else lookup.set(key, [value]);
326
+ }
327
+ function resolveImportPath(callerRel, source, stemLookup, callerExt) {
328
+ switch (callerExt) {
329
+ case ".ts":
330
+ case ".tsx":
331
+ case ".js":
332
+ case ".jsx": {
333
+ if (!source.startsWith(".")) return [];
334
+ const callerDir = callerRel.split("/").slice(0, -1).join("/");
335
+ const resolved = normalizePath(callerDir ? `${callerDir}/${source}` : source);
336
+ for (const ext of ["", ".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.js"]) {
337
+ const candidates = stemLookup.get(resolved + ext) || stemLookup.get((resolved + ext).replace(/\.[^.]+$/, ""));
338
+ if (candidates && candidates.length > 0) return [candidates[0]];
339
+ }
340
+ const direct = stemLookup.get(resolved.replace(/\.[^.]+$/, ""));
341
+ if (direct) return [direct[0]];
342
+ return [];
343
+ }
344
+ case ".java":
345
+ case ".kt":
346
+ case ".scala": {
347
+ const parts = source.split(".");
348
+ const className = parts[parts.length - 1];
349
+ if (className === "*") return [];
350
+ const candidates = stemLookup.get(className);
351
+ if (candidates) return [candidates[0]];
352
+ return [];
353
+ }
354
+ case ".py": {
355
+ if (source.startsWith(".")) {
356
+ const callerDir = callerRel.split("/").slice(0, -1).join("/");
357
+ const modulePath2 = source.replace(/^\.+/, "").replace(/\./g, "/");
358
+ const resolved = callerDir ? `${callerDir}/${modulePath2}` : modulePath2;
359
+ const pyResParts = resolved.split("/");
360
+ const candidates2 = stemLookup.get(resolved) || stemLookup.get(pyResParts[pyResParts.length - 1]);
361
+ if (candidates2) return [candidates2[0]];
362
+ }
363
+ const modulePath = source.replace(/\./g, "/");
364
+ const candidates = stemLookup.get(modulePath);
365
+ if (candidates) return [candidates[0]];
366
+ return [];
367
+ }
368
+ case ".go": {
369
+ const goSegments = source.split("/");
370
+ const lastSeg = goSegments[goSegments.length - 1];
371
+ const candidates = stemLookup.get(lastSeg);
372
+ if (candidates) return [candidates[0]];
373
+ return [];
374
+ }
375
+ default:
376
+ return [];
377
+ }
378
+ }
379
+ function normalizePath(p) {
380
+ const parts = p.split("/");
381
+ const result = [];
382
+ for (const part of parts) {
383
+ if (part === "." || part === "") continue;
384
+ if (part === "..") {
385
+ result.pop();
386
+ continue;
387
+ }
388
+ result.push(part);
389
+ }
390
+ return result.join("/");
391
+ }
392
+ function isTestPath(fp) {
393
+ const segments = fp.split("/");
394
+ return segments.some(
395
+ (s) => s === "test" || s === "tests" || s === "__tests__" || s === "spec" || s === "test_" || s === "__test__"
396
+ ) || /\.(test|spec)\.[^.]+$/.test(fp);
397
+ }
398
+ function collectFiles(rootPath) {
399
+ const files = [];
400
+ const walk = (dir, depth) => {
401
+ if (depth > 10) return;
402
+ try {
403
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
404
+ if (SKIP_DIRS.has(entry.name) || entry.name.startsWith(".")) continue;
405
+ const fullPath = join(dir, entry.name);
406
+ if (entry.isDirectory()) {
407
+ walk(fullPath, depth + 1);
408
+ } else {
409
+ const ext = extname(entry.name).toLowerCase();
410
+ if (!CODE_EXTENSIONS.has(ext)) continue;
411
+ if (entry.name.endsWith(".d.ts")) continue;
412
+ if (/\.(test|spec)\.[^.]+$/.test(entry.name)) continue;
413
+ const relDir = relative(rootPath, dir).replace(/\\/g, "/");
414
+ if (relDir.split("/").some((s) => s === "test" || s === "tests" || s === "__tests__" || s === "spec"))
415
+ continue;
416
+ files.push(fullPath);
417
+ }
418
+ }
419
+ } catch {
420
+ }
421
+ };
422
+ walk(rootPath, 0);
423
+ return files;
424
+ }
425
+ export {
426
+ extractRegexCallGraph
427
+ };
428
+ //# sourceMappingURL=regex-call-graph.js.map
@@ -0,0 +1,11 @@
1
+ import type { AnalysisResult, IAnalyzer, StructureAnalyzerOptions } from './types.js';
2
+ export declare class StructureAnalyzer implements IAnalyzer<StructureAnalyzerOptions> {
3
+ readonly name = "structure";
4
+ analyze(rootPath: string, options?: StructureAnalyzerOptions): Promise<AnalysisResult>;
5
+ private buildTree;
6
+ private computeStats;
7
+ private formatMarkdown;
8
+ private renderTree;
9
+ private countFiles;
10
+ }
11
+ //# sourceMappingURL=structure-analyzer.d.ts.map
@@ -0,0 +1,258 @@
1
+ import { readdir, stat } from "node:fs/promises";
2
+ import { extname, join } from "node:path";
3
+ const DIRECTORY_PURPOSES = {
4
+ src: "Application source",
5
+ lib: "Library code",
6
+ dist: "Build output",
7
+ build: "Build output",
8
+ test: "Tests",
9
+ tests: "Tests",
10
+ spec: "Tests",
11
+ __tests__: "Tests",
12
+ docs: "Documentation",
13
+ scripts: "Build/utility scripts",
14
+ config: "Configuration",
15
+ handlers: "Entry point handlers",
16
+ controllers: "HTTP controllers",
17
+ routes: "API routes",
18
+ middleware: "Middleware",
19
+ services: "Business logic services",
20
+ domain: "Domain/business logic",
21
+ infrastructure: "External integrations",
22
+ adapters: "Adapter implementations",
23
+ ports: "Port interfaces",
24
+ models: "Data models",
25
+ entities: "Domain entities",
26
+ repositories: "Data access",
27
+ utils: "Utilities",
28
+ helpers: "Helper functions",
29
+ types: "Type definitions",
30
+ interfaces: "Interface definitions",
31
+ constants: "Constants",
32
+ cdk: "CDK infrastructure",
33
+ stacks: "CDK stacks",
34
+ constructs: "CDK constructs",
35
+ lambdas: "Lambda functions",
36
+ components: "UI components",
37
+ hooks: "React hooks",
38
+ pages: "Page components",
39
+ layouts: "Layout components",
40
+ store: "State management",
41
+ assets: "Static assets",
42
+ styles: "Stylesheets",
43
+ fixtures: "Test fixtures",
44
+ mocks: "Test mocks",
45
+ migrations: "Database migrations"
46
+ };
47
+ const LANGUAGE_MAP = {
48
+ ".ts": "TypeScript",
49
+ ".tsx": "React TSX",
50
+ ".js": "JavaScript",
51
+ ".jsx": "React JSX",
52
+ ".mjs": "ES Module",
53
+ ".cjs": "CommonJS",
54
+ ".json": "JSON",
55
+ ".yaml": "YAML",
56
+ ".yml": "YAML",
57
+ ".md": "Markdown",
58
+ ".mdx": "MDX",
59
+ ".py": "Python",
60
+ ".go": "Go",
61
+ ".rs": "Rust",
62
+ ".java": "Java",
63
+ ".sh": "Shell",
64
+ ".ps1": "PowerShell",
65
+ ".css": "CSS",
66
+ ".scss": "SCSS",
67
+ ".html": "HTML",
68
+ ".sql": "SQL",
69
+ ".graphql": "GraphQL",
70
+ ".proto": "Protocol Buffers",
71
+ ".toml": "TOML",
72
+ ".env": "Environment"
73
+ };
74
+ const DEFAULT_EXCLUDES = /* @__PURE__ */ new Set([
75
+ "node_modules",
76
+ ".git",
77
+ "dist",
78
+ "build",
79
+ ".next",
80
+ ".nuxt",
81
+ "coverage",
82
+ ".turbo",
83
+ ".cache",
84
+ "__pycache__",
85
+ ".venv",
86
+ ".terraform",
87
+ "cdk.out"
88
+ ]);
89
+ const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
90
+ // Code
91
+ ".ts",
92
+ ".tsx",
93
+ ".js",
94
+ ".jsx",
95
+ ".mjs",
96
+ ".cjs",
97
+ ".java",
98
+ ".kt",
99
+ ".kts",
100
+ ".scala",
101
+ ".py",
102
+ ".go",
103
+ ".rs",
104
+ ".rb",
105
+ ".php",
106
+ ".swift",
107
+ ".cs",
108
+ ".c",
109
+ ".cpp",
110
+ ".h",
111
+ ".hpp",
112
+ ".sh",
113
+ ".bash",
114
+ ".ps1",
115
+ ".sql",
116
+ ".graphql",
117
+ ".gql",
118
+ ".proto",
119
+ // Config
120
+ ".json",
121
+ ".yaml",
122
+ ".yml",
123
+ ".toml",
124
+ ".env",
125
+ ".ini",
126
+ ".cfg",
127
+ ".xml",
128
+ ".pom",
129
+ ".gradle",
130
+ ".tf",
131
+ ".hcl",
132
+ // Build/project
133
+ ".lock",
134
+ ".mjs"
135
+ ]);
136
+ const COLLAPSED_DIRS = /* @__PURE__ */ new Set([
137
+ "__tests__",
138
+ "test",
139
+ "tests",
140
+ "spec",
141
+ "__mocks__",
142
+ "__fixtures__",
143
+ "fixtures",
144
+ "mocks"
145
+ ]);
146
+ class StructureAnalyzer {
147
+ name = "structure";
148
+ async analyze(rootPath, options = {}) {
149
+ const { format = "markdown", maxDepth = 6, sourceOnly = false } = options;
150
+ const startTime = Date.now();
151
+ const tree = await this.buildTree(rootPath, 0, maxDepth, sourceOnly);
152
+ const stats = this.computeStats(tree);
153
+ const output = format === "json" ? JSON.stringify({ tree, stats }, null, 2) : this.formatMarkdown(tree, stats, rootPath);
154
+ return {
155
+ output,
156
+ data: { tree, stats },
157
+ meta: {
158
+ analyzedAt: (/* @__PURE__ */ new Date()).toISOString(),
159
+ scope: rootPath,
160
+ fileCount: stats.totalFiles,
161
+ durationMs: Date.now() - startTime
162
+ }
163
+ };
164
+ }
165
+ async buildTree(dirPath, depth, maxDepth, sourceOnly) {
166
+ const entries = await readdir(dirPath, { withFileTypes: true });
167
+ const children = [];
168
+ for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
169
+ if (DEFAULT_EXCLUDES.has(entry.name)) continue;
170
+ if (entry.name.startsWith(".") && entry.name !== ".env.example") continue;
171
+ const fullPath = join(dirPath, entry.name);
172
+ if (entry.isDirectory() && depth < maxDepth) {
173
+ const subtree = await this.buildTree(fullPath, depth + 1, maxDepth, sourceOnly);
174
+ if (sourceOnly && (!subtree.children || subtree.children.length === 0)) continue;
175
+ children.push(subtree);
176
+ } else if (entry.isFile()) {
177
+ const ext = extname(entry.name).toLowerCase();
178
+ if (sourceOnly && ext && !SOURCE_EXTENSIONS.has(ext)) continue;
179
+ if (sourceOnly && !ext) continue;
180
+ const fileStat = await stat(fullPath);
181
+ children.push({
182
+ name: entry.name,
183
+ type: "file",
184
+ language: LANGUAGE_MAP[ext] ?? (ext || "unknown"),
185
+ size: fileStat.size
186
+ });
187
+ }
188
+ }
189
+ const dirName = dirPath.split(/[/\\]/).pop() ?? dirPath;
190
+ return {
191
+ name: dirName,
192
+ type: "directory",
193
+ purpose: DIRECTORY_PURPOSES[dirName.toLowerCase()],
194
+ children
195
+ };
196
+ }
197
+ computeStats(tree) {
198
+ const languages = {};
199
+ let totalFiles = 0;
200
+ let totalSize = 0;
201
+ const walk = (node) => {
202
+ if (node.type === "file") {
203
+ totalFiles++;
204
+ totalSize += node.size ?? 0;
205
+ const lang = node.language ?? "unknown";
206
+ languages[lang] = (languages[lang] ?? 0) + 1;
207
+ }
208
+ node.children?.forEach(walk);
209
+ };
210
+ walk(tree);
211
+ return { totalFiles, totalSize, languages };
212
+ }
213
+ formatMarkdown(tree, stats, rootPath) {
214
+ const lines = [];
215
+ lines.push(`## Project Structure: ${rootPath}
216
+ `);
217
+ lines.push(
218
+ `**${stats.totalFiles} files** | Languages: ${Object.entries(stats.languages).map(([l, c]) => `${l} (${c})`).join(", ")}
219
+ `
220
+ );
221
+ lines.push("```");
222
+ this.renderTree(tree, "", lines);
223
+ lines.push("```");
224
+ return lines.join("\n");
225
+ }
226
+ renderTree(node, prefix, lines) {
227
+ const annotation = node.purpose ? ` \u2500\u2500 ${node.purpose}` : "";
228
+ if (node.type === "directory") {
229
+ const lowerName = node.name.toLowerCase();
230
+ if (COLLAPSED_DIRS.has(lowerName) && node.children) {
231
+ const count = this.countFiles(node);
232
+ lines.push(`${prefix}${node.name}/${annotation} (${count} files)`);
233
+ return;
234
+ }
235
+ lines.push(`${prefix}${node.name}/${annotation}`);
236
+ node.children?.forEach((child, i) => {
237
+ const isLast = i === (node.children?.length ?? 0) - 1;
238
+ const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
239
+ const nextPrefix = prefix + (isLast ? " " : "\u2502 ");
240
+ if (child.type === "directory") {
241
+ this.renderTree(child, nextPrefix, lines);
242
+ } else {
243
+ lines.push(`${prefix}${connector}${child.name}`);
244
+ }
245
+ });
246
+ } else {
247
+ lines.push(`${prefix}${node.name}`);
248
+ }
249
+ }
250
+ countFiles(node) {
251
+ if (node.type === "file") return 1;
252
+ return (node.children ?? []).reduce((sum, child) => sum + this.countFiles(child), 0);
253
+ }
254
+ }
255
+ export {
256
+ StructureAnalyzer
257
+ };
258
+ //# sourceMappingURL=structure-analyzer.js.map