smol-logs 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,208 @@
1
+ # smol-logs
2
+
3
+ A CLI tool to compress verbose text output (logs, test output, build logs) into a human-readable, AI-friendly format. Reduces token usage when working with AI tools by intelligently encoding repetition.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g smol-logs
9
+ ```
10
+
11
+ Or run directly with npx:
12
+ ```bash
13
+ npx smol-logs
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```bash
19
+ # Pipe input from stdin
20
+ cat test.log | smol
21
+
22
+ # Read from file
23
+ smol test.log
24
+
25
+ # Write to file
26
+ smol test.log -o compressed.txt
27
+
28
+ # Adjust similarity threshold for pattern detection
29
+ smol test.log -t 0.9
30
+
31
+ # Exclude metadata header
32
+ smol test.log --no-meta
33
+ ```
34
+
35
+ ## How It Works
36
+
37
+ smol uses three compression strategies:
38
+
39
+ ### 1. Run-Length Encoding (RLE)
40
+ Collapses consecutive identical lines:
41
+
42
+ **Input:**
43
+ ```
44
+ Loading config...
45
+ Loading config...
46
+ Loading config...
47
+ Server started
48
+ ```
49
+
50
+ **Output:**
51
+ ```
52
+ Loading config...
53
+ ↑ repeated 3 times
54
+ Server started
55
+ ```
56
+
57
+ ### 2. Global Deduplication
58
+ Removes non-consecutive duplicate lines:
59
+
60
+ **Input:**
61
+ ```
62
+ console.log
63
+ Message 1
64
+ console.log
65
+ Message 2
66
+ console.log
67
+ Message 3
68
+ ```
69
+
70
+ **Output:**
71
+ ```
72
+ console.log
73
+ ↑ appears 3 times
74
+ Message 1
75
+ Message 2
76
+ Message 3
77
+ ```
78
+
79
+ ### 3. Pattern Templates
80
+ Detects near-duplicate lines and extracts variable parts:
81
+
82
+ **Input:**
83
+ ```
84
+ [INFO] Server ready on port 8080
85
+ [INFO] Server ready on port 8081
86
+ [INFO] Server ready on port 8082
87
+ ```
88
+
89
+ **Output:**
90
+ ```
91
+ "[INFO] Server ready on port {port}"
92
+ ↑ pattern matched 3 times: port = 8080, 8081, 8082
93
+ ```
94
+
95
+ ## Output Format
96
+
97
+ ```
98
+ === COMPRESSION: 1247 → 89 lines (93%) ===
99
+
100
+ Loading config...
101
+ ↑ repeated 3 times
102
+
103
+ Server started
104
+
105
+ "[INFO] Server ready on port {port}"
106
+ ↑ pattern matched 5 times: port = 8080, 8081, 8082, 8083, 8084
107
+
108
+ "[ERROR] Connection failed: {error}"
109
+ ↑ pattern matched 12 times: error = timeout, refused, reset, ...3 more
110
+ ↑ time range: 10:15:06 - 10:17:23
111
+
112
+ Done
113
+ ```
114
+
115
+ ### Format Elements
116
+
117
+ | Element | Syntax | Meaning |
118
+ |---------|--------|---------|
119
+ | Repeated line | `line` + `↑ repeated N times` | Line appeared N consecutive times |
120
+ | Deduplicated | `line` + `↑ appears N times` | Line appeared N times (non-consecutive) |
121
+ | Pattern | `"template"` + `↑ pattern matched` | Near-duplicate lines with variables |
122
+ | Unique line | just the line | Single occurrence |
123
+
124
+ ## CLI Options
125
+
126
+ | Option | Description | Default |
127
+ |--------|-------------|---------|
128
+ | `-o, --output <file>` | Output file (stdout if not provided) | - |
129
+ | `-t, --threshold <n>` | Similarity threshold for patterns (0-1) | 0.8 |
130
+ | `--no-meta` | Exclude compression stats header | false |
131
+ | `-p, --max-patterns <n>` | Maximum patterns to extract | 10 |
132
+ | `-v, --verbose` | Show compression statistics | false |
133
+
134
+ ## Examples
135
+
136
+ ### Compress Test Output
137
+
138
+ ```bash
139
+ npm test 2>&1 | smol
140
+ ```
141
+
142
+ ### Compress Build Logs
143
+
144
+ ```bash
145
+ npm run build 2>&1 | smol -o build-summary.txt
146
+ ```
147
+
148
+ ### Use with AI Tools
149
+
150
+ ```bash
151
+ # Compress and copy to clipboard (macOS)
152
+ cat verbose.log | smol | pbcopy
153
+
154
+ # Compress and copy to clipboard (Windows)
155
+ type verbose.log | smol | clip
156
+ ```
157
+
158
+ ## API Usage
159
+
160
+ You can also use the compressor programmatically:
161
+
162
+ ```typescript
163
+ import { compress, compressVerbose } from 'smol-logs';
164
+
165
+ const input = `
166
+ Loading...
167
+ Loading...
168
+ Server started
169
+ `;
170
+
171
+ // Basic compression
172
+ const output = compress(input);
173
+ console.log(output);
174
+
175
+ // With options
176
+ const output2 = compress(input, {
177
+ threshold: 0.9,
178
+ includeMeta: false,
179
+ });
180
+
181
+ // With statistics
182
+ const { output: result, stats } = compressVerbose(input);
183
+ console.log(`Compression: ${stats.totalLines} → ${stats.compressedItems} items`);
184
+ ```
185
+
186
+ ## Development
187
+
188
+ ```bash
189
+ # Clone the repository
190
+ git clone https://github.com/anthropics/smol-logs
191
+ cd smol-logs
192
+
193
+ # Install dependencies
194
+ npm install
195
+
196
+ # Run tests
197
+ npm test
198
+
199
+ # Build
200
+ npm run build
201
+
202
+ # Run in development
203
+ npm run dev sample.log
204
+ ```
205
+
206
+ ## License
207
+
208
+ MIT
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Block detection for repeated sequences of lines
3
+ * Uses content-defined chunking concepts to find natural boundaries
4
+ * and detect repeated blocks
5
+ */
6
+ import { LineInfo, DetectedBlock, BlockResult, CompressorOptions } from './types';
7
+ /**
8
+ * Detect repeated blocks of lines
9
+ * @param lines - Array of LineInfo
10
+ * @param options - Compressor options
11
+ * @returns BlockResult with detected blocks
12
+ */
13
+ export declare function detectBlocks(lines: LineInfo[], options: CompressorOptions): BlockResult;
14
+ /**
15
+ * Get block coverage info for debugging
16
+ * @param blocks - Detected blocks
17
+ * @param totalLines - Total number of lines
18
+ * @returns Coverage statistics
19
+ */
20
+ export declare function getBlockCoverage(blocks: DetectedBlock[], totalLines: number): {
21
+ coveredLines: number;
22
+ percentage: string;
23
+ };
24
+ //# sourceMappingURL=blocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AA0IlF;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,EAAE,EACjB,OAAO,EAAE,iBAAiB,GACzB,WAAW,CA8Eb;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,aAAa,EAAE,EACvB,UAAU,EAAE,MAAM,GACjB;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAe9C"}
package/dist/blocks.js ADDED
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ /**
3
+ * Block detection for repeated sequences of lines
4
+ * Uses content-defined chunking concepts to find natural boundaries
5
+ * and detect repeated blocks
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.detectBlocks = detectBlocks;
9
+ exports.getBlockCoverage = getBlockCoverage;
10
+ const hashing_1 = require("./hashing");
11
+ /** Gear table for rolling hash (256 random values) */
12
+ const GEAR_TABLE = (() => {
13
+ // Deterministic pseudo-random values using a simple LCG
14
+ const table = [];
15
+ let seed = 0x12345678;
16
+ for (let i = 0; i < 256; i++) {
17
+ seed = Math.imul(seed, 1103515245) + 12345;
18
+ table.push(seed >>> 0);
19
+ }
20
+ return table;
21
+ })();
22
+ /**
23
+ * Compute a hash for a sequence of lines
24
+ * @param lines - Array of line strings
25
+ * @returns Hash of the combined lines
26
+ */
27
+ function hashLineSequence(lines) {
28
+ return (0, hashing_1.fnv1a)(lines.join('\n'));
29
+ }
30
+ /**
31
+ * Find block boundaries using line content patterns
32
+ * Blocks are natural groupings where we see clear separators
33
+ * @param lines - Array of LineInfo
34
+ * @returns Array of boundary indices
35
+ */
36
+ function findBlockBoundaries(lines) {
37
+ const boundaries = [0]; // Start is always a boundary
38
+ // Common block separator patterns
39
+ const separatorPatterns = [
40
+ /^={3,}/, // ===...
41
+ /^-{3,}/, // ---...
42
+ /^#{3,}/, // ###...
43
+ /^\*{3,}/, // ***...
44
+ /^~{3,}/, // ~~~...
45
+ /^$/, // Empty line
46
+ /^(Test|Describe|Context|Suite|PASS|FAIL)[\s:]/i, // Test markers
47
+ /^\[?(INFO|ERROR|WARN|DEBUG)\]?[\s:]/i, // Log level changes
48
+ ];
49
+ for (let i = 1; i < lines.length; i++) {
50
+ const text = lines[i].text.trim();
51
+ // Check if line matches any separator pattern
52
+ const isSeparator = separatorPatterns.some((p) => p.test(text));
53
+ // Also check for significant content changes (header-like lines)
54
+ const isHeader = /^={2,}\s*\w/.test(text) || // === Something ===
55
+ /^#{1,3}\s/.test(text); // # Header
56
+ if (isSeparator || isHeader) {
57
+ boundaries.push(i);
58
+ }
59
+ }
60
+ boundaries.push(lines.length); // End is always a boundary
61
+ return [...new Set(boundaries)].sort((a, b) => a - b);
62
+ }
63
+ /**
64
+ * Extract blocks between boundaries and identify repeats
65
+ * @param lines - Array of LineInfo
66
+ * @param boundaries - Block boundary indices
67
+ * @param minBlockSize - Minimum lines to consider as block
68
+ * @returns Map of block hash to block info
69
+ */
70
+ function extractBlocks(lines, boundaries, minBlockSize) {
71
+ const blockMap = new Map();
72
+ for (let i = 0; i < boundaries.length - 1; i++) {
73
+ const start = boundaries[i];
74
+ const end = boundaries[i + 1];
75
+ const blockLines = lines.slice(start, end).map((l) => l.text);
76
+ // Skip blocks that are too small
77
+ if (blockLines.length < minBlockSize) {
78
+ continue;
79
+ }
80
+ const hash = hashLineSequence(blockLines);
81
+ const existing = blockMap.get(hash);
82
+ if (existing) {
83
+ existing.indices.push(start);
84
+ }
85
+ else {
86
+ blockMap.set(hash, { lines: blockLines, indices: [start] });
87
+ }
88
+ }
89
+ return blockMap;
90
+ }
91
+ /**
92
+ * Find repeated subsequences within the lines using sliding window
93
+ * @param lines - Array of LineInfo
94
+ * @param minBlockSize - Minimum block size
95
+ * @returns Map of hash to block info
96
+ */
97
+ function findRepeatedSubsequences(lines, minBlockSize) {
98
+ const blockMap = new Map();
99
+ // Try different window sizes from minBlockSize up to a reasonable max
100
+ const maxWindowSize = Math.min(20, Math.floor(lines.length / 2));
101
+ for (let windowSize = minBlockSize; windowSize <= maxWindowSize; windowSize++) {
102
+ for (let i = 0; i <= lines.length - windowSize; i++) {
103
+ const windowLines = lines.slice(i, i + windowSize).map((l) => l.text);
104
+ const hash = hashLineSequence(windowLines);
105
+ const existing = blockMap.get(hash);
106
+ if (existing) {
107
+ // Check if this is a new occurrence (not overlapping)
108
+ const lastIndex = existing.indices[existing.indices.length - 1];
109
+ if (i >= lastIndex + existing.lines.length) {
110
+ existing.indices.push(i);
111
+ }
112
+ }
113
+ else {
114
+ blockMap.set(hash, { lines: windowLines, indices: [i] });
115
+ }
116
+ }
117
+ }
118
+ return blockMap;
119
+ }
120
+ /**
121
+ * Detect repeated blocks of lines
122
+ * @param lines - Array of LineInfo
123
+ * @param options - Compressor options
124
+ * @returns BlockResult with detected blocks
125
+ */
126
+ function detectBlocks(lines, options) {
127
+ const { minBlockSize } = options;
128
+ // First try natural boundary detection
129
+ const boundaries = findBlockBoundaries(lines);
130
+ let blockMap = extractBlocks(lines, boundaries, minBlockSize);
131
+ // Also look for repeated subsequences that might not align with boundaries
132
+ const subseqBlocks = findRepeatedSubsequences(lines, minBlockSize);
133
+ // Merge results, preferring longer blocks
134
+ for (const [hash, info] of subseqBlocks) {
135
+ if (info.indices.length > 1) {
136
+ const existing = blockMap.get(hash);
137
+ if (!existing || info.lines.length > existing.lines.length) {
138
+ blockMap.set(hash, info);
139
+ }
140
+ }
141
+ }
142
+ // Filter to only blocks that appear more than once
143
+ const repeatedBlocks = [];
144
+ let blockId = 1;
145
+ const coveredIndices = new Set();
146
+ // Sort by occurrence count descending, then by size descending
147
+ const sortedBlocks = [...blockMap.entries()]
148
+ .filter(([_, info]) => info.indices.length > 1)
149
+ .sort((a, b) => {
150
+ const countDiff = b[1].indices.length - a[1].indices.length;
151
+ if (countDiff !== 0)
152
+ return countDiff;
153
+ return b[1].lines.length - a[1].lines.length;
154
+ });
155
+ for (const [hash, info] of sortedBlocks) {
156
+ // Check if any of these indices are already covered
157
+ const uncoveredIndices = info.indices.filter((idx) => {
158
+ for (let i = 0; i < info.lines.length; i++) {
159
+ if (coveredIndices.has(idx + i)) {
160
+ return false;
161
+ }
162
+ }
163
+ return true;
164
+ });
165
+ if (uncoveredIndices.length > 1) {
166
+ const block = {
167
+ id: `B${blockId++}`,
168
+ startIndex: uncoveredIndices[0],
169
+ lines: info.lines,
170
+ hash,
171
+ occurrences: uncoveredIndices.length,
172
+ indices: uncoveredIndices,
173
+ };
174
+ repeatedBlocks.push(block);
175
+ // Mark these indices as covered
176
+ for (const idx of uncoveredIndices) {
177
+ for (let i = 0; i < info.lines.length; i++) {
178
+ coveredIndices.add(idx + i);
179
+ }
180
+ }
181
+ }
182
+ }
183
+ // Calculate remaining indices
184
+ const remainingIndices = new Set();
185
+ for (let i = 0; i < lines.length; i++) {
186
+ if (!coveredIndices.has(i)) {
187
+ remainingIndices.add(i);
188
+ }
189
+ }
190
+ return {
191
+ blocks: repeatedBlocks,
192
+ remainingIndices,
193
+ };
194
+ }
195
+ /**
196
+ * Get block coverage info for debugging
197
+ * @param blocks - Detected blocks
198
+ * @param totalLines - Total number of lines
199
+ * @returns Coverage statistics
200
+ */
201
+ function getBlockCoverage(blocks, totalLines) {
202
+ const covered = new Set();
203
+ for (const block of blocks) {
204
+ for (const idx of block.indices) {
205
+ for (let i = 0; i < block.lines.length; i++) {
206
+ covered.add(idx + i);
207
+ }
208
+ }
209
+ }
210
+ const coveredLines = covered.size;
211
+ const percentage = ((coveredLines / totalLines) * 100).toFixed(1);
212
+ return { coveredLines, percentage: `${percentage}%` };
213
+ }
214
+ //# sourceMappingURL=blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.js","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Main compression orchestrator
3
+ * Coordinates all compression phases and produces final output
4
+ */
5
+ import { CompressorOptions } from './types';
6
+ /**
7
+ * Parse input text into lines
8
+ * Handles different line endings
9
+ */
10
+ declare function parseLines(input: string): string[];
11
+ /**
12
+ * Main compression function
13
+ * @param input - Raw input text
14
+ * @param options - Compression options (partial, merged with defaults)
15
+ * @returns Compressed output string
16
+ */
17
+ export declare function compress(input: string, options?: Partial<CompressorOptions>): string;
18
+ /**
19
+ * Compress with verbose output for debugging
20
+ */
21
+ export declare function compressVerbose(input: string, options?: Partial<CompressorOptions>): {
22
+ output: string;
23
+ stats: Record<string, unknown>;
24
+ };
25
+ export { parseLines };
26
+ //# sourceMappingURL=compressor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compressor.d.ts","sourceRoot":"","sources":["../src/compressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,iBAAiB,EASlB,MAAM,SAAS,CAAC;AAMjB;;;GAGG;AACH,iBAAS,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAG3C;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,OAAO,CAAC,iBAAiB,CAAM,GACvC,MAAM,CAgCR;AA4JD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,OAAO,CAAC,iBAAiB,CAAM,GACvC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAkBpD;AAGD,OAAO,EAAE,UAAU,EAAE,CAAC"}