make-laten 1.2.2 → 1.2.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.
@@ -475,14 +475,55 @@ var StrategyRouter = class {
475
475
  };
476
476
 
477
477
  // src/learn/pattern-miner.ts
478
+ import fs from "fs";
479
+ import path from "path";
480
+ var DATA_FILE = path.join(process.env.HOME || "~", ".make-laten", "patterns.json");
478
481
  var PatternMiner = class {
479
482
  operations = [];
480
483
  patterns = /* @__PURE__ */ new Map();
484
+ persistencePath;
485
+ lastPersist = 0;
486
+ constructor(options) {
487
+ this.persistencePath = options?.persistencePath || DATA_FILE;
488
+ this.loadFromDisk();
489
+ }
490
+ loadFromDisk() {
491
+ try {
492
+ if (fs.existsSync(this.persistencePath)) {
493
+ const data = JSON.parse(fs.readFileSync(this.persistencePath, "utf-8"));
494
+ if (Array.isArray(data.patterns)) {
495
+ for (const p of data.patterns) {
496
+ this.patterns.set(p.type, p);
497
+ }
498
+ }
499
+ if (Array.isArray(data.operations)) {
500
+ this.operations = data.operations.slice(-100);
501
+ }
502
+ }
503
+ } catch {
504
+ }
505
+ }
506
+ persistToDisk() {
507
+ const now = Date.now();
508
+ if (now - this.lastPersist < 5e3) return;
509
+ this.lastPersist = now;
510
+ try {
511
+ const dir = path.dirname(this.persistencePath);
512
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
513
+ fs.writeFileSync(this.persistencePath, JSON.stringify({
514
+ patterns: Array.from(this.patterns.values()),
515
+ operations: this.operations.slice(-100)
516
+ }, null, 2));
517
+ } catch {
518
+ }
519
+ }
481
520
  record(operation) {
482
521
  this.operations.push(operation);
522
+ if (this.operations.length > 100) this.operations.shift();
483
523
  if (operation.success) {
484
524
  this.updatePatterns(operation);
485
525
  }
526
+ this.persistToDisk();
486
527
  }
487
528
  getPatterns() {
488
529
  return Array.from(this.patterns.values());
@@ -509,8 +550,43 @@ var PatternMiner = class {
509
550
  };
510
551
 
511
552
  // src/learn/failure-learner.ts
553
+ import fs2 from "fs";
554
+ import path2 from "path";
555
+ var DATA_FILE2 = path2.join(process.env.HOME || "~", ".make-laten", "failures.json");
512
556
  var FailureLearner = class {
513
557
  failures = /* @__PURE__ */ new Map();
558
+ persistencePath;
559
+ lastPersist = 0;
560
+ constructor(options) {
561
+ this.persistencePath = options?.persistencePath || DATA_FILE2;
562
+ this.loadFromDisk();
563
+ }
564
+ loadFromDisk() {
565
+ try {
566
+ if (fs2.existsSync(this.persistencePath)) {
567
+ const data = JSON.parse(fs2.readFileSync(this.persistencePath, "utf-8"));
568
+ if (Array.isArray(data.failures)) {
569
+ for (const f of data.failures) {
570
+ this.failures.set(`${f.type}:${f.error}`, f);
571
+ }
572
+ }
573
+ }
574
+ } catch {
575
+ }
576
+ }
577
+ persistToDisk() {
578
+ const now = Date.now();
579
+ if (now - this.lastPersist < 5e3) return;
580
+ this.lastPersist = now;
581
+ try {
582
+ const dir = path2.dirname(this.persistencePath);
583
+ if (!fs2.existsSync(dir)) fs2.mkdirSync(dir, { recursive: true });
584
+ fs2.writeFileSync(this.persistencePath, JSON.stringify({
585
+ failures: Array.from(this.failures.values())
586
+ }, null, 2));
587
+ } catch {
588
+ }
589
+ }
514
590
  record(failure) {
515
591
  const key = `${failure.type}:${failure.error}`;
516
592
  const existing = this.failures.get(key);
@@ -524,6 +600,7 @@ var FailureLearner = class {
524
600
  count: 1
525
601
  });
526
602
  }
603
+ this.persistToDisk();
527
604
  }
528
605
  getFailures() {
529
606
  return Array.from(this.failures.values());
@@ -550,32 +627,95 @@ var FailureLearner = class {
550
627
  };
551
628
 
552
629
  // src/correct/auto-correct.ts
630
+ import fs3 from "fs";
631
+ import path3 from "path";
632
+ var DEFAULT_RULES = [
633
+ // Common typos
634
+ { name: "typo-teh", description: "Common typo", pattern: "teh", replacement: "the" },
635
+ { name: "typo-adn", description: "Common typo", pattern: "adn", replacement: "and" },
636
+ { name: "typo-fo", description: "Common typo", pattern: " fo ", replacement: " of " },
637
+ { name: "typo-ot", description: "Common typo", pattern: " ot ", replacement: " to " },
638
+ { name: "typo-isnt", description: "Common typo", pattern: "isnt", replacement: "isn't" },
639
+ { name: "typo-dont", description: "Common typo", pattern: "dont", replacement: "don't" },
640
+ { name: "typo-cant", description: "Common typo", pattern: "cant", replacement: "can't" },
641
+ { name: "typo-wont", description: "Common typo", pattern: "wont", replacement: "won't" },
642
+ { name: "typo-youre", description: "Common typo", pattern: "youre", replacement: "you're" },
643
+ { name: "typo-its", description: "Common typo", pattern: "its a", replacement: "it's a" },
644
+ // Code patterns
645
+ { name: "code-console-log", description: "Remove console.log", pattern: /console\.log\([^)]*\);?\n?/g, replacement: "" },
646
+ { name: "code-debugger", description: "Remove debugger", pattern: /debugger;?\n?/g, replacement: "" },
647
+ { name: "code-var-let", description: "var to let", pattern: /\bvar\b/g, replacement: "let" },
648
+ // Markdown
649
+ { name: "md-double-space", description: "Double space to single", pattern: " ", replacement: " " }
650
+ ];
651
+ var DATA_FILE3 = path3.join(process.env.HOME || "~", ".make-laten", "corrections.json");
553
652
  var AutoCorrect = class {
554
- rules = [];
653
+ rules;
555
654
  corrections = [];
556
655
  appliedCount = 0;
656
+ persistencePath;
657
+ constructor(options) {
658
+ this.persistencePath = options?.persistencePath || DATA_FILE3;
659
+ this.rules = [...DEFAULT_RULES];
660
+ this.loadPersistedRules();
661
+ }
662
+ loadPersistedRules() {
663
+ try {
664
+ if (fs3.existsSync(this.persistencePath)) {
665
+ const data = JSON.parse(fs3.readFileSync(this.persistencePath, "utf-8"));
666
+ if (Array.isArray(data.customRules)) {
667
+ this.rules.push(...data.customRules);
668
+ }
669
+ }
670
+ } catch {
671
+ }
672
+ }
673
+ persistRules() {
674
+ try {
675
+ const dir = path3.dirname(this.persistencePath);
676
+ if (!fs3.existsSync(dir)) fs3.mkdirSync(dir, { recursive: true });
677
+ const existing = this.loadExistingData();
678
+ existing.customRules = this.rules.filter((r) => !DEFAULT_RULES.includes(r));
679
+ fs3.writeFileSync(this.persistencePath, JSON.stringify(existing, null, 2));
680
+ } catch {
681
+ }
682
+ }
683
+ loadExistingData() {
684
+ try {
685
+ if (fs3.existsSync(this.persistencePath)) {
686
+ return JSON.parse(fs3.readFileSync(this.persistencePath, "utf-8"));
687
+ }
688
+ } catch {
689
+ }
690
+ return { customRules: [] };
691
+ }
557
692
  addRule(rule) {
558
693
  this.rules.push(rule);
694
+ this.persistRules();
559
695
  }
560
696
  getRules() {
561
697
  return this.rules;
562
698
  }
563
699
  correct(input) {
564
700
  let output = input;
701
+ let changed = false;
565
702
  for (const rule of this.rules) {
566
703
  if (typeof rule.pattern === "string") {
567
704
  if (output.includes(rule.pattern)) {
568
705
  output = output.split(rule.pattern).join(rule.replacement);
569
- this.recordCorrection(input, output, rule.name);
706
+ changed = true;
570
707
  }
571
708
  } else {
572
709
  const matches = output.match(rule.pattern);
573
710
  if (matches) {
574
711
  output = output.replace(rule.pattern, rule.replacement);
575
- this.recordCorrection(input, output, rule.name);
712
+ changed = true;
576
713
  }
577
714
  }
578
715
  }
716
+ if (changed) {
717
+ this.recordCorrection(input, output, "auto");
718
+ }
579
719
  return output;
580
720
  }
581
721
  getStats() {
@@ -959,7 +1099,7 @@ function extractSimpleTitle(html) {
959
1099
  // src/mcp/server.ts
960
1100
  import { exec } from "child_process";
961
1101
  import { promisify } from "util";
962
- import fs from "fs/promises";
1102
+ import fs4 from "fs/promises";
963
1103
  var execAsync = promisify(exec);
964
1104
  var sessionCache = new SessionCache();
965
1105
  var toolRouter = new ToolRouter();
@@ -1069,17 +1209,17 @@ var TOOLS = [
1069
1209
  // Learn Layer
1070
1210
  {
1071
1211
  name: "make-laten-patterns",
1072
- description: "Get learned patterns from usage",
1212
+ description: "Get learned patterns from usage (persisted across sessions)",
1073
1213
  inputSchema: { type: "object", properties: {} }
1074
1214
  },
1075
1215
  {
1076
1216
  name: "make-laten-failures",
1077
- description: "Get failure records and suggestions",
1217
+ description: "Get failure records and suggestions (persisted across sessions)",
1078
1218
  inputSchema: { type: "object", properties: {} }
1079
1219
  },
1080
1220
  {
1081
1221
  name: "make-laten-suggestions",
1082
- description: "Get suggestions based on learned patterns",
1222
+ description: "Get suggestions based on learned patterns and failures",
1083
1223
  inputSchema: {
1084
1224
  type: "object",
1085
1225
  properties: {
@@ -1090,7 +1230,7 @@ var TOOLS = [
1090
1230
  // Correct Layer
1091
1231
  {
1092
1232
  name: "make-laten-correct",
1093
- description: "Apply auto-corrections to text",
1233
+ description: "Apply auto-corrections to text (11 built-in rules + custom rules)",
1094
1234
  inputSchema: {
1095
1235
  type: "object",
1096
1236
  properties: {
@@ -1151,7 +1291,7 @@ function detectLanguage(filePath) {
1151
1291
  return map[ext] || "text";
1152
1292
  }
1153
1293
  async function handleRead(params) {
1154
- const content = await fs.readFile(params.file_path, "utf-8");
1294
+ const content = await fs4.readFile(params.file_path, "utf-8");
1155
1295
  const compressor = new FileReadCompressor();
1156
1296
  const result = await compressor.compress({
1157
1297
  content,
@@ -1293,7 +1433,7 @@ async function handleLine(line) {
1293
1433
  sendResponse(request.id, {
1294
1434
  protocolVersion: "2024-11-05",
1295
1435
  capabilities: { tools: {} },
1296
- serverInfo: { name: "make-laten", version: "1.2.0" }
1436
+ serverInfo: { name: "make-laten", version: "1.3.0" }
1297
1437
  });
1298
1438
  } else if (request.method === "notifications/initialized") {
1299
1439
  } else if (request.method === "tools/list") {