phantom-pr 0.4.19 → 0.5.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 (49) hide show
  1. package/README.md +216 -80
  2. package/dist/core/analysis/astExtractor.d.ts +15 -0
  3. package/dist/core/analysis/astExtractor.js +354 -0
  4. package/dist/core/analysis/astExtractor.js.map +1 -0
  5. package/dist/core/analysis/index.d.ts +3 -0
  6. package/dist/core/analysis/index.js +3 -0
  7. package/dist/core/analysis/index.js.map +1 -0
  8. package/dist/core/analysis/types.d.ts +50 -0
  9. package/dist/core/analysis/types.js +16 -0
  10. package/dist/core/analysis/types.js.map +1 -0
  11. package/dist/core/context/contextSelector.d.ts +29 -0
  12. package/dist/core/context/contextSelector.js +293 -0
  13. package/dist/core/context/contextSelector.js.map +1 -0
  14. package/dist/core/context/index.d.ts +4 -0
  15. package/dist/core/context/index.js +3 -0
  16. package/dist/core/context/index.js.map +1 -0
  17. package/dist/core/generator/enhancedContext.d.ts +34 -0
  18. package/dist/core/generator/enhancedContext.js +144 -0
  19. package/dist/core/generator/enhancedContext.js.map +1 -0
  20. package/dist/core/generator/llmGenerator.js +157 -15
  21. package/dist/core/generator/llmGenerator.js.map +1 -1
  22. package/dist/core/generator/postValidation.d.ts +24 -0
  23. package/dist/core/generator/postValidation.js +57 -0
  24. package/dist/core/generator/postValidation.js.map +1 -0
  25. package/dist/core/retry/errorParser.d.ts +12 -0
  26. package/dist/core/retry/errorParser.js +264 -0
  27. package/dist/core/retry/errorParser.js.map +1 -0
  28. package/dist/core/retry/feedbackGenerator.d.ts +12 -0
  29. package/dist/core/retry/feedbackGenerator.js +164 -0
  30. package/dist/core/retry/feedbackGenerator.js.map +1 -0
  31. package/dist/core/retry/index.d.ts +3 -0
  32. package/dist/core/retry/index.js +3 -0
  33. package/dist/core/retry/index.js.map +1 -0
  34. package/dist/core/retry/types.d.ts +40 -0
  35. package/dist/core/retry/types.js +5 -0
  36. package/dist/core/retry/types.js.map +1 -0
  37. package/dist/core/testRunner/retryEnhancer.d.ts +32 -0
  38. package/dist/core/testRunner/retryEnhancer.js +58 -0
  39. package/dist/core/testRunner/retryEnhancer.js.map +1 -0
  40. package/dist/core/validation/coverageVerifier.d.ts +16 -0
  41. package/dist/core/validation/coverageVerifier.js +226 -0
  42. package/dist/core/validation/coverageVerifier.js.map +1 -0
  43. package/dist/core/validation/index.d.ts +2 -0
  44. package/dist/core/validation/index.js +2 -0
  45. package/dist/core/validation/index.js.map +1 -0
  46. package/dist/core/validation/types.d.ts +24 -0
  47. package/dist/core/validation/types.js +6 -0
  48. package/dist/core/validation/types.js.map +1 -0
  49. package/package.json +1 -1
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Intelligent context selection using AST analysis.
3
+ * Minimizes token usage while maximizing test generation quality.
4
+ *
5
+ * Pure functions only - no file I/O (receives file contents as input).
6
+ */
7
+ /** Known external packages that should never be included in context. */
8
+ const EXTERNAL_PACKAGES = new Set([
9
+ 'react',
10
+ 'react-dom',
11
+ 'next',
12
+ 'next/router',
13
+ 'next/link',
14
+ 'next/image',
15
+ 'next/head',
16
+ 'next/script',
17
+ 'lodash',
18
+ 'underscore',
19
+ 'axios',
20
+ 'moment',
21
+ 'dayjs',
22
+ 'date-fns',
23
+ 'classnames',
24
+ 'clsx',
25
+ 'uuid',
26
+ 'zod',
27
+ 'yup',
28
+ 'formik',
29
+ 'react-hook-form',
30
+ 'react-query',
31
+ '@tanstack/react-query',
32
+ 'swr',
33
+ 'redux',
34
+ 'react-redux',
35
+ '@reduxjs/toolkit',
36
+ 'zustand',
37
+ 'jotai',
38
+ 'recoil',
39
+ 'framer-motion',
40
+ 'styled-components',
41
+ '@emotion/react',
42
+ '@emotion/styled',
43
+ 'tailwindcss',
44
+ '@mui/material',
45
+ '@chakra-ui/react',
46
+ 'antd',
47
+ 'prop-types',
48
+ ]);
49
+ /**
50
+ * Estimate token count from content length.
51
+ * Rough approximation: ~4 chars per token for English/code.
52
+ */
53
+ function estimateTokens(content) {
54
+ return Math.ceil(content.length / 4);
55
+ }
56
+ /**
57
+ * Extract mocked module paths from a test file.
58
+ * Looks for jest.mock('path') patterns.
59
+ */
60
+ function extractMockedModules(testContent) {
61
+ const mocked = new Set();
62
+ // jest.mock('...')
63
+ const jestMockRe = /jest\.mock\(\s*['"]([^'"]+)['"]/g;
64
+ for (const match of testContent.matchAll(jestMockRe)) {
65
+ const modulePath = match[1];
66
+ if (modulePath)
67
+ mocked.add(modulePath);
68
+ }
69
+ // vi.mock('...')
70
+ const viMockRe = /vi\.mock\(\s*['"]([^'"]+)['"]/g;
71
+ for (const match of testContent.matchAll(viMockRe)) {
72
+ const modulePath = match[1];
73
+ if (modulePath)
74
+ mocked.add(modulePath);
75
+ }
76
+ return mocked;
77
+ }
78
+ /**
79
+ * Check if a path is an external package (not a relative import).
80
+ */
81
+ function isExternalPackage(importPath) {
82
+ // Relative imports start with . or /
83
+ if (importPath.startsWith('.') || importPath.startsWith('/')) {
84
+ return false;
85
+ }
86
+ // Check against known external packages
87
+ if (EXTERNAL_PACKAGES.has(importPath)) {
88
+ return true;
89
+ }
90
+ // Scoped packages like @org/package
91
+ if (importPath.startsWith('@')) {
92
+ const parts = importPath.split('/');
93
+ const scopedName = parts.slice(0, 2).join('/');
94
+ if (EXTERNAL_PACKAGES.has(scopedName)) {
95
+ return true;
96
+ }
97
+ }
98
+ // Non-relative, non-scoped package names are likely external
99
+ // But we can't be sure without checking node_modules, so be conservative
100
+ return !importPath.includes('/') && !importPath.startsWith('.');
101
+ }
102
+ /**
103
+ * Resolve a relative import path to match against availableFiles.
104
+ * Handles extensions and index files.
105
+ */
106
+ function resolveImportPath(fromPath, importPath) {
107
+ if (!importPath.startsWith('.')) {
108
+ return [importPath];
109
+ }
110
+ // Get directory of the source file
111
+ const fromDir = fromPath.replace(/\/[^/]+$/, '');
112
+ // Join paths
113
+ let resolved = importPath;
114
+ if (importPath.startsWith('./')) {
115
+ resolved = `${fromDir}/${importPath.slice(2)}`;
116
+ }
117
+ else if (importPath.startsWith('../')) {
118
+ const parts = fromDir.split('/');
119
+ let upCount = 0;
120
+ let remaining = importPath;
121
+ while (remaining.startsWith('../')) {
122
+ upCount++;
123
+ remaining = remaining.slice(3);
124
+ }
125
+ const baseParts = parts.slice(0, -upCount);
126
+ resolved = [...baseParts, remaining].join('/');
127
+ }
128
+ // Normalize
129
+ resolved = resolved.replace(/\/+/g, '/').replace(/^\//, '');
130
+ // Generate candidates with different extensions
131
+ const exts = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];
132
+ const candidates = [resolved];
133
+ // Add extension variants
134
+ if (!exts.some(ext => resolved.endsWith(ext))) {
135
+ for (const ext of exts) {
136
+ candidates.push(`${resolved}${ext}`);
137
+ candidates.push(`${resolved}/index${ext}`);
138
+ }
139
+ }
140
+ return candidates;
141
+ }
142
+ /**
143
+ * Check if a path looks like a type definition file.
144
+ */
145
+ function isTypeDefinitionPath(path) {
146
+ const lower = path.toLowerCase();
147
+ return (lower.includes('/types') ||
148
+ lower.includes('.types.') ||
149
+ lower.includes('.d.ts') ||
150
+ lower.endsWith('types.ts') ||
151
+ lower.endsWith('types.tsx'));
152
+ }
153
+ /**
154
+ * Check if a path looks like a constants file.
155
+ */
156
+ function isConstantsPath(path) {
157
+ const lower = path.toLowerCase();
158
+ return (lower.includes('/constants') ||
159
+ lower.includes('.constants.') ||
160
+ lower.endsWith('constants.ts') ||
161
+ lower.endsWith('constants.js'));
162
+ }
163
+ /**
164
+ * Select context files based on analysis and heuristics.
165
+ * Returns files sorted by priority with reasons for selection.
166
+ */
167
+ export function selectContext(input) {
168
+ const selected = [];
169
+ let tokenBudgetUsed = 0;
170
+ // Track what we've included
171
+ const includedPaths = new Set();
172
+ // Get mocked modules from existing test
173
+ const mockedModules = input.existingTestContent
174
+ ? extractMockedModules(input.existingTestContent)
175
+ : new Set();
176
+ // Helper to add a file if within budget
177
+ const addFile = (path, priority, reason) => {
178
+ if (includedPaths.has(path))
179
+ return true;
180
+ const content = input.availableFiles.get(path);
181
+ if (!content)
182
+ return false;
183
+ const tokens = estimateTokens(content);
184
+ // Required files always included
185
+ if (priority !== 'required') {
186
+ if (tokenBudgetUsed + tokens > input.maxTokens) {
187
+ return false;
188
+ }
189
+ }
190
+ includedPaths.add(path);
191
+ tokenBudgetUsed += tokens;
192
+ selected.push({ path, content, priority, reason });
193
+ return true;
194
+ };
195
+ // 1. REQUIRED: Target file - always include
196
+ addFile(input.targetPath, 'required', 'Target file under test');
197
+ // 2. REQUIRED: Existing test file - if exists, include for pattern learning
198
+ if (input.existingTestPath && input.existingTestContent) {
199
+ addFile(input.existingTestPath, 'required', 'Existing test file for pattern learning');
200
+ }
201
+ // 3. Process child components - they should be mocked, not included
202
+ // But we note them as excluded for clarity
203
+ const childrenToMock = [];
204
+ for (const child of input.analysis.children) {
205
+ if (child.importPath && child.importPath !== 'unknown') {
206
+ childrenToMock.push(child.name);
207
+ }
208
+ }
209
+ // 4. Process external calls to find type definitions and constants
210
+ const typesNeeded = [];
211
+ const constantsNeeded = [];
212
+ for (const call of input.analysis.externalCalls) {
213
+ // Skip external packages
214
+ if (isExternalPackage(call.module))
215
+ continue;
216
+ // Skip mocked modules
217
+ if (mockedModules.has(call.module))
218
+ continue;
219
+ // Check if it's a type or constant
220
+ const candidates = resolveImportPath(input.targetPath, call.module);
221
+ for (const candidate of candidates) {
222
+ if (input.availableFiles.has(candidate)) {
223
+ if (isTypeDefinitionPath(candidate)) {
224
+ typesNeeded.push(candidate);
225
+ }
226
+ else if (isConstantsPath(candidate)) {
227
+ constantsNeeded.push(candidate);
228
+ }
229
+ break;
230
+ }
231
+ }
232
+ }
233
+ // 5. RECOMMENDED: Type definitions
234
+ const seenTypes = new Set();
235
+ for (const typePath of typesNeeded.sort()) {
236
+ if (seenTypes.has(typePath))
237
+ continue;
238
+ seenTypes.add(typePath);
239
+ addFile(typePath, 'recommended', 'Type definitions used by component');
240
+ }
241
+ // 6. RECOMMENDED: Constants
242
+ const seenConstants = new Set();
243
+ for (const constPath of constantsNeeded.sort()) {
244
+ if (seenConstants.has(constPath))
245
+ continue;
246
+ seenConstants.add(constPath);
247
+ addFile(constPath, 'recommended', 'Constants imported by component');
248
+ }
249
+ // 7. OPTIONAL: Other non-child, non-mocked, non-external imports
250
+ // Find all imports from target content
251
+ const importRe = /(?:import|from)\s+['"]([^'"]+)['"]/g;
252
+ const allImports = [];
253
+ for (const match of input.targetContent.matchAll(importRe)) {
254
+ const imp = match[1];
255
+ if (imp)
256
+ allImports.push(imp);
257
+ }
258
+ for (const imp of [...new Set(allImports)].sort()) {
259
+ // Skip external packages
260
+ if (isExternalPackage(imp))
261
+ continue;
262
+ // Skip mocked modules
263
+ if (mockedModules.has(imp))
264
+ continue;
265
+ // Skip child components (they should be mocked)
266
+ const isChildImport = input.analysis.children.some(c => c.importPath === imp || c.importPath.includes(imp));
267
+ if (isChildImport)
268
+ continue;
269
+ // Try to find the file
270
+ const candidates = resolveImportPath(input.targetPath, imp);
271
+ for (const candidate of candidates) {
272
+ if (input.availableFiles.has(candidate) && !includedPaths.has(candidate)) {
273
+ // Skip if already processed as type or constant
274
+ if (seenTypes.has(candidate) || seenConstants.has(candidate))
275
+ continue;
276
+ addFile(candidate, 'optional', `Imported module: ${imp}`);
277
+ break;
278
+ }
279
+ }
280
+ }
281
+ // Sort by priority order: required → recommended → optional
282
+ // Then alphabetically within each priority
283
+ const priorityOrder = { required: 0, recommended: 1, optional: 2 };
284
+ selected.sort((a, b) => {
285
+ const pa = priorityOrder[a.priority];
286
+ const pb = priorityOrder[b.priority];
287
+ if (pa !== pb)
288
+ return pa - pb;
289
+ return a.path.localeCompare(b.path);
290
+ });
291
+ return selected;
292
+ }
293
+ //# sourceMappingURL=contextSelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextSelector.js","sourceRoot":"","sources":["../../../src/core/context/contextSelector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export type { ContextBudgets, ContextFile, ContextPack } from './types.js';
2
+ export { buildContextPack } from './packer.js';
3
+ export type { SelectedContextFile, ContextSelectionInput } from './contextSelector.js';
4
+ export { selectContext } from './contextSelector.js';
@@ -0,0 +1,3 @@
1
+ export { buildContextPack } from './packer.js';
2
+ export { selectContext } from './contextSelector.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/context/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Enhanced context building that incorporates AST analysis.
3
+ * Wraps existing context packer with analysis-aware selection.
4
+ *
5
+ * Maintains backward compatibility - new features are additive.
6
+ */
7
+ import { type ComponentAnalysis } from '../analysis/index.js';
8
+ import { type SelectedContextFile } from '../context/contextSelector.js';
9
+ export type EnhancedContextOptions = {
10
+ rootAbs: string;
11
+ targetPathPosix: string;
12
+ existingTestPathPosix?: string;
13
+ maxTokens?: number;
14
+ enabled?: boolean;
15
+ };
16
+ export type EnhancedContextResult = {
17
+ analysis: ComponentAnalysis;
18
+ selectedFiles: SelectedContextFile[];
19
+ analysisJson: string;
20
+ enabled: boolean;
21
+ };
22
+ /**
23
+ * Build enhanced context using AST analysis.
24
+ * Returns analysis and selected files for inclusion in LLM prompt.
25
+ *
26
+ * @param opts - Context options
27
+ * @returns Enhanced context result with analysis and selected files
28
+ */
29
+ export declare function buildEnhancedContext(opts: EnhancedContextOptions): Promise<EnhancedContextResult>;
30
+ /**
31
+ * Format analysis for inclusion in LLM prompt.
32
+ * Returns a prompt section with key insights from the analysis.
33
+ */
34
+ export declare function formatAnalysisForPrompt(analysis: ComponentAnalysis): string;
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Enhanced context building that incorporates AST analysis.
3
+ * Wraps existing context packer with analysis-aware selection.
4
+ *
5
+ * Maintains backward compatibility - new features are additive.
6
+ */
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
9
+ import { extractComponentAnalysis, emptyAnalysis } from '../analysis/index.js';
10
+ import { selectContext } from '../context/contextSelector.js';
11
+ import { stableStringify } from '../stableJson.js';
12
+ /**
13
+ * Build enhanced context using AST analysis.
14
+ * Returns analysis and selected files for inclusion in LLM prompt.
15
+ *
16
+ * @param opts - Context options
17
+ * @returns Enhanced context result with analysis and selected files
18
+ */
19
+ export async function buildEnhancedContext(opts) {
20
+ const enabled = opts.enabled ?? true;
21
+ if (!enabled) {
22
+ return {
23
+ analysis: emptyAnalysis(opts.targetPathPosix),
24
+ selectedFiles: [],
25
+ analysisJson: '{}',
26
+ enabled: false,
27
+ };
28
+ }
29
+ // Read target file
30
+ let targetContent = '';
31
+ try {
32
+ const targetAbs = path.resolve(opts.rootAbs, ...opts.targetPathPosix.split('/'));
33
+ targetContent = await fs.promises.readFile(targetAbs, 'utf8');
34
+ }
35
+ catch {
36
+ // If we can't read the target, return empty analysis
37
+ return {
38
+ analysis: emptyAnalysis(opts.targetPathPosix),
39
+ selectedFiles: [],
40
+ analysisJson: '{}',
41
+ enabled: true,
42
+ };
43
+ }
44
+ // Extract component analysis
45
+ const analysis = extractComponentAnalysis(opts.targetPathPosix, targetContent);
46
+ // Read existing test file if provided
47
+ let existingTestContent;
48
+ if (opts.existingTestPathPosix) {
49
+ try {
50
+ const testAbs = path.resolve(opts.rootAbs, ...opts.existingTestPathPosix.split('/'));
51
+ existingTestContent = await fs.promises.readFile(testAbs, 'utf8');
52
+ }
53
+ catch {
54
+ // Test file doesn't exist yet - that's fine
55
+ }
56
+ }
57
+ // For now, just use the target file in available files
58
+ // A full implementation would scan the directory, but we keep it simple
59
+ const availableFiles = new Map();
60
+ availableFiles.set(opts.targetPathPosix, targetContent);
61
+ if (existingTestContent && opts.existingTestPathPosix) {
62
+ availableFiles.set(opts.existingTestPathPosix, existingTestContent);
63
+ }
64
+ // Select context using analysis
65
+ const contextInput = {
66
+ targetPath: opts.targetPathPosix,
67
+ targetContent,
68
+ availableFiles,
69
+ analysis,
70
+ maxTokens: opts.maxTokens ?? 8000,
71
+ };
72
+ // Add optional properties only if defined
73
+ if (opts.existingTestPathPosix !== undefined) {
74
+ contextInput.existingTestPath = opts.existingTestPathPosix;
75
+ }
76
+ if (existingTestContent !== undefined) {
77
+ contextInput.existingTestContent = existingTestContent;
78
+ }
79
+ const selectedFiles = selectContext(contextInput);
80
+ // Create deterministic JSON representation
81
+ const analysisJson = stableStringify({
82
+ filePath: analysis.filePath,
83
+ branchCount: analysis.branches.length,
84
+ branches: analysis.branches.map(b => ({
85
+ line: b.line,
86
+ kind: b.kind,
87
+ condition: b.condition.slice(0, 50), // Truncate long conditions
88
+ })),
89
+ effectCount: analysis.effects.length,
90
+ effects: analysis.effects.map(e => ({
91
+ line: e.line,
92
+ kind: e.kind,
93
+ hasCleanup: e.hasCleanup,
94
+ depCount: e.dependencies.length,
95
+ })),
96
+ childCount: analysis.children.length,
97
+ children: analysis.children.map(c => ({
98
+ name: c.name,
99
+ importPath: c.importPath,
100
+ isConditional: c.isConditional,
101
+ })),
102
+ });
103
+ return {
104
+ analysis,
105
+ selectedFiles,
106
+ analysisJson,
107
+ enabled: true,
108
+ };
109
+ }
110
+ /**
111
+ * Format analysis for inclusion in LLM prompt.
112
+ * Returns a prompt section with key insights from the analysis.
113
+ */
114
+ export function formatAnalysisForPrompt(analysis) {
115
+ if (analysis.branches.length === 0 &&
116
+ analysis.effects.length === 0 &&
117
+ analysis.children.length === 0) {
118
+ return '';
119
+ }
120
+ const lines = [];
121
+ lines.push('## PRE-ANALYZED STRUCTURE (use this to guide test coverage)');
122
+ if (analysis.branches.length > 0) {
123
+ lines.push(`- BRANCHES (${analysis.branches.length}): Test BOTH paths for each`);
124
+ for (const b of analysis.branches.slice(0, 5)) {
125
+ lines.push(` - Line ${b.line}: ${b.kind} on \`${b.condition.slice(0, 40)}\``);
126
+ }
127
+ }
128
+ if (analysis.effects.length > 0) {
129
+ lines.push(`- EFFECTS (${analysis.effects.length}):`);
130
+ for (const e of analysis.effects) {
131
+ const cleanup = e.hasCleanup ? ' [HAS CLEANUP - test unmount]' : '';
132
+ lines.push(` - Line ${e.line}: ${e.kind}${cleanup}`);
133
+ }
134
+ }
135
+ if (analysis.children.length > 0) {
136
+ lines.push(`- CHILDREN TO MOCK (${analysis.children.length}):`);
137
+ for (const c of analysis.children.slice(0, 5)) {
138
+ lines.push(` - ${c.name} from '${c.importPath}'`);
139
+ }
140
+ }
141
+ lines.push('');
142
+ return lines.join('\n');
143
+ }
144
+ //# sourceMappingURL=enhancedContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enhancedContext.js","sourceRoot":"","sources":["../../../src/core/generator/enhancedContext.ts"],"names":[],"mappings":"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"}