Skip to content

Commit 603aaae

Browse files
committed
feat(settings): enable custom agent by default and improve code readability pattern pipeline. #379
The changes include: - Default enableCustomAgent to true for better UX - Wrap PsiTreeUtil access in runReadAction - Use text property directly instead of psiElement.text - Add comprehensive tests for Shire pattern processing
1 parent 7628fc6 commit 603aaae

File tree

3 files changed

+163
-7
lines changed

3 files changed

+163
-7
lines changed

core/src/main/kotlin/cc/unitmesh/devti/settings/customize/AutoDevCustomizeSettings.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class AutoDevCustomizeSettings(
2929
}
3030

3131
class CustomizeProjectSettings : AdProjectSettingsBase<CustomizeProjectSettings>() {
32-
var enableCustomAgent by property(false)
32+
var enableCustomAgent by property(true)
3333
var agentJsonConfig by property("") { it.isEmpty() }
3434
var customPrompts by property("") { it.isEmpty() }
3535
var mcpServerConfig by property("") { it.isEmpty() }

exts/devins-lang/src/main/kotlin/cc/unitmesh/devti/language/compiler/DevInsCompiler.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ class DevInsCompiler(
9595
}
9696

9797
DevInTypes.FRONTMATTER_START -> {
98-
val nextElement = PsiTreeUtil.findChildOfType(
99-
psiElement.parent, DevInFrontMatterHeader::class.java
100-
)
98+
val nextElement = runReadAction {
99+
PsiTreeUtil.findChildOfType(psiElement.parent, DevInFrontMatterHeader::class.java)
100+
}
101101
if (nextElement == null) {
102102
return@forEach
103103
}
@@ -108,14 +108,14 @@ class DevInsCompiler(
108108
result.config = runReadAction { HobbitHoleParser.parse(psiElement as DevInFrontMatterHeader) }
109109
}
110110

111-
WHITE_SPACE, DUMMY_BLOCK -> output.append(psiElement.text)
111+
WHITE_SPACE, DUMMY_BLOCK -> output.append(text)
112112
DevInTypes.VELOCITY_EXPR -> {
113113
processVelocityExpr(psiElement as DevInVelocityExpr)
114-
logger.info("Velocity expression found: ${psiElement.text}")
114+
logger.info("Velocity expression found: ${text}")
115115
}
116116

117117
DevInTypes.MARKDOWN_HEADER -> {
118-
output.append("#[[${psiElement.text}]]#")
118+
output.append("#[[${text}]]#")
119119
}
120120

121121
else -> {
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
package cc.unitmesh.devti.language.regression
2+
3+
import cc.unitmesh.devti.language.ast.action.PatternActionProcessor
4+
import cc.unitmesh.devti.language.ast.variable.ShireVariableTemplateCompiler
5+
import cc.unitmesh.devti.language.compiler.DevInsCompiler
6+
import cc.unitmesh.devti.language.middleware.post.PostProcessorContext
7+
import cc.unitmesh.devti.language.psi.DevInFile
8+
import com.intellij.testFramework.fixtures.BasePlatformTestCase
9+
import kotlinx.coroutines.runBlocking
10+
import org.intellij.lang.annotations.Language
11+
12+
class ShirePatternPipelineTest : BasePlatformTestCase() {
13+
fun testShouldSupportForTee() {
14+
@Language("DevIn")
15+
val code = """
16+
---
17+
name: Summary
18+
description: "Generate Summary"
19+
interaction: AppendCursor
20+
data: ["a", "b"]
21+
when: ${'$'}fileName.matches("/.*.java/")
22+
variables:
23+
"var2": /.*ple.devin/ { cat | find("fileName") | sort }
24+
onStreamingEnd: { append(${'$'}var2) | saveFile("summary.md") }
25+
---
26+
27+
Summary webpage: ${'$'}fileName
28+
""".trimIndent()
29+
30+
val file = myFixture.addFileToProject("sample.devin", code)
31+
32+
myFixture.openFileInEditor(file.virtualFile)
33+
34+
val compile = runBlocking { DevInsCompiler(project, file as DevInFile, myFixture.editor).compile() }
35+
val hole = compile.config!!
36+
37+
val context = PostProcessorContext(
38+
genText = "User prompt:\n\n",
39+
)
40+
41+
runBlocking {
42+
val shireTemplateCompiler =
43+
ShireVariableTemplateCompiler(project, hole, compile.variableTable, code, myFixture.editor)
44+
val compiledVariables =
45+
shireTemplateCompiler.compileVariable(myFixture.editor, mutableMapOf())
46+
47+
context.compiledVariables = compiledVariables
48+
49+
hole.variables.mapValues {
50+
PatternActionProcessor(project, hole, mutableMapOf()).execute(it.value)
51+
}
52+
53+
hole.setupStreamingEndProcessor(project, context = context)
54+
hole.executeStreamingEndProcessor(project, null, context = context, compiledVariables)
55+
}
56+
57+
assertEquals("User prompt:\n\n" +
58+
" \"var2\": /.*ple.devin/ { cat | find(\"fileName\") | sort }\n" +
59+
"Summary webpage: \$fileName\n" +
60+
"when: \$fileName.matches(\"/.*.java/\")", context.genText)
61+
}
62+
63+
fun testShouldSupportAfterStreamingPattern() {
64+
@Language("Shire")
65+
val code = """
66+
---
67+
name: Summary
68+
description: "Generate Summary"
69+
interaction: AppendCursor
70+
variables:
71+
"var2": "sample"
72+
afterStreaming: {
73+
case condition {
74+
default { print(${'$'}output) }
75+
}
76+
}
77+
---
78+
79+
Summary webpage: ${'$'}fileName
80+
""".trimIndent()
81+
82+
val file = myFixture.addFileToProject("sample.devin", code)
83+
84+
myFixture.openFileInEditor(file.virtualFile)
85+
86+
val compile = runBlocking { DevInsCompiler(project, file as DevInFile, myFixture.editor).compile() }
87+
val hole = compile.config!!
88+
89+
val context = PostProcessorContext(
90+
genText = "User prompt:\n\n",
91+
)
92+
93+
runBlocking {
94+
val shireTemplateCompiler = ShireVariableTemplateCompiler(project, hole, compile.variableTable, code, myFixture.editor)
95+
val compiledVariables =
96+
shireTemplateCompiler.compileVariable(myFixture.editor, mutableMapOf())
97+
98+
context.compiledVariables = compiledVariables
99+
100+
hole.variables.mapValues {
101+
PatternActionProcessor(project, hole, mutableMapOf()).execute(it.value)
102+
}
103+
104+
hole.setupStreamingEndProcessor(project, context = context)
105+
hole.executeAfterStreamingProcessor(project, null, context = context)
106+
}
107+
108+
assertEquals("User prompt:\n\n", context.lastTaskOutput)
109+
}
110+
111+
fun testShouldUseSedReplaceContentInVariables() {
112+
@Language("Shire")
113+
val code = """
114+
---
115+
name: Summary
116+
description: "Generate Summary"
117+
interaction: AppendCursor
118+
variables:
119+
"openai": "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"
120+
"var2": /.*ple.devin/ { cat | find("openai") | sed("(?i)\b(sk-[a-zA-Z0-9]{20}T3BlbkFJ[a-zA-Z0-9]{20})(?:['|\"|\n|\r|\s|\x60|;]|${'$'})", "sk-***") }
121+
---
122+
123+
Summary webpage: ${'$'}var2
124+
""".trimIndent()
125+
126+
val file = myFixture.addFileToProject("sample.devin", code)
127+
128+
myFixture.openFileInEditor(file.virtualFile)
129+
130+
val compile = runBlocking { DevInsCompiler(project, file as DevInFile, myFixture.editor).compile() }
131+
val hole = compile.config!!
132+
133+
val context = PostProcessorContext(
134+
genText = "User prompt:\n\n",
135+
)
136+
137+
runBlocking {
138+
val shireTemplateCompiler = ShireVariableTemplateCompiler(project, hole, compile.variableTable, code, myFixture.editor)
139+
val compiledVariables =
140+
shireTemplateCompiler.compileVariable(myFixture.editor, mutableMapOf())
141+
142+
context.compiledVariables = compiledVariables
143+
144+
hole.variables.mapValues {
145+
PatternActionProcessor(project, hole, mutableMapOf()).execute(it.value)
146+
}
147+
148+
hole.setupStreamingEndProcessor(project, context = context)
149+
hole.executeAfterStreamingProcessor(project, null, context = context)
150+
}
151+
152+
assertEquals(" \"openai\": \"sk-***\n" +
153+
" \"var2\": /.*ple.devin/ { cat | find(\"openai\") | sed(\"(?i)\\b(sk-[a-zA-Z0-9]{20}T3BlbkFJ[a-zA-Z0-9]{20})(?:['|\\\"|\\n|\\r|\\s|\\x60|;]|\$)\", \"sk-***\") }", context.compiledVariables["var2"]
154+
)
155+
}
156+
}

0 commit comments

Comments
 (0)