Some checks failed
Release Gate / gate (push) Has been cancelled
- .gitignore에 bin/obj/publish 및 IDE/OS/비밀정보 패턴 추가 - Git 인덱스에서 publish 및 src 하위 bin/obj 빌드 부산물 추적을 해제하여 저장소 노이즈를 정리 - DraftQueue를 실행 대기/최근 결과 섹션과 상태 요약 pill 구조로 재정리 - composer 상단 모델/컨텍스트/프리셋 줄과 하단 작업 위치 칩 UI를 더 평평한 시각 언어로 통일 - 워크스페이스·브랜치·워크트리 패널에 공통 row 및 요약 strip을 적용해 panel UX를 정돈 - README.md와 docs/DEVELOPMENT.md, docs/AGENT_ROADMAP.md, AGENTS.md 이력을 갱신 검증 - dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ - 경고 0개, 오류 0개
289 lines
9.7 KiB
C#
289 lines
9.7 KiB
C#
using System.Text.Json.Serialization;
|
||
|
||
namespace AxCopilot.Models;
|
||
|
||
/// <summary>대화 주제 카테고리.</summary>
|
||
public static class ChatCategory
|
||
{
|
||
public const string General = "일반";
|
||
public const string Management = "경영";
|
||
public const string HR = "인사";
|
||
public const string Finance = "재무";
|
||
public const string RnD = "연구개발";
|
||
public const string Product = "제품분석";
|
||
public const string Yield = "수율분석";
|
||
public const string MfgTech = "제조기술";
|
||
public const string System = "시스템";
|
||
|
||
public static readonly (string Key, string Label, string Symbol, string Color)[] All =
|
||
{
|
||
(General, "일반", "\uE8BD", "#6B7280"), // Chat – gray
|
||
(Management, "경영", "\uE902", "#8B5CF6"), // Briefcase – purple
|
||
(HR, "인사", "\uE716", "#0EA5E9"), // People – sky blue
|
||
(Finance, "재무", "\uE8C7", "#D97706"), // Money – amber/orange
|
||
(RnD, "연구개발", "\uE9A8", "#3B82F6"), // Research – blue
|
||
(Product, "제품분석", "\uE9D9", "#EC4899"), // Design – pink
|
||
(Yield, "수율분석", "\uE9F9", "#F59E0B"), // Analytics – amber
|
||
(MfgTech, "제조기술", "\uE90F", "#10B981"), // Manufacturing – emerald
|
||
(System, "시스템", "\uE770", "#EF4444"), // IT System – red
|
||
};
|
||
|
||
public static string GetSymbol(string? category)
|
||
{
|
||
if (string.IsNullOrEmpty(category)) return "\uE8BD";
|
||
foreach (var (key, _, symbol, _) in All)
|
||
if (key == category) return symbol;
|
||
return "\uE8BD";
|
||
}
|
||
|
||
public static string GetColor(string? category)
|
||
{
|
||
if (string.IsNullOrEmpty(category)) return "#6B7280";
|
||
foreach (var (key, _, _, color) in All)
|
||
if (key == category) return color;
|
||
return "#6B7280";
|
||
}
|
||
}
|
||
|
||
/// <summary>하나의 대화(세션). 복수의 메시지를 포함합니다.</summary>
|
||
public class ChatConversation
|
||
{
|
||
[JsonPropertyName("id")]
|
||
public string Id { get; set; } = Guid.NewGuid().ToString("N");
|
||
|
||
[JsonPropertyName("title")]
|
||
public string Title { get; set; } = "새 대화";
|
||
|
||
[JsonPropertyName("createdAt")]
|
||
public DateTime CreatedAt { get; set; } = DateTime.Now;
|
||
|
||
[JsonPropertyName("updatedAt")]
|
||
public DateTime UpdatedAt { get; set; } = DateTime.Now;
|
||
|
||
[JsonPropertyName("pinned")]
|
||
public bool Pinned { get; set; } = false;
|
||
|
||
/// <summary>대화가 속한 탭. "Chat" | "Cowork" | "Code".</summary>
|
||
[JsonPropertyName("tab")]
|
||
public string Tab { get; set; } = "Chat";
|
||
|
||
/// <summary>대화 주제. ChatCategory 상수 중 하나.</summary>
|
||
[JsonPropertyName("category")]
|
||
public string Category { get; set; } = ChatCategory.General;
|
||
|
||
/// <summary>사용자가 보이지 않는 시스템 명령어 (대화별 커스텀 프롬프트).</summary>
|
||
[JsonPropertyName("systemCommand")]
|
||
public string SystemCommand { get; set; } = "";
|
||
|
||
/// <summary>대화에 연결된 작업 폴더 경로.</summary>
|
||
[JsonPropertyName("workFolder")]
|
||
public string WorkFolder { get; set; } = "";
|
||
|
||
/// <summary>첫 사용자 메시지 요약 (검색용, 최대 100자). 저장 시 자동 갱신.</summary>
|
||
[JsonPropertyName("preview")]
|
||
public string Preview { get; set; } = "";
|
||
|
||
/// <summary>분기 원본 대화 ID. null이면 원본 대화.</summary>
|
||
[JsonPropertyName("parentId")]
|
||
public string? ParentId { get; set; }
|
||
|
||
/// <summary>분기 라벨 (예: "대안 A", "접근법 2").</summary>
|
||
[JsonPropertyName("branchLabel")]
|
||
public string? BranchLabel { get; set; }
|
||
|
||
/// <summary>분기 시점의 메시지 인덱스 (parentId의 Messages[index] 이후부터 분기).</summary>
|
||
[JsonPropertyName("branchAtIndex")]
|
||
public int? BranchAtIndex { get; set; }
|
||
|
||
// ─── 대화별 설정 (하단 바에서 변경, 대화마다 독립 저장) ───
|
||
|
||
/// <summary>파일 접근 권한. null이면 전역 설정 사용. "Ask" | "Plan" | "Auto" | "Deny"</summary>
|
||
[JsonPropertyName("permission")]
|
||
public string? Permission { get; set; }
|
||
|
||
/// <summary>데이터 활용 모드. null이면 전역 설정 사용. "active" | "passive" | "none"</summary>
|
||
[JsonPropertyName("dataUsage")]
|
||
public string? DataUsage { get; set; }
|
||
|
||
/// <summary>출력 포맷. null이면 전역 설정 사용.</summary>
|
||
[JsonPropertyName("outputFormat")]
|
||
public string? OutputFormat { get; set; }
|
||
|
||
/// <summary>무드/디자인 템플릿. null이면 전역 설정 사용.</summary>
|
||
[JsonPropertyName("mood")]
|
||
public string? Mood { get; set; }
|
||
|
||
[JsonPropertyName("messages")]
|
||
public List<ChatMessage> Messages { get; set; } = new();
|
||
|
||
[JsonPropertyName("executionEvents")]
|
||
public List<ChatExecutionEvent> ExecutionEvents { get; set; } = new();
|
||
|
||
[JsonPropertyName("draftQueue")]
|
||
public List<string> DraftQueue { get; set; } = new();
|
||
|
||
[JsonPropertyName("draftQueueItems")]
|
||
public List<DraftQueueItem> DraftQueueItems { get; set; } = new();
|
||
|
||
[JsonPropertyName("showExecutionHistory")]
|
||
public bool ShowExecutionHistory { get; set; } = true;
|
||
|
||
[JsonPropertyName("agentRunHistory")]
|
||
public List<ChatAgentRunRecord> AgentRunHistory { get; set; } = new();
|
||
|
||
[JsonPropertyName("conversationFailedOnlyFilter")]
|
||
public bool ConversationFailedOnlyFilter { get; set; }
|
||
|
||
[JsonPropertyName("conversationRunningOnlyFilter")]
|
||
public bool ConversationRunningOnlyFilter { get; set; }
|
||
|
||
[JsonPropertyName("conversationSortMode")]
|
||
public string ConversationSortMode { get; set; } = "activity";
|
||
}
|
||
|
||
public class ChatAgentRunRecord
|
||
{
|
||
[JsonPropertyName("runId")]
|
||
public string RunId { get; set; } = "";
|
||
|
||
[JsonPropertyName("status")]
|
||
public string Status { get; set; } = "completed";
|
||
|
||
[JsonPropertyName("summary")]
|
||
public string Summary { get; set; } = "";
|
||
|
||
[JsonPropertyName("lastIteration")]
|
||
public int LastIteration { get; set; }
|
||
|
||
[JsonPropertyName("startedAt")]
|
||
public DateTime StartedAt { get; set; } = DateTime.Now;
|
||
|
||
[JsonPropertyName("updatedAt")]
|
||
public DateTime UpdatedAt { get; set; } = DateTime.Now;
|
||
}
|
||
|
||
public class DraftQueueItem
|
||
{
|
||
[JsonPropertyName("id")]
|
||
public string Id { get; set; } = Guid.NewGuid().ToString("N");
|
||
|
||
[JsonPropertyName("text")]
|
||
public string Text { get; set; } = "";
|
||
|
||
[JsonPropertyName("priority")]
|
||
public string Priority { get; set; } = "next";
|
||
|
||
[JsonPropertyName("kind")]
|
||
public string Kind { get; set; } = "message";
|
||
|
||
[JsonPropertyName("state")]
|
||
public string State { get; set; } = "queued";
|
||
|
||
[JsonPropertyName("attemptCount")]
|
||
public int AttemptCount { get; set; }
|
||
|
||
[JsonPropertyName("lastError")]
|
||
public string? LastError { get; set; }
|
||
|
||
[JsonPropertyName("nextRetryAt")]
|
||
public DateTime? NextRetryAt { get; set; }
|
||
|
||
[JsonPropertyName("createdAt")]
|
||
public DateTime CreatedAt { get; set; } = DateTime.Now;
|
||
}
|
||
|
||
/// <summary>대화 내 개별 메시지.</summary>
|
||
public class ChatMessage
|
||
{
|
||
[JsonPropertyName("role")]
|
||
public string Role { get; set; } = "user"; // "user" | "assistant" | "system"
|
||
|
||
[JsonPropertyName("content")]
|
||
public string Content { get; set; } = "";
|
||
|
||
[JsonPropertyName("timestamp")]
|
||
public DateTime Timestamp { get; set; } = DateTime.Now;
|
||
|
||
[JsonPropertyName("metaKind")]
|
||
public string? MetaKind { get; set; }
|
||
|
||
[JsonPropertyName("metaRunId")]
|
||
public string? MetaRunId { get; set; }
|
||
|
||
/// <summary>피드백 상태. null=없음, "like", "dislike"</summary>
|
||
[JsonPropertyName("feedback")]
|
||
public string? Feedback { get; set; }
|
||
|
||
/// <summary>첨부된 파일 경로 목록.</summary>
|
||
[JsonPropertyName("attachedFiles")]
|
||
public List<string>? AttachedFiles { get; set; }
|
||
|
||
/// <summary>첨부된 이미지 목록. base64 인코딩된 이미지 데이터.</summary>
|
||
[JsonPropertyName("images")]
|
||
public List<ImageAttachment>? Images { get; set; }
|
||
}
|
||
|
||
public class ChatExecutionEvent
|
||
{
|
||
[JsonPropertyName("timestamp")]
|
||
public DateTime Timestamp { get; set; } = DateTime.Now;
|
||
|
||
[JsonPropertyName("runId")]
|
||
public string RunId { get; set; } = "";
|
||
|
||
[JsonPropertyName("type")]
|
||
public string Type { get; set; } = "Thinking";
|
||
|
||
[JsonPropertyName("toolName")]
|
||
public string ToolName { get; set; } = "";
|
||
|
||
[JsonPropertyName("summary")]
|
||
public string Summary { get; set; } = "";
|
||
|
||
[JsonPropertyName("filePath")]
|
||
public string? FilePath { get; set; }
|
||
|
||
[JsonPropertyName("success")]
|
||
public bool Success { get; set; } = true;
|
||
|
||
[JsonPropertyName("stepCurrent")]
|
||
public int StepCurrent { get; set; }
|
||
|
||
[JsonPropertyName("stepTotal")]
|
||
public int StepTotal { get; set; }
|
||
|
||
[JsonPropertyName("steps")]
|
||
public List<string>? Steps { get; set; }
|
||
|
||
[JsonPropertyName("elapsedMs")]
|
||
public long ElapsedMs { get; set; }
|
||
|
||
[JsonPropertyName("inputTokens")]
|
||
public int InputTokens { get; set; }
|
||
|
||
[JsonPropertyName("outputTokens")]
|
||
public int OutputTokens { get; set; }
|
||
|
||
[JsonPropertyName("toolInput")]
|
||
public string? ToolInput { get; set; }
|
||
|
||
[JsonPropertyName("iteration")]
|
||
public int Iteration { get; set; }
|
||
}
|
||
|
||
/// <summary>이미지 첨부 데이터. LLM Vision API에 전달되는 base64 인코딩 이미지.</summary>
|
||
public class ImageAttachment
|
||
{
|
||
/// <summary>base64 인코딩된 이미지 데이터.</summary>
|
||
[JsonPropertyName("base64")]
|
||
public string Base64 { get; set; } = "";
|
||
|
||
/// <summary>MIME 타입. image/png, image/jpeg 등.</summary>
|
||
[JsonPropertyName("mimeType")]
|
||
public string MimeType { get; set; } = "image/png";
|
||
|
||
/// <summary>원본 파일명 또는 설명.</summary>
|
||
[JsonPropertyName("fileName")]
|
||
public string FileName { get; set; } = "";
|
||
}
|