Files
AX-Copilot-Codex/.decompiledproj/AxCopilot/Services/Agent/EncodingTool.cs

276 lines
8.3 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace AxCopilot.Services.Agent;
public class EncodingTool : IAgentTool
{
public string Name => "encoding_tool";
public string Description => "Detect and convert file text encoding. Actions: 'detect' — detect file encoding (UTF-8, EUC-KR, etc.); 'convert' — convert file from one encoding to another; 'list' — list common encoding names.";
public ToolParameterSchema Parameters
{
get
{
ToolParameterSchema toolParameterSchema = new ToolParameterSchema();
Dictionary<string, ToolProperty> dictionary = new Dictionary<string, ToolProperty>();
ToolProperty obj = new ToolProperty
{
Type = "string",
Description = "Action: detect, convert, list"
};
int num = 3;
List<string> list = new List<string>(num);
CollectionsMarshal.SetCount(list, num);
Span<string> span = CollectionsMarshal.AsSpan(list);
span[0] = "detect";
span[1] = "convert";
span[2] = "list";
obj.Enum = list;
dictionary["action"] = obj;
dictionary["path"] = new ToolProperty
{
Type = "string",
Description = "File path"
};
dictionary["from_encoding"] = new ToolProperty
{
Type = "string",
Description = "Source encoding name (e.g. 'euc-kr', 'shift-jis'). Auto-detected if omitted."
};
dictionary["to_encoding"] = new ToolProperty
{
Type = "string",
Description = "Target encoding name (default: 'utf-8')"
};
toolParameterSchema.Properties = dictionary;
num = 1;
List<string> list2 = new List<string>(num);
CollectionsMarshal.SetCount(list2, num);
CollectionsMarshal.AsSpan(list2)[0] = "action";
toolParameterSchema.Required = list2;
return toolParameterSchema;
}
}
public async Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default(CancellationToken))
{
string action = args.GetProperty("action").GetString() ?? "";
if (action == "list")
{
return ListEncodings();
}
JsonElement pv;
string rawPath = (args.TryGetProperty("path", out pv) ? (pv.GetString() ?? "") : "");
if (string.IsNullOrEmpty(rawPath))
{
return ToolResult.Fail("'path'가 필요합니다.");
}
string path = (Path.IsPathRooted(rawPath) ? rawPath : Path.Combine(context.WorkFolder, rawPath));
if (!context.IsPathAllowed(path))
{
return ToolResult.Fail("경로 접근 차단: " + path);
}
if (!File.Exists(path))
{
return ToolResult.Fail("파일 없음: " + path);
}
try
{
if (1 == 0)
{
}
string text = action;
ToolResult result = ((text == "detect") ? DetectEncoding(path) : ((!(text == "convert")) ? ToolResult.Fail("Unknown action: " + action) : (await ConvertEncoding(path, args, context))));
if (1 == 0)
{
}
return result;
}
catch (Exception ex)
{
return ToolResult.Fail("인코딩 처리 오류: " + ex.Message);
}
}
private static ToolResult DetectEncoding(string path)
{
byte[] array = File.ReadAllBytes(path);
Encoding encoding = DetectEncodingFromBytes(array);
StringBuilder stringBuilder = new StringBuilder();
StringBuilder stringBuilder2 = stringBuilder;
StringBuilder stringBuilder3 = stringBuilder2;
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(6, 1, stringBuilder2);
handler.AppendLiteral("File: ");
handler.AppendFormatted(Path.GetFileName(path));
stringBuilder3.AppendLine(ref handler);
stringBuilder2 = stringBuilder;
StringBuilder stringBuilder4 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(12, 1, stringBuilder2);
handler.AppendLiteral("Size: ");
handler.AppendFormatted(array.Length, "N0");
handler.AppendLiteral(" bytes");
stringBuilder4.AppendLine(ref handler);
stringBuilder2 = stringBuilder;
StringBuilder stringBuilder5 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(19, 1, stringBuilder2);
handler.AppendLiteral("Detected Encoding: ");
handler.AppendFormatted(encoding.EncodingName);
stringBuilder5.AppendLine(ref handler);
stringBuilder2 = stringBuilder;
StringBuilder stringBuilder6 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2);
handler.AppendLiteral("Code Page: ");
handler.AppendFormatted(encoding.CodePage);
stringBuilder6.AppendLine(ref handler);
stringBuilder2 = stringBuilder;
StringBuilder stringBuilder7 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(13, 1, stringBuilder2);
handler.AppendLiteral("BOM Present: ");
handler.AppendFormatted(HasBom(array));
stringBuilder7.AppendLine(ref handler);
return ToolResult.Ok(stringBuilder.ToString());
}
private static async Task<ToolResult> ConvertEncoding(string path, JsonElement args, AgentContext context)
{
JsonElement te;
string toName = (args.TryGetProperty("to_encoding", out te) ? (te.GetString() ?? "utf-8") : "utf-8");
if (!(await context.CheckWritePermissionAsync("encoding_tool", path)))
{
return ToolResult.Fail("파일 쓰기 권한이 거부되었습니다.");
}
Encoding fromEnc;
if (args.TryGetProperty("from_encoding", out var fe) && !string.IsNullOrEmpty(fe.GetString()))
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
fromEnc = Encoding.GetEncoding(fe.GetString());
}
else
{
byte[] rawBytes = File.ReadAllBytes(path);
fromEnc = DetectEncodingFromBytes(rawBytes);
}
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Encoding toEnc = Encoding.GetEncoding(toName);
string content = File.ReadAllText(path, fromEnc);
File.WriteAllText(path, content, toEnc);
return ToolResult.Ok($"변환 완료: {fromEnc.EncodingName} → {toEnc.EncodingName}\nFile: {path}", path);
}
private static ToolResult ListEncodings()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("주요 인코딩 목록:");
stringBuilder.AppendLine(" utf-8 — UTF-8 (유니코드, 기본)");
stringBuilder.AppendLine(" utf-16 — UTF-16 LE");
stringBuilder.AppendLine(" utf-16BE — UTF-16 BE");
stringBuilder.AppendLine(" euc-kr — EUC-KR (한국어)");
stringBuilder.AppendLine(" ks_c_5601-1987 — 한글 완성형");
stringBuilder.AppendLine(" shift_jis — Shift-JIS (일본어)");
stringBuilder.AppendLine(" gb2312 — GB2312 (중국어 간체)");
stringBuilder.AppendLine(" iso-8859-1 — Latin-1 (서유럽)");
stringBuilder.AppendLine(" ascii — US-ASCII");
stringBuilder.AppendLine(" utf-32 — UTF-32");
return ToolResult.Ok(stringBuilder.ToString());
}
private static Encoding DetectEncodingFromBytes(byte[] bytes)
{
if (bytes.Length >= 3 && bytes[0] == 239 && bytes[1] == 187 && bytes[2] == 191)
{
return Encoding.UTF8;
}
if (bytes.Length >= 2 && bytes[0] == byte.MaxValue && bytes[1] == 254)
{
return Encoding.Unicode;
}
if (bytes.Length >= 2 && bytes[0] == 254 && bytes[1] == byte.MaxValue)
{
return Encoding.BigEndianUnicode;
}
if (IsValidUtf8(bytes))
{
return Encoding.UTF8;
}
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
try
{
return Encoding.GetEncoding("euc-kr");
}
catch
{
return Encoding.Default;
}
}
private static bool IsValidUtf8(byte[] bytes)
{
int num = 0;
bool flag = false;
while (num < bytes.Length)
{
if (bytes[num] <= 127)
{
num++;
continue;
}
int num2;
if ((bytes[num] & 0xE0) == 192)
{
num2 = 1;
}
else if ((bytes[num] & 0xF0) == 224)
{
num2 = 2;
}
else
{
if ((bytes[num] & 0xF8) != 240)
{
return false;
}
num2 = 3;
}
if (num + num2 >= bytes.Length)
{
return false;
}
for (int i = 1; i <= num2; i++)
{
if ((bytes[num + i] & 0xC0) != 128)
{
return false;
}
}
flag = true;
num += num2 + 1;
}
return flag || bytes.Length < 100;
}
private static bool HasBom(byte[] bytes)
{
if (bytes.Length >= 3 && bytes[0] == 239 && bytes[1] == 187 && bytes[2] == 191)
{
return true;
}
if (bytes.Length >= 2 && bytes[0] == byte.MaxValue && bytes[1] == 254)
{
return true;
}
if (bytes.Length >= 2 && bytes[0] == 254 && bytes[1] == byte.MaxValue)
{
return true;
}
return false;
}
}