@phantomind/core 0.1.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 (265) hide show
  1. package/dist/adapters/aider.d.ts +12 -0
  2. package/dist/adapters/aider.d.ts.map +1 -0
  3. package/dist/adapters/aider.js +24 -0
  4. package/dist/adapters/aider.js.map +1 -0
  5. package/dist/adapters/base.d.ts +21 -0
  6. package/dist/adapters/base.d.ts.map +1 -0
  7. package/dist/adapters/base.js +83 -0
  8. package/dist/adapters/base.js.map +1 -0
  9. package/dist/adapters/claude-code.d.ts +12 -0
  10. package/dist/adapters/claude-code.d.ts.map +1 -0
  11. package/dist/adapters/claude-code.js +31 -0
  12. package/dist/adapters/claude-code.js.map +1 -0
  13. package/dist/adapters/cline.d.ts +12 -0
  14. package/dist/adapters/cline.d.ts.map +1 -0
  15. package/dist/adapters/cline.js +32 -0
  16. package/dist/adapters/cline.js.map +1 -0
  17. package/dist/adapters/codex.d.ts +18 -0
  18. package/dist/adapters/codex.d.ts.map +1 -0
  19. package/dist/adapters/codex.js +38 -0
  20. package/dist/adapters/codex.js.map +1 -0
  21. package/dist/adapters/continue.d.ts +12 -0
  22. package/dist/adapters/continue.d.ts.map +1 -0
  23. package/dist/adapters/continue.js +29 -0
  24. package/dist/adapters/continue.js.map +1 -0
  25. package/dist/adapters/copilot.d.ts +12 -0
  26. package/dist/adapters/copilot.d.ts.map +1 -0
  27. package/dist/adapters/copilot.js +31 -0
  28. package/dist/adapters/copilot.js.map +1 -0
  29. package/dist/adapters/cursor.d.ts +12 -0
  30. package/dist/adapters/cursor.d.ts.map +1 -0
  31. package/dist/adapters/cursor.js +34 -0
  32. package/dist/adapters/cursor.js.map +1 -0
  33. package/dist/adapters/index.d.ts +32 -0
  34. package/dist/adapters/index.d.ts.map +1 -0
  35. package/dist/adapters/index.js +64 -0
  36. package/dist/adapters/index.js.map +1 -0
  37. package/dist/adapters/windsurf.d.ts +12 -0
  38. package/dist/adapters/windsurf.d.ts.map +1 -0
  39. package/dist/adapters/windsurf.js +32 -0
  40. package/dist/adapters/windsurf.js.map +1 -0
  41. package/dist/adapters/zed.d.ts +12 -0
  42. package/dist/adapters/zed.d.ts.map +1 -0
  43. package/dist/adapters/zed.js +27 -0
  44. package/dist/adapters/zed.js.map +1 -0
  45. package/dist/agent/decomposer.d.ts +55 -0
  46. package/dist/agent/decomposer.d.ts.map +1 -0
  47. package/dist/agent/decomposer.js +172 -0
  48. package/dist/agent/decomposer.js.map +1 -0
  49. package/dist/agent/executor.d.ts +33 -0
  50. package/dist/agent/executor.d.ts.map +1 -0
  51. package/dist/agent/executor.js +260 -0
  52. package/dist/agent/executor.js.map +1 -0
  53. package/dist/agent/index.d.ts +8 -0
  54. package/dist/agent/index.d.ts.map +1 -0
  55. package/dist/agent/index.js +8 -0
  56. package/dist/agent/index.js.map +1 -0
  57. package/dist/agent/memory.d.ts +95 -0
  58. package/dist/agent/memory.d.ts.map +1 -0
  59. package/dist/agent/memory.js +211 -0
  60. package/dist/agent/memory.js.map +1 -0
  61. package/dist/agent/orchestrator.d.ts +54 -0
  62. package/dist/agent/orchestrator.d.ts.map +1 -0
  63. package/dist/agent/orchestrator.js +190 -0
  64. package/dist/agent/orchestrator.js.map +1 -0
  65. package/dist/agent/queue.d.ts +95 -0
  66. package/dist/agent/queue.d.ts.map +1 -0
  67. package/dist/agent/queue.js +231 -0
  68. package/dist/agent/queue.js.map +1 -0
  69. package/dist/agent/retry.d.ts +61 -0
  70. package/dist/agent/retry.d.ts.map +1 -0
  71. package/dist/agent/retry.js +162 -0
  72. package/dist/agent/retry.js.map +1 -0
  73. package/dist/agent/roles.d.ts +35 -0
  74. package/dist/agent/roles.d.ts.map +1 -0
  75. package/dist/agent/roles.js +269 -0
  76. package/dist/agent/roles.js.map +1 -0
  77. package/dist/cli/agent.d.ts +12 -0
  78. package/dist/cli/agent.d.ts.map +1 -0
  79. package/dist/cli/agent.js +85 -0
  80. package/dist/cli/agent.js.map +1 -0
  81. package/dist/cli/audit.d.ts +11 -0
  82. package/dist/cli/audit.d.ts.map +1 -0
  83. package/dist/cli/audit.js +63 -0
  84. package/dist/cli/audit.js.map +1 -0
  85. package/dist/cli/eval.d.ts +11 -0
  86. package/dist/cli/eval.d.ts.map +1 -0
  87. package/dist/cli/eval.js +79 -0
  88. package/dist/cli/eval.js.map +1 -0
  89. package/dist/cli/index.d.ts +9 -0
  90. package/dist/cli/index.d.ts.map +1 -0
  91. package/dist/cli/index.js +9 -0
  92. package/dist/cli/index.js.map +1 -0
  93. package/dist/cli/init.d.ts +13 -0
  94. package/dist/cli/init.d.ts.map +1 -0
  95. package/dist/cli/init.js +157 -0
  96. package/dist/cli/init.js.map +1 -0
  97. package/dist/cli/main.d.ts +7 -0
  98. package/dist/cli/main.d.ts.map +1 -0
  99. package/dist/cli/main.js +153 -0
  100. package/dist/cli/main.js.map +1 -0
  101. package/dist/cli/serve.d.ts +11 -0
  102. package/dist/cli/serve.d.ts.map +1 -0
  103. package/dist/cli/serve.js +23 -0
  104. package/dist/cli/serve.js.map +1 -0
  105. package/dist/cli/stats.d.ts +10 -0
  106. package/dist/cli/stats.d.ts.map +1 -0
  107. package/dist/cli/stats.js +68 -0
  108. package/dist/cli/stats.js.map +1 -0
  109. package/dist/cli/sync.d.ts +11 -0
  110. package/dist/cli/sync.d.ts.map +1 -0
  111. package/dist/cli/sync.js +49 -0
  112. package/dist/cli/sync.js.map +1 -0
  113. package/dist/cli/validate.d.ts +13 -0
  114. package/dist/cli/validate.d.ts.map +1 -0
  115. package/dist/cli/validate.js +125 -0
  116. package/dist/cli/validate.js.map +1 -0
  117. package/dist/config/index.d.ts +2 -0
  118. package/dist/config/index.d.ts.map +1 -0
  119. package/dist/config/index.js +2 -0
  120. package/dist/config/index.js.map +1 -0
  121. package/dist/config/loader.d.ts +25 -0
  122. package/dist/config/loader.d.ts.map +1 -0
  123. package/dist/config/loader.js +190 -0
  124. package/dist/config/loader.js.map +1 -0
  125. package/dist/context/embedder.d.ts +53 -0
  126. package/dist/context/embedder.d.ts.map +1 -0
  127. package/dist/context/embedder.js +235 -0
  128. package/dist/context/embedder.js.map +1 -0
  129. package/dist/context/engine.d.ts +82 -0
  130. package/dist/context/engine.d.ts.map +1 -0
  131. package/dist/context/engine.js +343 -0
  132. package/dist/context/engine.js.map +1 -0
  133. package/dist/context/index.d.ts +5 -0
  134. package/dist/context/index.d.ts.map +1 -0
  135. package/dist/context/index.js +5 -0
  136. package/dist/context/index.js.map +1 -0
  137. package/dist/context/learner.d.ts +44 -0
  138. package/dist/context/learner.d.ts.map +1 -0
  139. package/dist/context/learner.js +246 -0
  140. package/dist/context/learner.js.map +1 -0
  141. package/dist/context/versioning.d.ts +29 -0
  142. package/dist/context/versioning.d.ts.map +1 -0
  143. package/dist/context/versioning.js +81 -0
  144. package/dist/context/versioning.js.map +1 -0
  145. package/dist/index.d.ts +169 -0
  146. package/dist/index.d.ts.map +1 -0
  147. package/dist/index.js +285 -0
  148. package/dist/index.js.map +1 -0
  149. package/dist/mcp/index.d.ts +2 -0
  150. package/dist/mcp/index.d.ts.map +1 -0
  151. package/dist/mcp/index.js +2 -0
  152. package/dist/mcp/index.js.map +1 -0
  153. package/dist/mcp/server.d.ts +31 -0
  154. package/dist/mcp/server.d.ts.map +1 -0
  155. package/dist/mcp/server.js +334 -0
  156. package/dist/mcp/server.js.map +1 -0
  157. package/dist/observability/audit.d.ts +61 -0
  158. package/dist/observability/audit.d.ts.map +1 -0
  159. package/dist/observability/audit.js +168 -0
  160. package/dist/observability/audit.js.map +1 -0
  161. package/dist/observability/cost-tracker.d.ts +71 -0
  162. package/dist/observability/cost-tracker.d.ts.map +1 -0
  163. package/dist/observability/cost-tracker.js +206 -0
  164. package/dist/observability/cost-tracker.js.map +1 -0
  165. package/dist/observability/dashboard.d.ts +52 -0
  166. package/dist/observability/dashboard.d.ts.map +1 -0
  167. package/dist/observability/dashboard.js +134 -0
  168. package/dist/observability/dashboard.js.map +1 -0
  169. package/dist/observability/index.d.ts +4 -0
  170. package/dist/observability/index.d.ts.map +1 -0
  171. package/dist/observability/index.js +4 -0
  172. package/dist/observability/index.js.map +1 -0
  173. package/dist/providers/anthropic.d.ts +14 -0
  174. package/dist/providers/anthropic.d.ts.map +1 -0
  175. package/dist/providers/anthropic.js +99 -0
  176. package/dist/providers/anthropic.js.map +1 -0
  177. package/dist/providers/base.d.ts +52 -0
  178. package/dist/providers/base.d.ts.map +1 -0
  179. package/dist/providers/base.js +68 -0
  180. package/dist/providers/base.js.map +1 -0
  181. package/dist/providers/deepseek.d.ts +15 -0
  182. package/dist/providers/deepseek.d.ts.map +1 -0
  183. package/dist/providers/deepseek.js +99 -0
  184. package/dist/providers/deepseek.js.map +1 -0
  185. package/dist/providers/gemini.d.ts +15 -0
  186. package/dist/providers/gemini.d.ts.map +1 -0
  187. package/dist/providers/gemini.js +118 -0
  188. package/dist/providers/gemini.js.map +1 -0
  189. package/dist/providers/groq.d.ts +15 -0
  190. package/dist/providers/groq.d.ts.map +1 -0
  191. package/dist/providers/groq.js +101 -0
  192. package/dist/providers/groq.js.map +1 -0
  193. package/dist/providers/index.d.ts +11 -0
  194. package/dist/providers/index.d.ts.map +1 -0
  195. package/dist/providers/index.js +11 -0
  196. package/dist/providers/index.js.map +1 -0
  197. package/dist/providers/mistral.d.ts +15 -0
  198. package/dist/providers/mistral.d.ts.map +1 -0
  199. package/dist/providers/mistral.js +99 -0
  200. package/dist/providers/mistral.js.map +1 -0
  201. package/dist/providers/ollama.d.ts +14 -0
  202. package/dist/providers/ollama.d.ts.map +1 -0
  203. package/dist/providers/ollama.js +122 -0
  204. package/dist/providers/ollama.js.map +1 -0
  205. package/dist/providers/openai.d.ts +14 -0
  206. package/dist/providers/openai.d.ts.map +1 -0
  207. package/dist/providers/openai.js +80 -0
  208. package/dist/providers/openai.js.map +1 -0
  209. package/dist/providers/openrouter.d.ts +15 -0
  210. package/dist/providers/openrouter.d.ts.map +1 -0
  211. package/dist/providers/openrouter.js +101 -0
  212. package/dist/providers/openrouter.js.map +1 -0
  213. package/dist/providers/router.d.ts +51 -0
  214. package/dist/providers/router.d.ts.map +1 -0
  215. package/dist/providers/router.js +198 -0
  216. package/dist/providers/router.js.map +1 -0
  217. package/dist/quality/anomaly.d.ts +32 -0
  218. package/dist/quality/anomaly.d.ts.map +1 -0
  219. package/dist/quality/anomaly.js +126 -0
  220. package/dist/quality/anomaly.js.map +1 -0
  221. package/dist/quality/consistency.d.ts +26 -0
  222. package/dist/quality/consistency.d.ts.map +1 -0
  223. package/dist/quality/consistency.js +156 -0
  224. package/dist/quality/consistency.js.map +1 -0
  225. package/dist/quality/dual-verifier.d.ts +22 -0
  226. package/dist/quality/dual-verifier.d.ts.map +1 -0
  227. package/dist/quality/dual-verifier.js +137 -0
  228. package/dist/quality/dual-verifier.js.map +1 -0
  229. package/dist/quality/hallucination-guard.d.ts +57 -0
  230. package/dist/quality/hallucination-guard.d.ts.map +1 -0
  231. package/dist/quality/hallucination-guard.js +245 -0
  232. package/dist/quality/hallucination-guard.js.map +1 -0
  233. package/dist/quality/index.d.ts +7 -0
  234. package/dist/quality/index.d.ts.map +1 -0
  235. package/dist/quality/index.js +7 -0
  236. package/dist/quality/index.js.map +1 -0
  237. package/dist/quality/regression.d.ts +44 -0
  238. package/dist/quality/regression.d.ts.map +1 -0
  239. package/dist/quality/regression.js +181 -0
  240. package/dist/quality/regression.js.map +1 -0
  241. package/dist/quality/secret-scanner.d.ts +36 -0
  242. package/dist/quality/secret-scanner.d.ts.map +1 -0
  243. package/dist/quality/secret-scanner.js +187 -0
  244. package/dist/quality/secret-scanner.js.map +1 -0
  245. package/dist/schemas/index.d.ts +2 -0
  246. package/dist/schemas/index.d.ts.map +1 -0
  247. package/dist/schemas/index.js +2 -0
  248. package/dist/schemas/index.js.map +1 -0
  249. package/dist/schemas/registry.d.ts +72 -0
  250. package/dist/schemas/registry.d.ts.map +1 -0
  251. package/dist/schemas/registry.js +483 -0
  252. package/dist/schemas/registry.js.map +1 -0
  253. package/dist/templates/engine.d.ts +70 -0
  254. package/dist/templates/engine.d.ts.map +1 -0
  255. package/dist/templates/engine.js +71 -0
  256. package/dist/templates/engine.js.map +1 -0
  257. package/dist/templates/index.d.ts +2 -0
  258. package/dist/templates/index.d.ts.map +1 -0
  259. package/dist/templates/index.js +2 -0
  260. package/dist/templates/index.js.map +1 -0
  261. package/dist/types.d.ts +912 -0
  262. package/dist/types.d.ts.map +1 -0
  263. package/dist/types.js +75 -0
  264. package/dist/types.js.map +1 -0
  265. package/package.json +85 -0
