agentic-compaction 0.0.3 → 0.0.4
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.
|
@@ -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
|
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,18 +305,18 @@ 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
|
},
|
|
@@ -319,10 +325,14 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
319
325
|
const name = path.node.id?.name;
|
|
320
326
|
if (!name) return;
|
|
321
327
|
|
|
328
|
+
const params = getParamsString(path.node.params);
|
|
329
|
+
const isAsync = path.node.async || false;
|
|
330
|
+
const entry = { name, line: path.node.loc?.start?.line || 0, params, async: isAsync };
|
|
331
|
+
|
|
322
332
|
if (isPascalCase(name)) {
|
|
323
|
-
skeleton.components.push(
|
|
333
|
+
skeleton.components.push(entry);
|
|
324
334
|
} else {
|
|
325
|
-
skeleton.functions.push(
|
|
335
|
+
skeleton.functions.push(entry);
|
|
326
336
|
}
|
|
327
337
|
},
|
|
328
338
|
|
|
@@ -332,17 +342,25 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
332
342
|
if (!name || !init) return;
|
|
333
343
|
|
|
334
344
|
if (init.type === 'ArrowFunctionExpression' || init.type === 'FunctionExpression') {
|
|
345
|
+
const params = getParamsString(init.params);
|
|
346
|
+
const isAsync = init.async || false;
|
|
347
|
+
const entry = { name, line: path.node.loc?.start?.line || 0, params, async: isAsync };
|
|
348
|
+
|
|
335
349
|
if (isPascalCase(name)) {
|
|
336
|
-
skeleton.components.push(
|
|
350
|
+
skeleton.components.push(entry);
|
|
337
351
|
} else {
|
|
338
|
-
skeleton.functions.push(
|
|
352
|
+
skeleton.functions.push(entry);
|
|
339
353
|
}
|
|
340
354
|
return;
|
|
341
355
|
}
|
|
342
356
|
|
|
343
357
|
const hocInfo = getReactHOCInfo(init);
|
|
344
358
|
if (hocInfo) {
|
|
345
|
-
|
|
359
|
+
let params = '?';
|
|
360
|
+
if (hocInfo.innerFn) {
|
|
361
|
+
params = getParamsString(hocInfo.innerFn.params);
|
|
362
|
+
}
|
|
363
|
+
skeleton.components.push({ name, line: path.node.loc?.start?.line || 0, hoc: hocInfo.type, params, async: false });
|
|
346
364
|
return;
|
|
347
365
|
}
|
|
348
366
|
|
|
@@ -352,7 +370,7 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
352
370
|
return;
|
|
353
371
|
}
|
|
354
372
|
|
|
355
|
-
skeleton.constants
|
|
373
|
+
skeleton.constants.push(name);
|
|
356
374
|
},
|
|
357
375
|
|
|
358
376
|
CallExpression(path) {
|
|
@@ -361,7 +379,18 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
361
379
|
const hookName = callee.name;
|
|
362
380
|
const line = path.node.loc?.start?.line || 0;
|
|
363
381
|
|
|
364
|
-
if (hookName === '
|
|
382
|
+
if (hookName === 'useState') {
|
|
383
|
+
// Extract destructured variable name from parent: const [name, setName] = useState(...)
|
|
384
|
+
let varName = null;
|
|
385
|
+
const parent = path.parent;
|
|
386
|
+
if (parent?.type === 'VariableDeclarator' && parent.id?.type === 'ArrayPattern') {
|
|
387
|
+
const first = parent.id.elements[0];
|
|
388
|
+
if (first?.type === 'Identifier') {
|
|
389
|
+
varName = first.name;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
skeleton.hooks.useState.push(varName || '?');
|
|
393
|
+
} else if (hookName === 'useEffect') {
|
|
365
394
|
const deps = extractDependencyArray(path.node.arguments[1]);
|
|
366
395
|
skeleton.hooks.useEffect.push({ line, deps });
|
|
367
396
|
} else if (skeleton.hooks[hookName] !== undefined) {
|
|
@@ -396,6 +425,13 @@ export const extractSkeleton = (code, filePath = '') => {
|
|
|
396
425
|
},
|
|
397
426
|
});
|
|
398
427
|
|
|
428
|
+
// Apply export markers to components, functions, classes
|
|
429
|
+
for (const entry of [...skeleton.components, ...skeleton.functions, ...skeleton.classes]) {
|
|
430
|
+
const exportType = exportMap.get(entry.name);
|
|
431
|
+
if (exportType === 'default') entry.exportMarker = '*';
|
|
432
|
+
else if (exportType === 'named') entry.exportMarker = '+';
|
|
433
|
+
}
|
|
434
|
+
|
|
399
435
|
return skeleton;
|
|
400
436
|
};
|
|
401
437
|
|
|
@@ -418,13 +454,13 @@ export const formatSkeletonForPrompt = (skeleton) => {
|
|
|
418
454
|
lines.push(`imports: ${parts.join(', ')}`);
|
|
419
455
|
}
|
|
420
456
|
|
|
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
457
|
if (skeleton.components.length > 0) {
|
|
427
|
-
const componentList = skeleton.components.map(c =>
|
|
458
|
+
const componentList = skeleton.components.map(c => {
|
|
459
|
+
const marker = c.exportMarker || '';
|
|
460
|
+
const params = c.params !== undefined ? `(${c.params})` : '';
|
|
461
|
+
const hoc = c.hoc ? `(${c.hoc})` : '';
|
|
462
|
+
return `${c.name}${hoc}${params}${marker}:${c.line}`;
|
|
463
|
+
}).join(', ');
|
|
428
464
|
lines.push(`components: ${componentList}`);
|
|
429
465
|
}
|
|
430
466
|
|
|
@@ -433,11 +469,26 @@ export const formatSkeletonForPrompt = (skeleton) => {
|
|
|
433
469
|
}
|
|
434
470
|
|
|
435
471
|
if (skeleton.functions.length > 0) {
|
|
436
|
-
|
|
472
|
+
const funcList = skeleton.functions.map(f => {
|
|
473
|
+
const marker = f.exportMarker || '';
|
|
474
|
+
const asyncPrefix = f.async ? 'async ' : '';
|
|
475
|
+
const params = f.params !== undefined ? `(${f.params})` : '';
|
|
476
|
+
return `${asyncPrefix}${f.name}${params}${marker}:${f.line}`;
|
|
477
|
+
}).join(', ');
|
|
478
|
+
lines.push(`fn: ${funcList}`);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (skeleton.constants.length > 0) {
|
|
482
|
+
const names = skeleton.constants;
|
|
483
|
+
if (names.length > 5) {
|
|
484
|
+
lines.push(`const: ${names.slice(0, 5).join(', ')} +${names.length - 5} more`);
|
|
485
|
+
} else {
|
|
486
|
+
lines.push(`const: ${names.join(', ')}`);
|
|
487
|
+
}
|
|
437
488
|
}
|
|
438
489
|
|
|
439
490
|
const hookParts = [];
|
|
440
|
-
if (skeleton.hooks.useState > 0) hookParts.push(`useState
|
|
491
|
+
if (skeleton.hooks.useState.length > 0) hookParts.push(`useState: ${skeleton.hooks.useState.join(', ')}`);
|
|
441
492
|
if (skeleton.hooks.useCallback > 0) hookParts.push(`useCallback(${skeleton.hooks.useCallback})`);
|
|
442
493
|
if (skeleton.hooks.useMemo > 0) hookParts.push(`useMemo(${skeleton.hooks.useMemo})`);
|
|
443
494
|
if (skeleton.hooks.useRef > 0) hookParts.push(`useRef(${skeleton.hooks.useRef})`);
|
|
@@ -445,9 +496,9 @@ export const formatSkeletonForPrompt = (skeleton) => {
|
|
|
445
496
|
|
|
446
497
|
if (skeleton.hooks.useEffect.length > 0) {
|
|
447
498
|
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(',')}])
|
|
499
|
+
if (eff.deps === null) return `useEffect(∞)`;
|
|
500
|
+
if (eff.deps === '?') return `useEffect(?)`;
|
|
501
|
+
return `useEffect([${eff.deps.join(',')}])`;
|
|
451
502
|
});
|
|
452
503
|
hookParts.push(...effects);
|
|
453
504
|
}
|
|
@@ -457,7 +508,11 @@ export const formatSkeletonForPrompt = (skeleton) => {
|
|
|
457
508
|
}
|
|
458
509
|
|
|
459
510
|
if (skeleton.classes.length > 0) {
|
|
460
|
-
|
|
511
|
+
const classList = skeleton.classes.map(c => {
|
|
512
|
+
const marker = c.exportMarker || '';
|
|
513
|
+
return `${c.name}${marker}:${c.line}`;
|
|
514
|
+
}).join(', ');
|
|
515
|
+
lines.push(`classes: ${classList}`);
|
|
461
516
|
}
|
|
462
517
|
|
|
463
518
|
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', () => {
|