Files
AX-Copilot-Codex/src/AxCopilot/Models/AppSettings.cs
lacvet d3b6b1a936 코워크 코드 내부설정 컨텍스트 토큰 기본값을 32K로 상향
LlmSettings.MaxContextTokens 기본값을 32768로 조정하고 메인 설정의 컨텍스트 토큰 카드에 32K 선택지를 추가했다.

AgentSettingsWindow의 잘못된 입력 fallback도 32K 기준으로 바꿔 내부설정이 4K로 되돌아가지 않도록 정리했다.

검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_context32k\\ -p:IntermediateOutputPath=obj\\verify_context32k\\ / dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter SettingsServiceTests -p:OutputPath=bin\\verify_context32k_tests\\ -p:IntermediateOutputPath=obj\\verify_context32k_tests\
2026-04-15 14:29:04 +09:00

1640 lines
70 KiB
C#

using System.Text.Json.Serialization;
namespace AxCopilot.Models;
public class AppSettings
{
[JsonPropertyName("version")]
public string Version { get; set; } = "1.0";
/// <summary>
/// AI 기능 활성화 여부. false이면 ! 명령어 차단 + 설정의 AX Agent 탭 숨김.
/// AI 엔진 미포함 배포는 false로 설정합니다.
/// </summary>
[JsonPropertyName("ai_enabled")]
public bool AiEnabled { get; set; } = true;
/// <summary>
/// 운영 모드. internal(사내) | external(사외).
/// internal: 외부 검색/외부 HTTP 등 정보 유출 가능 기능 차단
/// external: 전체 기능 허용
/// </summary>
[JsonPropertyName("operationMode")]
public string OperationMode { get; set; } = "internal";
[JsonIgnore]
public bool InternalModeEnabled => string.Equals(OperationMode, "internal", StringComparison.OrdinalIgnoreCase);
[JsonPropertyName("hotkey")]
public string Hotkey { get; set; } = "Alt+Space";
/// <summary>
/// 대화 보관 기간(일). 0이면 대화 영구 보관.
/// 제품화 기본값은 30일이며, 앱 시작 시 만료 대화를 자동 정리합니다.
/// </summary>
[JsonPropertyName("cleanupPeriodDays")]
public int CleanupPeriodDays { get; set; } = 30;
[JsonPropertyName("launcher")]
public LauncherSettings Launcher { get; set; } = new();
[JsonPropertyName("indexPaths")]
public List<string> IndexPaths { get; set; } = new()
{
"%USERPROFILE%\\Desktop",
"%APPDATA%\\Microsoft\\Windows\\Start Menu"
};
/// <summary>
/// 인덱싱할 파일 확장자 목록 (점 포함). 빈 리스트 = 모든 파일.
/// 기본값: 실행 파일 + 문서 + 이미지 + 텍스트 파일.
/// </summary>
[JsonPropertyName("indexExtensions")]
public List<string> IndexExtensions { get; set; } = new()
{
// 실행 파일
".exe", ".lnk", ".bat", ".ps1", ".url", ".cmd", ".msi",
// 문서
".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx",
".hwp", ".hwpx",
// 텍스트
".txt", ".md", ".csv", ".json", ".xml", ".yaml", ".yml",
".log", ".ini", ".cfg", ".conf",
// 이미지
".png", ".jpg", ".jpeg", ".gif", ".bmp", ".svg", ".webp", ".ico", ".tiff",
// 기타
".zip", ".7z", ".rar"
};
/// <summary>인덱싱 속도. slow | normal | fast. 기본 normal.</summary>
[JsonPropertyName("indexSpeed")]
public string IndexSpeed { get; set; } = "normal"; // slow | normal | fast
[JsonPropertyName("monitorMismatch")]
public string MonitorMismatch { get; set; } = "warn"; // fit | skip | warn
[JsonPropertyName("profiles")]
public List<WorkspaceProfile> Profiles { get; set; } = new();
[JsonPropertyName("aliases")]
public List<AliasEntry> Aliases { get; set; } = new();
[JsonPropertyName("clipboardTransformers")]
public List<ClipboardTransformer> ClipboardTransformers { get; set; } = new();
[JsonPropertyName("apiAdapters")]
public List<ApiAdapter> ApiAdapters { get; set; } = new();
[JsonPropertyName("plugins")]
public List<PluginEntry> Plugins { get; set; } = new();
[JsonPropertyName("snippets")]
public List<SnippetEntry> Snippets { get; set; } = new();
[JsonPropertyName("quickLinks")]
public List<QuickLinkEntry> QuickLinks { get; set; } = new();
[JsonPropertyName("clipboardHistory")]
public ClipboardHistorySettings ClipboardHistory { get; set; } = new();
[JsonPropertyName("systemCommands")]
public SystemCommandSettings SystemCommands { get; set; } = new();
[JsonPropertyName("screenCapture")]
public ScreenCaptureSettings ScreenCapture { get; set; } = new();
[JsonPropertyName("reminder")]
public ReminderSettings Reminder { get; set; } = new();
[JsonPropertyName("customHotkeys")]
public List<HotkeyAssignment> CustomHotkeys { get; set; } = new();
[JsonPropertyName("appSessions")]
public List<AppSession> AppSessions { get; set; } = new();
[JsonPropertyName("schedules")]
public List<ScheduleEntry> Schedules { get; set; } = new();
[JsonPropertyName("macros")]
public List<MacroEntry> Macros { get; set; } = new();
[JsonPropertyName("ssh_hosts")]
public List<SshHostEntry> SshHosts { get; set; } = new();
[JsonPropertyName("llm")]
public LlmSettings Llm { get; set; } = new();
}
public class LauncherSettings
{
[JsonPropertyName("opacity")]
public double Opacity { get; set; } = 0.96;
[JsonPropertyName("maxResults")]
public int MaxResults { get; set; } = 7;
[JsonPropertyName("theme")]
// 지원 값: system | dark | light | oled | nord | monokai | catppuccin | sepia | custom
public string Theme { get; set; } = "system";
[JsonPropertyName("position")]
public string Position { get; set; } = "center-top"; // center-top | center | bottom
[JsonPropertyName("width")]
public double Width { get; set; } = 680;
[JsonPropertyName("webSearchEngine")]
public string WebSearchEngine { get; set; } = "g"; // g | n | d | y | w
[JsonPropertyName("snippetAutoExpand")]
public bool SnippetAutoExpand { get; set; } = true;
[JsonPropertyName("language")]
public string Language { get; set; } = "ko"; // ko | en | ja | zh | vi
[JsonPropertyName("customTheme")]
public CustomThemeColors? CustomTheme { get; set; }
// ─── 기능 토글 ─────────────────────────────────────────────────────────
/// <summary>번호 배지(1~9) 표시 여부. Ctrl+숫자로 바로 실행. 기본 true.</summary>
[JsonPropertyName("showNumberBadges")]
public bool ShowNumberBadges { get; set; } = true;
/// <summary>즐겨찾기 기능 활성화. fav 접두어, Ctrl+B. 기본 true.</summary>
[JsonPropertyName("enableFavorites")]
public bool EnableFavorites { get; set; } = true;
/// <summary>최근 실행 기록 저장 여부. recent 접두어, Ctrl+R. 기본 true.</summary>
[JsonPropertyName("enableRecent")]
public bool EnableRecent { get; set; } = true;
/// <summary>액션 모드 진입 허용 여부. Ctrl+Enter / Alt+Enter / → 키. 기본 true.</summary>
[JsonPropertyName("enableActionMode")]
public bool EnableActionMode { get; set; } = true;
/// <summary>포커스 잃을 때 런처 자동 닫기. 기본 true.</summary>
[JsonPropertyName("closeOnFocusLost")]
public bool CloseOnFocusLost { get; set; } = true;
/// <summary>입력창 좌측 프리픽스 배지 표시. 기본 true.</summary>
[JsonPropertyName("showPrefixBadge")]
public bool ShowPrefixBadge { get; set; } = true;
/// <summary>런처 아이콘 애니메이션 효과 활성화. 기본 true.</summary>
[JsonPropertyName("enableIconAnimation")]
public bool EnableIconAnimation { get; set; } = true;
/// <summary>채팅 본문 런처 아이콘 랜덤 애니메이션. false이면 숨쉬기만. 기본 false.</summary>
[JsonPropertyName("enableChatIconRandomAnimation")]
public bool EnableChatIconRandomAnimation { get; set; } = false;
/// <summary>채팅 본문 런처 아이콘 글로우 강도. strong/medium/weak. 기본 medium.</summary>
[JsonPropertyName("chatIconGlowIntensity")]
public string ChatIconGlowIntensity { get; set; } = "medium";
/// <summary>런처 안내 문구 랜덤 출력 활성화. false이면 고정 문구. 기본 true.</summary>
[JsonPropertyName("enableRandomPlaceholder")]
public bool EnableRandomPlaceholder { get; set; } = true;
/// <summary>런처 무지개 글로우 효과 활성화. 기본 false (성능 고려).</summary>
[JsonPropertyName("enableRainbowGlow")]
public bool EnableRainbowGlow { get; set; } = false;
/// <summary>선택된 아이템 상시 글로우 효과. 기본 false.</summary>
[JsonPropertyName("enableSelectionGlow")]
public bool EnableSelectionGlow { get; set; } = false;
/// <summary>런처 창 테두리 표시 여부. 기본 true(표시).</summary>
[JsonPropertyName("showLauncherBorder")]
public bool ShowLauncherBorder { get; set; } = true;
[JsonPropertyName("showWidgetPerf")]
public bool ShowWidgetPerf { get; set; } = false;
[JsonPropertyName("showWidgetPomo")]
public bool ShowWidgetPomo { get; set; } = false;
[JsonPropertyName("showWidgetNote")]
public bool ShowWidgetNote { get; set; } = false;
[JsonPropertyName("showWidgetWeather")]
public bool ShowWidgetWeather { get; set; } = false;
[JsonPropertyName("showWidgetCalendar")]
public bool ShowWidgetCalendar { get; set; } = false;
[JsonPropertyName("showWidgetBattery")]
public bool ShowWidgetBattery { get; set; } = false;
/// <summary>런처 하단 빠른 실행 칩 표시 여부. 기본 false.</summary>
[JsonPropertyName("showLauncherBottomQuickActions")]
public bool ShowLauncherBottomQuickActions { get; set; } = false;
/// <summary>단축키 헬프 창에서 아이콘 색상을 테마 AccentColor 기준으로 표시. 기본 true(테마색).</summary>
[JsonPropertyName("shortcutHelpUseThemeColor")]
public bool ShortcutHelpUseThemeColor { get; set; } = true;
// ─── 독 바 설정 ──────────────────────────────────────────────────────────
// ─── 선택 텍스트 AI 명령 설정 ───────────────────────────────────────────
/// <summary>선택 텍스트 AI 명령 활성화. 기본 false.</summary>
[JsonPropertyName("enableTextAction")]
public bool EnableTextAction { get; set; } = false;
/// <summary>활성화된 텍스트 AI 명령 목록. 가능한 값: translate, summarize, grammar, explain, rewrite</summary>
[JsonPropertyName("textActionCommands")]
public List<string> TextActionCommands { get; set; } = new();
/// <summary>번역 기본 언어. 기본 "한국어↔영어 자동".</summary>
[JsonPropertyName("textActionTranslateLanguage")]
public string TextActionTranslateLanguage { get; set; } = "auto";
// ─── 파일 대화상자 통합 설정 ─────────────────────────────────────────────
/// <summary>열기/저장 대화상자 감지 시 런처 자동 열기. 기본 false.</summary>
[JsonPropertyName("enableFileDialogIntegration")]
public bool EnableFileDialogIntegration { get; set; } = false;
// ─── 클립보드 핀/카테고리 설정 ───────────────────────────────────────────
/// <summary>클립보드 자동 카테고리 분류 활성화. 기본 true.</summary>
[JsonPropertyName("enableClipboardAutoCategory")]
public bool EnableClipboardAutoCategory { get; set; } = true;
/// <summary>최대 핀 고정 개수. 기본 20.</summary>
[JsonPropertyName("maxPinnedClipboardItems")]
public int MaxPinnedClipboardItems { get; set; } = 20;
// ─── 독 바 설정 ──────────────────────────────────────────────────────────
/// <summary>독 바 표시 항목. 가능한 값: launcher, clipboard, capture, agent, clock, cpu, ram, quickinput</summary>
[JsonPropertyName("dockBarItems")]
public List<string> DockBarItems { get; set; } = new() { "launcher", "clipboard", "capture", "agent", "clock", "cpu" };
/// <summary>독 바 앱 시작 시 자동 표시. 기본 false.</summary>
[JsonPropertyName("dockBarAutoShow")]
public bool DockBarAutoShow { get; set; } = false;
/// <summary>독 바 투명도 (0.3~1.0). 기본 0.92.</summary>
[JsonPropertyName("dockBarOpacity")]
public double DockBarOpacity { get; set; } = 0.92;
/// <summary>독 바 무지개 글로우 효과. 기본 false.</summary>
[JsonPropertyName("dockBarRainbowGlow")]
public bool DockBarRainbowGlow { get; set; } = false;
/// <summary>독 바 마지막 위치 X. -1이면 중앙.</summary>
[JsonPropertyName("dockBarLeft")]
public double DockBarLeft { get; set; } = -1;
/// <summary>독 바 마지막 위치 Y. -1이면 하단.</summary>
[JsonPropertyName("dockBarTop")]
public double DockBarTop { get; set; } = -1;
/// <summary>모니터별 독 바 위치. key=디바이스명, value=[left, top]</summary>
[JsonPropertyName("monitorDockPositions")]
public Dictionary<string, List<double>> MonitorDockPositions { get; set; } = new(StringComparer.OrdinalIgnoreCase);
/// <summary>런처 마지막 위치 기억 여부. 기본 false.</summary>
[JsonPropertyName("rememberPosition")]
public bool RememberPosition { get; set; } = false;
/// <summary>런처 마지막 Left 좌표. -1이면 기본 위치.</summary>
[JsonPropertyName("lastLeft")]
public double LastLeft { get; set; } = -1;
/// <summary>런처 마지막 Top 좌표. -1이면 기본 위치.</summary>
[JsonPropertyName("lastTop")]
public double LastTop { get; set; } = -1;
}
/// <summary>
/// "theme": "custom" 설정 시 사용할 사용자 정의 색상.
/// settings.json에서 직접 헥스 코드(#RRGGBB)로 지정합니다.
/// </summary>
public class CustomThemeColors
{
[JsonPropertyName("launcherBackground")]
public string LauncherBackground { get; set; } = "#1A1B2E";
[JsonPropertyName("itemBackground")]
public string ItemBackground { get; set; } = "#252637";
[JsonPropertyName("itemSelectedBackground")]
public string ItemSelectedBackground { get; set; } = "#3B4BDB";
[JsonPropertyName("itemHoverBackground")]
public string ItemHoverBackground { get; set; } = "#22233A";
[JsonPropertyName("primaryText")]
public string PrimaryText { get; set; } = "#F0F0FF";
[JsonPropertyName("secondaryText")]
public string SecondaryText { get; set; } = "#7A7D9C";
[JsonPropertyName("placeholderText")]
public string PlaceholderText { get; set; } = "#464868";
[JsonPropertyName("accentColor")]
public string AccentColor { get; set; } = "#4B5EFC";
[JsonPropertyName("separatorColor")]
public string SeparatorColor { get; set; } = "#252637";
[JsonPropertyName("hintBackground")]
public string HintBackground { get; set; } = "#252637";
[JsonPropertyName("hintText")]
public string HintText { get; set; } = "#4B5070";
[JsonPropertyName("borderColor")]
public string BorderColor { get; set; } = "#2E2F4A";
[JsonPropertyName("scrollbarThumb")]
public string ScrollbarThumb { get; set; } = "#3A3B5A";
[JsonPropertyName("shadowColor")]
public string ShadowColor { get; set; } = "#000000";
/// <summary>창 전체 모서리 라운딩 (0~30). 기본값 20.</summary>
[JsonPropertyName("windowCornerRadius")]
public int WindowCornerRadius { get; set; } = 20;
/// <summary>결과 항목 모서리 라운딩 (0~20). 기본값 10.</summary>
[JsonPropertyName("itemCornerRadius")]
public int ItemCornerRadius { get; set; } = 10;
}
public class WorkspaceProfile
{
[JsonPropertyName("name")]
public string Name { get; set; } = "";
[JsonPropertyName("windows")]
public List<WindowSnapshot> Windows { get; set; } = new();
[JsonPropertyName("createdAt")]
public DateTime CreatedAt { get; set; } = DateTime.Now;
}
public class WindowSnapshot
{
[JsonPropertyName("exe")]
public string Exe { get; set; } = "";
[JsonPropertyName("title")]
public string Title { get; set; } = "";
[JsonPropertyName("rect")]
public WindowRect Rect { get; set; } = new();
[JsonPropertyName("showCmd")]
public string ShowCmd { get; set; } = "Normal"; // Normal | Minimized | Maximized
[JsonPropertyName("monitor")]
public int Monitor { get; set; } = 0;
}
public class WindowRect
{
[JsonPropertyName("x")]
public int X { get; set; }
[JsonPropertyName("y")]
public int Y { get; set; }
[JsonPropertyName("width")]
public int Width { get; set; }
[JsonPropertyName("height")]
public int Height { get; set; }
}
public class AliasEntry
{
[JsonPropertyName("key")]
public string Key { get; set; } = "";
[JsonPropertyName("type")]
public string Type { get; set; } = "url"; // url | folder | app | batch | api | clipboard
[JsonPropertyName("target")]
public string Target { get; set; } = "";
[JsonPropertyName("description")]
public string? Description { get; set; }
[JsonPropertyName("showWindow")]
public bool ShowWindow { get; set; } = false;
[JsonPropertyName("adapter")]
public string? Adapter { get; set; }
[JsonPropertyName("query")]
public string? Query { get; set; }
}
public class ClipboardTransformer
{
[JsonPropertyName("key")]
public string Key { get; set; } = "";
[JsonPropertyName("type")]
public string Type { get; set; } = "regex"; // regex | script
[JsonPropertyName("pattern")]
public string? Pattern { get; set; }
[JsonPropertyName("replace")]
public string? Replace { get; set; }
[JsonPropertyName("command")]
public string? Command { get; set; }
[JsonPropertyName("timeout")]
public int Timeout { get; set; } = 5000;
[JsonPropertyName("description")]
public string? Description { get; set; }
}
public class ApiAdapter
{
[JsonPropertyName("id")]
public string Id { get; set; } = "";
[JsonPropertyName("baseUrl")]
public string BaseUrl { get; set; } = "";
[JsonPropertyName("credentialKey")]
public string CredentialKey { get; set; } = "";
}
public class PluginEntry
{
[JsonPropertyName("path")]
public string Path { get; set; } = "";
[JsonPropertyName("enabled")]
public bool Enabled { get; set; } = true;
}
// ─── 스니펫 ───────────────────────────────────────────────────────────────────
public class SnippetEntry
{
[JsonPropertyName("key")]
public string Key { get; set; } = ""; // 트리거 키워드 (예: addr, sig)
[JsonPropertyName("name")]
public string Name { get; set; } = ""; // 표시 이름
[JsonPropertyName("content")]
public string Content { get; set; } = ""; // 확장될 전체 텍스트
}
public class QuickLinkEntry
{
[JsonPropertyName("keyword")]
public string Keyword { get; set; } = "";
[JsonPropertyName("name")]
public string Name { get; set; } = "";
[JsonPropertyName("urlTemplate")]
public string UrlTemplate { get; set; } = "";
[JsonPropertyName("description")]
public string Description { get; set; } = "";
}
public class HotkeyAssignment
{
[JsonPropertyName("hotkey")]
public string Hotkey { get; set; } = "";
[JsonPropertyName("target")]
public string Target { get; set; } = "";
[JsonPropertyName("label")]
public string Label { get; set; } = "";
[JsonPropertyName("type")]
public string Type { get; set; } = "app";
}
public class AppSession
{
[JsonPropertyName("name")]
public string Name { get; set; } = "";
[JsonPropertyName("description")]
public string Description { get; set; } = "";
[JsonPropertyName("apps")]
public List<SessionApp> Apps { get; set; } = new();
[JsonPropertyName("createdAt")]
public DateTime CreatedAt { get; set; } = DateTime.Now;
}
public class SessionApp
{
[JsonPropertyName("path")]
public string Path { get; set; } = "";
[JsonPropertyName("args")]
public string Arguments { get; set; } = "";
[JsonPropertyName("label")]
public string Label { get; set; } = "";
[JsonPropertyName("snap")]
public string SnapPosition { get; set; } = "full";
[JsonPropertyName("delayMs")]
public int DelayMs { get; set; } = 0;
}
public class ScheduleEntry
{
[JsonPropertyName("id")]
public string Id { get; set; } = Guid.NewGuid().ToString("N")[..8];
[JsonPropertyName("name")]
public string Name { get; set; } = "";
[JsonPropertyName("enabled")]
public bool Enabled { get; set; } = true;
[JsonPropertyName("triggerType")]
public string TriggerType { get; set; } = "daily";
[JsonPropertyName("triggerTime")]
public string TriggerTime { get; set; } = "09:00";
[JsonPropertyName("weekDays")]
public List<int> WeekDays { get; set; } = new();
[JsonPropertyName("triggerDate")]
public string? TriggerDate { get; set; }
[JsonPropertyName("actionType")]
public string ActionType { get; set; } = "app";
[JsonPropertyName("actionTarget")]
public string ActionTarget { get; set; } = "";
[JsonPropertyName("actionArgs")]
public string ActionArgs { get; set; } = "";
[JsonPropertyName("lastRun")]
public DateTime? LastRun { get; set; }
[JsonPropertyName("conditionProcess")]
public string ConditionProcess { get; set; } = "";
[JsonPropertyName("conditionProcessMustRun")]
public bool ConditionProcessMustRun { get; set; } = true;
}
public class MacroEntry
{
[JsonPropertyName("id")]
public string Id { get; set; } = Guid.NewGuid().ToString("N")[..8];
[JsonPropertyName("name")]
public string Name { get; set; } = "";
[JsonPropertyName("description")]
public string Description { get; set; } = "";
[JsonPropertyName("steps")]
public List<MacroStep> Steps { get; set; } = new();
[JsonPropertyName("createdAt")]
public DateTime CreatedAt { get; set; } = DateTime.Now;
}
public class MacroStep
{
[JsonPropertyName("type")]
public string Type { get; set; } = "app";
[JsonPropertyName("target")]
public string Target { get; set; } = "";
[JsonPropertyName("args")]
public string Args { get; set; } = "";
[JsonPropertyName("label")]
public string Label { get; set; } = "";
[JsonPropertyName("delayMs")]
public int DelayMs { get; set; } = 500;
}
public class SshHostEntry
{
[JsonPropertyName("id")]
public string Id { get; set; } = Guid.NewGuid().ToString();
[JsonPropertyName("name")]
public string Name { get; set; } = "";
[JsonPropertyName("host")]
public string Host { get; set; } = "";
[JsonPropertyName("port")]
public int Port { get; set; } = 22;
[JsonPropertyName("user")]
public string User { get; set; } = "";
[JsonPropertyName("note")]
public string Note { get; set; } = "";
}
// ─── 클립보드 히스토리 ────────────────────────────────────────────────────────
public class ClipboardHistorySettings
{
[JsonPropertyName("enabled")]
public bool Enabled { get; set; } = true;
[JsonPropertyName("maxItems")]
public int MaxItems { get; set; } = 50;
[JsonPropertyName("excludePatterns")]
public List<string> ExcludePatterns { get; set; } = new()
{
@"^\d{4}[\s\-]?\d{4}[\s\-]?\d{4}[\s\-]?\d{4}$", // 카드번호
@"^(?:\d{1,3}\.){3}\d{1,3}$" // IP 주소
};
}
// ─── 시스템 명령 ──────────────────────────────────────────────────────────────
public class SystemCommandSettings
{
[JsonPropertyName("showLock")] public bool ShowLock { get; set; } = true;
[JsonPropertyName("showSleep")] public bool ShowSleep { get; set; } = true;
[JsonPropertyName("showRestart")] public bool ShowRestart { get; set; } = true;
[JsonPropertyName("showShutdown")] public bool ShowShutdown { get; set; } = true;
[JsonPropertyName("showHibernate")] public bool ShowHibernate { get; set; } = false;
[JsonPropertyName("showLogout")] public bool ShowLogout { get; set; } = true;
[JsonPropertyName("showRecycleBin")] public bool ShowRecycleBin { get; set; } = true;
/// <summary>
/// 시스템 명령 별칭. key = 기본 명령어(lock/sleep 등), value = 사용자 정의 별칭 목록.
/// 예: { "lock": ["잠금", "l"] } → /잠금, /l 로도 실행 가능
/// </summary>
[JsonPropertyName("commandAliases")]
public Dictionary<string, List<string>> CommandAliases { get; set; } = new();
}
// ─── 스크린 캡처 설정 ──────────────────────────────────────────────────────────
public class ScreenCaptureSettings
{
/// <summary>캡처 명령어 프리픽스. 기본값 "cap".</summary>
[JsonPropertyName("prefix")]
public string Prefix { get; set; } = "cap";
/// <summary>런처를 열지 않고 글로벌 단축키로 캡처하는 기능 활성화 여부.</summary>
[JsonPropertyName("globalHotkeyEnabled")]
public bool GlobalHotkeyEnabled { get; set; } = false;
/// <summary>글로벌 캡처 단축키 문자열. 기본값 "PrintScreen".</summary>
[JsonPropertyName("globalHotkey")]
public string GlobalHotkey { get; set; } = "PrintScreen";
/// <summary>글로벌 캡처 단축키 실행 모드. screen|window|region.</summary>
[JsonPropertyName("globalHotkeyMode")]
public string GlobalHotkeyMode { get; set; } = "screen";
/// <summary>스크롤 캡처 프레임 간 대기 시간(ms). 기본값 120.</summary>
[JsonPropertyName("scrollDelayMs")]
public int ScrollDelayMs { get; set; } = 120;
}
// ─── 잠금 해제 알림 설정 ───────────────────────────────────────────────────────
public class ReminderSettings
{
/// <summary>기능 활성화 여부. 기본값 false.</summary>
[JsonPropertyName("enabled")]
public bool Enabled { get; set; } = false;
/// <summary>팝업 표시 위치. top-left | top-right | bottom-left | bottom-right</summary>
[JsonPropertyName("corner")]
public string Corner { get; set; } = "bottom-right";
/// <summary>알림 간격(분). 30 | 60 | 120 | 180 | 240</summary>
[JsonPropertyName("intervalMinutes")]
public int IntervalMinutes { get; set; } = 60;
/// <summary>팝업 자동 닫힘 시간(초). 기본값 15. (5/10/15/20/30/60/120/180)</summary>
[JsonPropertyName("displaySeconds")]
public int DisplaySeconds { get; set; } = 15;
/// <summary>알림 콘텐츠 카테고리 활성화 목록.</summary>
[JsonPropertyName("enabledCategories")]
public List<string> EnabledCategories { get; set; } = new() { "motivational" };
}
// ─── LLM 채팅 설정 ──────────────────────────────────────────────────────────
public class LlmSettings
{
/// <summary>LLM 서비스 종류. ollama | vllm | gemini | claude</summary>
[JsonPropertyName("service")]
public string Service { get; set; } = "ollama";
/// <summary>엔드포인트 URL. Ollama 기본값 http://localhost:11434</summary>
[JsonPropertyName("endpoint")]
public string Endpoint { get; set; } = "http://localhost:11434";
/// <summary>모델 이름. 미설정 시 빈 문자열.</summary>
[JsonPropertyName("model")]
public string Model { get; set; } = "";
/// <summary>암호화된 API 키 (사내 Ollama/vLLM 전용). DPAPI+AES로 암호화된 Base64.</summary>
[JsonPropertyName("encryptedApiKey")]
public string EncryptedApiKey { get; set; } = "";
/// <summary>평문 API 키 (Gemini/Claude 등 외부 서비스). 사내 연결 제한으로 별도 암호화 없음.</summary>
[JsonPropertyName("apiKey")]
public string ApiKey { get; set; } = "";
/// <summary>스트리밍 응답 활성화. 기본값 true.</summary>
[JsonPropertyName("streaming")]
public bool Streaming { get; set; } = true;
/// <summary>최대 컨텍스트 토큰 수. 기본값 32768.</summary>
[JsonPropertyName("maxContextTokens")]
public int MaxContextTokens { get; set; } = 32_768;
/// <summary>대화 보관 기간(일). 7 | 30 | 90 | 0(무제한). 기본값 30.</summary>
[JsonPropertyName("retentionDays")]
public int RetentionDays { get; set; } = 30;
/// <summary>Temperature. 0.0~2.0, 기본값 0.7.</summary>
[JsonPropertyName("temperature")]
public double Temperature { get; set; } = 0.7;
/// <summary>등록 모델 프로파일의 자동 temperature 정책 사용 여부. 기본값 true.</summary>
[JsonPropertyName("useAutomaticProfileTemperature")]
public bool UseAutomaticProfileTemperature { get; set; } = true;
/// <summary>사내 서비스(Ollama/vLLM)용 등록 모델 목록. 별칭 + 암호화된 모델명.</summary>
[JsonPropertyName("registeredModels")]
public List<RegisteredModel> RegisteredModels { get; set; } = new();
/// <summary>
/// API 키/모델명 암호화 활성화 여부.
/// false: 평문 저장 (내부 개발 배포용)
/// true: PortableEncrypt로 암호화 저장 (운영 배포용)
/// 기본값 false. 운영 배포 시 true로 변경.
/// </summary>
[JsonPropertyName("encryptionEnabled")]
public bool EncryptionEnabled { get; set; } = false;
/// <summary>프롬프트 템플릿 목록.</summary>
[JsonPropertyName("promptTemplates")]
public List<PromptTemplate> PromptTemplates { get; set; } = new();
[JsonPropertyName("favoritePromptTemplates")]
public List<string> FavoritePromptTemplates { get; set; } = new();
[JsonPropertyName("recentPromptTemplates")]
public List<string> RecentPromptTemplates { get; set; } = new();
/// <summary>작업 폴더 경로. 빈 문자열이면 미선택. (레거시 — 탭별 경로 미지정 시 폴백)</summary>
[JsonPropertyName("workFolder")]
public string WorkFolder { get; set; } = "";
/// <summary>코워크(Cowork) 탭 전용 작업 폴더.</summary>
[JsonPropertyName("coworkWorkFolder")]
public string CoworkWorkFolder { get; set; } = "";
/// <summary>코드(Code) 탭 전용 작업 폴더.</summary>
[JsonPropertyName("codeWorkFolder")]
public string CodeWorkFolder { get; set; } = "";
/// <summary>최근 사용한 작업 폴더 목록.</summary>
[JsonPropertyName("recentWorkFolders")]
public List<string> RecentWorkFolders { get; set; } = new();
/// <summary>최근 폴더 최대 표시 개수 (기본 10, 범위 3~30).</summary>
[JsonPropertyName("maxRecentFolders")]
public int MaxRecentFolders { get; set; } = 10;
/// <summary>파일 탐색기 패널 표시 여부 (코워크 탭).</summary>
[JsonPropertyName("showFileBrowser")]
public bool ShowFileBrowser { get; set; } = false;
/// <summary>
/// 파일 접근 권한 수준.
/// Default = 매번 확인 | AcceptEdits = 파일 편집 자동 허용 | Plan = 계획/승인 중심
/// BypassPermissions = 모든 확인 생략 | Deny = 읽기 전용
/// </summary>
[JsonPropertyName("filePermission")]
public string FilePermission { get; set; } = "Deny";
/// <summary>Cowork/Code 탭의 기본 파일 접근 권한. 탭 전환 시 자동 적용.</summary>
[JsonPropertyName("defaultAgentPermission")]
public string DefaultAgentPermission { get; set; } = "Deny";
// ── 서비스별 독립 설정 ──────────────────────────────────────
[JsonPropertyName("ollamaEndpoint")] public string OllamaEndpoint { get; set; } = "http://localhost:11434";
[JsonPropertyName("ollamaApiKey")] public string OllamaApiKey { get; set; } = "";
[JsonPropertyName("ollamaModel")] public string OllamaModel { get; set; } = "";
[JsonPropertyName("vllmEndpoint")] public string VllmEndpoint { get; set; } = "";
[JsonPropertyName("vllmApiKey")] public string VllmApiKey { get; set; } = "";
[JsonPropertyName("vllmModel")] public string VllmModel { get; set; } = "";
[JsonPropertyName("vllmAllowInsecureTls")] public bool VllmAllowInsecureTls { get; set; } = false;
[JsonPropertyName("geminiApiKey")] public string GeminiApiKey { get; set; } = "";
[JsonPropertyName("geminiModel")] public string GeminiModel { get; set; } = "gemini-2.5-flash";
[JsonPropertyName("claudeApiKey")] public string ClaudeApiKey { get; set; } = "";
[JsonPropertyName("claudeModel")] public string ClaudeModel { get; set; } = "cl" + "aude-sonnet-4-6";
[JsonIgnore] public string SigmoidApiKey { get => ClaudeApiKey; set => ClaudeApiKey = value; }
[JsonIgnore] public string SigmoidModel { get => ClaudeModel; set => ClaudeModel = value; }
// ── Cowork 에이전트 설정 ─────────────────────────────────
/// <summary>기본 출력 포맷. auto | xlsx | docx | html | md | csv</summary>
[JsonPropertyName("defaultOutputFormat")]
public string DefaultOutputFormat { get; set; } = "auto";
/// <summary>기본 디자인 무드. modern | professional | creative 등</summary>
[JsonPropertyName("defaultMood")]
public string DefaultMood { get; set; } = "modern";
/// <summary>문서 미리보기 자동 열기. auto | manual | off</summary>
[JsonPropertyName("autoPreview")]
public string AutoPreview { get; set; } = "off";
/// <summary>미리보기 패널 너비 (픽셀). 드래그 조절 후 저장.</summary>
[JsonPropertyName("previewPanelWidth")]
public double PreviewPanelWidth { get; set; } = 420;
/// <summary>에이전트 최대 루프 반복 횟수.</summary>
[JsonPropertyName("maxAgentIterations")]
public int MaxAgentIterations { get; set; } = 25;
/// <summary>컨텍스트 사전 압축 활성화 여부.</summary>
[JsonPropertyName("enableProactiveContextCompact")]
public bool EnableProactiveContextCompact { get; set; } = true;
/// <summary>컨텍스트 압축 시작 임계치(%). 최대 토큰의 몇 %에서 압축 시작할지.</summary>
[JsonPropertyName("contextCompactTriggerPercent")]
public int ContextCompactTriggerPercent { get; set; } = 80;
/// <summary>도구 실패 시 최대 재시도 횟수 (Self-Reflection).</summary>
[JsonPropertyName("maxRetryOnError")]
public int MaxRetryOnError { get; set; } = 3;
/// <summary>테스트-수정 자동 반복 최대 횟수. auto_fix 모드에서 사용. 기본 5.</summary>
[JsonPropertyName("maxTestFixIterations")]
public int MaxTestFixIterations { get; set; } = 5;
/// <summary>에이전트 로그 표시 수준. hidden | simple | detailed | debug</summary>
[JsonPropertyName("agentLogLevel")]
public string AgentLogLevel { get; set; } = "detailed";
/// <summary>IBM+Qwen 조합 상세 진단 로깅 활성화. true 시 [IBM진단] 태그 Debug 로그 출력. 기본 false.</summary>
[JsonPropertyName("enableIbmDiagnosticLog")]
public bool EnableIbmDiagnosticLog { get; set; } = false;
/// <summary>AX Agent UI 표현 수준. rich | balanced | simple</summary>
[JsonPropertyName("agentUiExpressionLevel")]
public string AgentUiExpressionLevel { get; set; } = "balanced";
/// <summary>권한 팝업 섹션 접힘/펼침 상태. key=section id, value=true(펼침).</summary>
[JsonPropertyName("permissionPopupSections")]
public Dictionary<string, bool> PermissionPopupSections { get; set; } = new(StringComparer.OrdinalIgnoreCase);
/// <summary>슬래시 팔레트 그룹 접힘/펼침 상태. key=group id, value=true(펼침).</summary>
[JsonPropertyName("slashPaletteSections")]
public Dictionary<string, bool> SlashPaletteSections { get; set; } = new(StringComparer.OrdinalIgnoreCase);
/// <summary>계획 diff 심각도 중간 기준: 변경 개수 임계값.</summary>
[JsonPropertyName("planDiffSeverityMediumCount")]
public int PlanDiffSeverityMediumCount { get; set; } = 2;
/// <summary>계획 diff 심각도 대폭 기준: 변경 개수 임계값.</summary>
[JsonPropertyName("planDiffSeverityHighCount")]
public int PlanDiffSeverityHighCount { get; set; } = 5;
/// <summary>계획 diff 심각도 중간 기준: 변경 비율(%) 임계값.</summary>
[JsonPropertyName("planDiffSeverityMediumRatioPercent")]
public int PlanDiffSeverityMediumRatioPercent { get; set; } = 25;
/// <summary>계획 diff 심각도 대폭 기준: 변경 비율(%) 임계값.</summary>
[JsonPropertyName("planDiffSeverityHighRatioPercent")]
public int PlanDiffSeverityHighRatioPercent { get; set; } = 60;
/// <summary>LLM이 다수 도구를 동시 호출할 때 병렬 실행 활성화. 파일 충돌 없는 도구만 병렬 실행.</summary>
[JsonPropertyName("enableParallelTools")]
public bool EnableParallelTools { get; set; } = false;
/// <summary>멀티패스 문서 생성 사용 여부. 긴 문서(3페이지 이상) 작성 시 개요→섹션별 상세→조립 방식으로 품질 향상.</summary>
[JsonPropertyName("enableMultiPassDocument")]
public bool EnableMultiPassDocument { get; set; } = false;
/// <summary>
/// [Cowork] 도구 실행 후 검증 강제.
/// true: 문서 생성 도구(file_write, docx_create, html_create, xlsx_create 등) 실행 후
/// LLM에 검증 전용 호출을 자동 삽입하여 결과물 품질을 확인합니다.
/// false: LLM이 자율적으로 검증 여부를 결정합니다 (기존 동작).
/// </summary>
[JsonPropertyName("enableCoworkVerification")]
public bool EnableCoworkVerification { get; set; } = false;
/// <summary>
/// [Cowork] 검증 강제 시 워크스페이스 파일/폴더 참조를 채팅에서 파란색으로 강조 표시.
/// </summary>
[JsonPropertyName("enableFilePathHighlight")]
public bool EnableFilePathHighlight { get; set; } = true;
/// <summary>멀티패스 자동 실행 기준 (예상 페이지 수 이상일 때). 기본 3페이지.</summary>
[JsonPropertyName("multiPassThresholdPages")]
public int MultiPassThresholdPages { get; set; } = 3;
/// <summary>탭별 마지막 활성 대화 ID. 앱 재시작 시 마지막 대화를 자동 복원합니다.</summary>
[JsonPropertyName("lastConversationIds")]
public Dictionary<string, string> LastConversationIds { get; set; } = new();
/// <summary>마지막으로 활성화된 채팅 탭. Chat | Cowork | Code</summary>
[JsonPropertyName("lastActiveTab")]
public string LastActiveTab { get; set; } = "Chat";
/// <summary>폴더 데이터 활용 모드. none(미활용) | passive(소극) | active(적극)</summary>
[JsonPropertyName("folderDataUsage")]
public string FolderDataUsage { get; set; } = "none";
/// <summary>
/// 에이전트 의사결정 수준. AI가 중요한 작업 전에 사용자 확인을 요청하는 빈도.
/// minimal: 파일 삭제, 외부 명령만 확인
/// normal: + 새 파일 생성, 여러 파일 수정, 문서 생성, Git 커밋
/// detailed: + 모든 파일 수정에 diff 미리보기
/// </summary>
[JsonPropertyName("agentDecisionLevel")]
public string AgentDecisionLevel { get; set; } = "detailed";
/// <summary>
/// 프로젝트 규칙 자동 주입 활성화.
/// true: .ax/rules/ 디렉토리의 규칙을 시스템 프롬프트에 자동 포함
/// false: 규칙 주입 비활성 (project_rules 도구로 수동 읽기는 가능)
/// </summary>
[JsonPropertyName("enableProjectRules")]
public bool EnableProjectRules { get; set; } = true;
// ─── 모델 폴백 ──────────────────────────────────────────────────────
/// <summary>모델 API 실패 시 순차 시도할 폴백 모델 리스트. (예: "gemini:gemini-2.5-flash")</summary>
[JsonPropertyName("fallbackModels")]
public List<string> FallbackModels { get; set; } = new();
// ─── v1.4.0 에이전트 설정 ──────────────────────────────────────────────
/// <summary>서브에이전트 최대 동시 실행 수. 기본 3.</summary>
[JsonPropertyName("maxSubAgents")]
public int MaxSubAgents { get; set; } = 5;
/// <summary>PDF 내보내기 기본 경로. 빈 문자열이면 바탕화면.</summary>
[JsonPropertyName("pdfExportPath")]
public string PdfExportPath { get; set; } = "";
// ─── 보안 감사 로그 ──────────────────────────────────────────────────
/// <summary>에이전트 도구 호출 감사 로그 활성화. 기본 true.</summary>
[JsonPropertyName("enableAuditLog")]
public bool EnableAuditLog { get; set; } = true;
/// <summary>워크플로우 상세 로그 기록 활성화. 워크플로우 분석기와 함께 사용하면 LLM 요청/응답, 도구 호출 전체 이력을 기록합니다.</summary>
[JsonPropertyName("enableDetailedLog")]
public bool EnableDetailedLog { get; set; } = false;
/// <summary>상세 로그 보관 기간 (일). 이 기간이 지난 로그는 자동 삭제됩니다. 기본 3일.</summary>
[JsonPropertyName("detailedLogRetentionDays")]
public int DetailedLogRetentionDays { get; set; } = 3;
/// <summary>LLM에 보낸 요청 JSON과 돌아온 응답 원문을 모두 기록합니다. 디버깅용이며 파일 크기가 클 수 있습니다.</summary>
[JsonPropertyName("enableRawLlmLog")]
public bool EnableRawLlmLog { get; set; } = false;
/// <summary>에이전트 메모리 (지속적 학습) 활성화. 기본 true.</summary>
[JsonPropertyName("enableAgentMemory")]
public bool EnableAgentMemory { get; set; } = true;
/// <summary>폴더별 최대 메모리 항목 수. 기본 100.</summary>
[JsonPropertyName("maxMemoryEntries")]
public int MaxMemoryEntries { get; set; } = 100;
/// <summary>프로젝트 바깥 메모리 include 허용. 기본 false.</summary>
[JsonPropertyName("allowExternalMemoryIncludes")]
public bool AllowExternalMemoryIncludes { get; set; } = false;
// ─── 이미지 입력 (멀티모달) ──────────────────────────────────────────
/// <summary>이미지 입력(Ctrl+V 붙여넣기, 파일 첨부) 활성화. 기본 true.</summary>
[JsonPropertyName("enableImageInput")]
public bool EnableImageInput { get; set; } = true;
/// <summary>이미지 최대 크기(KB). 기본 5120 (5MB).</summary>
[JsonPropertyName("maxImageSizeKb")]
public int MaxImageSizeKb { get; set; } = 5120;
// ─── 자동 모델 라우팅 ─────────────────────────────────────────────
/// <summary>자동 모델 라우팅 활성화. 질문 유형 감지 → 최적 모델 자동 선택. 기본 false (잠금).</summary>
[JsonPropertyName("enableAutoRouter")]
public bool EnableAutoRouter { get; set; } = false;
/// <summary>자동 라우팅 최소 확신도. 이 값 미만이면 기본 모델 유지. 0.5~0.95, 기본 0.7.</summary>
[JsonPropertyName("autoRouterConfidence")]
public double AutoRouterConfidence { get; set; } = 0.7;
/// <summary>모델별 능력 점수 설정. 인텐트 카테고리별 적합도 0.0~1.0.</summary>
[JsonPropertyName("modelCapabilities")]
public List<ModelCapability> ModelCapabilities { get; set; } = new();
// ─── MCP ──────────────────────────────────────────────────────────
/// <summary>MCP 서버 설정 목록.</summary>
[JsonPropertyName("mcpServers")]
public List<McpServerEntry> McpServers { get; set; } = new();
// ─── 시각 효과 ──────────────────────────────────────────────────────
/// <summary>채팅 입력창 무지개 글로우 효과 활성화. 기본 false (성능 고려).</summary>
[JsonPropertyName("enableChatRainbowGlow")]
public bool EnableChatRainbowGlow { get; set; } = false;
/// <summary>새로운 뷰어 표시 버전(V2 사이드바 레이아웃) 사용. 기본 true.</summary>
[JsonPropertyName("enableNewPlanViewer")]
public bool EnableNewPlanViewer { get; set; } = true;
/// <summary>새로운 채팅 렌더링(V2 상세 이력) 사용. 기본 false.</summary>
[JsonPropertyName("enableNewChatRendering")]
public bool EnableNewChatRendering { get; set; } = false;
/// <summary>IntentGate LLM 폴백 활성화. 키워드 분류 confidence가 낮을 때 LLM 1-shot 분류 사용.</summary>
[JsonPropertyName("enableIntentGateLlmFallback")]
public bool EnableIntentGateLlmFallback { get; set; } = false;
/// <summary>IntentGate confidence 임계값. 이 값 미만이면 LLM 폴백 발동 (EnableIntentGateLlmFallback=true 시).</summary>
[JsonPropertyName("intentGateConfidenceThreshold")]
public double IntentGateConfidenceThreshold { get; set; } = 0.6;
/// <summary>세션 내 누적 학습 활성화. 도구 결과에서 학습 포인트를 자동 수집하여 후속 반복에 주입.</summary>
[JsonPropertyName("enableSessionLearnings")]
public bool EnableSessionLearnings { get; set; } = true;
/// <summary>최대 누적 학습 항목 수. FIFO로 관리.</summary>
[JsonPropertyName("maxSessionLearnings")]
public int MaxSessionLearnings { get; set; } = 10;
/// <summary>워크스페이스 컨텍스트 자동 생성 (.ax-context.md) 활성화.</summary>
[JsonPropertyName("enableAutoWorkspaceContext")]
public bool EnableAutoWorkspaceContext { get; set; } = true;
/// <summary>
/// 모델별 프롬프트 전략 수준.
/// "off": 모든 모델에 동일한 기본 프롬프트 사용 (기존 동작).
/// "basic": 모델 패밀리별 가벼운 프롬프트 어댑테이션 (규칙 추가/재배치).
/// "detailed": 모델별 전용 프롬프트 파일 적용 (임베디드 리소스, 수백 줄급 상세 지침).
/// </summary>
[JsonPropertyName("modelPromptLevel")]
public string ModelPromptLevel { get; set; } = "off";
/// <summary>이전 호환: EnableModelSpecificPrompting=true → "basic" 으로 마이그레이션.</summary>
[JsonPropertyName("enableModelSpecificPrompting")]
public bool EnableModelSpecificPrompting
{
get => !string.Equals(ModelPromptLevel, "off", StringComparison.OrdinalIgnoreCase);
set
{
if (value && string.Equals(ModelPromptLevel, "off", StringComparison.OrdinalIgnoreCase))
ModelPromptLevel = "basic";
else if (!value)
ModelPromptLevel = "off";
}
}
/// <summary>
/// Hash-Anchored Edits 활성화.
/// true: file_read 출력에 라인별 해시 앵커를 포함하고, file_edit에서 앵커 기반 편집 지원.
/// 편집 성공률이 크게 향상되며 스테일 편집을 자동 감지합니다.
/// false: 기존 라인번호 + old_string 방식 유지.
/// </summary>
[JsonPropertyName("enableHashAnchoredEdits")]
public bool EnableHashAnchoredEdits { get; set; } = false;
/// <summary>AX Agent 전용 테마. system | light | dark</summary>
[JsonPropertyName("agentTheme")]
public string AgentTheme { get; set; } = "system";
/// <summary>AX Agent 전용 테마 스타일. claude | codex | slate</summary>
[JsonPropertyName("agentThemePreset")]
public string AgentThemePreset { get; set; } = "claude";
// ─── 알림 ──────────────────────────────────────────────────────────
/// <summary>에이전트 작업 완료 시 시스템 알림 표시 여부. (Cowork/Code 공통)</summary>
[JsonPropertyName("notifyOnComplete")]
public bool NotifyOnComplete { get; set; } = false;
/// <summary>코워크 작업 완료 후 문서 자동 처리 방식.
/// "none" = 아무것도 안하기, "open" = 문서 실행(기본 앱), "preview" = 미리보기 뷰어.</summary>
[JsonPropertyName("coworkOnComplete")]
public string CoworkOnComplete { get; set; } = "none";
/// <summary>AI 대화창에서 팁 알림 표시 여부.</summary>
[JsonPropertyName("showTips")]
public bool ShowTips { get; set; } = false;
/// <summary>팁 알림 자동 사라짐 시간 (초). 0이면 수동 닫기.</summary>
[JsonPropertyName("tipDurationSeconds")]
public int TipDurationSeconds { get; set; } = 5;
// ─── 개발자 모드 ──────────────────────────────────────────────────
/// <summary>개발자 모드 활성화. 에이전트 워크플로우 상세 이력을 대화창에 실시간 표시.</summary>
[JsonPropertyName("devMode")]
public bool DevMode { get; set; } = false;
/// <summary>개발자 모드: 도구 실행 전 매번 사용자 승인 대기 (스텝 바이 스텝 디버깅).</summary>
[JsonPropertyName("devModeStepApproval")]
public bool DevModeStepApproval { get; set; } = false;
/// <summary>개발자 모드: 에이전트 실행 시 워크플로우 시각화 창을 자동으로 표시.</summary>
[JsonPropertyName("workflowVisualizer")]
public bool WorkflowVisualizer { get; set; } = false;
/// <summary>개발자 모드: 무료 티어 호출 제한 모드. 활성화하면 LLM 호출 간 딜레이를 추가하여 RPM 한도를 초과하지 않습니다.</summary>
[JsonPropertyName("freeTierMode")]
public bool FreeTierMode { get; set; } = false;
/// <summary>무료 티어 모드: LLM 호출 간 딜레이 (초). 기본 4초 (Gemini 무료 15 RPM ≈ 4초 간격).</summary>
[JsonPropertyName("freeTierDelaySeconds")]
public int FreeTierDelaySeconds { get; set; } = 4;
/// <summary>개발자 모드: 전체 누적 호출 횟수 및 토큰 합계를 상태바에 표시.</summary>
[JsonPropertyName("showTotalCallStats")]
public bool ShowTotalCallStats { get; set; } = false;
/// <summary>차단할 경로 패턴 목록 (에이전트 파일 접근 시 적용).</summary>
[JsonPropertyName("blockedPaths")]
public List<string> BlockedPaths { get; set; } = new()
{
"*\\Windows\\*", "*\\Program Files\\*", "*\\Program Files (x86)\\*",
"*\\System32\\*", "*\\AppData\\Local\\*",
};
/// <summary>차단할 파일 확장자 목록.</summary>
[JsonPropertyName("blockedExtensions")]
public List<string> BlockedExtensions { get; set; } = new()
{
".exe", ".dll", ".sys", ".msi",
".reg", ".vbs", ".com", ".scr", ".pif",
};
/// <summary>사용자가 만든 커스텀 프리셋 목록.</summary>
[JsonPropertyName("customPresets")]
public List<CustomPresetEntry> CustomPresets { get; set; } = new();
/// <summary>사용자가 만든 커스텀 디자인 무드 목록.</summary>
[JsonPropertyName("customMoods")]
public List<CustomMoodEntry> CustomMoods { get; set; } = new();
// ─── 도구 관리 ──────────────────────────────────────────────────
/// <summary>비활성화된 에이전트 도구 이름 목록. 여기에 포함된 도구는 LLM에 노출되지 않습니다.</summary>
[JsonPropertyName("disabledTools")]
public List<string> DisabledTools { get; set; } = new();
/// <summary>
/// 도구별 실행 권한 오버라이드. 키: 도구 이름 또는 tool@pattern, 값: 권한 모드.
/// 여기에 없는 도구는 전역 FilePermission 설정을 따릅니다.
/// </summary>
[JsonPropertyName("toolPermissions")]
public Dictionary<string, string> ToolPermissions { get; set; } = new();
// ─── 에이전트 훅 시스템 ───────────────────────────────────────────
/// <summary>에이전트 훅 활성화 여부. 기본 true.</summary>
[JsonPropertyName("enableToolHooks")]
public bool EnableToolHooks { get; set; } = true;
/// <summary>훅 스크립트 실행 타임아웃 (밀리초). 기본 10000 (10초).</summary>
[JsonPropertyName("toolHookTimeoutMs")]
public int ToolHookTimeoutMs { get; set; } = 10000;
/// <summary>Pre 훅의 입력(JSON) 갱신 결과를 실제 도구 입력에 반영할지 여부. 기본 false.</summary>
[JsonPropertyName("enableHookInputMutation")]
public bool EnableHookInputMutation { get; set; } = false;
/// <summary>훅의 도구 권한 업데이트 결과를 현재 실행 컨텍스트에 반영할지 여부. 기본 false.</summary>
[JsonPropertyName("enableHookPermissionUpdate")]
public bool EnableHookPermissionUpdate { get; set; } = false;
/// <summary>도구 실행 타임아웃 (밀리초). 0이면 기본값/환경변수 사용.</summary>
[JsonPropertyName("toolExecutionTimeoutMs")]
public int ToolExecutionTimeoutMs { get; set; } = 0;
/// <summary>같은 읽기 도구 시그니처 반복 루프 차단 임계값. 0이면 기본값/환경변수 사용.</summary>
[JsonPropertyName("readOnlySignatureLoopThreshold")]
public int ReadOnlySignatureLoopThreshold { get; set; } = 0;
/// <summary>읽기 전용 도구 연속 실행 정체 감지 임계값. 0이면 기본값/환경변수 사용.</summary>
[JsonPropertyName("readOnlyStagnationThreshold")]
public int ReadOnlyStagnationThreshold { get; set; } = 0;
/// <summary>비진행 복구 전환 임계값. 0이면 기본값/환경변수 사용.</summary>
[JsonPropertyName("noProgressRecoveryThreshold")]
public int NoProgressRecoveryThreshold { get; set; } = 0;
/// <summary>비진행 강제 중단 임계값. 0이면 기본값/환경변수 사용.</summary>
[JsonPropertyName("noProgressAbortThreshold")]
public int NoProgressAbortThreshold { get; set; } = 0;
/// <summary>비진행 복구 최대 재시도 횟수. 0이면 기본값/환경변수 사용.</summary>
[JsonPropertyName("noProgressRecoveryMaxRetries")]
public int NoProgressRecoveryMaxRetries { get; set; } = 0;
/// <summary>등록된 에이전트 훅 목록.</summary>
[JsonPropertyName("agentHooks")]
public List<AgentHookEntry> AgentHooks { get; set; } = new();
// ─── 스킬 시스템 ─────────────────────────────────────────────────
/// <summary>스킬 시스템 활성화 여부. 기본 true.</summary>
[JsonPropertyName("enableSkillSystem")]
public bool EnableSkillSystem { get; set; } = true;
/// <summary>
/// context=fork 스킬의 위임 우선 강제 여부. 기본 true.
/// true면 spawn_agent 우선 재계획을 유도하고, false면 정책 힌트만 적용합니다.
/// </summary>
[JsonPropertyName("enableForkSkillDelegationEnforcement")]
public bool EnableForkSkillDelegationEnforcement { get; set; } = true;
/// <summary>추가 스킬 폴더 경로. 빈 문자열이면 기본 폴더만 사용.</summary>
[JsonPropertyName("skillsFolderPath")]
public string SkillsFolderPath { get; set; } = "";
/// <summary>여분 스킬 폴더 목록. 프로젝트 외부 재사용 스킬 폴더를 추가로 연결합니다.</summary>
[JsonPropertyName("additionalSkillFolders")]
public List<string> AdditionalSkillFolders { get; set; } = new();
[JsonPropertyName("enableManagedSkillSource")]
public bool EnableManagedSkillSource { get; set; } = true;
[JsonPropertyName("enableUserSkillSource")]
public bool EnableUserSkillSource { get; set; } = true;
[JsonPropertyName("enableAdditionalSkillDiscovery")]
public bool EnableAdditionalSkillDiscovery { get; set; } = true;
[JsonPropertyName("enableProjectSkillDiscovery")]
public bool EnableProjectSkillDiscovery { get; set; } = true;
[JsonPropertyName("enablePluginSkillDiscovery")]
public bool EnablePluginSkillDiscovery { get; set; } = true;
[JsonPropertyName("enableMcpSkillDiscovery")]
public bool EnableMcpSkillDiscovery { get; set; } = true;
[JsonPropertyName("enablePluginOnlySkillMode")]
public bool EnablePluginOnlySkillMode { get; set; } = false;
[JsonPropertyName("enableLegacyCommandSkills")]
public bool EnableLegacyCommandSkills { get; set; } = true;
[JsonPropertyName("enableSkillInlineShell")]
public bool EnableSkillInlineShell { get; set; } = true;
[JsonPropertyName("allowPluginSkillInlineShell")]
public bool AllowPluginSkillInlineShell { get; set; } = false;
[JsonPropertyName("allowMcpSkillInlineShell")]
public bool AllowMcpSkillInlineShell { get; set; } = false;
[JsonPropertyName("skillInlineShellTimeoutSeconds")]
public int SkillInlineShellTimeoutSeconds { get; set; } = 8;
[JsonPropertyName("skillInlineShellMaxOutputChars")]
public int SkillInlineShellMaxOutputChars { get; set; } = 4000;
/// <summary>슬래시 명령어 팝업 한 번에 표시할 최대 항목 수 (3~20). 기본 7.</summary>
[JsonPropertyName("slashPopupPageSize")]
public int SlashPopupPageSize { get; set; } = 7;
/// <summary>즐겨찾기 슬래시 명령어 목록 (팝업 상단에 고정 표시). 예: ["/review", "/summary"]</summary>
[JsonPropertyName("favoriteSlashCommands")]
public List<string> FavoriteSlashCommands { get; set; } = new();
/// <summary>슬래시 핀(즐겨찾기) 최대 개수. 기본 10.</summary>
[JsonPropertyName("maxFavoriteSlashCommands")]
public int MaxFavoriteSlashCommands { get; set; } = 10;
/// <summary>최근 사용 슬래시 명령어 목록(MRU, 최신 순). 예: ["/compact", "/status"]</summary>
[JsonPropertyName("recentSlashCommands")]
public List<string> RecentSlashCommands { get; set; } = new();
/// <summary>슬래시 최근 사용(MRU) 최대 개수. 기본 20.</summary>
[JsonPropertyName("maxRecentSlashCommands")]
public int MaxRecentSlashCommands { get; set; } = 20;
// ─── 드래그 앤 드롭 AI 처리 ──────────────────────────────────────
/// <summary>파일 드래그 시 AI 액션 팝업 표시 여부. 기본 true.</summary>
[JsonPropertyName("enableDragDropAiActions")]
public bool EnableDragDropAiActions { get; set; } = true;
/// <summary>AI 액션 선택 시 자동 전송 여부. 기본 false.</summary>
[JsonPropertyName("dragDropAutoSend")]
public bool DragDropAutoSend { get; set; } = false;
/// <summary>Code 탭 전용 설정.</summary>
[JsonPropertyName("code")]
public CodeSettings Code { get; set; } = new();
}
/// <summary>Code 탭 설정 — 사내 개발 환경 연동.</summary>
public class CodeSettings
{
/// <summary>사내 Nexus 저장소 기본 URL. 빈 문자열이면 공용 저장소 사용.</summary>
[JsonPropertyName("nexusBaseUrl")]
public string NexusBaseUrl { get; set; } = "";
/// <summary>NuGet 패키지 소스 URL (.NET).</summary>
[JsonPropertyName("nugetSource")]
public string NugetSource { get; set; } = "https://api.nuget.org/v3/index.json";
/// <summary>PyPI/Conda 패키지 소스 URL (Python).</summary>
[JsonPropertyName("pypiSource")]
public string PypiSource { get; set; } = "https://conda.anaconda.org/conda-forge";
/// <summary>Maven 저장소 URL (Java).</summary>
[JsonPropertyName("mavenSource")]
public string MavenSource { get; set; } = "https://repo1.maven.org/maven2";
/// <summary>npm 레지스트리 URL (JavaScript/Node.js).</summary>
[JsonPropertyName("npmSource")]
public string NpmSource { get; set; } = "https://registry.npmjs.org";
/// <summary>선호 IDE 실행 경로. 빈 문자열이면 자동 감지.</summary>
[JsonPropertyName("preferredIdePath")]
public string PreferredIdePath { get; set; } = "";
/// <summary>빌드/테스트 명령 타임아웃 (초). 기본 120초.</summary>
[JsonPropertyName("buildTimeout")]
public int BuildTimeout { get; set; } = 120;
// ─── v1.4.0 코드 인텔리전스 설정 ─────────────────────────────────────────
/// <summary>LSP 코드 인텔리전스 활성화. 기본 true.</summary>
[JsonPropertyName("enableLsp")]
public bool EnableLsp { get; set; } = true;
/// <summary>코드 시맨틱 검색 자동 인덱싱 활성화. 기본 true.</summary>
[JsonPropertyName("enableCodeIndex")]
public bool EnableCodeIndex { get; set; } = true;
/// <summary>인덱싱 최대 파일 크기 (KB). 기본 500.</summary>
[JsonPropertyName("codeIndexMaxFileKb")]
public int CodeIndexMaxFileKb { get; set; } = 500;
/// <summary>파일 수정 시 diff 뷰어 자동 표시. 기본 true.</summary>
[JsonPropertyName("enableAutoDiff")]
public bool EnableAutoDiff { get; set; } = true;
/// <summary>AI 코드 리뷰 도구 활성화. 기본 true.</summary>
[JsonPropertyName("enableCodeReview")]
public bool EnableCodeReview { get; set; } = true;
/// <summary>코드 스니펫 즉시 실행 도구 활성화. 기본 true.</summary>
[JsonPropertyName("enableSnippetRunner")]
public bool EnableSnippetRunner { get; set; } = true;
/// <summary>
/// [Code] 도구 실행 후 검증 강제.
/// true: 코드 생성/수정 도구(script_create, file_write, file_edit 등) 실행 후
/// LLM에 검증 전용 호출을 자동 삽입하여 구문 오류, 참조 무결성을 확인합니다.
/// false: LLM이 자율적으로 검증 여부를 결정합니다 (기존 동작).
/// </summary>
[JsonPropertyName("enableCodeVerification")]
public bool EnableCodeVerification { get; set; } = false;
/// <summary>Code 탭에서 Worktree 도구(enter/exit worktree) 사용 여부. 기본 true.</summary>
[JsonPropertyName("enableWorktreeTools")]
public bool EnableWorktreeTools { get; set; } = true;
/// <summary>Code 탭에서 Team 도구(team create/delete) 사용 여부. 기본 true.</summary>
[JsonPropertyName("enableTeamTools")]
public bool EnableTeamTools { get; set; } = true;
/// <summary>Code 탭에서 Cron 도구(cron create/list/delete) 사용 여부. 기본 true.</summary>
[JsonPropertyName("enableCronTools")]
public bool EnableCronTools { get; set; } = true;
/// <summary>
/// Code 탭 빈 화면 마스코트 캐릭터 출동 수준.
/// "none"=출동 안하기, "one"=한명만(1), "few"=적게(3), "mid"=중간(6), "all"=전부(9+)
/// 기본 "none" (메모리 절약).
/// </summary>
[JsonPropertyName("mascotLevel")]
public string MascotLevel { get; set; } = "none";
/// <summary>(하위호환) 이전 bool 설정 — 무시됨. MascotLevel로 대체.</summary>
[JsonPropertyName("enableMascotCharacter")]
public bool EnableMascotCharacter { get; set; } = false;
}
/// <summary>사용자 정의 커스텀 프리셋 (settings.json에 저장).</summary>
public class CustomPresetEntry
{
[JsonPropertyName("id")]
public string Id { get; set; } = Guid.NewGuid().ToString("N")[..8];
[JsonPropertyName("label")]
public string Label { get; set; } = "";
[JsonPropertyName("description")]
public string Description { get; set; } = "";
[JsonPropertyName("systemPrompt")]
public string SystemPrompt { get; set; } = "";
[JsonPropertyName("color")]
public string Color { get; set; } = "#6366F1";
[JsonPropertyName("symbol")]
public string Symbol { get; set; } = "\uE713";
/// <summary>프리셋이 속하는 탭. "Chat" | "Cowork" | "Code"</summary>
[JsonPropertyName("tab")]
public string Tab { get; set; } = "Chat";
}
/// <summary>사용자 정의 디자인 무드 (CSS 템플릿).</summary>
public class CustomMoodEntry
{
[JsonPropertyName("key")]
public string Key { get; set; } = "";
[JsonPropertyName("label")]
public string Label { get; set; } = "";
[JsonPropertyName("icon")]
public string Icon { get; set; } = "🎯";
[JsonPropertyName("description")]
public string Description { get; set; } = "";
[JsonPropertyName("css")]
public string Css { get; set; } = "";
}
/// <summary>저장된 프롬프트 템플릿.</summary>
public class PromptTemplate
{
[JsonPropertyName("name")]
public string Name { get; set; } = "";
[JsonPropertyName("content")]
public string Content { get; set; } = "";
[JsonPropertyName("icon")]
public string Icon { get; set; } = "\uE8BD";
}
/// <summary>
/// 사내 LLM 등록 모델. 별칭(UI 표시용) + 암호화된 실제 모델명.
/// 향후 멀티 에이전트에서는 특화 업무와 연결됩니다.
/// </summary>
public class RegisteredModel
{
/// <summary>UI에 표시할 별칭 (예: "코드 리뷰 전용", "일반 대화")</summary>
[JsonPropertyName("alias")]
public string Alias { get; set; } = "";
/// <summary>실제 모델명. EncryptionEnabled=true일 때 PortableEncrypt로 암호화된 Base64 값, false일 때 평문.</summary>
[JsonPropertyName("encryptedModelName")]
public string EncryptedModelName { get; set; } = "";
/// <summary>이 모델이 연결될 서비스 타입. ollama | vllm</summary>
[JsonPropertyName("service")]
public string Service { get; set; } = "ollama";
/// <summary>
/// 실행 프로파일. balanced | tool_call_strict | reasoning_first | fast_readonly | document_heavy
/// 모델 성향에 따라 도구 호출 강도, 재시도, 메모리/압축 주입량을 조절합니다.
/// </summary>
[JsonPropertyName("executionProfile")]
public string ExecutionProfile { get; set; } = "balanced";
/// <summary>
/// 프롬프트 전략 패밀리. qwen | deepseek | kimi | gemma | llama | mistral | phi | yi | gemini | claude | default
/// 비어있으면 모델명에서 자동 감지합니다.
/// </summary>
[JsonPropertyName("promptFamily")]
public string PromptFamily { get; set; } = "";
/// <summary>이 모델 전용 서버 엔드포인트. 비어있으면 LlmSettings의 기본 엔드포인트 사용.</summary>
[JsonPropertyName("endpoint")]
public string Endpoint { get; set; } = "";
/// <summary>이 모델 전용 API 키. 비어있으면 LlmSettings의 기본 API 키 사용.</summary>
[JsonPropertyName("apiKey")]
public string ApiKey { get; set; } = "";
/// <summary>이 모델에 한해 TLS 인증서 검증을 생략합니다(vLLM 사내 인증서 예외 대응).</summary>
[JsonPropertyName("allowInsecureTls")]
public bool AllowInsecureTls { get; set; } = false;
// ── CP4D (IBM Cloud Pak for Data) 인증 ──────────────────────────────
/// <summary>인증 방식. bearer (기본) | ibm_iam | cp4d_password | cp4d_api_key</summary>
[JsonPropertyName("authType")]
public string AuthType { get; set; } = "bearer";
/// <summary>CP4D 인증 서버 URL (예: https://cpd-host.example.com)</summary>
[JsonPropertyName("cp4dUrl")]
public string Cp4dUrl { get; set; } = "";
/// <summary>CP4D 사용자 이름</summary>
[JsonPropertyName("cp4dUsername")]
public string Cp4dUsername { get; set; } = "";
/// <summary>CP4D 비밀번호 또는 API 키 (인증 방식에 따라 사용, EncryptionEnabled=true 시 암호화 저장)</summary>
[JsonPropertyName("cp4dPassword")]
public string Cp4dPassword { get; set; } = "";
}
/// <summary>
/// 자동 모델 라우팅용 모델 능력 점수.
/// 각 모델의 인텐트 카테고리별 적합도를 0.0~1.0으로 지정합니다.
/// 개발자가 하드코딩 기본값을 수정하려면 ModelRouterService.GetDefaultCapabilities()를 참조하세요.
/// </summary>
public class ModelCapability
{
/// <summary>서비스 타입. ollama | vllm | gemini | claude</summary>
[JsonPropertyName("service")]
public string Service { get; set; } = "";
/// <summary>모델 식별자. 서비스별 모델 ID (예: "gemini-2.5-flash", "claude-sonnet-4-6")</summary>
[JsonPropertyName("model")]
public string Model { get; set; } = "";
/// <summary>UI 표시용 별칭.</summary>
[JsonPropertyName("alias")]
public string Alias { get; set; } = "";
/// <summary>인텐트 카테고리별 적합도 점수. key=카테고리명, value=0.0~1.0</summary>
[JsonPropertyName("scores")]
public Dictionary<string, double> Scores { get; set; } = new();
/// <summary>라우팅 후보에 포함 여부.</summary>
[JsonPropertyName("enabled")]
public bool Enabled { get; set; } = true;
}
/// <summary>에이전트 훅 설정 항목. 도구 실행 전/후 사용자 스크립트 실행.</summary>
public class AgentHookEntry
{
/// <summary>훅 이름 (UI 표시용).</summary>
[JsonPropertyName("name")]
public string Name { get; set; } = "";
/// <summary>대상 도구 이름. "*" = 모든 도구, 특정 도구명 = 해당 도구만.</summary>
[JsonPropertyName("toolName")]
public string ToolName { get; set; } = "*";
/// <summary>실행 타이밍. "pre" = 도구 실행 전, "post" = 도구 실행 후.</summary>
[JsonPropertyName("timing")]
public string Timing { get; set; } = "post";
/// <summary>실행할 스크립트 경로 (.bat, .ps1, .cmd).</summary>
[JsonPropertyName("scriptPath")]
public string ScriptPath { get; set; } = "";
/// <summary>스크립트에 전달할 추가 인수 (선택).</summary>
[JsonPropertyName("arguments")]
public string Arguments { get; set; } = "";
/// <summary>활성화 여부.</summary>
[JsonPropertyName("enabled")]
public bool Enabled { get; set; } = true;
}