encoding-aware-fs 0.1.1 → 0.1.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.
package/dist/index.js CHANGED
@@ -26539,6 +26539,10 @@ var init_config_io = __esm({
26539
26539
  // src/uninstaller.ts
26540
26540
  var uninstaller_exports = {};
26541
26541
  __export(uninstaller_exports, {
26542
+ detectInstalled: () => detectInstalled,
26543
+ isOpenCodeJsoncEmpty: () => isOpenCodeJsoncEmpty,
26544
+ removeOpenCodeConfig: () => removeOpenCodeConfig,
26545
+ removeRuleFile: () => removeRuleFile,
26542
26546
  runUninstaller: () => runUninstaller
26543
26547
  });
26544
26548
  async function fileExists(filePath) {
@@ -26561,8 +26565,18 @@ async function removeDirIfEmpty(dirPath) {
26561
26565
  function isEmptyMcpJson(data) {
26562
26566
  return data && typeof data === "object" && data.mcpServers && typeof data.mcpServers === "object" && Object.keys(data.mcpServers).length === 0 && Object.keys(data).length === 1;
26563
26567
  }
26564
- function isEmptyOpenCodeJsonc(data) {
26565
- return data && typeof data === "object" && data.mcp && typeof data.mcp === "object" && Object.keys(data.mcp).length === 0 && Object.keys(data).length === 1;
26568
+ function isOpenCodeJsoncEmpty(data) {
26569
+ if (!data || typeof data !== "object")
26570
+ return false;
26571
+ const keys = Object.keys(data);
26572
+ return keys.every((key) => {
26573
+ const val = data[key];
26574
+ if (Array.isArray(val))
26575
+ return val.length === 0;
26576
+ if (typeof val === "object" && val !== null)
26577
+ return Object.keys(val).length === 0;
26578
+ return false;
26579
+ });
26566
26580
  }
26567
26581
  async function detectInstalled(cwd) {
26568
26582
  const found = [];
@@ -26570,24 +26584,31 @@ async function detectInstalled(cwd) {
26570
26584
  const mcpJson = await readJsonFile(mcpJsonPath);
26571
26585
  const claudeSkillPath = path5.join(cwd, ".claude", "skills", "encoding-aware-fs", "SKILL.md");
26572
26586
  const hasClaudeSkill = await fileExists(claudeSkillPath);
26573
- if (mcpJson?.mcpServers?.["encoding-aware-fs"] || hasClaudeSkill) {
26587
+ const claudeRulePath = path5.join(cwd, ".claude", "rules", "encoding-aware-fs.md");
26588
+ const hasClaudeRule = await fileExists(claudeRulePath);
26589
+ if (mcpJson?.mcpServers?.["encoding-aware-fs"] || hasClaudeSkill || hasClaudeRule) {
26574
26590
  found.push({
26575
26591
  type: "claude-code",
26576
26592
  name: "Claude Code (.mcp.json)",
26577
26593
  configPath: mcpJsonPath,
26578
- skillPath: hasClaudeSkill ? claudeSkillPath : void 0
26594
+ skillPath: hasClaudeSkill ? claudeSkillPath : void 0,
26595
+ rulePath: hasClaudeRule ? claudeRulePath : void 0
26579
26596
  });
26580
26597
  }
26581
26598
  const openCodePath = path5.join(cwd, "opencode.jsonc");
26582
26599
  const openCode = await readJsonFile(openCodePath);
26583
26600
  const openCodeSkillPath = path5.join(cwd, ".agents", "skills", "encoding-aware-fs", "SKILL.md");
26584
26601
  const hasOpenCodeSkill = await fileExists(openCodeSkillPath);
26585
- if (openCode?.mcp?.["encoding-aware-fs"] || hasOpenCodeSkill) {
26602
+ const openCodeRulePath = path5.join(cwd, ".agents", "rules", "encoding-aware-fs.md");
26603
+ const hasOpenCodeRule = await fileExists(openCodeRulePath);
26604
+ const hasOpenCodeInstructions = Array.isArray(openCode?.instructions) && openCode.instructions.includes(".agents/rules/encoding-aware-fs.md");
26605
+ if (openCode?.mcp?.["encoding-aware-fs"] || hasOpenCodeSkill || hasOpenCodeRule || hasOpenCodeInstructions) {
26586
26606
  found.push({
26587
26607
  type: "opencode",
26588
26608
  name: "OpenCode (opencode.jsonc)",
26589
26609
  configPath: openCodePath,
26590
- skillPath: hasOpenCodeSkill ? openCodeSkillPath : void 0
26610
+ skillPath: hasOpenCodeSkill ? openCodeSkillPath : void 0,
26611
+ rulePath: hasOpenCodeRule ? openCodeRulePath : void 0
26591
26612
  });
26592
26613
  }
26593
26614
  return found;
@@ -26605,17 +26626,28 @@ async function removeClaudeCodeEntry(configPath) {
26605
26626
  console.log(` \u2713 Removed encoding-aware-fs entry from ${configPath}`);
26606
26627
  }
26607
26628
  }
26608
- async function removeOpenCodeEntry(configPath) {
26629
+ async function removeOpenCodeConfig(configPath) {
26609
26630
  const data = await readJsonFile(configPath);
26610
- if (!data?.mcp?.["encoding-aware-fs"])
26631
+ if (!data)
26611
26632
  return;
26612
- delete data.mcp["encoding-aware-fs"];
26613
- if (isEmptyOpenCodeJsonc(data)) {
26633
+ if (data.mcp?.["encoding-aware-fs"]) {
26634
+ delete data.mcp["encoding-aware-fs"];
26635
+ if (Object.keys(data.mcp).length === 0)
26636
+ delete data.mcp;
26637
+ }
26638
+ if (Array.isArray(data.instructions)) {
26639
+ data.instructions = data.instructions.filter(
26640
+ (i) => i !== ".agents/rules/encoding-aware-fs.md"
26641
+ );
26642
+ if (data.instructions.length === 0)
26643
+ delete data.instructions;
26644
+ }
26645
+ if (isOpenCodeJsoncEmpty(data) || Object.keys(data).length === 0) {
26614
26646
  await fs9.unlink(configPath);
26615
26647
  console.log(` \u2713 Removed ${configPath} (was empty after cleanup)`);
26616
26648
  } else {
26617
26649
  await writeJsonFile(configPath, data);
26618
- console.log(` \u2713 Removed encoding-aware-fs entry from ${configPath}`);
26650
+ console.log(` \u2713 Removed encoding-aware-fs entries from ${configPath}`);
26619
26651
  }
26620
26652
  }
26621
26653
  async function removeSkillFiles(platform) {
@@ -26636,6 +26668,22 @@ async function removeSkillFiles(platform) {
26636
26668
  const parentDir = path5.dirname(skillsDir);
26637
26669
  await removeDirIfEmpty(parentDir);
26638
26670
  }
26671
+ async function removeRuleFile(platform) {
26672
+ if (!platform.rulePath)
26673
+ return;
26674
+ try {
26675
+ await fs9.unlink(platform.rulePath);
26676
+ console.log(` \u2713 Removed ${platform.rulePath}`);
26677
+ } catch (err) {
26678
+ if (err.code !== "ENOENT")
26679
+ throw err;
26680
+ return;
26681
+ }
26682
+ const ruleDir = path5.dirname(platform.rulePath);
26683
+ await removeDirIfEmpty(ruleDir);
26684
+ const parentDir = path5.dirname(ruleDir);
26685
+ await removeDirIfEmpty(parentDir);
26686
+ }
26639
26687
  async function runUninstaller() {
26640
26688
  const cwd = process.cwd();
26641
26689
  console.log();
@@ -26655,10 +26703,13 @@ async function runUninstaller() {
26655
26703
  if (p.skillPath) {
26656
26704
  console.log(` + Skill file: ${p.skillPath}`);
26657
26705
  }
26706
+ if (p.rulePath) {
26707
+ console.log(` + Rule file: ${p.rulePath}`);
26708
+ }
26658
26709
  }
26659
26710
  console.log();
26660
26711
  const proceed = await (0, import_prompts.confirm)({
26661
- message: "Remove encoding-aware-fs MCP config entries and skill files?",
26712
+ message: "Remove encoding-aware-fs MCP config entries, skill files, and rule files?",
26662
26713
  default: false
26663
26714
  });
26664
26715
  if (!proceed) {
@@ -26670,12 +26721,15 @@ async function runUninstaller() {
26670
26721
  if (p.type === "claude-code") {
26671
26722
  await removeClaudeCodeEntry(p.configPath);
26672
26723
  } else if (p.type === "opencode") {
26673
- await removeOpenCodeEntry(p.configPath);
26724
+ await removeOpenCodeConfig(p.configPath);
26674
26725
  }
26675
26726
  }
26676
26727
  for (const p of installed) {
26677
26728
  await removeSkillFiles(p);
26678
26729
  }
26730
+ for (const p of installed) {
26731
+ await removeRuleFile(p);
26732
+ }
26679
26733
  const encodingConfigPath = path5.join(cwd, ".encoding-converter.json");
26680
26734
  try {
26681
26735
  await fs9.access(encodingConfigPath);
@@ -26700,6 +26754,8 @@ var init_uninstaller = __esm({
26700
26754
  // src/installer.ts
26701
26755
  var installer_exports = {};
26702
26756
  __export(installer_exports, {
26757
+ addOpenCodeInstructions: () => addOpenCodeInstructions,
26758
+ copyRuleFile: () => copyRuleFile,
26703
26759
  runInstaller: () => runInstaller
26704
26760
  });
26705
26761
  function checkNodeVersion() {
@@ -26725,9 +26781,10 @@ async function writeClaudeCodeConfig(cwd) {
26725
26781
  if (!merged.mcpServers) {
26726
26782
  merged.mcpServers = {};
26727
26783
  }
26784
+ const isWindows = process.platform === "win32";
26728
26785
  merged.mcpServers["encoding-aware-fs"] = {
26729
- command: "npx",
26730
- args: ["-y", "encoding-aware-fs", "serve"],
26786
+ command: isWindows ? "cmd" : "npx",
26787
+ args: isWindows ? ["/c", "npx", "-y", "encoding-aware-fs", "serve"] : ["-y", "encoding-aware-fs", "serve"],
26731
26788
  env: {}
26732
26789
  };
26733
26790
  await writeJsonFile(configPath, merged);
@@ -26740,9 +26797,10 @@ async function writeOpenCodeConfig(cwd) {
26740
26797
  if (!merged.mcp) {
26741
26798
  merged.mcp = {};
26742
26799
  }
26800
+ const isWindows = process.platform === "win32";
26743
26801
  merged.mcp["encoding-aware-fs"] = {
26744
26802
  type: "local",
26745
- command: ["npx", "-y", "encoding-aware-fs", "serve"],
26803
+ command: isWindows ? ["cmd", "/c", "npx", "-y", "encoding-aware-fs", "serve"] : ["npx", "-y", "encoding-aware-fs", "serve"],
26746
26804
  enabled: true,
26747
26805
  timeout: 3e4
26748
26806
  };
@@ -26763,6 +26821,33 @@ async function copySkillFile(cwd, platform) {
26763
26821
  await fs10.copyFile(sourcePath, targetPath);
26764
26822
  console.log(` \u2713 Installed skill \u2192 ${targetPath}`);
26765
26823
  }
26824
+ async function copyRuleFile(cwd, platform) {
26825
+ const sourcePath = path6.join(path6.resolve(__dirname, ".."), "skills", platform, "RULE.md");
26826
+ try {
26827
+ await fs10.access(sourcePath);
26828
+ } catch {
26829
+ console.log(` \u26A0 Rule file template not found, skipping`);
26830
+ return;
26831
+ }
26832
+ const ruleDir = platform === "claude-code" ? path6.join(cwd, ".claude", "rules") : path6.join(cwd, ".agents", "rules");
26833
+ const rulePath = path6.join(ruleDir, "encoding-aware-fs.md");
26834
+ await fs10.mkdir(ruleDir, { recursive: true });
26835
+ await fs10.copyFile(sourcePath, rulePath);
26836
+ console.log(` \u2713 Installed rule \u2192 ${rulePath}`);
26837
+ }
26838
+ async function addOpenCodeInstructions(cwd) {
26839
+ const configPath = path6.join(cwd, "opencode.jsonc");
26840
+ const existing = await readJsonFile(configPath);
26841
+ const merged = existing ?? {};
26842
+ if (!merged.instructions) {
26843
+ merged.instructions = [];
26844
+ }
26845
+ const rulePath = ".agents/rules/encoding-aware-fs.md";
26846
+ if (!merged.instructions.includes(rulePath)) {
26847
+ merged.instructions.push(rulePath);
26848
+ }
26849
+ await writeJsonFile(configPath, merged);
26850
+ }
26766
26851
  async function ensureEncodingConfig(cwd) {
26767
26852
  const configPath = path6.join(cwd, ".encoding-converter.json");
26768
26853
  try {
@@ -26826,6 +26911,15 @@ async function runInstaller() {
26826
26911
  for (const platform of platforms) {
26827
26912
  await copySkillFile(cwd, platform);
26828
26913
  }
26914
+ console.log();
26915
+ console.log("Rule files:");
26916
+ for (const platform of platforms) {
26917
+ await copyRuleFile(cwd, platform);
26918
+ }
26919
+ if (platforms.includes("opencode")) {
26920
+ await addOpenCodeInstructions(cwd);
26921
+ console.log(" \u2713 Added rule to opencode.jsonc instructions");
26922
+ }
26829
26923
  await ensureEncodingConfig(cwd);
26830
26924
  console.log();
26831
26925
  console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
@@ -26838,7 +26932,7 @@ async function runInstaller() {
26838
26932
  console.log("\u2502 OpenCode: restart opencode \u2502");
26839
26933
  }
26840
26934
  console.log("\u2502 \u2502");
26841
- console.log("\u2502 Skill files installed for AI discovery. \u2502");
26935
+ console.log("\u2502 Rule + Skill files installed for AI. \u2502");
26842
26936
  console.log("\u2502 The MCP server will start automatically \u2502");
26843
26937
  console.log("\u2502 when your AI tool connects. \u2502");
26844
26938
  console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "encoding-aware-fs",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Encoding-aware file operations MCP Server for AI tools working with GB18030 projects",
5
5
  "main": "dist/server.js",
6
6
  "bin": {
@@ -0,0 +1,3 @@
1
+ MUST use encoding-aware-fs MCP tools (read_file, write_file, edit_file)
2
+ for ALL file operations in this project. NEVER use the built-in Read, Write,
3
+ or Edit tools for any file inside the project directory.
@@ -0,0 +1,3 @@
1
+ MUST use encoding-aware-fs MCP tools (read_file, write_file, edit_file)
2
+ for ALL file operations in this project. NEVER use the built-in Read, Write,
3
+ or Edit tools for any file inside the project directory.
@@ -1,5 +0,0 @@
1
- {
2
- "sourceEncoding": "GB18030",
3
- "targetEncoding": "UTF-8",
4
- "confidenceThreshold": 0.8
5
- }
package/.mcp.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "mcpServers": {
3
- "encoding-aware-fs": {
4
- "command": "npx",
5
- "args": [
6
- "-y",
7
- "encoding-aware-fs",
8
- "serve"
9
- ],
10
- "env": {}
11
- }
12
- }
13
- }
package/opencode.jsonc DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "mcp": {
3
- "encoding-aware-fs": {
4
- "type": "local",
5
- "command": [
6
- "npx",
7
- "-y",
8
- "encoding-aware-fs",
9
- "serve"
10
- ],
11
- "enabled": true,
12
- "timeout": 30000
13
- }
14
- }
15
- }