make-laten 1.0.0 → 1.0.3

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,379 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/compress/confidence.ts
4
+ function calculateConfidence(original, compressed) {
5
+ if (!original.length) return 0;
6
+ let score = 1;
7
+ const ratio = compressed.length / original.length;
8
+ if (ratio < 0.01) score -= 0.5;
9
+ else if (ratio < 0.05) score -= 0.3;
10
+ if (codeBlocksModified(original, compressed)) score -= 0.4;
11
+ if (isKnownPattern(original)) score += 0.1;
12
+ return Math.max(0, Math.min(1, score));
13
+ }
14
+ function codeBlocksModified(original, compressed) {
15
+ const codeBlockRegex = /```[\s\S]*?```/g;
16
+ const originalBlocks = original.match(codeBlockRegex) || [];
17
+ const compressedBlocks = compressed.match(codeBlockRegex) || [];
18
+ if (originalBlocks.length !== compressedBlocks.length) return true;
19
+ for (let i = 0; i < originalBlocks.length; i++) {
20
+ if (originalBlocks[i] !== compressedBlocks[i]) return true;
21
+ }
22
+ return false;
23
+ }
24
+ function isKnownPattern(content) {
25
+ const patterns = [
26
+ /export\s+(default\s+)?(function|class|const|let|var)/,
27
+ /import\s+.*from\s+['"]/
28
+ ];
29
+ return patterns.some((p) => p.test(content));
30
+ }
31
+
32
+ // src/compress/file-read.ts
33
+ var FileReadCompressor = class {
34
+ async compress(input) {
35
+ const { content, filePath, language } = input;
36
+ const signatures = this.extractSignatures(content, language);
37
+ const exports = this.extractExports(content);
38
+ const lines = [
39
+ `// ${filePath} (${content.split("\n").length} lines)`,
40
+ "",
41
+ ...signatures,
42
+ "",
43
+ "// Exports:",
44
+ ...exports
45
+ ];
46
+ const compressed = lines.join("\n");
47
+ return {
48
+ content: compressed,
49
+ original: content,
50
+ confidence: calculateConfidence(content, compressed),
51
+ metadata: {
52
+ strategy: "signatures",
53
+ originalLines: content.split("\n").length,
54
+ compressedLines: lines.length,
55
+ savings: 1 - compressed.length / content.length
56
+ }
57
+ };
58
+ }
59
+ async decompress(compressed) {
60
+ return compressed.original;
61
+ }
62
+ extractSignatures(content, language) {
63
+ const signatures = [];
64
+ const lines = content.split("\n");
65
+ for (const line of lines) {
66
+ const trimmed = line.trim();
67
+ if (/^(export\s+)?(async\s+)?function\s+\w+/.test(trimmed)) {
68
+ signatures.push(trimmed.replace(/\{[\s\S]*$/, "{ ... }"));
69
+ }
70
+ if (/^(export\s+)?class\s+\w+/.test(trimmed)) {
71
+ signatures.push(trimmed);
72
+ }
73
+ if (/^(export\s+)?(type|interface)\s+\w+/.test(trimmed)) {
74
+ signatures.push(trimmed);
75
+ }
76
+ }
77
+ return signatures;
78
+ }
79
+ extractExports(content) {
80
+ const exports = [];
81
+ const exportRegex = /export\s+(default\s+)?(function|class|const|let|var|type|interface)\s+(\w+)/g;
82
+ let match;
83
+ while ((match = exportRegex.exec(content)) !== null) {
84
+ exports.push(` - ${match[3]} (${match[2]})`);
85
+ }
86
+ return exports;
87
+ }
88
+ };
89
+
90
+ // src/compress/grep.ts
91
+ var GrepCompressor = class {
92
+ async compress(input) {
93
+ const { results } = input;
94
+ const grouped = this.groupByFile(results);
95
+ const lines = [];
96
+ for (const [file, matches] of grouped) {
97
+ lines.push(`${file} (${matches.length} matches)`);
98
+ const unique = this.deduplicate(matches);
99
+ for (const match of unique) {
100
+ lines.push(` L${match.line}: ${match.content}`);
101
+ }
102
+ }
103
+ const compressed = lines.join("\n");
104
+ const original = results.map((r) => `${r.file}:${r.line}: ${r.content}`).join("\n");
105
+ return {
106
+ content: compressed,
107
+ original,
108
+ confidence: calculateConfidence(original, compressed),
109
+ metadata: {
110
+ strategy: "grouped",
111
+ totalMatches: results.length,
112
+ uniqueFiles: grouped.size,
113
+ savings: 1 - compressed.length / original.length
114
+ }
115
+ };
116
+ }
117
+ async decompress(compressed) {
118
+ return compressed.original;
119
+ }
120
+ groupByFile(results) {
121
+ const grouped = /* @__PURE__ */ new Map();
122
+ for (const result of results) {
123
+ const existing = grouped.get(result.file) || [];
124
+ existing.push(result);
125
+ grouped.set(result.file, existing);
126
+ }
127
+ return grouped;
128
+ }
129
+ deduplicate(matches) {
130
+ const seen = /* @__PURE__ */ new Set();
131
+ return matches.filter((match) => {
132
+ const key = match.content.trim();
133
+ if (seen.has(key)) return false;
134
+ seen.add(key);
135
+ return true;
136
+ });
137
+ }
138
+ };
139
+
140
+ // src/compress/git-diff.ts
141
+ var GitDiffCompressor = class {
142
+ async compress(input) {
143
+ const { diff } = input;
144
+ const hunks = this.parseDiff(diff);
145
+ const condensed = hunks.map((hunk) => ({
146
+ file: hunk.file,
147
+ changes: this.condenseHunk(hunk),
148
+ stats: { additions: hunk.additions, deletions: hunk.deletions }
149
+ }));
150
+ const lines = [];
151
+ for (const hunk of condensed) {
152
+ if (hunk.changes.length > 0) {
153
+ lines.push(`${hunk.file} (+${hunk.stats.additions} -${hunk.stats.deletions})`);
154
+ lines.push(...hunk.changes);
155
+ }
156
+ }
157
+ const compressed = lines.join("\n");
158
+ return {
159
+ content: compressed,
160
+ original: diff,
161
+ confidence: calculateConfidence(diff, compressed),
162
+ metadata: {
163
+ strategy: "condensed",
164
+ filesChanged: condensed.length,
165
+ savings: 1 - compressed.length / diff.length
166
+ }
167
+ };
168
+ }
169
+ async decompress(compressed) {
170
+ return compressed.original;
171
+ }
172
+ parseDiff(diff) {
173
+ const hunks = [];
174
+ const lines = diff.split("\n");
175
+ let currentHunk = null;
176
+ for (const line of lines) {
177
+ if (line.startsWith("diff --git")) {
178
+ if (currentHunk) hunks.push(currentHunk);
179
+ const fileMatch = line.match(/b\/(.+)/);
180
+ currentHunk = {
181
+ file: fileMatch?.[1] || "unknown",
182
+ lines: [],
183
+ additions: 0,
184
+ deletions: 0
185
+ };
186
+ } else if (currentHunk) {
187
+ if (line.startsWith("+")) {
188
+ currentHunk.additions++;
189
+ currentHunk.lines.push({ type: "addition", content: line.slice(1) });
190
+ } else if (line.startsWith("-")) {
191
+ currentHunk.deletions++;
192
+ currentHunk.lines.push({ type: "deletion", content: line.slice(1) });
193
+ }
194
+ }
195
+ }
196
+ if (currentHunk) hunks.push(currentHunk);
197
+ return hunks;
198
+ }
199
+ condenseHunk(hunk) {
200
+ return hunk.lines.filter((l) => l.type === "addition" || l.type === "deletion").map((l) => `${l.type === "addition" ? "+" : "-"} ${l.content}`);
201
+ }
202
+ };
203
+
204
+ // src/mcp/server.ts
205
+ import { exec } from "child_process";
206
+ import { promisify } from "util";
207
+ import fs from "fs/promises";
208
+ var execAsync = promisify(exec);
209
+ var TOOLS = [
210
+ {
211
+ name: "make-laten-read",
212
+ description: "Read and compress a file (60-90% token savings)",
213
+ inputSchema: {
214
+ type: "object",
215
+ properties: {
216
+ file_path: { type: "string", description: "Path to file" }
217
+ },
218
+ required: ["file_path"]
219
+ }
220
+ },
221
+ {
222
+ name: "make-laten-grep",
223
+ description: "Search code and return compressed grouped results",
224
+ inputSchema: {
225
+ type: "object",
226
+ properties: {
227
+ pattern: { type: "string", description: "Search pattern" },
228
+ path: { type: "string", description: "Directory to search", default: "." }
229
+ },
230
+ required: ["pattern"]
231
+ }
232
+ },
233
+ {
234
+ name: "make-laten-git-diff",
235
+ description: "Compressed git diff output",
236
+ inputSchema: {
237
+ type: "object",
238
+ properties: {
239
+ staged: { type: "boolean", description: "Show staged changes", default: false }
240
+ }
241
+ }
242
+ },
243
+ {
244
+ name: "make-laten-git-status",
245
+ description: "Compressed git status",
246
+ inputSchema: { type: "object", properties: {} }
247
+ },
248
+ {
249
+ name: "make-laten-cache-stats",
250
+ description: "Show cache performance stats",
251
+ inputSchema: { type: "object", properties: {} }
252
+ }
253
+ ];
254
+ function detectLanguage(filePath) {
255
+ const ext = filePath.split(".").pop()?.toLowerCase() || "";
256
+ const map = {
257
+ ts: "typescript",
258
+ tsx: "typescript",
259
+ js: "javascript",
260
+ jsx: "javascript",
261
+ py: "python",
262
+ rs: "rust",
263
+ go: "go",
264
+ java: "java",
265
+ rb: "ruby",
266
+ json: "json",
267
+ yaml: "yaml",
268
+ yml: "yaml",
269
+ md: "markdown"
270
+ };
271
+ return map[ext] || "text";
272
+ }
273
+ async function handleRead(params) {
274
+ const content = await fs.readFile(params.file_path, "utf-8");
275
+ const compressor = new FileReadCompressor();
276
+ const result = await compressor.compress({
277
+ content,
278
+ filePath: params.file_path,
279
+ language: detectLanguage(params.file_path)
280
+ });
281
+ return {
282
+ content: [{ type: "text", text: JSON.stringify({ compressed: result.content, savings: result.metadata.savings, confidence: result.confidence }) }]
283
+ };
284
+ }
285
+ async function handleGrep(params) {
286
+ const dir = params.path || ".";
287
+ const { stdout } = await execAsync(`grep -rn "${params.pattern}" ${dir} 2>/dev/null || true`, { maxBuffer: 10 * 1024 * 1024 });
288
+ if (!stdout.trim()) {
289
+ return { content: [{ type: "text", text: JSON.stringify({ matches: [], total: 0 }) }] };
290
+ }
291
+ const matches = stdout.split("\n").filter(Boolean).map((line) => {
292
+ const parts = line.split(":");
293
+ return { file: parts[0], line: parseInt(parts[1], 10) || 0, content: parts.slice(2).join(":").trim() };
294
+ });
295
+ const compressor = new GrepCompressor();
296
+ const result = await compressor.compress({ results: matches, pattern: params.pattern, directory: dir });
297
+ return { content: [{ type: "text", text: JSON.stringify({ compressed: result.content, total: matches.length, savings: result.metadata.savings }) }] };
298
+ }
299
+ async function handleGitDiff(params) {
300
+ const flag = params.staged ? "--staged" : "";
301
+ const { stdout } = await execAsync(`git diff ${flag}`, { maxBuffer: 10 * 1024 * 1024 });
302
+ if (!stdout.trim()) {
303
+ return { content: [{ type: "text", text: JSON.stringify({ diff: "", changes: 0 }) }] };
304
+ }
305
+ const compressor = new GitDiffCompressor();
306
+ const result = await compressor.compress({ diff: stdout });
307
+ return { content: [{ type: "text", text: JSON.stringify({ compressed: result.content, savings: result.metadata.savings }) }] };
308
+ }
309
+ async function handleGitStatus() {
310
+ const { stdout } = await execAsync("git status --porcelain");
311
+ const lines = stdout.split("\n").filter(Boolean);
312
+ const files = lines.map((l) => ({ status: l[0], path: l.slice(3) }));
313
+ return { content: [{ type: "text", text: JSON.stringify({ total: files.length, files }) }] };
314
+ }
315
+ async function handleCacheStats() {
316
+ return { content: [{ type: "text", text: JSON.stringify({ message: "Cache stats \u2014 use CLI: make-laten cache stats" }) }] };
317
+ }
318
+ var handlers = {
319
+ "make-laten-read": handleRead,
320
+ "make-laten-grep": handleGrep,
321
+ "make-laten-git-diff": handleGitDiff,
322
+ "make-laten-git-status": handleGitStatus,
323
+ "make-laten-cache-stats": handleCacheStats
324
+ };
325
+ function sendResponse(id, result) {
326
+ const response = { jsonrpc: "2.0", id, result };
327
+ process.stdout.write(JSON.stringify(response) + "\n");
328
+ }
329
+ function sendError(id, code, message) {
330
+ const response = { jsonrpc: "2.0", id, error: { code, message } };
331
+ process.stdout.write(JSON.stringify(response) + "\n");
332
+ }
333
+ async function handleLine(line) {
334
+ try {
335
+ const request = JSON.parse(line);
336
+ if (request.method === "initialize") {
337
+ sendResponse(request.id, {
338
+ protocolVersion: "2024-11-05",
339
+ capabilities: { tools: {} },
340
+ serverInfo: { name: "make-laten", version: "1.0.0" }
341
+ });
342
+ } else if (request.method === "notifications/initialized") {
343
+ } else if (request.method === "tools/list") {
344
+ sendResponse(request.id, { tools: TOOLS });
345
+ } else if (request.method === "tools/call") {
346
+ const { name, arguments: params } = request.params;
347
+ const handler = handlers[name];
348
+ if (!handler) {
349
+ sendError(request.id, -32601, `Unknown tool: ${name}`);
350
+ return;
351
+ }
352
+ try {
353
+ const result = await handler(params || {});
354
+ sendResponse(request.id, result);
355
+ } catch (error) {
356
+ sendError(request.id, -32e3, error.message);
357
+ }
358
+ } else {
359
+ sendError(request.id, -32601, `Method not found: ${request.method}`);
360
+ }
361
+ } catch (error) {
362
+ process.stderr.write(`Error: ${error.message}
363
+ `);
364
+ }
365
+ }
366
+ var buffer = "";
367
+ process.stdin.setEncoding("utf-8");
368
+ process.stdin.on("data", async (chunk) => {
369
+ buffer += chunk;
370
+ const lines = buffer.split("\n");
371
+ buffer = lines.pop() || "";
372
+ for (const line of lines) {
373
+ if (line.trim()) {
374
+ await handleLine(line.trim());
375
+ }
376
+ }
377
+ });
378
+ process.stderr.write("make-laten MCP server started\n");
379
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/compress/confidence.ts","../../src/compress/file-read.ts","../../src/compress/grep.ts","../../src/compress/git-diff.ts","../../src/mcp/server.ts"],"sourcesContent":["export function calculateConfidence(original: string, compressed: string): number {\n if (!original.length) return 0\n\n let score = 1.0\n\n // Penalize if too much dropped\n const ratio = compressed.length / original.length\n if (ratio < 0.01) score -= 0.5\n else if (ratio < 0.05) score -= 0.3\n\n // Penalize if code blocks were modified\n if (codeBlocksModified(original, compressed)) score -= 0.4\n\n // Bonus for known patterns\n if (isKnownPattern(original)) score += 0.1\n\n return Math.max(0, Math.min(1, score))\n}\n\nfunction codeBlocksModified(original: string, compressed: string): boolean {\n const codeBlockRegex = /```[\\s\\S]*?```/g\n const originalBlocks = original.match(codeBlockRegex) || []\n const compressedBlocks = compressed.match(codeBlockRegex) || []\n\n if (originalBlocks.length !== compressedBlocks.length) return true\n\n for (let i = 0; i < originalBlocks.length; i++) {\n if (originalBlocks[i] !== compressedBlocks[i]) return true\n }\n\n return false\n}\n\nfunction isKnownPattern(content: string): boolean {\n const patterns = [\n /export\\s+(default\\s+)?(function|class|const|let|var)/,\n /import\\s+.*from\\s+['\"]/\n ]\n return patterns.some(p => p.test(content))\n}\n","import type { Compressor, CompressedResult, FileReadInput } from './types.js'\nimport { calculateConfidence } from './confidence.js'\n\nexport class FileReadCompressor implements Compressor {\n async compress(input: unknown): Promise<CompressedResult> {\n const { content, filePath, language } = input as FileReadInput\n \n const signatures = this.extractSignatures(content, language)\n const exports = this.extractExports(content)\n \n const lines = [\n `// ${filePath} (${content.split('\\n').length} lines)`,\n '',\n ...signatures,\n '',\n '// Exports:',\n ...exports\n ]\n \n const compressed = lines.join('\\n')\n \n return {\n content: compressed,\n original: content,\n confidence: calculateConfidence(content, compressed),\n metadata: {\n strategy: 'signatures',\n originalLines: content.split('\\n').length,\n compressedLines: lines.length,\n savings: 1 - (compressed.length / content.length)\n }\n }\n }\n\n async decompress(compressed: CompressedResult): Promise<unknown> {\n return compressed.original\n }\n\n private extractSignatures(content: string, language?: string): string[] {\n const signatures: string[] = []\n const lines = content.split('\\n')\n \n for (const line of lines) {\n const trimmed = line.trim()\n \n if (/^(export\\s+)?(async\\s+)?function\\s+\\w+/.test(trimmed)) {\n signatures.push(trimmed.replace(/\\{[\\s\\S]*$/, '{ ... }'))\n }\n \n if (/^(export\\s+)?class\\s+\\w+/.test(trimmed)) {\n signatures.push(trimmed)\n }\n \n if (/^(export\\s+)?(type|interface)\\s+\\w+/.test(trimmed)) {\n signatures.push(trimmed)\n }\n }\n \n return signatures\n }\n\n private extractExports(content: string): string[] {\n const exports: string[] = []\n const exportRegex = /export\\s+(default\\s+)?(function|class|const|let|var|type|interface)\\s+(\\w+)/g\n let match\n \n while ((match = exportRegex.exec(content)) !== null) {\n exports.push(` - ${match[3]} (${match[2]})`)\n }\n \n return exports\n }\n}\n","import type { Compressor, CompressedResult, GrepInput } from './types.js'\nimport { calculateConfidence } from './confidence.js'\n\nexport class GrepCompressor implements Compressor {\n async compress(input: unknown): Promise<CompressedResult> {\n const { results } = input as GrepInput\n \n // Group by file\n const grouped = this.groupByFile(results)\n \n // Format output\n const lines: string[] = []\n for (const [file, matches] of grouped) {\n lines.push(`${file} (${matches.length} matches)`)\n const unique = this.deduplicate(matches)\n for (const match of unique) {\n lines.push(` L${match.line}: ${match.content}`)\n }\n }\n \n const compressed = lines.join('\\n')\n const original = results.map(r => `${r.file}:${r.line}: ${r.content}`).join('\\n')\n \n return {\n content: compressed,\n original,\n confidence: calculateConfidence(original, compressed),\n metadata: {\n strategy: 'grouped',\n totalMatches: results.length,\n uniqueFiles: grouped.size,\n savings: 1 - (compressed.length / original.length)\n }\n }\n }\n\n async decompress(compressed: CompressedResult): Promise<unknown> {\n return compressed.original\n }\n\n private groupByFile(results: GrepInput['results']): Map<string, GrepInput['results']> {\n const grouped = new Map<string, GrepInput['results']>()\n \n for (const result of results) {\n const existing = grouped.get(result.file) || []\n existing.push(result)\n grouped.set(result.file, existing)\n }\n \n return grouped\n }\n\n private deduplicate(matches: GrepInput['results']): GrepInput['results'] {\n const seen = new Set<string>()\n return matches.filter(match => {\n const key = match.content.trim()\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n}\n","import type { Compressor, CompressedResult, GitDiffInput } from './types.js'\nimport { calculateConfidence } from './confidence.js'\n\nexport class GitDiffCompressor implements Compressor {\n async compress(input: unknown): Promise<CompressedResult> {\n const { diff } = input as GitDiffInput\n \n // Parse diff into hunks\n const hunks = this.parseDiff(diff)\n \n // Condense each hunk\n const condensed = hunks.map(hunk => ({\n file: hunk.file,\n changes: this.condenseHunk(hunk),\n stats: { additions: hunk.additions, deletions: hunk.deletions }\n }))\n \n // Format output\n const lines: string[] = []\n for (const hunk of condensed) {\n if (hunk.changes.length > 0) {\n lines.push(`${hunk.file} (+${hunk.stats.additions} -${hunk.stats.deletions})`)\n lines.push(...hunk.changes)\n }\n }\n \n const compressed = lines.join('\\n')\n \n return {\n content: compressed,\n original: diff,\n confidence: calculateConfidence(diff, compressed),\n metadata: {\n strategy: 'condensed',\n filesChanged: condensed.length,\n savings: 1 - (compressed.length / diff.length)\n }\n }\n }\n\n async decompress(compressed: CompressedResult): Promise<unknown> {\n return compressed.original\n }\n\n private parseDiff(diff: string): Hunk[] {\n const hunks: Hunk[] = []\n const lines = diff.split('\\n')\n \n let currentHunk: Hunk | null = null\n \n for (const line of lines) {\n if (line.startsWith('diff --git')) {\n if (currentHunk) hunks.push(currentHunk)\n const fileMatch = line.match(/b\\/(.+)/)\n currentHunk = {\n file: fileMatch?.[1] || 'unknown',\n lines: [],\n additions: 0,\n deletions: 0\n }\n } else if (currentHunk) {\n if (line.startsWith('+')) {\n currentHunk.additions++\n currentHunk.lines.push({ type: 'addition', content: line.slice(1) })\n } else if (line.startsWith('-')) {\n currentHunk.deletions++\n currentHunk.lines.push({ type: 'deletion', content: line.slice(1) })\n }\n }\n }\n \n if (currentHunk) hunks.push(currentHunk)\n return hunks\n }\n\n private condenseHunk(hunk: Hunk): string[] {\n return hunk.lines\n .filter(l => l.type === 'addition' || l.type === 'deletion')\n .map(l => `${l.type === 'addition' ? '+' : '-'} ${l.content}`)\n }\n}\n\ninterface Hunk {\n file: string\n lines: { type: string; content: string }[]\n additions: number\n deletions: number\n}\n","#!/usr/bin/env node\n\nimport { FileReadCompressor } from '../compress/file-read.js'\nimport { GrepCompressor } from '../compress/grep.js'\nimport { GitDiffCompressor } from '../compress/git-diff.js'\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\nimport fs from 'fs/promises'\n\nconst execAsync = promisify(exec)\n\nconst TOOLS = [\n {\n name: 'make-laten-read',\n description: 'Read and compress a file (60-90% token savings)',\n inputSchema: {\n type: 'object',\n properties: {\n file_path: { type: 'string', description: 'Path to file' }\n },\n required: ['file_path']\n }\n },\n {\n name: 'make-laten-grep',\n description: 'Search code and return compressed grouped results',\n inputSchema: {\n type: 'object',\n properties: {\n pattern: { type: 'string', description: 'Search pattern' },\n path: { type: 'string', description: 'Directory to search', default: '.' }\n },\n required: ['pattern']\n }\n },\n {\n name: 'make-laten-git-diff',\n description: 'Compressed git diff output',\n inputSchema: {\n type: 'object',\n properties: {\n staged: { type: 'boolean', description: 'Show staged changes', default: false }\n }\n }\n },\n {\n name: 'make-laten-git-status',\n description: 'Compressed git status',\n inputSchema: { type: 'object', properties: {} }\n },\n {\n name: 'make-laten-cache-stats',\n description: 'Show cache performance stats',\n inputSchema: { type: 'object', properties: {} }\n }\n]\n\nfunction detectLanguage(filePath: string): string {\n const ext = filePath.split('.').pop()?.toLowerCase() || ''\n const map: Record<string, string> = {\n ts: 'typescript', tsx: 'typescript', js: 'javascript', jsx: 'javascript',\n py: 'python', rs: 'rust', go: 'go', java: 'java', rb: 'ruby',\n json: 'json', yaml: 'yaml', yml: 'yaml', md: 'markdown'\n }\n return map[ext] || 'text'\n}\n\nasync function handleRead(params: { file_path: string }) {\n const content = await fs.readFile(params.file_path, 'utf-8')\n const compressor = new FileReadCompressor()\n const result = await compressor.compress({\n content,\n filePath: params.file_path,\n language: detectLanguage(params.file_path)\n })\n return {\n content: [{ type: 'text', text: JSON.stringify({ compressed: result.content, savings: result.metadata.savings, confidence: result.confidence }) }]\n }\n}\n\nasync function handleGrep(params: { pattern: string; path?: string }) {\n const dir = params.path || '.'\n const { stdout } = await execAsync(`grep -rn \"${params.pattern}\" ${dir} 2>/dev/null || true`, { maxBuffer: 10 * 1024 * 1024 })\n\n if (!stdout.trim()) {\n return { content: [{ type: 'text', text: JSON.stringify({ matches: [], total: 0 }) }] }\n }\n\n const matches = stdout.split('\\n').filter(Boolean).map(line => {\n const parts = line.split(':')\n return { file: parts[0], line: parseInt(parts[1], 10) || 0, content: parts.slice(2).join(':').trim() }\n })\n\n const compressor = new GrepCompressor()\n const result = await compressor.compress({ results: matches, pattern: params.pattern, directory: dir })\n\n return { content: [{ type: 'text', text: JSON.stringify({ compressed: result.content, total: matches.length, savings: result.metadata.savings }) }] }\n}\n\nasync function handleGitDiff(params: { staged?: boolean }) {\n const flag = params.staged ? '--staged' : ''\n const { stdout } = await execAsync(`git diff ${flag}`, { maxBuffer: 10 * 1024 * 1024 })\n\n if (!stdout.trim()) {\n return { content: [{ type: 'text', text: JSON.stringify({ diff: '', changes: 0 }) }] }\n }\n\n const compressor = new GitDiffCompressor()\n const result = await compressor.compress({ diff: stdout })\n\n return { content: [{ type: 'text', text: JSON.stringify({ compressed: result.content, savings: result.metadata.savings }) }] }\n}\n\nasync function handleGitStatus() {\n const { stdout } = await execAsync('git status --porcelain')\n const lines = stdout.split('\\n').filter(Boolean)\n const files = lines.map(l => ({ status: l[0], path: l.slice(3) }))\n return { content: [{ type: 'text', text: JSON.stringify({ total: files.length, files }) }] }\n}\n\nasync function handleCacheStats() {\n return { content: [{ type: 'text', text: JSON.stringify({ message: 'Cache stats — use CLI: make-laten cache stats' }) }] }\n}\n\nconst handlers: Record<string, (params: any) => Promise<any>> = {\n 'make-laten-read': handleRead,\n 'make-laten-grep': handleGrep,\n 'make-laten-git-diff': handleGitDiff,\n 'make-laten-git-status': handleGitStatus,\n 'make-laten-cache-stats': handleCacheStats\n}\n\nlet requestId = 0\n\nfunction sendResponse(id: number, result: any) {\n const response = { jsonrpc: '2.0', id, result }\n process.stdout.write(JSON.stringify(response) + '\\n')\n}\n\nfunction sendError(id: number, code: number, message: string) {\n const response = { jsonrpc: '2.0', id, error: { code, message } }\n process.stdout.write(JSON.stringify(response) + '\\n')\n}\n\nasync function handleLine(line: string) {\n try {\n const request = JSON.parse(line)\n\n if (request.method === 'initialize') {\n sendResponse(request.id, {\n protocolVersion: '2024-11-05',\n capabilities: { tools: {} },\n serverInfo: { name: 'make-laten', version: '1.0.0' }\n })\n } else if (request.method === 'notifications/initialized') {\n // no response needed\n } else if (request.method === 'tools/list') {\n sendResponse(request.id, { tools: TOOLS })\n } else if (request.method === 'tools/call') {\n const { name, arguments: params } = request.params\n const handler = handlers[name]\n\n if (!handler) {\n sendError(request.id, -32601, `Unknown tool: ${name}`)\n return\n }\n\n try {\n const result = await handler(params || {})\n sendResponse(request.id, result)\n } catch (error: any) {\n sendError(request.id, -32000, error.message)\n }\n } else {\n sendError(request.id, -32601, `Method not found: ${request.method}`)\n }\n } catch (error: any) {\n process.stderr.write(`Error: ${error.message}\\n`)\n }\n}\n\nlet buffer = ''\n\nprocess.stdin.setEncoding('utf-8')\nprocess.stdin.on('data', async (chunk: string) => {\n buffer += chunk\n const lines = buffer.split('\\n')\n buffer = lines.pop() || ''\n\n for (const line of lines) {\n if (line.trim()) {\n await handleLine(line.trim())\n }\n }\n})\n\nprocess.stderr.write('make-laten MCP server started\\n')\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "make-laten",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "Universal efficiency toolkit for AI coding agents — compress, cache, route, and optimize token usage",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -13,7 +13,8 @@
13
13
  }
14
14
  },
15
15
  "bin": {
16
- "make-laten": "dist/cli/index.js"
16
+ "make-laten": "dist/cli/index.js",
17
+ "make-laten-mcp": "dist/mcp/server.js"
17
18
  },
18
19
  "directories": {
19
20
  "doc": "docs"
@@ -34,18 +35,25 @@
34
35
  "claude-code",
35
36
  "cursor",
36
37
  "codex",
38
+ "opencode",
39
+ "windsurf",
40
+ "cline",
41
+ "copilot",
42
+ "mcp",
37
43
  "efficiency",
38
44
  "cli",
39
45
  "tool"
40
46
  ],
41
- "author": "",
47
+ "author": "Sukirman",
42
48
  "license": "MIT",
43
49
  "repository": {
44
50
  "type": "git",
45
- "url": "https://github.com/make-laten/make-laten.git"
51
+ "url": "https://github.com/sukirman1901/make-laten.git"
46
52
  },
47
53
  "files": [
48
- "dist"
54
+ "dist",
55
+ "skills",
56
+ "shell"
49
57
  ],
50
58
  "engines": {
51
59
  "node": ">=18.0.0"
package/shell/init.sh ADDED
@@ -0,0 +1,62 @@
1
+ #!/bin/bash
2
+ # make-laten shell integration
3
+ # Add to ~/.bashrc or ~/.zshrc:
4
+ # source $(npm root -g)/make-laten/shell/init.sh
5
+
6
+ MAKE_LATEN_BIN="make-laten"
7
+
8
+ _make_laten_original_read() { command cat "$@" 2>/dev/null || command /bin/cat "$@"; }
9
+ _make_laten_original_grep() { command grep "$@"; }
10
+ _make_laten_original_git() { command git "$@"; }
11
+
12
+ ml_read() {
13
+ if [ -z "$MAKE_LATEN_QUIET" ]; then
14
+ $_MAKE_LATEN_BIN read "$@" 2>/dev/null || _make_laten_original_read "$@"
15
+ else
16
+ $_MAKE_LATEN_BIN read "$@"
17
+ fi
18
+ }
19
+
20
+ ml_grep() {
21
+ $_MAKE_LATEN_BIN grep "$@"
22
+ }
23
+
24
+ ml_git() {
25
+ if [ "$1" = "diff" ]; then
26
+ shift
27
+ $_MAKE_LATEN_BIN git diff "$@"
28
+ elif [ "$1" = "status" ]; then
29
+ $_MAKE_LATEN_BIN git status
30
+ else
31
+ _make_laten_original_git "$@"
32
+ fi
33
+ }
34
+
35
+ ml_search() {
36
+ $_MAKE_LATEN_BIN search "$@"
37
+ }
38
+
39
+ ml_fetch() {
40
+ $_MAKE_LATEN_BIN fetch "$@"
41
+ }
42
+
43
+ alias mread='ml_read'
44
+ alias mgrep='ml_grep'
45
+ alias mdiff='ml_git diff'
46
+ alias mstatus='ml_git status'
47
+ alias msearch='ml_search'
48
+ alias mfetch='ml_fetch'
49
+
50
+ make-laten-status() {
51
+ echo "make-laten shell integration active"
52
+ echo " mread <file> → compressed file read"
53
+ echo " mgrep <pattern> → grouped grep"
54
+ echo " mdiff → compressed git diff"
55
+ echo " mstatus → git status summary"
56
+ echo " msearch <query> → web search"
57
+ echo " mfetch <url> → web fetch + compress"
58
+ echo ""
59
+ $_MAKE_LATEN_BIN cache stats 2>/dev/null
60
+ }
61
+
62
+ echo "✓ make-laten shell loaded (aliases: mread, mgrep, mdiff, mstatus, msearch, mfetch)"
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: make-laten
3
+ description: Token optimization toolkit for AI coding agents — compress file reads, grep, git diff, web search/fetch, cache. Use when reading files, searching code, checking git status, or fetching web content to save 60-90% tokens.
4
+ ---
5
+
6
+ # make-laten Skill
7
+
8
+ Efficiency toolkit that compresses outputs to save tokens. Use CLI commands for all file/code/git/web operations.
9
+
10
+ ## When to Use
11
+
12
+ **ALWAYS use make-laten instead of raw tools when:**
13
+ - Reading files → `make-laten read <file>` (89% savings)
14
+ - Searching code → `make-laten grep <pattern>` (grouped by file)
15
+ - Git operations → `make-laten git diff` / `make-laten git status`
16
+ - Web search → `make-laten search <query>`
17
+ - Web fetch → `make-laten fetch <url>` (75% savings)
18
+
19
+ ## CLI Commands
20
+
21
+ ### File Read (89% savings)
22
+ ```bash
23
+ make-laten read <file-path>
24
+ ```
25
+ Returns compressed JSON with file summary, exports, classes, functions.
26
+
27
+ ### Grep (grouped by file)
28
+ ```bash
29
+ make-laten grep "<pattern>" [directory]
30
+ make-laten grep "TODO" src/
31
+ make-laten grep "export" . --ignore ts
32
+ ```
33
+
34
+ ### Git Operations
35
+ ```bash
36
+ make-laten git diff # unstaged changes
37
+ make-laten git diff --staged # staged changes
38
+ make-laten git status # status summary
39
+ ```
40
+
41
+ ### Web Search (via DuckDuckGo)
42
+ ```bash
43
+ make-laten search "query"
44
+ make-laten search "react hooks" --max 10
45
+ ```
46
+
47
+ ### Web Fetch + Compress
48
+ ```bash
49
+ make-laten fetch <url>
50
+ make-laten fetch https://docs.example.com
51
+ ```
52
+
53
+ ### Cache Management
54
+ ```bash
55
+ make-laten cache stats # show hit rate
56
+ make-laten cache clear # reset
57
+ ```
58
+
59
+ ## Tool Mapping
60
+
61
+ Replace native tools with make-laten equivalents:
62
+
63
+ | Instead of | Use |
64
+ |-----------|-----|
65
+ | `Read` tool | `make-laten read <file>` |
66
+ | `Grep` tool | `make-laten grep "<pattern>"` |
67
+ | `Bash` with `git diff` | `make-laten git diff` |
68
+ | `Bash` with `git status` | `make-laten git status` |
69
+ | `WebSearch` tool | `make-laten search "<query>"` |
70
+ | `WebFetch` tool | `make-laten fetch <url>` |
71
+
72
+ ## Output Format
73
+
74
+ All commands return JSON:
75
+ ```json
76
+ {
77
+ "compressed": "...",
78
+ "confidence": 1,
79
+ "metadata": { "savings": 0.89 }
80
+ }
81
+ ```
82
+
83
+ ## Integration
84
+
85
+ make-laten is installed globally. Works from any directory. No configuration needed.
86
+
87
+ ```bash
88
+ # Verify installation
89
+ make-laten --version
90
+
91
+ # Check adapter status
92
+ make-laten install --status
93
+ ```