agentic-compaction 0.0.4 → 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 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,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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-compaction",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Walk a project directory and output a compact structural skeleton of the entire codebase",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -322,6 +322,7 @@ export const extractSkeleton = (code, filePath = '') => {
322
322
  },
323
323
 
324
324
  FunctionDeclaration(path) {
325
+ if (path.parent.type !== 'Program' && path.parent.type !== 'ExportNamedDeclaration' && path.parent.type !== 'ExportDefaultDeclaration') return;
325
326
  const name = path.node.id?.name;
326
327
  if (!name) return;
327
328
 
@@ -337,6 +338,8 @@ export const extractSkeleton = (code, filePath = '') => {
337
338
  },
338
339
 
339
340
  VariableDeclarator(path) {
341
+ const declParent = path.parentPath?.parent;
342
+ if (declParent?.type !== 'Program' && declParent?.type !== 'ExportNamedDeclaration' && declParent?.type !== 'ExportDefaultDeclaration') return;
340
343
  const name = path.node.id?.name;
341
344
  const init = path.node.init;
342
345
  if (!name || !init) return;
@@ -376,6 +379,9 @@ export const extractSkeleton = (code, filePath = '') => {
376
379
  CallExpression(path) {
377
380
  const callee = path.node.callee;
378
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;
379
385
  const hookName = callee.name;
380
386
  const line = path.node.loc?.start?.line || 0;
381
387
 
@@ -450,7 +456,7 @@ export const formatSkeletonForPrompt = (skeleton) => {
450
456
  const extCount = skeleton.imports.length - local.length;
451
457
  const parts = [];
452
458
  if (extCount > 0) parts.push(`${extCount} ext`);
453
- parts.push(...local.map(i => i.source));
459
+ parts.push(...[...new Set(local.map(i => i.source))]);
454
460
  lines.push(`imports: ${parts.join(', ')}`);
455
461
  }
456
462