What the Unminifier Does
The unminifier takes minified JavaScript (likeunderscore-umd-min.js) and produces readable code through five steps:
- Pretty-print with Prettier (no LLM needed)
- Convert UMD to ESM - strip the UMD boilerplate and use modern module syntax
- Extract functions - identify all top-level functions with minified names
- Analyze functions - suggest descriptive names for each function (in parallel batches)
- Apply renames - perform all identifier renames in a single pass
The Schema Definitions
First, define the structured outputs for each LLM step using the@JSONSchema annotation:
ModuleConversioncaptures both the transformed code and metadata about what was exportedFunctionListuses a nested structure to return multiple itemsFunctionAnalysisincludes aconfidencefield with literal union types for quality signalsFunctionAnalysisBatchwraps multiple analyses for efficient batched processing
Step 1: Pretty-Print with Prettier
The first step is purely mechanical - no LLM required. Use Prettier to make the minified code readable:Step 2: Convert UMD to ESM
Now we need semantic understanding. The LLM can recognize UMD boilerplate patterns and extract the module body:.code() method formats the code as a fenced code block in the prompt, making it clear to the agent where the code begins and ends.
Step 3: Extract Function List
Next, ask the agent to identify all functions that need renaming:FunctionList output gives you an array you can iterate over in TypeScript - bridging the gap between natural language analysis and programmatic control flow.
Step 4: Parallel Batch Analysis
Analyzing functions one at a time would be slow. Instead, batch them and process in parallel with a concurrency limit:p-limitprevents overwhelming the agent with too many concurrent requests_.chunkgroups functions into manageable batchesFunctionAnalysisBatchreturns multiple analyses per request, reducing round trips- Sending full source code as context helps the LLM understand function interdependencies
Step 5: Apply Renames
Finally, ask the agent to apply all the renames in a single pass:a calls function b and both need renaming?).
The Complete Pipeline
Here’s how it all fits together:Running the Example
Key Takeaways
- Mix LLM and traditional tools - Use Prettier for formatting, LLM for semantic understanding
- Sequential
agent.think()calls create natural pipeline stages - Parallel processing with
p-limitkeeps pipelines efficient without overwhelming the agent - Batch schemas like
FunctionAnalysisBatchreduce round trips for repeated operations - The
.code()method clearly delineates code blocks in prompts - Send full context when the LLM needs to understand relationships between code elements
