Initial commit to new repository
This commit is contained in:
117
src/AxCopilot/Services/PresetService.cs
Normal file
117
src/AxCopilot/Services/PresetService.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace AxCopilot.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 대화 주제 프리셋을 EmbeddedResource에서 동적으로 로드합니다.
|
||||
/// Assets/Presets/*.json 파일을 빌드 시 내장하고 런타임에 읽어옵니다.
|
||||
/// </summary>
|
||||
public static class PresetService
|
||||
{
|
||||
private static readonly List<TopicPreset> _presets = new();
|
||||
private static bool _loaded;
|
||||
|
||||
public static IReadOnlyList<TopicPreset> Presets
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_loaded) Load();
|
||||
return _presets;
|
||||
}
|
||||
}
|
||||
|
||||
public static TopicPreset? GetByCategory(string category)
|
||||
=> Presets.FirstOrDefault(p => p.Category == category);
|
||||
|
||||
/// <summary>특정 탭의 프리셋만 반환.</summary>
|
||||
public static IReadOnlyList<TopicPreset> GetByTab(string tab)
|
||||
=> Presets.Where(p => p.Tab.Equals(tab, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
|
||||
/// <summary>내장 프리셋 + 커스텀 프리셋을 병합하여 탭별로 반환.</summary>
|
||||
public static IReadOnlyList<TopicPreset> GetByTabWithCustom(string tab, IEnumerable<Models.CustomPresetEntry> customPresets)
|
||||
{
|
||||
var result = GetByTab(tab).ToList();
|
||||
foreach (var cp in customPresets.Where(c => c.Tab.Equals(tab, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
result.Add(new TopicPreset
|
||||
{
|
||||
Category = $"custom_{cp.Id}",
|
||||
Label = cp.Label,
|
||||
Symbol = cp.Symbol,
|
||||
Color = cp.Color,
|
||||
Description = cp.Description,
|
||||
SystemPrompt = cp.SystemPrompt,
|
||||
Placeholder = "",
|
||||
Tab = cp.Tab,
|
||||
IsCustom = true,
|
||||
CustomId = cp.Id,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void Load()
|
||||
{
|
||||
_loaded = true;
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var prefix = "AxCopilot.Assets.Presets.";
|
||||
|
||||
foreach (var name in assembly.GetManifestResourceNames())
|
||||
{
|
||||
if (!name.StartsWith(prefix) || !name.EndsWith(".json")) continue;
|
||||
|
||||
try
|
||||
{
|
||||
using var stream = assembly.GetManifestResourceStream(name);
|
||||
if (stream == null) continue;
|
||||
using var reader = new StreamReader(stream);
|
||||
var json = reader.ReadToEnd();
|
||||
var preset = JsonSerializer.Deserialize<TopicPreset>(json, new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
});
|
||||
if (preset != null)
|
||||
_presets.Add(preset);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogService.Warn($"프리셋 로드 실패 ({name}): {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// Order 필드 → ChatCategory 순서로 정렬
|
||||
var catOrder = Models.ChatCategory.All.Select((c, i) => (c.Key, i)).ToDictionary(x => x.Key, x => x.i);
|
||||
_presets.Sort((a, b) =>
|
||||
{
|
||||
var oa = a.Order; var ob = b.Order;
|
||||
if (oa != ob) return oa.CompareTo(ob);
|
||||
var ia = catOrder.GetValueOrDefault(a.Category, 99);
|
||||
var ib = catOrder.GetValueOrDefault(b.Category, 99);
|
||||
return ia.CompareTo(ib);
|
||||
});
|
||||
|
||||
LogService.Info($"대화 주제 프리셋 {_presets.Count}개 로드 완료");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>대화 주제 프리셋 모델.</summary>
|
||||
public class TopicPreset
|
||||
{
|
||||
public string Category { get; set; } = "";
|
||||
public string Label { get; set; } = "";
|
||||
public string Symbol { get; set; } = "";
|
||||
public string Color { get; set; } = "";
|
||||
public string Description { get; set; } = "";
|
||||
public string SystemPrompt { get; set; } = "";
|
||||
public string Placeholder { get; set; } = "";
|
||||
/// <summary>표시 순서 (낮을수록 먼저). 기본 50.</summary>
|
||||
public int Order { get; set; } = 50;
|
||||
/// <summary>프리셋이 속하는 탭. "Chat" | "Cowork" | "Code"</summary>
|
||||
public string Tab { get; set; } = "Chat";
|
||||
/// <summary>사용자 커스텀 프리셋 여부.</summary>
|
||||
public bool IsCustom { get; set; }
|
||||
/// <summary>커스텀 프리셋의 고유 ID (IsCustom == true일 때만 사용).</summary>
|
||||
public string? CustomId { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user