Skip to content

Commit ec45f40

Browse files
authored
Merge pull request #7 from phodal/feat/idea-advanced-input
feat(mpp-idea): add advanced DevIn input components with SwingPanel integration
2 parents 737ed17 + 72babb1 commit ec45f40

File tree

8 files changed

+803
-79
lines changed

8 files changed

+803
-79
lines changed

core/src/main/kotlin/cc/unitmesh/devti/gui/chat/ui/AutoDevInput.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.intellij.openapi.command.CommandProcessor
1111
import com.intellij.openapi.command.WriteCommandAction
1212
import com.intellij.openapi.editor.Document
1313
import com.intellij.openapi.editor.Editor
14+
import com.intellij.openapi.editor.EditorFactory
1415
import com.intellij.openapi.editor.EditorModificationUtil
1516
import com.intellij.openapi.editor.actions.EnterAction
1617
import com.intellij.openapi.editor.actions.IncrementalFindAction
@@ -181,7 +182,9 @@ class AutoDevInput(
181182
val id = UUID.randomUUID()
182183
val file = LightVirtualFile("AutoDevInput-$id", language, "")
183184

184-
val document = file.findDocument() ?: throw IllegalStateException("Can't create in-memory document")
185+
val document = ReadAction.compute<Document, Throwable> {
186+
EditorFactory.getInstance().createDocument("")
187+
}
185188

186189
initializeDocumentListeners(document)
187190
setDocument(document)

mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/orchestrator/ToolOrchestrator.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -585,13 +585,28 @@ class ToolOrchestrator(
585585
context: cc.unitmesh.agent.tool.ToolExecutionContext
586586
): ToolResult {
587587
return try {
588-
// Cast to ExecutableTool (all new tools should implement this)
588+
// For SubAgent, we need to validate input first
589+
if (tool is cc.unitmesh.agent.core.SubAgent<*, *>) {
590+
@Suppress("UNCHECKED_CAST")
591+
val subAgent = tool as cc.unitmesh.agent.core.SubAgent<Any, ToolResult>
592+
593+
// Validate and convert Map to proper input type
594+
val validatedInput = subAgent.validateInput(params)
595+
596+
// Create invocation with validated input
597+
val invocation = subAgent.createInvocation(validatedInput)
598+
599+
// Execute the tool
600+
return invocation.execute(context)
601+
}
602+
603+
// For other ExecutableTools, use params directly
589604
@Suppress("UNCHECKED_CAST")
590605
val executableTool = tool as? ExecutableTool<Any, ToolResult>
591606
?: return ToolResult.Error("Tool ${tool.name} does not implement ExecutableTool interface")
592607

593608
val invocation = executableTool.createInvocation(params)
594-
609+
595610
// Execute the tool
596611
invocation.execute(context)
597612
} catch (e: Exception) {
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package cc.unitmesh.devins.idea.editor
2+
3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.layout.*
5+
import androidx.compose.runtime.*
6+
import androidx.compose.ui.Alignment
7+
import androidx.compose.ui.Modifier
8+
import androidx.compose.ui.text.font.FontWeight
9+
import androidx.compose.ui.unit.dp
10+
import androidx.compose.ui.unit.sp
11+
import cc.unitmesh.devins.ui.compose.theme.AutoDevColors
12+
import org.jetbrains.jewel.foundation.theme.JewelTheme
13+
import org.jetbrains.jewel.ui.component.*
14+
15+
/**
16+
* Bottom toolbar for the input section.
17+
* Provides send/stop buttons, @ trigger for agent completion, settings, and token info.
18+
*
19+
* Uses Jewel components for native IntelliJ IDEA look and feel.
20+
*/
21+
@Composable
22+
fun IdeaBottomToolbar(
23+
onSendClick: () -> Unit,
24+
sendEnabled: Boolean,
25+
isExecuting: Boolean = false,
26+
onStopClick: () -> Unit = {},
27+
onAtClick: () -> Unit = {},
28+
onSettingsClick: () -> Unit = {},
29+
workspacePath: String? = null,
30+
totalTokens: Int? = null,
31+
modifier: Modifier = Modifier
32+
) {
33+
Row(
34+
modifier = modifier
35+
.fillMaxWidth()
36+
.padding(horizontal = 8.dp, vertical = 6.dp),
37+
horizontalArrangement = Arrangement.SpaceBetween,
38+
verticalAlignment = Alignment.CenterVertically
39+
) {
40+
// Left side: workspace and token info
41+
Row(
42+
horizontalArrangement = Arrangement.spacedBy(8.dp),
43+
verticalAlignment = Alignment.CenterVertically,
44+
modifier = Modifier.weight(1f, fill = false)
45+
) {
46+
// Workspace indicator
47+
if (!workspacePath.isNullOrEmpty()) {
48+
// Extract project name from path, handling both Unix and Windows separators
49+
val projectName = workspacePath
50+
.replace('\\', '/') // Normalize to Unix separator
51+
.substringAfterLast('/')
52+
.ifEmpty { "Project" }
53+
54+
Box(
55+
modifier = Modifier
56+
.background(
57+
JewelTheme.globalColors.panelBackground.copy(alpha = 0.8f)
58+
)
59+
.padding(horizontal = 8.dp, vertical = 4.dp)
60+
) {
61+
Row(
62+
verticalAlignment = Alignment.CenterVertically,
63+
horizontalArrangement = Arrangement.spacedBy(4.dp)
64+
) {
65+
Text(
66+
text = "📁",
67+
style = JewelTheme.defaultTextStyle.copy(fontSize = 12.sp)
68+
)
69+
Text(
70+
text = projectName,
71+
style = JewelTheme.defaultTextStyle.copy(fontSize = 12.sp),
72+
maxLines = 1
73+
)
74+
}
75+
}
76+
}
77+
78+
// Token usage indicator
79+
if (totalTokens != null && totalTokens > 0) {
80+
Box(
81+
modifier = Modifier
82+
.background(AutoDevColors.Blue.c400.copy(alpha = 0.2f))
83+
.padding(horizontal = 8.dp, vertical = 4.dp)
84+
) {
85+
Row(
86+
verticalAlignment = Alignment.CenterVertically,
87+
horizontalArrangement = Arrangement.spacedBy(4.dp)
88+
) {
89+
Text(
90+
text = "Token",
91+
style = JewelTheme.defaultTextStyle.copy(fontSize = 11.sp)
92+
)
93+
Text(
94+
text = "$totalTokens",
95+
style = JewelTheme.defaultTextStyle.copy(
96+
fontSize = 11.sp,
97+
fontWeight = FontWeight.Bold
98+
)
99+
)
100+
}
101+
}
102+
}
103+
}
104+
105+
// Right side: action buttons
106+
Row(
107+
horizontalArrangement = Arrangement.spacedBy(4.dp),
108+
verticalAlignment = Alignment.CenterVertically
109+
) {
110+
// @ trigger button for agent completion
111+
IconButton(
112+
onClick = onAtClick,
113+
modifier = Modifier.size(32.dp)
114+
) {
115+
Text(
116+
text = "@",
117+
style = JewelTheme.defaultTextStyle.copy(
118+
fontSize = 16.sp,
119+
fontWeight = FontWeight.Bold
120+
)
121+
)
122+
}
123+
124+
// Settings button
125+
IconButton(
126+
onClick = onSettingsClick,
127+
modifier = Modifier.size(32.dp)
128+
) {
129+
Text(
130+
text = "",
131+
style = JewelTheme.defaultTextStyle.copy(fontSize = 14.sp)
132+
)
133+
}
134+
135+
// Send or Stop button
136+
if (isExecuting) {
137+
DefaultButton(
138+
onClick = onStopClick,
139+
modifier = Modifier.height(32.dp)
140+
) {
141+
Text(
142+
text = "⏹ Stop",
143+
style = JewelTheme.defaultTextStyle.copy(
144+
color = AutoDevColors.Red.c400
145+
)
146+
)
147+
}
148+
} else {
149+
DefaultButton(
150+
onClick = onSendClick,
151+
enabled = sendEnabled,
152+
modifier = Modifier.height(32.dp)
153+
) {
154+
Text(
155+
text = "Send",
156+
style = JewelTheme.defaultTextStyle
157+
)
158+
}
159+
}
160+
}
161+
}
162+
}
163+

0 commit comments

Comments
 (0)