Skip to content

Commit 202a98d

Browse files
authored
Merge pull request #601 from devoxx/issue-587
Fix #587 - Escape {{ }} prompt content
2 parents 28671e9 + 3a7a782 commit 202a98d

File tree

6 files changed

+46
-6
lines changed

6 files changed

+46
-6
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ plugins {
77
}
88

99
group = "com.devoxx.genie"
10-
version = "0.5.3"
10+
version = "0.5.4"
1111

1212
repositories {
1313
mavenCentral()

src/main/java/com/devoxx/genie/service/prompt/memory/ChatMemoryManager.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.devoxx.genie.service.prompt.error.MemoryException;
88
import com.devoxx.genie.ui.settings.DevoxxGenieStateService;
99
import com.devoxx.genie.util.ChatMessageContextUtil;
10+
import com.devoxx.genie.util.TemplateVariableEscaper;
1011
import com.intellij.openapi.application.ApplicationManager;
1112
import com.intellij.openapi.project.Project;
1213
import dev.langchain4j.data.message.AiMessage;
@@ -146,12 +147,14 @@ public void addUserMessage(@NotNull ChatMessageContext context) {
146147
try {
147148
if (context.getUserMessage() == null && context.getUserPrompt() != null) {
148149
// Create user message if not already set
149-
context.setUserMessage(UserMessage.from(context.getUserPrompt()));
150+
context.setUserMessage(UserMessage.from(TemplateVariableEscaper.escape(context.getUserPrompt())));
150151
}
151152

152153
if (context.getUserMessage() != null) {
153154
log.debug("Adding user message to memory for context ID: {}", context.getId());
154-
chatMemoryService.addMessage(context.getProject(), context.getUserMessage());
155+
UserMessage userMessage = context.getUserMessage();
156+
String cleanValue = TemplateVariableEscaper.escape(userMessage.singleText());
157+
chatMemoryService.addMessage(context.getProject(), UserMessage.from(cleanValue));
155158
log.debug("Successfully added user message to memory");
156159
} else {
157160
log.warn("Attempted to add null user message to memory for context ID: {}", context.getId());

src/main/java/com/devoxx/genie/service/prompt/response/nonstreaming/NonStreamingPromptExecutionService.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
import com.devoxx.genie.ui.settings.DevoxxGenieStateService;
1313
import com.devoxx.genie.ui.util.NotificationUtil;
1414
import com.devoxx.genie.util.ClipboardUtil;
15+
import com.devoxx.genie.util.TemplateVariableEscaper;
1516
import com.intellij.openapi.application.ApplicationManager;
1617
import com.intellij.openapi.project.Project;
1718
import dev.langchain4j.data.message.AiMessage;
19+
import dev.langchain4j.data.message.UserMessage;
1820
import dev.langchain4j.memory.ChatMemory;
1921
import dev.langchain4j.model.chat.ChatLanguageModel;
2022
import dev.langchain4j.model.chat.response.ChatResponse;
@@ -166,12 +168,15 @@ public void cancelExecutingQuery() {
166168
}
167169

168170
if (chatMessageContext.getUserMessage().hasSingleText()) {
169-
String queryResponse = assistant.chat(chatMessageContext.getUserMessage().singleText());
171+
String cleanText = TemplateVariableEscaper.escape(chatMessageContext.getUserMessage().singleText());
172+
String queryResponse = assistant.chat(cleanText);
170173
return ChatResponse.builder()
171174
.aiMessage(AiMessage.aiMessage(queryResponse))
172175
.build();
173176
} else {
174-
return chatLanguageModel.chat(chatMessageContext.getUserMessage());
177+
UserMessage originalUserMessage = chatMessageContext.getUserMessage();
178+
String cleanText = TemplateVariableEscaper.escape(originalUserMessage.singleText());
179+
return chatLanguageModel.chat(UserMessage.from(cleanText));
175180
}
176181

177182
} catch (Exception e) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.devoxx.genie.util;
2+
3+
/**
4+
* Utility class to escape LangChain4j template variables.
5+
* LangChain4j uses the syntax {{variable_name}} for template variables,
6+
* which can conflict with other template systems like Angular.
7+
*/
8+
public class TemplateVariableEscaper {
9+
10+
private TemplateVariableEscaper() {
11+
// Utility class, no instantiation
12+
}
13+
14+
/**
15+
* Escapes LangChain4j template variables by replacing {{ with \\{{ and }} with \\}}
16+
* This prevents LangChain4j from attempting to substitute variables that aren't meant for it.
17+
*
18+
* @param text The text containing template variables to escape
19+
* @return The text with escaped template variables
20+
*/
21+
public static String escape(String text) {
22+
if (text == null) {
23+
return null;
24+
}
25+
return text.replace("{{", "\\{\\{").replace("}}", "\\}\\}");
26+
}
27+
}

src/main/resources/META-INF/plugin.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
]]></description>
3636

3737
<change-notes><![CDATA[
38+
<h2>v0.5.4</h2>
39+
<UL>
40+
<LI>Feat: Show MCP Ai Message in chat output panel by @stephanj</LI>
41+
<LI>Fix #587 : Escape template variables by @stephanj</LI>
42+
</UL>
3843
<h2>v0.5.3</h2>
3944
<UL>
4045
<Li>Feat #586 : Added Gemini 2.5 Pro model by @stephanj</LI>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version=0.5.3
1+
version=0.5.4

0 commit comments

Comments
 (0)