Skip to content

Commit 67b3136

Browse files
committed
feat(ui): unify agent type handling and routing
#453 Refactor agent type management to use a unified AgentType enum and centralize agent interface routing. Simplifies switching between local, coding, code review, and remote agents. Updates state handling and interface logic for consistency.
1 parent 61fed2c commit 67b3136

File tree

5 files changed

+251
-145
lines changed

5 files changed

+251
-145
lines changed

mpp-core/src/androidMain/kotlin/cc/unitmesh/agent/platform/GitOperations.android.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package cc.unitmesh.agent.platform
22

33
import cc.unitmesh.agent.logging.getLogger
4+
import cc.unitmesh.devins.workspace.GitCommitInfo
5+
import cc.unitmesh.devins.workspace.GitDiffInfo
46

57
/**
68
* Android 平台的 Git 操作实现
@@ -22,4 +24,20 @@ actual class GitOperations actual constructor(private val projectPath: String) {
2224
}
2325

2426
actual fun isSupported(): Boolean = false
27+
28+
actual suspend fun getRecentCommits(count: Int): List<GitCommitInfo> {
29+
return emptyList()
30+
}
31+
32+
actual suspend fun getTotalCommitCount(): Int? {
33+
return null
34+
}
35+
36+
actual suspend fun getCommitDiff(commitHash: String): GitDiffInfo? {
37+
return null
38+
}
39+
40+
actual suspend fun getDiff(base: String, target: String): GitDiffInfo? {
41+
return null
42+
}
2543
}

mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/AutoDevApp.kt

Lines changed: 113 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,10 @@ private fun AutoDevContent(
8484
var useAgentMode by remember { mutableStateOf(true) } // 恢复默认 Agent 模式(SessionSidebar 现在支持所有模式)
8585
var isTreeViewVisible by remember { mutableStateOf(false) } // TreeView visibility for agent mode
8686

87-
// Agent Type Selection (Coding vs Code Review)
88-
var currentAgentType by remember { mutableStateOf(AgentType.CODING) }
87+
// Unified Agent Type Selection (LOCAL, CODING, CODE_REVIEW, REMOTE)
88+
var selectedAgentType by remember { mutableStateOf(AgentType.CODING) }
8989

9090
// Remote Agent state
91-
var selectedAgentType by remember { mutableStateOf("Local") }
9291
var serverUrl by remember { mutableStateOf("http://localhost:8080") }
9392
var useServerConfig by remember { mutableStateOf(false) }
9493
var showRemoteConfigDialog by remember { mutableStateOf(false) }
@@ -108,8 +107,9 @@ private fun AutoDevContent(
108107

109108
val workspaceState by WorkspaceManager.workspaceFlow.collectAsState()
110109

111-
fun handleAgentTypeChange(type: String) {
112-
if (type == "Remote") {
110+
fun handleAgentTypeChange(type: AgentType) {
111+
// Check remote configuration if switching to remote mode
112+
if (type == AgentType.REMOTE) {
113113
val hasValidServerConfig = serverUrl.isNotBlank() && serverUrl != "http://localhost:8080"
114114
if (!hasValidServerConfig) {
115115
showRemoteConfigDialog = true
@@ -120,7 +120,13 @@ private fun AutoDevContent(
120120
selectedAgentType = type
121121
scope.launch {
122122
try {
123-
cc.unitmesh.devins.ui.config.saveAgentTypePreference(type)
123+
// Save as string for config compatibility
124+
val typeString = when (type) {
125+
AgentType.REMOTE -> "Remote"
126+
AgentType.LOCAL -> "Local"
127+
else -> "Local" // CODING and CODE_REVIEW are local modes
128+
}
129+
cc.unitmesh.devins.ui.config.saveAgentTypePreference(typeString)
124130
} catch (e: Exception) {
125131
println("⚠️ 保存 Agent 类型失败: ${e.message}")
126132
}
@@ -214,10 +220,19 @@ private fun AutoDevContent(
214220
}
215221
}
216222

223+
// Load agent type from config or initial mode
217224
selectedAgentType = when (initialMode) {
218-
"remote", "session" -> "Remote"
219-
"local" -> "Local"
220-
else -> wrapper.getAgentType() // "auto" - 从配置加载
225+
"remote", "session" -> AgentType.REMOTE
226+
"local" -> AgentType.LOCAL
227+
else -> {
228+
// "auto" - load from config
229+
val configType = wrapper.getAgentType()
230+
when (configType) {
231+
"Remote" -> AgentType.REMOTE
232+
"Local" -> AgentType.LOCAL
233+
else -> AgentType.CODING // Default to CODING
234+
}
235+
}
221236
}
222237

223238
useSessionManagement = (initialMode == "session")
@@ -298,7 +313,7 @@ private fun AutoDevContent(
298313
onOpenLocalChat = if (Platform.isJvm) {
299314
{
300315
useSessionManagement = false
301-
selectedAgentType = "Local"
316+
selectedAgentType = AgentType.LOCAL
302317
}
303318
} else null
304319
)
@@ -361,7 +376,11 @@ private fun AutoDevContent(
361376
availableAgents = availableAgents,
362377
useAgentMode = useAgentMode,
363378
isTreeViewVisible = isTreeViewVisible,
364-
selectedAgentType = selectedAgentType,
379+
selectedAgentType = if (selectedAgentType == AgentType.REMOTE) "Remote" else "Local",
380+
selectedTaskAgentType = selectedAgentType,
381+
onTaskAgentTypeChange = { type ->
382+
handleAgentTypeChange(type)
383+
},
365384
useSessionManagement = useSessionManagement,
366385
showSessionSidebar = showSessionSidebar,
367386
onToggleSidebar = { showSessionSidebar = !showSessionSidebar },
@@ -387,7 +406,15 @@ private fun AutoDevContent(
387406
},
388407
onModeToggle = { useAgentMode = !useAgentMode },
389408
onToggleTreeView = { isTreeViewVisible = !isTreeViewVisible },
390-
onAgentTypeChange = ::handleAgentTypeChange,
409+
onAgentTypeChange = { typeString ->
410+
// Convert string to AgentType
411+
val type = when (typeString) {
412+
"Remote" -> AgentType.REMOTE
413+
"Local" -> AgentType.LOCAL
414+
else -> AgentType.LOCAL
415+
}
416+
handleAgentTypeChange(type)
417+
},
391418
onConfigureRemote = { showRemoteConfigDialog = true },
392419
onSessionManagementToggle = {
393420
useSessionManagement = !useSessionManagement
@@ -402,116 +429,79 @@ private fun AutoDevContent(
402429
}
403430

404431
if (useAgentMode) {
405-
if (selectedAgentType == "Local") {
406-
AgentInterfaceRouter(
407-
llmService = llmService,
408-
isTreeViewVisible = isTreeViewVisible,
409-
onConfigWarning = { showModelConfigDialog = true },
410-
onToggleTreeView = { isTreeViewVisible = it },
411-
chatHistoryManager = chatHistoryManager,
412-
onSessionSelected = { sessionId ->
413-
messages = chatHistoryManager.getMessages()
414-
currentStreamingOutput = ""
415-
},
416-
onNewChat = {
417-
messages = emptyList()
418-
currentStreamingOutput = ""
419-
},
420-
onInternalSessionSelected = { handler ->
421-
agentSessionSelectedHandler = handler
422-
},
423-
onInternalNewChat = { handler ->
424-
agentNewChatHandler = handler
425-
},
426-
hasHistory = messages.isNotEmpty(),
427-
hasDebugInfo = compilerOutput.isNotEmpty(),
428-
currentModelConfig = currentModelConfig,
429-
selectedAgent = selectedAgent,
430-
availableAgents = availableAgents,
431-
useAgentMode = useAgentMode,
432-
selectedAgentType = currentAgentType,
433-
selectedRemoteAgentType = selectedAgentType,
434-
onOpenDirectory = { openDirectoryChooser() },
435-
onClearHistory = {
436-
chatHistoryManager.clearCurrentSession()
437-
messages = emptyList()
438-
currentStreamingOutput = ""
439-
println("🗑️ [SimpleAIChat] 聊天历史已清空")
440-
},
441-
onModelConfigChange = { config ->
442-
currentModelConfig = config
443-
if (config.isValid()) {
444-
try {
445-
llmService = KoogLLMService.create(config)
446-
println("✅ 切换模型: ${config.provider.displayName} / ${config.modelName}")
447-
} catch (e: Exception) {
448-
println("❌ 切换模型失败: ${e.message}")
449-
}
432+
// Use unified AgentInterfaceRouter for all agent types
433+
AgentInterfaceRouter(
434+
llmService = llmService,
435+
isTreeViewVisible = isTreeViewVisible,
436+
onConfigWarning = { showModelConfigDialog = true },
437+
onToggleTreeView = { isTreeViewVisible = it },
438+
chatHistoryManager = chatHistoryManager,
439+
selectedAgentType = selectedAgentType,
440+
onAgentTypeChange = { type ->
441+
handleAgentTypeChange(type)
442+
println("🔄 切换 Agent Type: ${type.getDisplayName()}")
443+
},
444+
onSessionSelected = { sessionId ->
445+
messages = chatHistoryManager.getMessages()
446+
currentStreamingOutput = ""
447+
},
448+
onNewChat = {
449+
messages = emptyList()
450+
currentStreamingOutput = ""
451+
},
452+
onInternalSessionSelected = { handler ->
453+
agentSessionSelectedHandler = handler
454+
},
455+
onInternalNewChat = { handler ->
456+
agentNewChatHandler = handler
457+
},
458+
hasHistory = messages.isNotEmpty(),
459+
hasDebugInfo = compilerOutput.isNotEmpty(),
460+
currentModelConfig = currentModelConfig,
461+
selectedAgent = selectedAgent,
462+
availableAgents = availableAgents,
463+
useAgentMode = useAgentMode,
464+
onOpenDirectory = { openDirectoryChooser() },
465+
onClearHistory = {
466+
chatHistoryManager.clearCurrentSession()
467+
messages = emptyList()
468+
currentStreamingOutput = ""
469+
println("🗑️ [SimpleAIChat] 聊天历史已清空")
470+
},
471+
onModelConfigChange = { config ->
472+
currentModelConfig = config
473+
if (config.isValid()) {
474+
try {
475+
llmService = KoogLLMService.create(config)
476+
println("✅ 切换模型: ${config.provider.displayName} / ${config.modelName}")
477+
} catch (e: Exception) {
478+
println("❌ 切换模型失败: ${e.message}")
450479
}
451-
},
452-
onAgentChange = { agent ->
453-
selectedAgent = agent
454-
println("🤖 切换 Agent: $agent")
455-
},
456-
onModeToggle = { useAgentMode = !useAgentMode },
457-
onAgentTypeChange = { type ->
458-
currentAgentType = type
459-
println("🔄 切换 Agent Type: $type")
460-
},
461-
onConfigureRemote = { showRemoteConfigDialog = true },
462-
onShowModelConfig = { showModelConfigDialog = true },
463-
onShowToolConfig = { showToolConfigDialog = true },
464-
modifier = Modifier.fillMaxSize()
465-
)
466-
} else {
467-
// Remote Agent
468-
RemoteAgentChatInterface(
469-
serverUrl = serverUrl,
470-
useServerConfig = useServerConfig,
471-
isTreeViewVisible = isTreeViewVisible,
472-
onToggleTreeView = { isTreeViewVisible = it },
473-
// TopBar 参数
474-
hasHistory = false, // Remote agent manages its own history
475-
hasDebugInfo = compilerOutput.isNotEmpty(),
476-
currentModelConfig = currentModelConfig,
477-
selectedAgent = selectedAgent,
478-
availableAgents = availableAgents,
479-
useAgentMode = useAgentMode,
480-
selectedAgentType = selectedAgentType,
481-
onOpenDirectory = { openDirectoryChooser() },
482-
onClearHistory = {
483-
// Remote agent clears history on server side
484-
println("🗑️ [RemoteAgent] 清空远程历史")
485-
},
486-
onModelConfigChange = { config ->
487-
currentModelConfig = config
488-
},
489-
onAgentChange = { agent ->
490-
selectedAgent = agent
491-
println("🤖 切换 Agent: $agent")
492-
},
493-
onModeToggle = { useAgentMode = !useAgentMode },
494-
onAgentTypeChange = { type ->
495-
selectedAgentType = type
496-
println("🔄 切换 Agent Type: $type")
497-
},
498-
onConfigureRemote = { showRemoteConfigDialog = true },
499-
onShowModelConfig = { showModelConfigDialog = true },
500-
onShowToolConfig = { showToolConfigDialog = true },
501-
// Remote-specific
502-
projectId = remoteProjectId,
503-
gitUrl = remoteGitUrl,
504-
onProjectChange = { projectId ->
505-
remoteProjectId = projectId
506-
println("📁 Project ID: $projectId")
507-
},
508-
onGitUrlChange = { url ->
509-
remoteGitUrl = url
510-
println("📦 Git URL: $url")
511-
},
512-
modifier = Modifier.fillMaxSize()
513-
)
514-
}
480+
}
481+
},
482+
onAgentChange = { agent ->
483+
selectedAgent = agent
484+
println("🤖 切换 Agent: $agent")
485+
},
486+
onModeToggle = { useAgentMode = !useAgentMode },
487+
onConfigureRemote = { showRemoteConfigDialog = true },
488+
onShowModelConfig = { showModelConfigDialog = true },
489+
onShowToolConfig = { showToolConfigDialog = true },
490+
// Remote-specific parameters (only used when selectedAgentType is REMOTE)
491+
serverUrl = serverUrl,
492+
useServerConfig = useServerConfig,
493+
projectId = remoteProjectId,
494+
gitUrl = remoteGitUrl,
495+
onProjectChange = { projectId ->
496+
remoteProjectId = projectId
497+
println("📁 Project ID: $projectId")
498+
},
499+
onGitUrlChange = { url ->
500+
remoteGitUrl = url
501+
println("📦 Git URL: $url")
502+
},
503+
modifier = Modifier.fillMaxSize()
504+
)
515505
} else {
516506
val isCompactMode = messages.isNotEmpty() || isLLMProcessing
517507

@@ -675,9 +665,9 @@ private fun AutoDevContent(
675665
)
676666
)
677667

678-
// 重要:保存 Remote 配置后,自动切换 Agent Type 为 "Remote"
668+
// 重要:保存 Remote 配置后,自动切换 Agent Type 为 REMOTE
679669
cc.unitmesh.devins.ui.config.saveAgentTypePreference("Remote")
680-
selectedAgentType = "Remote"
670+
selectedAgentType = AgentType.REMOTE
681671
} catch (e: Exception) {
682672
println("⚠️ 保存远程配置失败: ${e.message}")
683673
errorMessage = "保存远程配置失败: ${e.message}"

0 commit comments

Comments
 (0)