package cc.unitmesh.devins.ui.compose.agent.codereview import cc.unitmesh.agent.codereview.ModifiedCodeRange import cc.unitmesh.agent.linter.LintFileResult import cc.unitmesh.agent.diff.ChangeType import cc.unitmesh.agent.diff.DiffHunk import cc.unitmesh.agent.tracker.IssueInfo import kotlinx.serialization.Serializable /** * Complete state for Code Review side-by-side UI */ data class CodeReviewState( val isLoading: Boolean = false, val isLoadingDiff: Boolean = false, // Loading diff for a specific commit (not blocking UI) val error: String? = null, val commitHistory: List = emptyList(), val selectedCommitIndices: Set = emptySet(), val diffFiles: List = emptyList(), val selectedFileIndex: Int = 0, val aiProgress: AIAnalysisProgress = AIAnalysisProgress(), val fixResults: List = emptyList(), // Infinite scroll support val hasMoreCommits: Boolean = false, val isLoadingMore: Boolean = false, val totalCommitCount: Int? = null, val originDiff: String? = null, // Test coverage val relatedTests: Map> = emptyMap(), val isLoadingTests: Boolean = false, // File viewer val fileViewerPath: String? = null, val fileViewerStartLine: Int? = null, val fileViewerEndLine: Int? = null, // PR Review Comments val prNumber: Int? = null, val prCommentThreads: Map> = emptyMap(), // Grouped by file path val isLoadingPRComments: Boolean = false, val prCommentsError: String? = null, val expandedThreadId: String? = null // Currently expanded thread ID ) /** * Information about a file in the diff * Extends FileDiff from sketch package with CodeReview-specific fields */ data class DiffFileInfo( val path: String, val oldPath: String? = null, // For renamed files val changeType: ChangeType = ChangeType.EDIT, val hunks: List = emptyList(), val language: String? = null ) /** * AI analysis progress for streaming display */ data class AIAnalysisProgress( val stage: AnalysisStage = AnalysisStage.IDLE, val currentFile: String? = null, val currentLine: Int? = null, val lintOutput: String = "", val lintResults: List = emptyList(), val modifiedCodeRanges: Map> = emptyMap(), val analysisOutput: String = "", val reviewFindings: List = emptyList(), val planOutput: String = "", val fixOutput: String = "", val userFeedback: String = "", // ComposeRenderer for streaming fix generation (null if not started) val fixRenderer: cc.unitmesh.devins.ui.compose.agent.ComposeRenderer? = null ) /** * Stages of AI analysis */ enum class AnalysisStage { IDLE, RUNNING_LINT, ANALYZING_LINT, GENERATING_PLAN, WAITING_FOR_USER_INPUT, GENERATING_FIX, COMPLETED, ERROR } /** * Result of a single fix for a specific issue */ @Serializable data class FixResult( val filePath: String, val line: Int, val lintIssue: String, val lintValid: Boolean, val risk: RiskLevel, val aiFix: String, val fixedCode: String? = null, val status: FixStatus ) /** * Risk level of the issue */ @Serializable enum class RiskLevel { CRITICAL, HIGH, MEDIUM, LOW, INFO } /** * Status of the fix */ @Serializable enum class FixStatus { FIXED, // AI has fixed the issue NO_ISSUE, // No issue found SKIPPED, // User chose to skip FAILED // Fix failed } /** * Request to get diff from workspace */ data class DiffRequest( val commitHash: String? = null, // null = get last commit val baseBranch: String? = null, val compareWith: String? = null ) data class CommitInfo( val hash: String, val shortHash: String, val author: String, val timestamp: Long, val date: String, val message: String, val issueInfo: IssueInfo? = null, // Issue information extracted from commit message val isLoadingIssue: Boolean = false, // Whether issue info is being loaded val issueLoadError: String? = null, // Error message if issue loading failed (e.g., needs token) val issueFromCache: Boolean = false, // Whether issue info was loaded from cache val issueCacheAge: String? = null // Human-readable cache age (e.g., "5m ago") )