@@ -0,0 +1,125 @@
1
+ /**
2
+ * PhantomMindAI — CLI Validate Command
3
+ * Validate code output for quality issues.
4
+ */
5
+ import { readFile } from 'node:fs/promises';
6
+ import { existsSync } from 'node:fs';
7
+ import { SecretScanner } from '../quality/secret-scanner.js';
8
+ import { HallucinationGuard } from '../quality/hallucination-guard.js';
9
+ import { ConsistencyEnforcer } from '../quality/consistency.js';
10
+ export async function validateCommand(projectRoot, options) {
11
+ const chalk = (await import('chalk')).default;
12
+ const ora = (await import('ora')).default;
13
+ const fastGlob = (await import('fast-glob')).default;
14
+ console.log(chalk.bold.cyan('\n🔍 PhantomMindAI — Code Validation\n'));
15
+ const spinner = ora('Scanning files...').start();
16
+ let totalIssues = 0;
17
+ try {
18
+ // Determine files to scan
19
+ let files;
20
+ if (options.files && options.files.length > 0) {
21
+ files = options.files.filter(f => existsSync(f));
22
+ }
23
+ else {
24
+ files = await fastGlob(['**/*.{ts,tsx,js,jsx,py,go,rs,java,kt,swift}'], {
25
+ cwd: projectRoot,
26
+ ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**', '**/build/**'],
27
+ absolute: true,
28
+ });
29
+ }
30
+ spinner.text = `Found ${files.length} files to validate`;
31
+ // Secret scanning
32
+ if (options.secrets !== false) {
33
+ spinner.text = 'Scanning for secrets...';
34
+ const scanner = new SecretScanner();
35
+ let secretCount = 0;
36
+ for (const file of files) {
37
+ const content = await readFile(file, 'utf-8');
38
+ const secrets = scanner.scan(content, file);
39
+ if (secrets.length > 0) {
40
+ secretCount += secrets.length;
41
+ for (const secret of secrets) {
42
+ const relPath = file.replace(projectRoot + '/', '');
43
+ console.log(` ${chalk.red('SECRET')} ${chalk.dim(relPath)}:${secret.line} ${chalk.yellow(secret.pattern)} ${chalk.dim(`[${secret.severity}]`)}`);
44
+ if (options.fix) {
45
+ const { cleaned } = scanner.scanAndReplace(content, file);
46
+ await import('node:fs/promises').then(fs => fs.writeFile(file, cleaned));
47
+ }
48
+ }
49
+ }
50
+ }
51
+ totalIssues += secretCount;
52
+ if (secretCount > 0) {
53
+ console.log(chalk.red(`\n Found ${secretCount} secret(s)${options.fix ? ' (auto-fixed)' : ''}`));
54
+ }
55
+ else {
56
+ console.log(chalk.green(' ✓ No secrets detected'));
57
+ }
58
+ console.log('');
59
+ }
60
+ // Hallucination checking
61
+ if (options.hallucinations !== false) {
62
+ spinner.text = 'Checking for hallucinations...';
63
+ const guard = new HallucinationGuard(projectRoot);
64
+ let hallucinationCount = 0;
65
+ for (const file of files.filter(f => f.endsWith('.ts') || f.endsWith('.tsx') || f.endsWith('.js') || f.endsWith('.jsx'))) {
66
+ const content = await readFile(file, 'utf-8');
67
+ const issues = await guard.check(content, file);
68
+ if (issues.length > 0) {
69
+ hallucinationCount += issues.length;
70
+ for (const issue of issues) {
71
+ const relPath = file.replace(projectRoot + '/', '');
72
+ console.log(` ${chalk.yellow('HALLUCINATION')} ${chalk.dim(relPath)}:${issue.line} [${issue.type}] ${issue.reference} ${issue.exists ? chalk.green('exists') : chalk.red('not found')}`);
73
+ if (issue.suggestions && issue.suggestions.length > 0) {
74
+ console.log(chalk.dim(` Suggestions: ${issue.suggestions.join(', ')}`));
75
+ }
76
+ }
77
+ }
78
+ }
79
+ totalIssues += hallucinationCount;
80
+ if (hallucinationCount > 0) {
81
+ console.log(chalk.yellow(`\n Found ${hallucinationCount} potential hallucination(s)`));
82
+ }
83
+ else {
84
+ console.log(chalk.green(' ✓ No hallucinations detected'));
85
+ }
86
+ console.log('');
87
+ }
88
+ // Consistency checking
89
+ if (options.consistency !== false) {
90
+ spinner.text = 'Checking consistency...';
91
+ const enforcer = new ConsistencyEnforcer(projectRoot);
92
+ const report = await enforcer.scan();
93
+ if (report.issues.length > 0) {
94
+ totalIssues += report.issues.length;
95
+ for (const issue of report.issues) {
96
+ console.log(` ${chalk.magenta('CONSISTENCY')} ${chalk.dim(issue.files.join(', '))} ${issue.description} ${chalk.dim(`[${issue.severity}]`)}`);
97
+ }
98
+ console.log(chalk.magenta(`\n Found ${report.issues.length} consistency issue(s)`));
99
+ }
100
+ else {
101
+ console.log(chalk.green(' ✓ No consistency issues'));
102
+ }
103
+ console.log('');
104
+ }
105
+ spinner.stop();
106
+ // Summary
107
+ console.log(chalk.dim('─'.repeat(50)));
108
+ if (totalIssues > 0) {
109
+ console.log(chalk.yellow(`\n⚠️ Total: ${totalIssues} issue(s) found`));
110
+ }
111
+ else {
112
+ console.log(chalk.green('\n✅ All checks passed!'));
113
+ }
114
+ console.log('');
115
+ if (totalIssues > 0) {
116
+ process.exitCode = 1;
117
+ }
118
+ }
119
+ catch (error) {
120
+ spinner.fail('Validation failed');
121
+ console.error(chalk.red(error.message));
122
+ process.exit(1);
123
+ }
124
+ }
125
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/cli/validate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAUhE,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,WAAmB,EACnB,OAAwB;IAExB,MAAM,KAAK,GAAG,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IAC9C,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1C,MAAM,QAAQ,GAAG,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;IAErD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAC,KAAK,EAAE,CAAC;IACjD,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,IAAI,CAAC;QACH,0BAA0B;QAC1B,IAAI,KAAe,CAAC;QACpB,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,MAAM,QAAQ,CAAC,CAAC,6CAA6C,CAAC,EAAE;gBACtE,GAAG,EAAE,WAAW;gBAChB,MAAM,EAAE,CAAC,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,CAAC;gBACzE,QAAQ,EAAE,IAAI;aACf,CAAC,CAAC;QACL,CAAC;QAED,OAAO,CAAC,IAAI,GAAG,SAAS,KAAK,CAAC,MAAM,oBAAoB,CAAC;QAEzD,kBAAkB;QAClB,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,GAAG,yBAAyB,CAAC;YACzC,MAAM,OAAO,GAAG,IAAI,aAAa,EAAE,CAAC;YACpC,IAAI,WAAW,GAAG,CAAC,CAAC;YAEpB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBAC5C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;oBAC9B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;wBAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC;wBACpD,OAAO,CAAC,GAAG,CACT,KAAK,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE,CACrI,CAAC;wBAEF,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;4BAChB,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;4BAC1D,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;wBAC3E,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,WAAW,IAAI,WAAW,CAAC;YAC3B,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;gBACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,WAAW,aAAa,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YACpG,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACtD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAED,yBAAyB;QACzB,IAAI,OAAO,CAAC,cAAc,KAAK,KAAK,EAAE,CAAC;YACrC,OAAO,CAAC,IAAI,GAAG,gCAAgC,CAAC;YAChD,MAAM,KAAK,GAAG,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAC;YAClD,IAAI,kBAAkB,GAAG,CAAC,CAAC;YAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBACzH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBAC9C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBAChD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtB,kBAAkB,IAAI,MAAM,CAAC,MAAM,CAAC;oBACpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;wBAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC;wBACpD,OAAO,CAAC,GAAG,CACT,KAAK,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAC7K,CAAC;wBACF,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;4BACtD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,oBAAoB,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;wBAC7E,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,WAAW,IAAI,kBAAkB,CAAC;YAClC,IAAI,kBAAkB,GAAG,CAAC,EAAE,CAAC;gBAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,kBAAkB,6BAA6B,CAAC,CAAC,CAAC;YAC1F,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAC;YAC7D,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAED,uBAAuB;QACvB,IAAI,OAAO,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,GAAG,yBAAyB,CAAC;YACzC,MAAM,QAAQ,GAAG,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAErC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;gBACpC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;oBAClC,OAAO,CAAC,GAAG,CACT,KAAK,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,EAAE,CAClI,CAAC;gBACJ,CAAC;gBACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,MAAM,CAAC,MAAM,CAAC,MAAM,uBAAuB,CAAC,CAAC,CAAC;YACvF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;YACxD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,IAAI,EAAE,CAAC;QAEf,UAAU;QACV,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACvC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,WAAW,iBAAiB,CAAC,CAAC,CAAC;QAC1E,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAE,KAAe,CAAC,OAAO,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { loadConfig, loadEnvFile, getDefaultConfig, findProjectRoot, deepMerge } from './loader.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { loadConfig, loadEnvFile, getDefaultConfig, findProjectRoot, deepMerge } from './loader.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * PhantomMindAI — Configuration Loader
3
+ */
4
+ import { PhantomConfig } from '../types.js';
5
+ /**
6
+ * Find project root by looking for .phantomind/ directory
7
+ */
8
+ export declare function findProjectRoot(startDir?: string): Promise<string>;
9
+ /**
10
+ * Load PhantomMindAI configuration from .phantomind/config.yaml
11
+ */
12
+ export declare function loadConfig(projectRoot?: string): Promise<PhantomConfig>;
13
+ /**
14
+ * Load .phantomind/.env file into process.env
15
+ */
16
+ export declare function loadEnvFile(projectRoot?: string): Promise<void>;
17
+ /**
18
+ * Get the default configuration
19
+ */
20
+ export declare function getDefaultConfig(): PhantomConfig;
21
+ /**
22
+ * Deep merge two objects
23
+ */
24
+ export declare function deepMerge(target: unknown, source: unknown): unknown;
25
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAAE,aAAa,EAAuB,MAAM,aAAa,CAAC;AAgEjE;;GAEG;AACH,wBAAsB,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAexE;AAwBD;;GAEG;AACH,wBAAsB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA0B7E;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBrE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAenE"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * PhantomMindAI — Configuration Loader
3
+ */
4
+ import { readFile, access } from 'node:fs/promises';
5
+ import { join, resolve } from 'node:path';
6
+ import yaml from 'js-yaml';
7
+ import { PhantomConfigSchema } from '../types.js';
8
+ const DEFAULT_CONFIG = {
9
+ version: '1',
10
+ providers: {
11
+ primary: {
12
+ name: 'anthropic',
13
+ model: 'claude-sonnet-4-20250514',
14
+ maxTokens: 8096,
15
+ temperature: 0.2,
16
+ },
17
+ },
18
+ context: {
19
+ skills: '.phantomind/SKILLS.md',
20
+ rules: '.phantomind/RULES.md',
21
+ schema: '.phantomind/schema.json',
22
+ prds: '.phantomind/prds/',
23
+ decisions: '.phantomind/decisions/',
24
+ },
25
+ adapters: ['copilot', 'cursor', 'cline', 'continue', 'windsurf'],
26
+ mcp: {
27
+ enabled: true,
28
+ port: 3741,
29
+ autoStart: true,
30
+ },
31
+ quality: {
32
+ secretScanner: true,
33
+ hallucinationGuard: true,
34
+ dualVerification: false,
35
+ },
36
+ agent: {
37
+ maxSteps: 30,
38
+ humanCheckpoint: {
39
+ before: ['write_file', 'delete_file', 'run_command'],
40
+ after: ['run_tests'],
41
+ onError: true,
42
+ onAnomalyDetected: true,
43
+ },
44
+ sandbox: {
45
+ allowedCommands: ['npm test', 'npm run build', 'npx tsc --noEmit'],
46
+ networkAccess: false,
47
+ },
48
+ memory: {
49
+ type: 'persistent',
50
+ path: '.phantomind/memory/',
51
+ },
52
+ },
53
+ budget: {
54
+ maxTokensPerTask: 100000,
55
+ maxCostPerDay: 10.0,
56
+ warningAt: 80,
57
+ fallbackOnBudget: 'budget',
58
+ },
59
+ git: {
60
+ autoCommit: false,
61
+ commitMessageFormat: 'conventional',
62
+ requireApproval: true,
63
+ },
64
+ team: {
65
+ contextSync: false,
66
+ remoteContext: '',
67
+ },
68
+ };
69
+ /**
70
+ * Find project root by looking for .phantomind/ directory
71
+ */
72
+ export async function findProjectRoot(startDir) {
73
+ let dir = startDir ? resolve(startDir) : process.cwd();
74
+ const root = resolve('/');
75
+ while (dir !== root) {
76
+ try {
77
+ await access(join(dir, '.phantomind'));
78
+ return dir;
79
+ }
80
+ catch {
81
+ dir = resolve(dir, '..');
82
+ }
83
+ }
84
+ // If no .phantomind/ found, use cwd
85
+ return startDir ? resolve(startDir) : process.cwd();
86
+ }
87
+ /**
88
+ * Resolve environment variable references in config values
89
+ */
90
+ function resolveEnvVars(value) {
91
+ if (typeof value === 'string') {
92
+ return value.replace(/\$\{([^}]+)\}/g, (_, envVar) => {
93
+ return process.env[envVar] ?? '';
94
+ });
95
+ }
96
+ if (Array.isArray(value)) {
97
+ return value.map(resolveEnvVars);
98
+ }
99
+ if (value !== null && typeof value === 'object') {
100
+ const resolved = {};
101
+ for (const [key, val] of Object.entries(value)) {
102
+ resolved[key] = resolveEnvVars(val);
103
+ }
104
+ return resolved;
105
+ }
106
+ return value;
107
+ }
108
+ /**
109
+ * Load PhantomMindAI configuration from .phantomind/config.yaml
110
+ */
111
+ export async function loadConfig(projectRoot) {
112
+ const root = projectRoot ?? await findProjectRoot();
113
+ const configPath = join(root, '.phantomind', 'config.yaml');
114
+ try {
115
+ const raw = await readFile(configPath, 'utf-8');
116
+ const parsed = yaml.load(raw);
117
+ const resolved = resolveEnvVars(parsed);
118
+ // Deep merge with defaults
119
+ const merged = deepMerge(DEFAULT_CONFIG, resolved);
120
+ // Validate
121
+ const result = PhantomConfigSchema.safeParse(merged);
122
+ if (!result.success) {
123
+ const errors = result.error.issues.map(i => ` - ${i.path.join('.')}: ${i.message}`).join('\n');
124
+ throw new Error(`Invalid PhantomMindAI config:\n${errors}`);
125
+ }
126
+ return result.data;
127
+ }
128
+ catch (err) {
129
+ if (err.code === 'ENOENT') {
130
+ return DEFAULT_CONFIG;
131
+ }
132
+ throw err;
133
+ }
134
+ }
135
+ /**
136
+ * Load .phantomind/.env file into process.env
137
+ */
138
+ export async function loadEnvFile(projectRoot) {
139
+ const root = projectRoot ?? await findProjectRoot();
140
+ const envPath = join(root, '.phantomind', '.env');
141
+ try {
142
+ const content = await readFile(envPath, 'utf-8');
143
+ for (const line of content.split('\n')) {
144
+ const trimmed = line.trim();
145
+ if (!trimmed || trimmed.startsWith('#'))
146
+ continue;
147
+ const eqIdx = trimmed.indexOf('=');
148
+ if (eqIdx === -1)
149
+ continue;
150
+ const key = trimmed.slice(0, eqIdx).trim();
151
+ let value = trimmed.slice(eqIdx + 1).trim();
152
+ // Remove surrounding quotes
153
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
154
+ value = value.slice(1, -1);
155
+ }
156
+ if (!process.env[key]) {
157
+ process.env[key] = value;
158
+ }
159
+ }
160
+ }
161
+ catch {
162
+ // .env file not required
163
+ }
164
+ }
165
+ /**
166
+ * Get the default configuration
167
+ */
168
+ export function getDefaultConfig() {
169
+ return structuredClone(DEFAULT_CONFIG);
170
+ }
171
+ /**
172
+ * Deep merge two objects
173
+ */
174
+ export function deepMerge(target, source) {
175
+ if (source === undefined || source === null)
176
+ return target;
177
+ if (target === undefined || target === null)
178
+ return source;
179
+ if (typeof target !== 'object' || typeof source !== 'object') {
180
+ return source;
181
+ }
182
+ if (Array.isArray(source))
183
+ return source;
184
+ const result = { ...target };
185
+ for (const [key, value] of Object.entries(source)) {
186
+ result[key] = deepMerge(result[key], value);
187
+ }
188
+ return result;
189
+ }
190
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * PhantomMindAI — Live Codebase Embedder
3
+ * Creates and maintains embeddings of project source files for semantic search.
4
+ */
5
+ export declare class CodebaseEmbedder {
6
+ private projectRoot;
7
+ private embeddings;
8
+ private documentFrequency;
9
+ private totalDocuments;
10
+ private cachePath;
11
+ private initialized;
12
+ constructor(projectRoot: string);
13
+ /**
14
+ * Build or update embeddings for the codebase
15
+ */
16
+ build(): Promise<{
17
+ indexed: number;
18
+ skipped: number;
19
+ }>;
20
+ /**
21
+ * Semantic search across the codebase
22
+ */
23
+ search(query: string, limit?: number): Promise<Array<{
24
+ path: string;
25
+ score: number;
26
+ snippet: string;
27
+ }>>;
28
+ /**
29
+ * Get relevant code snippet from a file
30
+ */
31
+ private getSnippet;
32
+ /**
33
+ * Tokenize text into meaningful words
34
+ */
35
+ private tokenize;
36
+ /**
37
+ * Compute term frequency
38
+ */
39
+ private computeTF;
40
+ /**
41
+ * Cosine similarity between two TF-IDF vectors
42
+ */
43
+ private cosineSimilarity;
44
+ /**
45
+ * Save embeddings to cache
46
+ */
47
+ private saveCache;
48
+ /**
49
+ * Load embeddings from cache
50
+ */
51
+ private loadCache;
52
+ }
53
+ //# sourceMappingURL=embedder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedder.d.ts","sourceRoot":"","sources":["../../src/context/embedder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0BH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAyC;IAC3D,OAAO,CAAC,iBAAiB,CAAkC;IAC3D,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,EAAE,MAAM;IAK/B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAmE5D;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAkCxG;;OAEG;YACW,UAAU;IA4BxB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAShB;;OAEG;IACH,OAAO,CAAC,SAAS;IAYjB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;OAEG;YACW,SAAS;IAmBvB;;OAEG;YACW,SAAS;CAqBxB"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * PhantomMindAI — Live Codebase Embedder
3
+ * Creates and maintains embeddings of project source files for semantic search.
4
+ */
5
+ import { readFile, stat, writeFile, mkdir } from 'node:fs/promises';
6
+ import { join, extname } from 'node:path';
7
+ import fastGlob from 'fast-glob';
8
+ const CODE_EXTENSIONS = new Set([
9
+ '.ts', '.tsx', '.js', '.jsx', '.swift', '.go', '.py', '.rs', '.java',
10
+ '.kt', '.rb', '.php', '.c', '.cpp', '.h', '.cs', '.vue', '.svelte',
11
+ '.md', '.json', '.yaml', '.yml', '.toml',
12
+ ]);
13
+ const IGNORE_DIRS = new Set([
14
+ 'node_modules', '.git', 'dist', 'build', '.next', '.nuxt',
15
+ 'coverage', '.phantomind/cache', '.phantomind/memory', '.phantomind/audit',
16
+ 'vendor', '__pycache__', '.tox', 'venv', '.venv',
17
+ ]);
18
+ export class CodebaseEmbedder {
19
+ projectRoot;
20
+ embeddings = new Map();
21
+ documentFrequency = new Map();
22
+ totalDocuments = 0;
23
+ cachePath;
24
+ initialized = false;
25
+ constructor(projectRoot) {
26
+ this.projectRoot = projectRoot;
27
+ this.cachePath = join(projectRoot, '.phantomind', 'cache', 'embeddings.json');
28
+ }
29
+ /**
30
+ * Build or update embeddings for the codebase
31
+ */
32
+ async build() {
33
+ let indexed = 0;
34
+ let skipped = 0;
35
+ const files = await fastGlob('**/*', {
36
+ cwd: this.projectRoot,
37
+ ignore: [...IGNORE_DIRS].map(d => `${d}/**`),
38
+ onlyFiles: true,
39
+ absolute: false,
40
+ });
41
+ const sourceFiles = files.filter(f => CODE_EXTENSIONS.has(extname(f)));
42
+ // Build TF for each document
43
+ for (const file of sourceFiles) {
44
+ const fullPath = join(this.projectRoot, file);
45
+ try {
46
+ const stats = await stat(fullPath);
47
+ const existing = this.embeddings.get(file);
48
+ // Skip if not modified
49
+ if (existing && existing.lastModified >= stats.mtimeMs) {
50
+ skipped++;
51
+ continue;
52
+ }
53
+ const content = await readFile(fullPath, 'utf-8');
54
+ const tokens = this.tokenize(content);
55
+ const tf = this.computeTF(tokens);
56
+ this.embeddings.set(file, {
57
+ path: file,
58
+ tokens,
59
+ tfidf: tf,
60
+ lastModified: stats.mtimeMs,
61
+ });
62
+ indexed++;
63
+ }
64
+ catch {
65
+ skipped++;
66
+ }
67
+ }
68
+ // Compute IDF
69
+ this.totalDocuments = this.embeddings.size;
70
+ this.documentFrequency.clear();
71
+ for (const embedding of this.embeddings.values()) {
72
+ const uniqueTokens = new Set(embedding.tokens);
73
+ for (const token of uniqueTokens) {
74
+ this.documentFrequency.set(token, (this.documentFrequency.get(token) ?? 0) + 1);
75
+ }
76
+ }
77
+ // Update TF-IDF scores
78
+ for (const embedding of this.embeddings.values()) {
79
+ for (const [token, tf] of embedding.tfidf.entries()) {
80
+ const df = this.documentFrequency.get(token) ?? 1;
81
+ const idf = Math.log(this.totalDocuments / df) + 1;
82
+ embedding.tfidf.set(token, tf * idf);
83
+ }
84
+ }
85
+ this.initialized = true;
86
+ await this.saveCache();
87
+ return { indexed, skipped };
88
+ }
89
+ /**
90
+ * Semantic search across the codebase
91
+ */
92
+ async search(query, limit = 5) {
93
+ if (!this.initialized) {
94
+ await this.loadCache();
95
+ if (!this.initialized) {
96
+ await this.build();
97
+ }
98
+ }
99
+ const queryTokens = this.tokenize(query);
100
+ const queryTF = this.computeTF(queryTokens);
101
+ const results = [];
102
+ for (const [path, embedding] of this.embeddings) {
103
+ const score = this.cosineSimilarity(queryTF, embedding.tfidf);
104
+ if (score > 0) {
105
+ results.push({ path, score });
106
+ }
107
+ }
108
+ results.sort((a, b) => b.score - a.score);
109
+ const topResults = results.slice(0, limit);
110
+ // Load snippets for top results
111
+ const withSnippets = await Promise.all(topResults.map(async (r) => {
112
+ const content = await this.getSnippet(r.path, queryTokens);
113
+ return { ...r, snippet: content };
114
+ }));
115
+ return withSnippets;
116
+ }
117
+ /**
118
+ * Get relevant code snippet from a file
119
+ */
120
+ async getSnippet(filePath, queryTokens) {
121
+ try {
122
+ const content = await readFile(join(this.projectRoot, filePath), 'utf-8');
123
+ const lines = content.split('\n');
124
+ // Find the most relevant line range
125
+ let bestStart = 0;
126
+ let bestScore = 0;
127
+ const windowSize = 15;
128
+ for (let i = 0; i < lines.length - windowSize; i++) {
129
+ const window = lines.slice(i, i + windowSize).join('\n').toLowerCase();
130
+ let score = 0;
131
+ for (const token of queryTokens) {
132
+ if (window.includes(token))
133
+ score++;
134
+ }
135
+ if (score > bestScore) {
136
+ bestScore = score;
137
+ bestStart = i;
138
+ }
139
+ }
140
+ return lines.slice(bestStart, bestStart + windowSize).join('\n');
141
+ }
142
+ catch {
143
+ return '';
144
+ }
145
+ }
146
+ /**
147
+ * Tokenize text into meaningful words
148
+ */
149
+ tokenize(text) {
150
+ return (text
151
+ .replace(/([a-z])([A-Z])/g, '$1 $2') // camelCase split
152
+ .replace(/[_\-./\\]/g, ' ') // separator split
153
+ .match(/[a-zA-Z][a-zA-Z0-9]{1,}/g) ?? [])
154
+ .map(w => w.toLowerCase())
155
+ .filter(w => w.length > 2);
156
+ }
157
+ /**
158
+ * Compute term frequency
159
+ */
160
+ computeTF(tokens) {
161
+ const tf = new Map();
162
+ const total = tokens.length || 1;
163
+ for (const token of tokens) {
164
+ tf.set(token, (tf.get(token) ?? 0) + 1);
165
+ }
166
+ for (const [token, count] of tf.entries()) {
167
+ tf.set(token, count / total);
168
+ }
169
+ return tf;
170
+ }
171
+ /**
172
+ * Cosine similarity between two TF-IDF vectors
173
+ */
174
+ cosineSimilarity(a, b) {
175
+ let dotProduct = 0;
176
+ let normA = 0;
177
+ let normB = 0;
178
+ for (const [token, va] of a) {
179
+ const vb = b.get(token) ?? 0;
180
+ dotProduct += va * vb;
181
+ normA += va * va;
182
+ }
183
+ for (const vb of b.values()) {
184
+ normB += vb * vb;
185
+ }
186
+ const denominator = Math.sqrt(normA) * Math.sqrt(normB);
187
+ return denominator === 0 ? 0 : dotProduct / denominator;
188
+ }
189
+ /**
190
+ * Save embeddings to cache
191
+ */
192
+ async saveCache() {
193
+ try {
194
+ await mkdir(join(this.projectRoot, '.phantomind', 'cache'), { recursive: true });
195
+ const data = {
196
+ totalDocuments: this.totalDocuments,
197
+ embeddings: Array.from(this.embeddings.entries()).map(([path, emb]) => ({
198
+ path,
199
+ tokens: emb.tokens.slice(0, 200), // limit for cache size
200
+ tfidf: Object.fromEntries(emb.tfidf),
201
+ lastModified: emb.lastModified,
202
+ })),
203
+ documentFrequency: Object.fromEntries(this.documentFrequency),
204
+ };
205
+ await writeFile(this.cachePath, JSON.stringify(data), 'utf-8');
206
+ }
207
+ catch {
208
+ // Cache save failure is non-critical
209
+ }
210
+ }
211
+ /**
212
+ * Load embeddings from cache
213
+ */
214
+ async loadCache() {
215
+ try {
216
+ const raw = await readFile(this.cachePath, 'utf-8');
217
+ const data = JSON.parse(raw);
218
+ this.totalDocuments = data.totalDocuments;
219
+ this.documentFrequency = new Map(Object.entries(data.documentFrequency));
220
+ for (const emb of data.embeddings) {
221
+ this.embeddings.set(emb.path, {
222
+ path: emb.path,
223
+ tokens: emb.tokens,
224
+ tfidf: new Map(Object.entries(emb.tfidf)),
225
+ lastModified: emb.lastModified,
226
+ });
227
+ }
228
+ this.initialized = true;
229
+ }
230
+ catch {
231
+ // No cache or invalid cache
232
+ }
233
+ }
234
+ }
235
+ //# sourceMappingURL=embedder.js.map