make-laten 1.1.1 → 1.2.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/dist/index.js CHANGED
@@ -43,6 +43,7 @@ __export(index_exports, {
43
43
  FileReadCompressor: () => FileReadCompressor,
44
44
  GeminiCliAdapter: () => GeminiCliAdapter,
45
45
  GitDiffCompressor: () => GitDiffCompressor,
46
+ GitStatusCompressor: () => GitStatusCompressor,
46
47
  GrepCompressor: () => GrepCompressor,
47
48
  HookAdapter: () => HookAdapter,
48
49
  Installer: () => Installer,
@@ -77,13 +78,25 @@ __export(index_exports, {
77
78
  createRouter: () => createRouter,
78
79
  createRulesAdapter: () => createRulesAdapter,
79
80
  createToolRegistry: () => createToolRegistry,
81
+ extractClassMethods: () => extractClassMethods,
82
+ extractExports: () => extractExports,
83
+ extractFunctionSignatures: () => extractFunctionSignatures,
80
84
  extractSemantic: () => extractSemantic,
85
+ extractTypeDefinitions: () => extractTypeDefinitions,
81
86
  getAdapter: () => getAdapter,
82
87
  getAdapters: () => getAdapters,
83
88
  getSemanticTools: () => getSemanticTools,
84
89
  makeLatenCache: () => makeLatenCache,
90
+ preserveContext: () => preserveContext,
85
91
  registerAdapter: () => registerAdapter,
86
- selectBackend: () => selectBackend
92
+ selectBackend: () => selectBackend,
93
+ smartTruncate: () => smartTruncate,
94
+ stripAll: () => stripAll,
95
+ stripBlankLines: () => stripBlankLines,
96
+ stripComments: () => stripComments,
97
+ stripImports: () => stripImports,
98
+ stripWhitespace: () => stripWhitespace,
99
+ truncateByTokens: () => truncateByTokens
87
100
  });
88
101
  module.exports = __toCommonJS(index_exports);
89
102
 
@@ -269,29 +282,157 @@ function isKnownPattern(content) {
269
282
  return patterns.some((p) => p.test(content));
270
283
  }
271
284
 
285
+ // src/compress/strip.ts
286
+ function stripImports(content) {
287
+ return content.replace(/^import\s+[\s\S]*?from\s+['"][^'"]+['"]\s*;?\s*$/gm, "").replace(/^import\s+['"][^'"]+['"]\s*;?\s*$/gm, "").replace(/^import\s+\{[^}]*\}\s+from\s+['"][^'"]+['"]\s*;?\s*$/gm, "").split("\n").filter((l) => l.trim() !== "").join("\n");
288
+ }
289
+ function stripComments(content) {
290
+ let result = content.replace(/(?<!["'`])\/\/.*$/gm, "");
291
+ result = result.replace(/\/\*[\s\S]*?\*\//g, "");
292
+ return result.split("\n").filter((l) => l.trim() !== "").join("\n");
293
+ }
294
+ function stripBlankLines(content) {
295
+ return content.replace(/\n{3,}/g, "\n\n");
296
+ }
297
+ function stripWhitespace(content) {
298
+ return content.replace(/[ \t]+$/gm, "");
299
+ }
300
+ function stripAll(content) {
301
+ let result = content;
302
+ result = stripImports(result);
303
+ result = stripComments(result);
304
+ result = stripBlankLines(result);
305
+ result = stripWhitespace(result);
306
+ return result.trim();
307
+ }
308
+
309
+ // src/compress/structure.ts
310
+ function extractExports(content) {
311
+ const lines = content.split("\n");
312
+ const exports2 = [];
313
+ for (const line of lines) {
314
+ const trimmed = line.trim();
315
+ if (/^export\s+(default\s+)?/.test(trimmed)) {
316
+ if (trimmed.includes("{") && !trimmed.includes("}")) {
317
+ exports2.push(trimmed.replace(/\{[\s\S]*$/, "{ ... }"));
318
+ } else {
319
+ exports2.push(trimmed);
320
+ }
321
+ }
322
+ }
323
+ return exports2.join("\n");
324
+ }
325
+ function extractClassMethods(content) {
326
+ const classRegex = /class\s+\w+[^{]*\{([\s\S]*?)\n\}/g;
327
+ const methods = [];
328
+ let match;
329
+ while ((match = classRegex.exec(content)) !== null) {
330
+ const classBody = match[1];
331
+ const methodRegex = /(^\s*(?:public|private|protected|static|async|abstract|\s)*\w+\s*\([^)]*\)(?:\s*:\s*[^{]+)?)\s*\{/gm;
332
+ let methodMatch;
333
+ while ((methodMatch = methodRegex.exec(classBody)) !== null) {
334
+ methods.push(methodMatch[1].trim());
335
+ }
336
+ }
337
+ return methods.join("\n");
338
+ }
339
+ function extractFunctionSignatures(content) {
340
+ const funcRegex = /(export\s+)?(async\s+)?function\s+\w+\s*\([^)]*\)(?:\s*:\s*[^{]+)?\s*\{/g;
341
+ const signatures = [];
342
+ let match;
343
+ while ((match = funcRegex.exec(content)) !== null) {
344
+ signatures.push(match[0].replace(/\{$/, ""));
345
+ }
346
+ return signatures.join("\n");
347
+ }
348
+ function extractTypeDefinitions(content) {
349
+ const typeRegex = /(export\s+)?(interface|type)\s+\w+[^{]*\{[^}]*\}|(export\s+)?type\s+\w+\s*=[^;]+;?/g;
350
+ const types = [];
351
+ let match;
352
+ while ((match = typeRegex.exec(content)) !== null) {
353
+ types.push(match[0].trim());
354
+ }
355
+ return types.join("\n");
356
+ }
357
+
358
+ // src/compress/truncate.ts
359
+ function smartTruncate(content, maxTokens) {
360
+ const lines = content.split("\n");
361
+ const estimatedTokens = Math.ceil(content.length / 4);
362
+ if (estimatedTokens <= maxTokens) return content;
363
+ const targetLines = Math.round(maxTokens * 4 / (content.length / lines.length));
364
+ const headerLines = Math.floor(targetLines * 0.3);
365
+ const footerLines = Math.floor(targetLines * 0.3);
366
+ const omitted = lines.length - headerLines - footerLines;
367
+ const header = lines.slice(0, headerLines);
368
+ const footer = lines.slice(-footerLines);
369
+ return [...header, `
370
+ ... [${omitted} lines omitted] ...
371
+ `, ...footer].join("\n");
372
+ }
373
+ function truncateByTokens(text, maxTokens) {
374
+ const maxChars = maxTokens * 4;
375
+ if (text.length <= maxChars) return text;
376
+ const truncated = text.slice(0, maxChars);
377
+ const lastNewline = truncated.lastIndexOf("\n");
378
+ return truncated.slice(0, lastNewline > 0 ? lastNewline : maxChars) + "\n\n... (truncated)";
379
+ }
380
+ function preserveContext(lines, targetIndex, before, after) {
381
+ const start = Math.max(0, targetIndex - before);
382
+ const end = Math.min(lines.length, targetIndex + after + 1);
383
+ return lines.slice(start, end);
384
+ }
385
+
272
386
  // src/compress/file-read.ts
273
387
  var FileReadCompressor = class {
274
388
  async compress(input) {
275
389
  const { content, filePath, language } = input;
276
- const signatures = this.extractSignatures(content, language);
277
- const exports2 = this.extractExports(content);
278
- const lines = [
390
+ const lines = content.split("\n").length;
391
+ const tokens = Math.ceil(content.length / 4);
392
+ if (tokens < 200) {
393
+ return {
394
+ content,
395
+ original: content,
396
+ confidence: 1,
397
+ metadata: {
398
+ strategy: "passthrough",
399
+ originalLines: lines,
400
+ compressedLines: lines,
401
+ savings: 0
402
+ }
403
+ };
404
+ }
405
+ const stripped = stripAll(content);
406
+ const exports2 = extractExports(stripped);
407
+ const classes = extractClassMethods(stripped);
408
+ const functions = extractFunctionSignatures(stripped);
409
+ const types = extractTypeDefinitions(stripped);
410
+ const sections = [
279
411
  `// ${filePath} (${content.split("\n").length} lines)`,
280
412
  "",
281
- ...signatures,
282
- "",
283
413
  "// Exports:",
284
- ...exports2
285
- ];
286
- const compressed = lines.join("\n");
414
+ exports2,
415
+ "",
416
+ "// Classes:",
417
+ classes,
418
+ "",
419
+ "// Functions:",
420
+ functions,
421
+ "",
422
+ "// Types:",
423
+ types
424
+ ].filter((l) => l !== "" && !l.endsWith(":"));
425
+ let compressed = sections.join("\n");
426
+ const maxTokens = 2e3;
427
+ compressed = smartTruncate(compressed, maxTokens);
287
428
  return {
288
429
  content: compressed,
289
430
  original: content,
290
431
  confidence: calculateConfidence(content, compressed),
291
432
  metadata: {
292
- strategy: "signatures",
433
+ strategy: "hybrid",
293
434
  originalLines: content.split("\n").length,
294
- compressedLines: lines.length,
435
+ compressedLines: compressed.split("\n").length,
295
436
  savings: 1 - compressed.length / content.length
296
437
  }
297
438
  };
@@ -299,50 +440,27 @@ var FileReadCompressor = class {
299
440
  async decompress(compressed) {
300
441
  return compressed.original;
301
442
  }
302
- extractSignatures(content, language) {
303
- const signatures = [];
304
- const lines = content.split("\n");
305
- for (const line of lines) {
306
- const trimmed = line.trim();
307
- if (/^(export\s+)?(async\s+)?function\s+\w+/.test(trimmed)) {
308
- signatures.push(trimmed.replace(/\{[\s\S]*$/, "{ ... }"));
309
- }
310
- if (/^(export\s+)?class\s+\w+/.test(trimmed)) {
311
- signatures.push(trimmed);
312
- }
313
- if (/^(export\s+)?(type|interface)\s+\w+/.test(trimmed)) {
314
- signatures.push(trimmed);
315
- }
316
- }
317
- return signatures;
318
- }
319
- extractExports(content) {
320
- const exports2 = [];
321
- const exportRegex = /export\s+(default\s+)?(function|class|const|let|var|type|interface)\s+(\w+)/g;
322
- let match;
323
- while ((match = exportRegex.exec(content)) !== null) {
324
- exports2.push(` - ${match[3]} (${match[2]})`);
325
- }
326
- return exports2;
327
- }
328
443
  };
329
444
 
330
445
  // src/compress/git-diff.ts
331
446
  var GitDiffCompressor = class {
332
447
  async compress(input) {
333
448
  const { diff } = input;
334
- const hunks = this.parseDiff(diff);
335
- const condensed = hunks.map((hunk) => ({
336
- file: hunk.file,
337
- changes: this.condenseHunk(hunk),
338
- stats: { additions: hunk.additions, deletions: hunk.deletions }
339
- }));
449
+ const files = this.parseDiff(diff);
340
450
  const lines = [];
341
- for (const hunk of condensed) {
342
- if (hunk.changes.length > 0) {
343
- lines.push(`${hunk.file} (+${hunk.stats.additions} -${hunk.stats.deletions})`);
344
- lines.push(...hunk.changes);
451
+ const totalAdd = files.reduce((s, f) => s + f.additions, 0);
452
+ const totalDel = files.reduce((s, f) => s + f.deletions, 0);
453
+ lines.push(`# ${files.length} files changed: +${totalAdd} -${totalDel}`);
454
+ lines.push("");
455
+ for (const file of files) {
456
+ lines.push(`${file.path} (+${file.additions} -${file.deletions})`);
457
+ const changes = file.lines.filter((l) => l.type === "add" || l.type === "del").map((l) => `${l.type === "add" ? "+" : "-"}${l.content}`);
458
+ const limited = changes.slice(0, 20);
459
+ lines.push(...limited);
460
+ if (changes.length > 20) {
461
+ lines.push(`... [${changes.length - 20} more changes]`);
345
462
  }
463
+ lines.push("");
346
464
  }
347
465
  const compressed = lines.join("\n");
348
466
  return {
@@ -351,7 +469,7 @@ var GitDiffCompressor = class {
351
469
  confidence: calculateConfidence(diff, compressed),
352
470
  metadata: {
353
471
  strategy: "condensed",
354
- filesChanged: condensed.length,
472
+ filesChanged: files.length,
355
473
  savings: 1 - compressed.length / diff.length
356
474
  }
357
475
  };
@@ -360,34 +478,123 @@ var GitDiffCompressor = class {
360
478
  return compressed.original;
361
479
  }
362
480
  parseDiff(diff) {
363
- const hunks = [];
481
+ const files = [];
364
482
  const lines = diff.split("\n");
365
- let currentHunk = null;
483
+ let current = null;
366
484
  for (const line of lines) {
367
485
  if (line.startsWith("diff --git")) {
368
- if (currentHunk) hunks.push(currentHunk);
369
- const fileMatch = line.match(/b\/(.+)/);
370
- currentHunk = {
371
- file: fileMatch?.[1] || "unknown",
372
- lines: [],
486
+ if (current) files.push(current);
487
+ const match = line.match(/b\/(.+)/);
488
+ current = {
489
+ path: match?.[1] || "unknown",
373
490
  additions: 0,
374
- deletions: 0
491
+ deletions: 0,
492
+ lines: []
375
493
  };
376
- } else if (currentHunk) {
494
+ } else if (current) {
377
495
  if (line.startsWith("+")) {
378
- currentHunk.additions++;
379
- currentHunk.lines.push({ type: "addition", content: line.slice(1) });
496
+ current.additions++;
497
+ current.lines.push({ type: "add", content: line.slice(1) });
380
498
  } else if (line.startsWith("-")) {
381
- currentHunk.deletions++;
382
- currentHunk.lines.push({ type: "deletion", content: line.slice(1) });
499
+ current.deletions++;
500
+ current.lines.push({ type: "del", content: line.slice(1) });
383
501
  }
384
502
  }
385
503
  }
386
- if (currentHunk) hunks.push(currentHunk);
387
- return hunks;
504
+ if (current) files.push(current);
505
+ return files;
388
506
  }
389
- condenseHunk(hunk) {
390
- return hunk.lines.filter((l) => l.type === "addition" || l.type === "deletion").map((l) => `${l.type === "addition" ? "+" : "-"} ${l.content}`);
507
+ };
508
+
509
+ // src/compress/git-status.ts
510
+ var GitStatusCompressor = class {
511
+ async compress(input) {
512
+ const { status } = input;
513
+ const statusLines = status.split("\n").filter(Boolean).length;
514
+ const tokens = Math.ceil(status.length / 4);
515
+ if (tokens < 10) {
516
+ return {
517
+ content: status,
518
+ original: status,
519
+ confidence: 1,
520
+ metadata: {
521
+ strategy: "passthrough",
522
+ totalFiles: statusLines,
523
+ savings: 0
524
+ }
525
+ };
526
+ }
527
+ const files = this.parseStatus(status);
528
+ const grouped = this.groupByStatus(files);
529
+ const lines = [];
530
+ for (const [statusType, statusFiles] of grouped) {
531
+ const label = this.statusLabel(statusType);
532
+ lines.push(`${label} (${statusFiles.length})`);
533
+ const compressed2 = this.compressPaths(statusFiles.map((f) => f.path));
534
+ lines.push(...compressed2);
535
+ lines.push("");
536
+ }
537
+ const compressed = lines.join("\n");
538
+ return {
539
+ content: compressed,
540
+ original: status,
541
+ confidence: calculateConfidence(status, compressed),
542
+ metadata: {
543
+ strategy: "grouped",
544
+ totalFiles: files.length,
545
+ savings: 1 - compressed.length / status.length
546
+ }
547
+ };
548
+ }
549
+ async decompress(compressed) {
550
+ return compressed.original;
551
+ }
552
+ parseStatus(status) {
553
+ return status.split("\n").filter(Boolean).map((line) => {
554
+ const match = line.match(/^(\?\?|[MADRC]+\s+)(.+)$/);
555
+ if (match) {
556
+ return { status: match[1].trim(), path: match[2] };
557
+ }
558
+ return { status: line[0], path: line.slice(3) };
559
+ });
560
+ }
561
+ groupByStatus(files) {
562
+ const grouped = /* @__PURE__ */ new Map();
563
+ for (const file of files) {
564
+ const existing = grouped.get(file.status) || [];
565
+ existing.push(file);
566
+ grouped.set(file.status, existing);
567
+ }
568
+ return grouped;
569
+ }
570
+ statusLabel(status) {
571
+ const labels = {
572
+ "M": "Modified",
573
+ "A": "Added",
574
+ "D": "Deleted",
575
+ "??": "Untracked",
576
+ "R": "Renamed"
577
+ };
578
+ return labels[status] || `Status ${status}`;
579
+ }
580
+ compressPaths(paths) {
581
+ if (paths.length <= 3) return paths.map((p) => ` ${p}`);
582
+ const parts = paths.map((p) => p.split("/"));
583
+ const minLength = Math.min(...parts.map((p) => p.length));
584
+ let commonIndex = 0;
585
+ for (let i = 0; i < minLength; i++) {
586
+ if (parts.every((p) => p[i] === parts[0][i])) {
587
+ commonIndex = i;
588
+ } else {
589
+ break;
590
+ }
591
+ }
592
+ if (commonIndex > 0) {
593
+ const prefix = parts[0].slice(0, commonIndex).join("/");
594
+ const suffixes = paths.map((p) => p.slice(prefix.length + 1));
595
+ return [` ${prefix}/`, ...suffixes.map((s) => ` ${s}`)];
596
+ }
597
+ return paths.map((p) => ` ${p}`);
391
598
  }
392
599
  };
393
600
 
@@ -2120,7 +2327,7 @@ function compressWebContent(semantic, options = {}) {
2120
2327
  let result = lines.join("\n");
2121
2328
  const estimatedTokens = estimateTokens(result);
2122
2329
  if (estimatedTokens > maxTokens) {
2123
- result = truncateByTokens(result, maxTokens);
2330
+ result = truncateByTokens2(result, maxTokens);
2124
2331
  }
2125
2332
  return result;
2126
2333
  }
@@ -2136,7 +2343,7 @@ function truncateContent(content, maxLength) {
2136
2343
  function estimateTokens(text) {
2137
2344
  return Math.ceil(text.length / 4);
2138
2345
  }
2139
- function truncateByTokens(text, maxTokens) {
2346
+ function truncateByTokens2(text, maxTokens) {
2140
2347
  const maxChars = maxTokens * 4;
2141
2348
  if (text.length <= maxChars) return text;
2142
2349
  const truncated = text.slice(0, maxChars);
@@ -2274,6 +2481,7 @@ var VERSION = "0.1.0";
2274
2481
  FileReadCompressor,
2275
2482
  GeminiCliAdapter,
2276
2483
  GitDiffCompressor,
2484
+ GitStatusCompressor,
2277
2485
  GrepCompressor,
2278
2486
  HookAdapter,
2279
2487
  Installer,
@@ -2308,12 +2516,24 @@ var VERSION = "0.1.0";
2308
2516
  createRouter,
2309
2517
  createRulesAdapter,
2310
2518
  createToolRegistry,
2519
+ extractClassMethods,
2520
+ extractExports,
2521
+ extractFunctionSignatures,
2311
2522
  extractSemantic,
2523
+ extractTypeDefinitions,
2312
2524
  getAdapter,
2313
2525
  getAdapters,
2314
2526
  getSemanticTools,
2315
2527
  makeLatenCache,
2528
+ preserveContext,
2316
2529
  registerAdapter,
2317
- selectBackend
2530
+ selectBackend,
2531
+ smartTruncate,
2532
+ stripAll,
2533
+ stripBlankLines,
2534
+ stripComments,
2535
+ stripImports,
2536
+ stripWhitespace,
2537
+ truncateByTokens
2318
2538
  });
2319
2539
  //# sourceMappingURL=index.js.map