Skip to content

Commit 5e6a4a2

Browse files
committed
feat(shire): merge local agent language shire into AutoDev #379
1 parent d2cc8a3 commit 5e6a4a2

File tree

112 files changed

+8274
-18
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+8274
-18
lines changed

build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,11 @@ project(":exts:devins-lang") {
783783
testFramework(TestFrameworkType.Plugin.Java)
784784
}
785785

786+
implementation("com.jayway.jsonpath:json-path:2.9.0")
787+
implementation("org.reflections:reflections:0.10.2") {
788+
exclude(group = "org.slf4j", module = "slf4j-api")
789+
}
790+
786791
implementation(project(":core"))
787792
implementation(project(":exts:ext-git"))
788793
}

core/src/legacy/embedding/InMemoryEmbeddingSearchIndex.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import kotlin.sequences.map
2121
import kotlin.to
2222

2323
/**
24-
* Concurrent [com.phodal.shirecore.search.indices.EmbeddingSearchIndex] that stores all embeddings in the memory and allows
24+
* Concurrent [cc.unitmesh.devti.language.search.indices.EmbeddingSearchIndex] that stores all embeddings in the memory and allows
2525
* simultaneous read operations from multiple consumers.
2626
* Can be persisted to disk.
2727
*/

core/src/main/kotlin/cc/unitmesh/devti/custom/compile/VariableTemplateCompiler.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import com.intellij.psi.PsiElement
1515
import com.intellij.psi.PsiFile
1616
import com.intellij.psi.PsiNameIdentifierOwner
1717
import cc.unitmesh.devti.intentions.action.getElementToAction
18+
import com.intellij.openapi.application.ReadAction
19+
import com.intellij.psi.PsiManager
1820
import kotlinx.coroutines.runBlocking
1921
import org.apache.velocity.VelocityContext
2022
import org.apache.velocity.app.Velocity
@@ -41,6 +43,12 @@ class VariableTemplateCompiler(
4143
velocityContext.put(key, value)
4244
}
4345

46+
fun putAll(map: Map<String, Any>) {
47+
map.forEach { (key, value) ->
48+
velocityContext.put(key, value)
49+
}
50+
}
51+
4452
fun compile(template: String): String {
4553
velocityContext.put(CustomVariable.FILE_NAME.variable, file.name)
4654
velocityContext.put(CustomVariable.FILE_PATH.variable, file.virtualFile?.path ?: "")
@@ -119,5 +127,24 @@ class VariableTemplateCompiler(
119127
selectedText = selectedText,
120128
)
121129
}
130+
131+
fun defaultEditor(myProject: Project): Editor? {
132+
return FileEditorManager.getInstance(myProject).selectedTextEditor
133+
}
134+
135+
fun defaultElement(myProject: Project, currentEditor: Editor?): PsiElement? =
136+
ReadAction.compute<PsiElement?, Throwable> {
137+
currentEditor?.caretModel?.currentCaret?.offset?.let {
138+
val psiFile = currentEditor.let { editor ->
139+
val psiFile = editor.virtualFile?.let { file ->
140+
PsiManager.getInstance(myProject).findFile(file)
141+
}
142+
143+
psiFile
144+
} ?: return@let null
145+
146+
psiFile.findElementAt(it) ?: return@let psiFile
147+
}
148+
}
122149
}
123150
}
Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,34 @@
11
package cc.unitmesh.devti.custom.team
22

