agentic-compaction 0.0.3 → 0.0.5
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.
- package/README.md +8 -7
- package/compacted_standalonecompaction_2026-02-12_17-57-32.md +37 -0
- package/compacted_standalonecompaction_2026-02-12_17-58-28.md +37 -0
- package/compacted_standalonecompaction_2026-02-12_18-05-15.md +35 -0
- package/package.json +1 -1
- package/src/parsers/babel.js +90 -29
- package/src/parsers/python.js +14 -4
- package/test/test.js +2 -2
package/README.md
CHANGED
|
@@ -74,11 +74,12 @@ hooks: useState(2), useEffect([user]):18, useAuth
|
|
|
74
74
|
```
|
|
75
75
|
|
|
76
76
|
The skeleton captures:
|
|
77
|
-
- **Imports** (local paths shown, externals counted)
|
|
77
|
+
- **Imports** (deduplicated local paths shown, externals counted)
|
|
78
78
|
- **Exports** (default marked with `*`)
|
|
79
|
-
- **Components** (PascalCase functions, HOC-wrapped)
|
|
80
|
-
- **Functions** (with line numbers)
|
|
81
|
-
- **Hooks** (counts, useEffect deps, custom hooks)
|
|
79
|
+
- **Components** (top-level PascalCase functions, HOC-wrapped)
|
|
80
|
+
- **Functions** (top-level only, with line numbers)
|
|
81
|
+
- **Hooks** (only from top-level components: counts, useEffect deps, custom hooks)
|
|
82
|
+
- **Constants** (top-level only)
|
|
82
83
|
- **Classes, interfaces, types** (TS)
|
|
83
84
|
- **Python**: imports, classes (with bases/decorators), functions, constants
|
|
84
85
|
|
|
@@ -86,9 +87,9 @@ The skeleton captures:
|
|
|
86
87
|
|
|
87
88
|
| Language | Parser | Extensions |
|
|
88
89
|
|----------|--------|------------|
|
|
89
|
-
| JavaScript | `@babel/parser` | `.js`, `.jsx`, `.mjs`, `.cjs` |
|
|
90
|
-
| TypeScript | `@babel/parser` | `.ts`, `.tsx`, `.mts`, `.cts` |
|
|
91
|
-
| Python | Regex-based (zero deps) | `.py` |
|
|
90
|
+
| JavaScript | `@babel/parser` (top-level only) | `.js`, `.jsx`, `.mjs`, `.cjs` |
|
|
91
|
+
| TypeScript | `@babel/parser` (top-level only) | `.ts`, `.tsx`, `.mts`, `.cts` |
|
|
92
|
+
| Python | Regex-based (top-level only, zero deps) | `.py` |
|
|
92
93
|
|
|
93
94
|
## Skipped Directories
|
|
94
95
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
## src/cli.js
|
|
2
|
+
imports: 3 ext, ./index.js, ./formatter.js
|
|
3
|
+
fn: getDateStamp():9, pad(n):11
|
|
4
|
+
const: now, args, targetPath, jsonOutput, i +5 more
|
|
5
|
+
## src/formatter.js
|
|
6
|
+
imports: ./parsers/python.js, ./parsers/babel.js, ./parsers/python.js
|
|
7
|
+
fn: estimateTokens(text)+:5, formatTokenCount(count)+:10, formatOutput(results)+:16
|
|
8
|
+
const: lines, output
|
|
9
|
+
## src/index.js
|
|
10
|
+
imports: 1 ext, ./walker.js, ./formatter.js, ./parsers/babel.js, ./parsers/python.js
|
|
11
|
+
fn: compactFile(filePath, content)+:17, compactProject(rootPath, options = ...)+:38
|
|
12
|
+
const: skeleton, formatted, files, results, rawTokens +4 more
|
|
13
|
+
## src/parsers/babel.js
|
|
14
|
+
imports: 2 ext
|
|
15
|
+
fn: isBabelParseable(path)+:9, isPascalCase(name):13, getReactHOCInfo(node):17, isCreateContext(node):52, extractDependencyArray(node):69, getParamsString(params):97, getTypeName(typeAnnotation):127, getReturnType(node):145, extractSignatures(code, filePath = ...)+:150, extractSkeleton(code, filePath = ...)+:246, formatSignaturesForPrompt(signatures)+:438, formatSkeletonForPrompt(skeleton)+:443
|
|
16
|
+
const: traverse, BABEL_EXTENSIONS, callee, hocType, method +75 more
|
|
17
|
+
## src/parsers/python.js
|
|
18
|
+
fn: isPythonParseable(path)+:3, extractSkeleton(code, filePath = ...)+:14, formatSkeletonForPrompt(skeleton)+:148
|
|
19
|
+
const: PYTHON_EXTENSIONS, lines, skeleton, pendingDecorators, i +25 more
|
|
20
|
+
## src/walker.js
|
|
21
|
+
imports: 2 ext, ./parsers/babel.js, ./parsers/python.js
|
|
22
|
+
fn: collectFiles(dir, rootDir = ..., files = ...)+:24, SKIP_DIRS_OR_DOT(name):48, isParseable(path):52
|
|
23
|
+
const: SKIP_DIRECTORIES, fullPath, relativePath
|
|
24
|
+
## test/fixtures/sample.js
|
|
25
|
+
imports: 1 ext, ./api
|
|
26
|
+
components: MyComponent({ id })*:6
|
|
27
|
+
fn: helper(x):16
|
|
28
|
+
const: API_URL
|
|
29
|
+
hooks: useState: data, useEffect([id])
|
|
30
|
+
## test/fixtures/sample.py
|
|
31
|
+
imports: 4 ext
|
|
32
|
+
classes: BaseProcessor:9, Config @dataclass (BaseProcessor):13
|
|
33
|
+
fn: process_data(items, timeout=30):17, fetch_remote(url, **kwargs):20, @app.route api_handler(request):24
|
|
34
|
+
const: MAX_RETRIES, DEFAULT_TIMEOUT
|
|
35
|
+
## test/test.js
|
|
36
|
+
imports: 5 ext, ../src/index.js, ../src/parsers/babel.js, ../src/parsers/python.js, ../src/walker.js
|
|
37
|
+
const: __dirname, fixturesDir, code, skeleton, code +14 more
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
## src/cli.js
|
|
2
|
+
imports: 3 ext, ./index.js, ./formatter.js
|
|
3
|
+
fn: getDateStamp():9, pad(n):11
|
|
4
|
+
const: now, args, targetPath, jsonOutput, i +5 more
|
|
5
|
+
## src/formatter.js
|
|
6
|
+
imports: ./parsers/python.js, ./parsers/babel.js, ./parsers/python.js
|
|
7
|
+
fn: estimateTokens(text)+:5, formatTokenCount(count)+:10, formatOutput(results)+:16
|
|
8
|
+
const: lines, output
|
|
9
|
+
## src/index.js
|
|
10
|
+
imports: 1 ext, ./walker.js, ./formatter.js, ./parsers/babel.js, ./parsers/python.js
|
|
11
|
+
fn: compactFile(filePath, content)+:17, compactProject(rootPath, options = ...)+:38
|
|
12
|
+
const: skeleton, formatted, files, results, rawTokens +4 more
|
|
13
|
+
## src/parsers/babel.js
|
|
14
|
+
imports: 2 ext
|
|
15
|
+
fn: isBabelParseable(path)+:9, isPascalCase(name):13, getReactHOCInfo(node):17, isCreateContext(node):52, extractDependencyArray(node):69, getParamsString(params):97, getTypeName(typeAnnotation):127, getReturnType(node):145, extractSignatures(code, filePath = ...)+:150, extractSkeleton(code, filePath = ...)+:246, formatSignaturesForPrompt(signatures)+:438, formatSkeletonForPrompt(skeleton)+:443
|
|
16
|
+
const: traverse, BABEL_EXTENSIONS, callee, hocType, method +75 more
|
|
17
|
+
## src/parsers/python.js
|
|
18
|
+
fn: isPythonParseable(path)+:3, extractSkeleton(code, filePath = ...)+:14, formatSkeletonForPrompt(skeleton)+:148
|
|
19
|
+
const: PYTHON_EXTENSIONS, lines, skeleton, pendingDecorators, i +25 more
|
|
20
|
+
## src/walker.js
|
|
21
|
+
imports: 2 ext, ./parsers/babel.js, ./parsers/python.js
|
|
22
|
+
fn: collectFiles(dir, rootDir = ..., files = ...)+:24, SKIP_DIRS_OR_DOT(name):48, isParseable(path):52
|
|
23
|
+
const: SKIP_DIRECTORIES, fullPath, relativePath
|
|
24
|
+
## test/fixtures/sample.js
|
|
25
|
+
imports: 1 ext, ./api
|
|
26
|
+
components: MyComponent({ id })*:6
|
|
27
|
+
fn: helper(x):16
|
|
28
|
+
const: API_URL
|
|
29
|
+
hooks: useState: data, useEffect([id])
|
|
30
|
+
## test/fixtures/sample.py
|
|
31
|
+
imports: 4 ext
|
|
32
|
+
classes: BaseProcessor:9, Config @dataclass (BaseProcessor):13
|
|
33
|
+
fn: process_data(items, timeout=30):17, fetch_remote(url, **kwargs):20, @app.route api_handler(request):24
|
|
34
|
+
const: MAX_RETRIES, DEFAULT_TIMEOUT
|
|
35
|
+
## test/test.js
|
|
36
|
+
imports: 5 ext, ../src/index.js, ../src/parsers/babel.js, ../src/parsers/python.js, ../src/walker.js
|
|
37
|
+
const: __dirname, fixturesDir, code, skeleton, code +14 more
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
## src/cli.js
|
|
2
|
+
imports: 3 ext, ./index.js, ./formatter.js
|
|
3
|
+
fn: getDateStamp():9
|
|
4
|
+
const: args, targetPath, jsonOutput, dirName, filename +2 more
|
|
5
|
+
## src/formatter.js
|
|
6
|
+
imports: ./parsers/python.js, ./parsers/babel.js
|
|
7
|
+
fn: estimateTokens(text)+:5, formatTokenCount(count)+:10, formatOutput(results)+:16
|
|
8
|
+
## src/index.js
|
|
9
|
+
imports: 1 ext, ./walker.js, ./formatter.js, ./parsers/babel.js, ./parsers/python.js
|
|
10
|
+
fn: compactFile(filePath, content)+:17, compactProject(rootPath, options = ...)+:38
|
|
11
|
+
## src/parsers/babel.js
|
|
12
|
+
imports: 2 ext
|
|
13
|
+
fn: isBabelParseable(path)+:9, isPascalCase(name):13, getReactHOCInfo(node):17, isCreateContext(node):52, extractDependencyArray(node):69, getParamsString(params):97, getTypeName(typeAnnotation):127, getReturnType(node):145, extractSignatures(code, filePath = ...)+:150, extractSkeleton(code, filePath = ...)+:246, formatSignaturesForPrompt(signatures)+:444, formatSkeletonForPrompt(skeleton)+:449
|
|
14
|
+
const: traverse, BABEL_EXTENSIONS
|
|
15
|
+
## src/parsers/python.js
|
|
16
|
+
fn: isPythonParseable(path)+:3, extractSkeleton(code, filePath = ...)+:14, formatSkeletonForPrompt(skeleton)+:148
|
|
17
|
+
const: PYTHON_EXTENSIONS
|
|
18
|
+
## src/walker.js
|
|
19
|
+
imports: 2 ext, ./parsers/babel.js, ./parsers/python.js
|
|
20
|
+
fn: collectFiles(dir, rootDir = ..., files = ...)+:24, SKIP_DIRS_OR_DOT(name):48, isParseable(path):52
|
|
21
|
+
const: SKIP_DIRECTORIES
|
|
22
|
+
## test/fixtures/sample.js
|
|
23
|
+
imports: 1 ext, ./api
|
|
24
|
+
components: MyComponent({ id })*:6
|
|
25
|
+
fn: helper(x):16
|
|
26
|
+
const: API_URL
|
|
27
|
+
hooks: useState: data, useEffect([id])
|
|
28
|
+
## test/fixtures/sample.py
|
|
29
|
+
imports: 4 ext
|
|
30
|
+
classes: BaseProcessor:9, Config @dataclass (BaseProcessor):13
|
|
31
|
+
fn: process_data(items, timeout=30):17, fetch_remote(url, **kwargs):20, @app.route api_handler(request):24
|
|
32
|
+
const: MAX_RETRIES, DEFAULT_TIMEOUT
|
|
33
|
+
## test/test.js
|
|
34
|
+
imports: 5 ext, ../src/index.js, ../src/parsers/babel.js, ../src/parsers/python.js, ../src/walker.js
|
|
35
|
+
const: __dirname, fixturesDir
|
package/package.json
CHANGED
package/src/parsers/babel.js
CHANGED
|
@@ -111,7 +111,11 @@ const getParamsString = (params) => {
|
|
|
111
111
|
return `...${param.argument?.name || 'args'}`;
|
|
112
112
|
}
|
|
113
113
|
if (param.type === 'ObjectPattern') {
|
|
114
|
-
|
|
114
|
+
const keys = param.properties.map(p => {
|
|
115
|
+
if (p.type === 'RestElement') return `...${p.argument?.name || 'rest'}`;
|
|
116
|
+
return p.key?.name || '?';
|
|
117
|
+
});
|
|
118
|
+
return `{ ${keys.join(', ')} }`;
|
|
115
119
|
}
|
|
116
120
|
if (param.type === 'ArrayPattern') {
|
|
117
121
|
return '[ ... ]';
|
|
@@ -265,16 +269,18 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
265
269
|
|
|
266
270
|
const skeleton = {
|
|
267
271
|
imports: [],
|
|
268
|
-
exports: [],
|
|
269
272
|
components: [],
|
|
270
273
|
functions: [],
|
|
271
|
-
hooks: { useState:
|
|
272
|
-
constants:
|
|
274
|
+
hooks: { useState: [], useEffect: [], useCallback: 0, useMemo: 0, useRef: 0, custom: [] },
|
|
275
|
+
constants: [],
|
|
273
276
|
classes: [],
|
|
274
277
|
interfaces: [],
|
|
275
278
|
types: [],
|
|
276
279
|
};
|
|
277
280
|
|
|
281
|
+
// Collect export info: name -> 'default' | 'named'
|
|
282
|
+
const exportMap = new Map();
|
|
283
|
+
|
|
278
284
|
traverse(ast, {
|
|
279
285
|
ImportDeclaration(path) {
|
|
280
286
|
const source = path.node.source.value;
|
|
@@ -289,9 +295,9 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
289
295
|
ExportDefaultDeclaration(path) {
|
|
290
296
|
const decl = path.node.declaration;
|
|
291
297
|
if (decl.type === 'Identifier') {
|
|
292
|
-
|
|
298
|
+
exportMap.set(decl.name, 'default');
|
|
293
299
|
} else if (decl.type === 'FunctionDeclaration' && decl.id) {
|
|
294
|
-
|
|
300
|
+
exportMap.set(decl.id.name, 'default');
|
|
295
301
|
}
|
|
296
302
|
},
|
|
297
303
|
|
|
@@ -299,50 +305,65 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
299
305
|
if (path.node.declaration) {
|
|
300
306
|
const decl = path.node.declaration;
|
|
301
307
|
if (decl.type === 'FunctionDeclaration' && decl.id) {
|
|
302
|
-
|
|
308
|
+
exportMap.set(decl.id.name, 'named');
|
|
303
309
|
} else if (decl.type === 'VariableDeclaration') {
|
|
304
310
|
decl.declarations.forEach(d => {
|
|
305
311
|
if (d.id?.name) {
|
|
306
|
-
|
|
312
|
+
exportMap.set(d.id.name, 'named');
|
|
307
313
|
}
|
|
308
314
|
});
|
|
309
315
|
}
|
|
310
316
|
}
|
|
311
317
|
if (path.node.specifiers) {
|
|
312
318
|
path.node.specifiers.forEach(s => {
|
|
313
|
-
|
|
319
|
+
exportMap.set(s.exported?.name || s.local.name, 'named');
|
|
314
320
|
});
|
|
315
321
|
}
|
|
316
322
|
},
|
|
317
323
|
|
|
318
324
|
FunctionDeclaration(path) {
|
|
325
|
+
if (path.parent.type !== 'Program' && path.parent.type !== 'ExportNamedDeclaration' && path.parent.type !== 'ExportDefaultDeclaration') return;
|
|
319
326
|
const name = path.node.id?.name;
|
|
320
327
|
if (!name) return;
|
|
321
328
|
|
|
329
|
+
const params = getParamsString(path.node.params);
|
|
330
|
+
const isAsync = path.node.async || false;
|
|
331
|
+
const entry = { name, line: path.node.loc?.start?.line || 0, params, async: isAsync };
|
|
332
|
+
|
|
322
333
|
if (isPascalCase(name)) {
|
|
323
|
-
skeleton.components.push(
|
|
334
|
+
skeleton.components.push(entry);
|
|
324
335
|
} else {
|
|
325
|
-
skeleton.functions.push(
|
|
336
|
+
skeleton.functions.push(entry);
|
|
326
337
|
}
|
|
327
338
|
},
|
|
328
339
|
|
|
329
340
|
VariableDeclarator(path) {
|
|
341
|
+
const declParent = path.parentPath?.parent;
|
|
342
|
+
if (declParent?.type !== 'Program' && declParent?.type !== 'ExportNamedDeclaration' && declParent?.type !== 'ExportDefaultDeclaration') return;
|
|
330
343
|
const name = path.node.id?.name;
|
|
331
344
|
const init = path.node.init;
|
|
332
345
|
if (!name || !init) return;
|
|
333
346
|
|
|
334
347
|
if (init.type === 'ArrowFunctionExpression' || init.type === 'FunctionExpression') {
|
|
348
|
+
const params = getParamsString(init.params);
|
|
349
|
+
const isAsync = init.async || false;
|
|
350
|
+
const entry = { name, line: path.node.loc?.start?.line || 0, params, async: isAsync };
|
|
351
|
+
|
|
335
352
|
if (isPascalCase(name)) {
|
|
336
|
-
skeleton.components.push(
|
|
353
|
+
skeleton.components.push(entry);
|
|
337
354
|
} else {
|
|
338
|
-
skeleton.functions.push(
|
|
355
|
+
skeleton.functions.push(entry);
|
|
339
356
|
}
|
|
340
357
|
return;
|
|
341
358
|
}
|
|
342
359
|
|
|
343
360
|
const hocInfo = getReactHOCInfo(init);
|
|
344
361
|
if (hocInfo) {
|
|
345
|
-
|
|
362
|
+
let params = '?';
|
|
363
|
+
if (hocInfo.innerFn) {
|
|
364
|
+
params = getParamsString(hocInfo.innerFn.params);
|
|
365
|
+
}
|
|
366
|
+
skeleton.components.push({ name, line: path.node.loc?.start?.line || 0, hoc: hocInfo.type, params, async: false });
|
|
346
367
|
return;
|
|
347
368
|
}
|
|
348
369
|
|
|
@@ -352,16 +373,30 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
352
373
|
return;
|
|
353
374
|
}
|
|
354
375
|
|
|
355
|
-
skeleton.constants
|
|
376
|
+
skeleton.constants.push(name);
|
|
356
377
|
},
|
|
357
378
|
|
|
358
379
|
CallExpression(path) {
|
|
359
380
|
const callee = path.node.callee;
|
|
360
381
|
if (callee.type === 'Identifier' && callee.name.startsWith('use')) {
|
|
382
|
+
// Only capture hooks inside top-level functions (components)
|
|
383
|
+
const funcScope = path.scope.getFunctionParent();
|
|
384
|
+
if (funcScope && funcScope.parent?.block?.type !== 'Program') return;
|
|
361
385
|
const hookName = callee.name;
|
|
362
386
|
const line = path.node.loc?.start?.line || 0;
|
|
363
387
|
|
|
364
|
-
if (hookName === '
|
|
388
|
+
if (hookName === 'useState') {
|
|
389
|
+
// Extract destructured variable name from parent: const [name, setName] = useState(...)
|
|
390
|
+
let varName = null;
|
|
391
|
+
const parent = path.parent;
|
|
392
|
+
if (parent?.type === 'VariableDeclarator' && parent.id?.type === 'ArrayPattern') {
|
|
393
|
+
const first = parent.id.elements[0];
|
|
394
|
+
if (first?.type === 'Identifier') {
|
|
395
|
+
varName = first.name;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
skeleton.hooks.useState.push(varName || '?');
|
|
399
|
+
} else if (hookName === 'useEffect') {
|
|
365
400
|
const deps = extractDependencyArray(path.node.arguments[1]);
|
|
366
401
|
skeleton.hooks.useEffect.push({ line, deps });
|
|
367
402
|
} else if (skeleton.hooks[hookName] !== undefined) {
|
|
@@ -396,6 +431,13 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
396
431
|
},
|
|
397
432
|
});
|
|
398
433
|
|
|
434
|
+
// Apply export markers to components, functions, classes
|
|
435
|
+
for (const entry of [...skeleton.components, ...skeleton.functions, ...skeleton.classes]) {
|
|
436
|
+
const exportType = exportMap.get(entry.name);
|
|
437
|
+
if (exportType === 'default') entry.exportMarker = '*';
|
|
438
|
+
else if (exportType === 'named') entry.exportMarker = '+';
|
|
439
|
+
}
|
|
440
|
+
|
|
399
441
|
return skeleton;
|
|
400
442
|
};
|
|
401
443
|
|
|
@@ -414,17 +456,17 @@ export const formatSkeletonForPrompt = (skeleton) => {
|
|
|
414
456
|
const extCount = skeleton.imports.length - local.length;
|
|
415
457
|
const parts = [];
|
|
416
458
|
if (extCount > 0) parts.push(`${extCount} ext`);
|
|
417
|
-
parts.push(...local.map(i => i.source));
|
|
459
|
+
parts.push(...[...new Set(local.map(i => i.source))]);
|
|
418
460
|
lines.push(`imports: ${parts.join(', ')}`);
|
|
419
461
|
}
|
|
420
462
|
|
|
421
|
-
if (skeleton.exports.length > 0) {
|
|
422
|
-
const exportNames = skeleton.exports.map(e => e.type === 'default' ? `${e.name}*` : e.name).join(', ');
|
|
423
|
-
lines.push(`exports: ${exportNames}`);
|
|
424
|
-
}
|
|
425
|
-
|
|
426
463
|
if (skeleton.components.length > 0) {
|
|
427
|
-
const componentList = skeleton.components.map(c =>
|
|
464
|
+
const componentList = skeleton.components.map(c => {
|
|
465
|
+
const marker = c.exportMarker || '';
|
|
466
|
+
const params = c.params !== undefined ? `(${c.params})` : '';
|
|
467
|
+
const hoc = c.hoc ? `(${c.hoc})` : '';
|
|
468
|
+
return `${c.name}${hoc}${params}${marker}:${c.line}`;
|
|
469
|
+
}).join(', ');
|
|
428
470
|
lines.push(`components: ${componentList}`);
|
|
429
471
|
}
|
|
430
472
|
|
|
@@ -433,11 +475,26 @@ export const formatSkeletonForPrompt = (skeleton) => {
|
|
|
433
475
|
}
|
|
434
476
|
|
|
435
477
|
if (skeleton.functions.length > 0) {
|
|
436
|
-
|
|
478
|
+
const funcList = skeleton.functions.map(f => {
|
|
479
|
+
const marker = f.exportMarker || '';
|
|
480
|
+
const asyncPrefix = f.async ? 'async ' : '';
|
|
481
|
+
const params = f.params !== undefined ? `(${f.params})` : '';
|
|
482
|
+
return `${asyncPrefix}${f.name}${params}${marker}:${f.line}`;
|
|
483
|
+
}).join(', ');
|
|
484
|
+
lines.push(`fn: ${funcList}`);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (skeleton.constants.length > 0) {
|
|
488
|
+
const names = skeleton.constants;
|
|
489
|
+
if (names.length > 5) {
|
|
490
|
+
lines.push(`const: ${names.slice(0, 5).join(', ')} +${names.length - 5} more`);
|
|
491
|
+
} else {
|
|
492
|
+
lines.push(`const: ${names.join(', ')}`);
|
|
493
|
+
}
|
|
437
494
|
}
|
|
438
495
|
|
|
439
496
|
const hookParts = [];
|
|
440
|
-
if (skeleton.hooks.useState > 0) hookParts.push(`useState
|
|
497
|
+
if (skeleton.hooks.useState.length > 0) hookParts.push(`useState: ${skeleton.hooks.useState.join(', ')}`);
|
|
441
498
|
if (skeleton.hooks.useCallback > 0) hookParts.push(`useCallback(${skeleton.hooks.useCallback})`);
|
|
442
499
|
if (skeleton.hooks.useMemo > 0) hookParts.push(`useMemo(${skeleton.hooks.useMemo})`);
|
|
443
500
|
if (skeleton.hooks.useRef > 0) hookParts.push(`useRef(${skeleton.hooks.useRef})`);
|
|
@@ -445,9 +502,9 @@ export const formatSkeletonForPrompt = (skeleton) => {
|
|
|
445
502
|
|
|
446
503
|
if (skeleton.hooks.useEffect.length > 0) {
|
|
447
504
|
const effects = skeleton.hooks.useEffect.map(eff => {
|
|
448
|
-
if (eff.deps === null) return `useEffect(∞)
|
|
449
|
-
if (eff.deps === '?') return `useEffect(?)
|
|
450
|
-
return `useEffect([${eff.deps.join(',')}])
|
|
505
|
+
if (eff.deps === null) return `useEffect(∞)`;
|
|
506
|
+
if (eff.deps === '?') return `useEffect(?)`;
|
|
507
|
+
return `useEffect([${eff.deps.join(',')}])`;
|
|
451
508
|
});
|
|
452
509
|
hookParts.push(...effects);
|
|
453
510
|
}
|
|
@@ -457,7 +514,11 @@ export const formatSkeletonForPrompt = (skeleton) => {
|
|
|
457
514
|
}
|
|
458
515
|
|
|
459
516
|
if (skeleton.classes.length > 0) {
|
|
460
|
-
|
|
517
|
+
const classList = skeleton.classes.map(c => {
|
|
518
|
+
const marker = c.exportMarker || '';
|
|
519
|
+
return `${c.name}${marker}:${c.line}`;
|
|
520
|
+
}).join(', ');
|
|
521
|
+
lines.push(`classes: ${classList}`);
|
|
461
522
|
}
|
|
462
523
|
|
|
463
524
|
if (skeleton.interfaces.length > 0 || skeleton.types.length > 0) {
|
package/src/parsers/python.js
CHANGED
|
@@ -17,7 +17,7 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
17
17
|
imports: [],
|
|
18
18
|
functions: [],
|
|
19
19
|
classes: [],
|
|
20
|
-
constants:
|
|
20
|
+
constants: [],
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
// Collect decorators as we scan
|
|
@@ -126,9 +126,9 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
// Top-level assignments (constants)
|
|
129
|
-
const assignMatch = line.match(/^[A-Za-z_]\w
|
|
129
|
+
const assignMatch = line.match(/^([A-Za-z_]\w*)\s*[=:]/);
|
|
130
130
|
if (assignMatch) {
|
|
131
|
-
skeleton.constants
|
|
131
|
+
skeleton.constants.push(assignMatch[1]);
|
|
132
132
|
pendingDecorators = [];
|
|
133
133
|
continue;
|
|
134
134
|
}
|
|
@@ -172,10 +172,20 @@ export const formatSkeletonForPrompt = (skeleton) => {
|
|
|
172
172
|
if (skeleton.functions.length > 0) {
|
|
173
173
|
const funcList = skeleton.functions.map(f => {
|
|
174
174
|
const deco = f.decorators.length > 0 ? `@${f.decorators[0]} ` : '';
|
|
175
|
-
|
|
175
|
+
const params = f.params ? `(${f.params})` : '()';
|
|
176
|
+
return `${deco}${f.name}${params}:${f.line}`;
|
|
176
177
|
}).join(', ');
|
|
177
178
|
lines.push(`fn: ${funcList}`);
|
|
178
179
|
}
|
|
179
180
|
|
|
181
|
+
if (skeleton.constants.length > 0) {
|
|
182
|
+
const names = skeleton.constants;
|
|
183
|
+
if (names.length > 5) {
|
|
184
|
+
lines.push(`const: ${names.slice(0, 5).join(', ')} +${names.length - 5} more`);
|
|
185
|
+
} else {
|
|
186
|
+
lines.push(`const: ${names.join(', ')}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
180
190
|
return lines.join('\n');
|
|
181
191
|
};
|
package/test/test.js
CHANGED
|
@@ -21,7 +21,7 @@ describe('babel parser', () => {
|
|
|
21
21
|
assert.ok(skeleton.imports.length > 0);
|
|
22
22
|
assert.ok(skeleton.components.length > 0);
|
|
23
23
|
assert.ok(skeleton.functions.length > 0);
|
|
24
|
-
assert.
|
|
24
|
+
assert.deepStrictEqual(skeleton.hooks.useState, ['data']);
|
|
25
25
|
assert.strictEqual(skeleton.hooks.useEffect.length, 1);
|
|
26
26
|
});
|
|
27
27
|
});
|
|
@@ -35,7 +35,7 @@ describe('python parser', () => {
|
|
|
35
35
|
assert.strictEqual(skeleton.imports.length, 4);
|
|
36
36
|
assert.strictEqual(skeleton.functions.length, 3);
|
|
37
37
|
assert.strictEqual(skeleton.classes.length, 2);
|
|
38
|
-
assert.ok(skeleton.constants >= 2);
|
|
38
|
+
assert.ok(skeleton.constants.length >= 2);
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
it('parses decorators', () => {
|