3-
enum class InteractionType {
4-
ChatPanel,
5-
AppendCursor,
6-
AppendCursorStream,
7-
OutputFile,
8-
ReplaceSelection,
9-
ReplaceCurrentFile,
3+
enum class InteractionType(val description: String) {
4+
AppendCursor("Append content at the current cursor position"),
5+
AppendCursorStream("Append content at the current cursor position, stream output"),
6+
OutputFile("Output to a new file"),
7+
ReplaceSelection("Replace the currently selected content"),
8+
ReplaceCurrentFile("Replace the content of the current file"),
9+
InsertBeforeSelection("Insert content before the currently selected content"),
10+
RunPanel("Show Result in Run panel which is the bottom of the IDE"),
11+
ChatPanel("Show Result in Chat panel which is the right of the IDE"),
12+
OnPaste("Copy the content to the clipboard"),
13+
RightPanel("Show Result in Right panel which is the right of the IDE"),
14+
StreamDiff("Use streaming diff to show the result")
1015
;
16+
17+
companion object {
18+
fun from(interaction: String): InteractionType {
19+
return when (interaction.lowercase()) {
20+
AppendCursor.name.lowercase() -> InteractionType.AppendCursor
21+
AppendCursorStream.name.lowercase() -> InteractionType.AppendCursorStream
22+
OutputFile.name.lowercase() -> InteractionType.OutputFile
23+
ReplaceSelection.name.lowercase() -> InteractionType.ReplaceSelection
24+
ReplaceCurrentFile.name.lowercase() -> InteractionType.ReplaceCurrentFile
25+
InsertBeforeSelection.name.lowercase() -> InsertBeforeSelection
26+
RunPanel.name.lowercase() -> InteractionType.RunPanel
27+
OnPaste.name.lowercase() -> OnPaste
28+
RightPanel.name.lowercase() -> RightPanel
29+
StreamDiff.name.lowercase() -> StreamDiff
30+
else -> RunPanel
31+
}
32+
}
33+
}
1134
}

core/src/main/kotlin/cc/unitmesh/devti/custom/team/TeamPromptExecTask.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
package cc.unitmesh.devti.custom.team
22

33
import cc.unitmesh.cf.core.llms.LlmMsg
4+
import cc.unitmesh.cf.core.llms.LlmProvider
45
import cc.unitmesh.devti.AutoDevBundle
56
import cc.unitmesh.devti.custom.tasks.FileGenerateTask
67
import cc.unitmesh.devti.gui.chat.message.ChatActionType
78
import cc.unitmesh.devti.gui.sendToChatWindow
89
import cc.unitmesh.devti.intentions.action.task.BaseCompletionTask
910
import cc.unitmesh.devti.intentions.action.task.CodeCompletionRequest
11+
import cc.unitmesh.devti.llms.LlmFactory
12+
import cc.unitmesh.devti.util.AutoDevCoroutineScope
13+
import com.intellij.execution.ui.ConsoleViewContentType
14+
import com.intellij.openapi.application.invokeLater
1015
import com.intellij.openapi.application.runReadAction
1116
import com.intellij.openapi.editor.Editor
1217
import com.intellij.openapi.progress.ProgressIndicator
@@ -16,6 +21,9 @@ import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator
1621
import com.intellij.openapi.project.Project
1722
import com.intellij.openapi.vfs.VirtualFile
1823
import com.intellij.psi.PsiElement
24+
import kotlinx.coroutines.flow.Flow
25+
import kotlinx.coroutines.flow.cancellable
26+
import kotlinx.coroutines.launch
1927

2028
/**
2129
* The `TeamPromptExecTask` class is a background task that executes a team prompt action in the context of a project.
@@ -98,6 +106,12 @@ class TeamPromptExecTask(
98106
ProgressManager.getInstance()
99107
.runProcessWithProgressAsynchronously(task, BackgroundableProcessIndicator(task))
100108
}
109+
110+
InteractionType.InsertBeforeSelection -> TODO()
111+
InteractionType.RunPanel -> TODO()
112+
InteractionType.OnPaste -> TODO()
113+
InteractionType.RightPanel -> TODO()
114+
InteractionType.StreamDiff -> TODO()
101115
}
102116
}
103117
}

core/src/main/kotlin/cc/unitmesh/devti/provider/toolchain/ToolchainFunctionProvider.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,11 @@ interface ToolchainFunctionProvider {
2626
it.javaClass.simpleName == providerName
2727
}
2828
}
29+
30+
suspend fun provide(project: Project, funcName: String): ToolchainFunctionProvider? {
31+
return EP_NAME.extensionList.firstOrNull {
32+
it.isApplicable(project, funcName)
33+
}
34+
}
2935
}
3036
}

core/src/main/kotlin/cc/unitmesh/devti/util/AutoDevCoroutineScope.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import com.intellij.openapi.project.Project
88
import com.intellij.util.concurrency.AppExecutorUtil
99
import kotlinx.coroutines.*
1010

11-
private val workerThread = AppExecutorUtil.getAppExecutorService().asCoroutineDispatcher()
11+
public val workerThread = AppExecutorUtil.getAppExecutorService().asCoroutineDispatcher()
1212

1313
@Service(Service.Level.APP)
1414
class AutoDevAppScope: Disposable {

core/src/main/resources/messages/AutoDevBundle_en.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,4 @@ mcp.preview.editor.loading.response=Loading response...
266266
mcp.editor.preview.title=Preview
267267
mcp.editor.preview.tooltip=Preview panel
268268
mcp.editor.refresh.title=Refresh
269+
shire.toolchain.function.not.found=Toolchain Not Found

core/src/main/resources/messages/AutoDevBundle_zh.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,3 +256,4 @@ mcp.preview.editor.loading.response=加载响应中...
256256
mcp.editor.preview.title=预览
257257
mcp.editor.preview.tooltip=预览面板
258258
mcp.editor.refresh.title=刷新
259+
shire.toolchain.function.not.found=Toolchain Not Found

exts/devins-lang/src/main/kotlin/cc/unitmesh/devti/language/actions/DevInsRunFileAction.kt

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
11
package cc.unitmesh.devti.language.actions
22

3+
import cc.unitmesh.devti.startup.DynamicDevInActionConfig
4+
import cc.unitmesh.devti.language.middleware.post.PostProcessorContext
35
import cc.unitmesh.devti.language.psi.DevInFile
46
import cc.unitmesh.devti.language.run.DevInsConfiguration
57
import cc.unitmesh.devti.language.run.DevInsConfigurationType
68
import cc.unitmesh.devti.language.run.DevInsRunConfigurationProducer
9+
import cc.unitmesh.devti.language.status.DevInsRunListener
710
import com.intellij.execution.ExecutionManager
811
import com.intellij.execution.RunManager
912
import com.intellij.execution.actions.ConfigurationContext
1013
import com.intellij.execution.actions.RunConfigurationProducer
1114
import com.intellij.execution.executors.DefaultRunExecutor
15+
import com.intellij.execution.process.ProcessEvent
1216
import com.intellij.execution.runners.ExecutionEnvironmentBuilder
1317
import com.intellij.openapi.actionSystem.ActionUpdateThread
1418
import com.intellij.openapi.actionSystem.AnActionEvent
1519
import com.intellij.openapi.actionSystem.CommonDataKeys
20+
import com.intellij.openapi.application.ApplicationManager
21+
import com.intellij.openapi.diagnostic.logger
1622
import com.intellij.openapi.project.DumbAwareAction
23+
import com.intellij.openapi.project.Project
24+
import com.intellij.openapi.util.Disposer
1725
import org.jetbrains.annotations.NonNls
26+
import java.util.concurrent.CompletableFuture
1827

1928
class DevInsRunFileAction : DumbAwareAction() {
2029
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
@@ -50,6 +59,83 @@ class DevInsRunFileAction : DumbAwareAction() {
5059

5160
companion object {
5261
val ID: @NonNls String = "runDevInsFileAction"
62+
63+
fun suspendExecuteFile(
64+
project: Project,
65+
file: DevInFile,
66+
variableNames: Array<String> = arrayOf(),
67+
variableTable: MutableMap<String, Any?> = mutableMapOf(),
68+
): String? {
69+
val variables: MutableMap<String, String> = mutableMapOf()
70+
for (i in variableNames.indices) {
71+
val varName = variableNames[i]
72+
val varValue = variableTable[varName].toString()
73+
variables[varName] = varValue
74+
}
75+
76+
val config = DynamicDevInActionConfig.from(file)
77+
78+
val settings = try {
79+
RunManager.getInstance(project)
80+
.createConfiguration(config.name, DevInsConfigurationType::class.java)
81+
} catch (e: Exception) {
82+
logger<DevInsRunFileAction>().error("Failed to create configuration", e)
83+
return null
84+
}
85+
86+
val runConfiguration = settings.configuration as DevInsConfiguration
87+
runConfiguration.setScriptPath(config.devinFile.virtualFile.path)
88+
if (variables.isNotEmpty()) {
89+
runConfiguration.setVariables(variables)
90+
PostProcessorContext.updateRunConfigVariables(variables)
91+
}
92+
93+
val executorInstance = DefaultRunExecutor.getRunExecutorInstance()
94+
val executionEnvironment = ExecutionEnvironmentBuilder
95+
.createOrNull(executorInstance, runConfiguration)
96+
?.build()
97+
98+
if (executionEnvironment == null) {
99+
logger<DevInsRunFileAction>().error("Failed to create execution environment")
100+
return null
101+
}
102+
103+
val future = CompletableFuture<String>()
104+
105+
val hintDisposable = Disposer.newDisposable()
106+
val connection = ApplicationManager.getApplication().messageBus.connect(hintDisposable)
107+
connection.subscribe(DevInsRunListener.TOPIC, object : DevInsRunListener {
108+
// override fun runFinish(
109+
// allOutput: String,
110+
// llmOutput: String,
111+
// event: ProcessEvent,
112+
// scriptPath: String,
113+
// consoleView: DevInConsoleView?,
114+
// ) {
115+
// future.complete(llmOutput)
116+
// connection.disconnect()
117+
// Disposer.dispose(hintDisposable)
118+
// }
119+
override fun runFinish(
120+
string: String,
121+
event: ProcessEvent,
122+
scriptPath: String
123+
) {
124+
125+
}
126+
})
127+
128+
ExecutionManager.getInstance(project).restartRunProfile(
129+
project,
130+
executorInstance,
131+
executionEnvironment.executionTarget,
132+
settings,
133+
null
134+
)
135+
136+
return future.get()
137+
}
138+
53139
}
54140

55141
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package cc.unitmesh.devti.language.ast
2+
3+
/**
4+
* This enum class `ExpressionBuiltInMethod` provides a set of built-in methods for string manipulation in Kotlin.
5+
* Each enum constant represents a specific built-in method, and holds information about the method's name, description,
6+
* the string to be inserted after the method call, and the position to move the caret to after insertion.
7+
*
8+
*/
9+
enum class ExpressionBuiltInMethod(
10+
val methodName: String,
11+
val description: String,
12+
val postInsertString: String = "()",
13+
val moveCaret: Int = 2,
14+
) {
15+
LENGTH("length", "The length of the string"),
16+
TRIM("trim", "The trimmed string"),
17+
CONTAINS("contains", "Check if the string contains a substring", "(\"\")", 2),
18+
STARTS_WITH("startsWith", "Check if the string starts with a substring", "(\"\")", 2),
19+
ENDS_WITH("endsWith", "Check if the string ends with a substring", "(\"\")", 2),
20+
LOWERCASE("lowercase", "The lowercase version of the string"),
21+
UPPERCASE("uppercase", "The uppercase version of the string"),
22+
IS_EMPTY("isEmpty", "Check if the string is empty"),
23+
IS_NOT_EMPTY("isNotEmpty", "Check if the string is not empty"),
24+
FIRST("first", "The first character of the string"),
25+
LAST("last", "The last character of the string"),
26+
MATCHES("matches", "Check if the string matches a regex pattern", "(\"//\")", 3);
27+
28+
companion object {
29+
fun fromString(methodName: String): ExpressionBuiltInMethod? {
30+
return values().find { it.methodName == methodName }
31+
}
32+
33+
fun completionProvider(): Array<ExpressionBuiltInMethod> {
34+
return values()
35+
}
36+
}
37+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package cc.unitmesh.devti.language.ast
2+
3+
data class ForeignFunction(
4+
val funcName: String,
5+
val funcPath: String,
6+
val accessFuncName: String,
7+
val inputTypes: List<String>,
8+
val returnVars: Map<String, Any>,
9+
) {
10+
companion object {
11+
fun from(map: Map<String, FrontMatterType>): List<ForeignFunction> {
12+
return map
13+
.filter { (_, value) ->
14+
value is FrontMatterType.EXPRESSION && value.value is ForeignFunctionStmt
15+
}
16+
.map { (key, value) ->
17+
val stmt = value.value as ForeignFunctionStmt
18+
ForeignFunction(
19+
key,
20+
stmt.funcPath,
21+
stmt.accessFuncName,
22+
stmt.inputTypes,
23+
stmt.returnVars
24+
)
25+
}
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)