Skip to content

Commit 542eb3e

Browse files
committed
Use selmer syntax for prompt templates.
1 parent 55b2e06 commit 542eb3e

File tree

13 files changed

+94
-83
lines changed

13 files changed

+94
-83
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
## Unreleased
44

5-
- Improve agent behavior prompt to mention usage of editor_diagnostics tool.
5+
- Improve agent behavior prompt to mention usage of editor_diagnostics tool. #230
6+
- Use selmer syntax for prompt templates.
67

78
## 0.85.3
89

deps.edn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
com.github.clojure-lsp/jsonrpc4clj {:mvn/version "1.0.2"}
66
io.modelcontextprotocol.sdk/mcp {:mvn/version "0.15.0"}
77
borkdude/dynaload {:mvn/version "0.3.5"}
8+
selmer/selmer {:mvn/version "1.12.69"}
89
babashka/fs {:mvn/version "0.5.26"}
910
babashka/process {:mvn/version "0.6.23"}
1011
br.dev.zz/parc {:git/url "https://github.com/souenzzo/parc"

resources/prompts/agent_behavior.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ You are an agent - please keep going until the user's query is completely resolv
1010

1111
NEVER show the code edits or new files to the user - only call the proper tool. The system will apply and display the edits.
1212
For each file, give a short description of what needs to be edited, then use the available tool. You can use the tool multiple times in a response, and you can keep writing text after using a tool. Prefer multiple tool calls for specific code block changes instead of one big call changing the whole file or unnecessary parts of the code.
13+
{% if toolEnabled_eca__editor_diagnostics %}
1314
After finishing your changes, use eca__editor_diagnostics to check for diagnostics, making sure you didn't introduce any errors or warnings.
15+
{% endif %}
1416

1517
## Communication
1618

resources/prompts/compact.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ However, if the session is primarily a general conversation and not technical, f
1313
- Summarize the chat in a way that allows any LLM to continue the conversation based on the summary.
1414

1515
Purpose: To create a comprehensive record that ensures no important details or context are lost between sessions. This process prioritizes thoroughness over brevity to retain all critical information..
16-
{additionalUserInput}
16+
{{additionalUserInput}}
1717

1818
## Response
1919

resources/prompts/init.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ Analyze this codebase and create an AGENTS.md file containing:
44

55
The file you create will be given to agentic coding agents (such as yourself) that operate in this repository. Make it about 20 lines long.
66

7-
If there's already an AGENTS.md, improve it if it's located in {workspaceFolders}.
7+
If there's already an AGENTS.md, improve it if it's located in {{workspaceRoots}}.

resources/prompts/rewrite.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@ Given the following text in USER editor, replace it following the USER request.
66

77
## General Context
88

9-
{path}
10-
{fullText}
9+
{{path}}
10+
{{fullText}}
1111

1212
## User text
1313

1414
```
15-
{text}
15+
{{text}}
1616
```
1717

1818
## User selection range
1919

20-
{rangeText}
20+
{{rangeText}}
2121

2222
## Core Principle
2323

src/eca/features/chat.clj

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@
10171017
Run preRequest hooks before any heavy lifting.
10181018
Only :prompt-message supports rewrite, other only allow additionalContext append."
10191019
[user-messages source-type
1020-
{:keys [db* config chat-id behavior full-model instructions metrics message] :as chat-ctx}]
1020+
{:keys [db* config chat-id full-model instructions metrics message] :as chat-ctx}]
10211021
(let [original-text (or message (-> user-messages first :content first :text))
10221022
modify-allowed? (= source-type :prompt-message)
10231023
run-hooks? (#{:prompt-message :eca-command :mcp-prompt} source-type)
@@ -1062,7 +1062,7 @@
10621062
past-messages (get-in db [:chats chat-id :messages] [])
10631063
model-capabilities (get-in db [:models full-model])
10641064
provider-auth (get-in @db* [:auth provider])
1065-
all-tools (f.tools/all-tools chat-id behavior @db* config)
1065+
all-tools (:all-tools chat-ctx)
10661066
received-msgs* (atom "")
10671067
reasonings* (atom {})
10681068
add-to-history! (fn [msg]
@@ -1306,12 +1306,14 @@
13061306
(f.context/agents-file-contexts db)
13071307
(f.context/raw-contexts->refined contexts db))
13081308
repo-map* (delay (f.index/repo-map db config {:as-string? true}))
1309+
all-tools (f.tools/all-tools chat-id behavior @db* config)
13091310
instructions (f.prompt/build-chat-instructions refined-contexts
13101311
rules
13111312
repo-map*
13121313
selected-behavior
13131314
config
13141315
chat-id
1316+
all-tools
13151317
db)
13161318
image-contents (->> refined-contexts
13171319
(filter #(= :image (:type %))))
@@ -1330,6 +1332,7 @@
13301332
:instructions instructions
13311333
:user-messages user-messages
13321334
:full-model full-model
1335+
:all-tools all-tools
13331336
:db* db*
13341337
:metrics metrics
13351338
:config config

src/eca/features/commands.clj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,14 +195,14 @@
195195
existing-files))
196196
"Credential files: None found"))))
197197

198-
(defn handle-command! [command args {:keys [chat-id db* config messenger full-model instructions user-messages metrics]}]
198+
(defn handle-command! [command args {:keys [chat-id db* config messenger full-model all-tools instructions user-messages metrics]}]
199199
(let [db @db*
200200
custom-cmds (custom-commands config (:workspace-folders db))]
201201
(case command
202202
"init" {:type :send-prompt
203203
:on-finished-side-effect (fn []
204204
(swap! db* assoc-in [:chats chat-id :messages] []))
205-
:prompt (f.prompt/init-prompt db)}
205+
:prompt (f.prompt/init-prompt all-tools db)}
206206
"compact" (do
207207
(swap! db* assoc-in [:chats chat-id :compacting?] true)
208208
{:type :send-prompt
@@ -240,7 +240,7 @@
240240
:role :system
241241
:content (merge {:type :usage}
242242
usage)})))
243-
:prompt (f.prompt/compact-prompt (string/join " " args) config)})
243+
:prompt (f.prompt/compact-prompt (string/join " " args) all-tools config db)})
244244
"login" (do (f.login/handle-step {:message (or (first args) "")
245245
:chat-id chat-id}
246246
db*

src/eca/features/prompt.clj

Lines changed: 64 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
[clojure.string :as string]
66
[eca.features.tools.mcp :as f.mcp]
77
[eca.logger :as logger]
8-
[eca.shared :refer [multi-str] :as shared])
8+
[eca.shared :refer [multi-str] :as shared]
9+
[selmer.parser :as selmer])
910
(:import
1011
[java.util Map]))
1112

@@ -32,13 +33,6 @@
3233

3334
(def ^:private compact-prompt-template (memoize compact-prompt-template*))
3435

35-
(defn ^:private replace-vars [s vars]
36-
(reduce
37-
(fn [p [k v]]
38-
(string/replace p (str "{{" (name k) "}}") (str v)))
39-
s
40-
vars))
41-
4236
(defn ^:private eca-chat-prompt [behavior config]
4337
(let [behavior-config (get-in config [:behavior behavior])
4438
prompt (:systemPrompt behavior-config)
@@ -91,30 +85,38 @@
9185
(str "\n<additionalContext from=\"chatStart\">\n" startup-ctx "\n</additionalContext>\n\n"))
9286
"</contexts>"))
9387

94-
(defn build-chat-instructions [refined-contexts rules repo-map* behavior config chat-id db]
95-
(multi-str
96-
(eca-chat-prompt behavior config)
97-
(when (seq rules)
98-
["## Rules"
99-
""
100-
"<rules description=\"Rules defined by user\">\n"
101-
(reduce
102-
(fn [rule-str {:keys [name content]}]
103-
(str rule-str (format "<rule name=\"%s\">%s</rule>\n" name content)))
104-
""
105-
rules)
106-
"</rules>"])
107-
""
108-
(when (seq refined-contexts)
109-
["## Contexts"
110-
""
111-
(contexts-str refined-contexts repo-map* (get-in db [:chats chat-id :startup-context]))])
112-
""
113-
(replace-vars
114-
(load-builtin-prompt "additional_system_info.md")
115-
{:workspaceRoots (shared/workspaces-as-str db)})))
116-
117-
(defn build-rewrite-instructions [text path full-text range config]
88+
(defn ^:private ->base-selmer-ctx [all-tools db]
89+
(merge
90+
{:workspaceRoots (shared/workspaces-as-str db)}
91+
(reduce
92+
(fn [m tool]
93+
(assoc m (keyword (str "toolEnabled_" (:full-name tool))) true))
94+
{}
95+
all-tools)))
96+
97+
(defn build-chat-instructions [refined-contexts rules repo-map* behavior config chat-id all-tools db]
98+
(let [selmer-ctx (->base-selmer-ctx all-tools db)]
99+
(multi-str
100+
(selmer/render (eca-chat-prompt behavior config) selmer-ctx)
101+
(when (seq rules)
102+
["## Rules"
103+
""
104+
"<rules description=\"Rules defined by user\">\n"
105+
(reduce
106+
(fn [rule-str {:keys [name content]}]
107+
(str rule-str (format "<rule name=\"%s\">%s</rule>\n" name content)))
108+
""
109+
rules)
110+
"</rules>"])
111+
""
112+
(when (seq refined-contexts)
113+
["## Contexts"
114+
""
115+
(contexts-str refined-contexts repo-map* (get-in db [:chats chat-id :startup-context]))])
116+
""
117+
(selmer/render (load-builtin-prompt "additional_system_info.md") selmer-ctx))))
118+
119+
(defn build-rewrite-instructions [text path full-text range all-tools config db]
118120
(let [legacy-prompt-file (-> config :rewrite :systemPromptFile)
119121
prompt (-> config :rewrite :systemPrompt)
120122
prompt-str (cond
@@ -128,39 +130,42 @@
128130
;; Resource path
129131
:else
130132
(load-builtin-prompt (some-> legacy-prompt-file (string/replace-first #"prompts/" ""))))]
131-
(replace-vars
132-
prompt-str
133-
{:text text
134-
:path (when path
135-
(str "- File path: " path))
136-
:rangeText (multi-str
137-
(str "- Start line: " (-> range :start :line))
138-
(str "- Start character: " (-> range :start :character))
139-
(str "- End line: " (-> range :end :line))
140-
(str "- End character: " (-> range :end :character)))
141-
:fullText (when full-text
142-
(multi-str
143-
"- Full file content"
144-
"```"
145-
full-text
146-
"```"))})))
147-
148-
(defn init-prompt [db]
149-
(replace-vars
133+
(selmer/render prompt-str
134+
(merge
135+
(->base-selmer-ctx all-tools db)
136+
{:text text
137+
:path (when path
138+
(str "- File path: " path))
139+
:rangeText (multi-str
140+
(str "- Start line: " (-> range :start :line))
141+
(str "- Start character: " (-> range :start :character))
142+
(str "- End line: " (-> range :end :line))
143+
(str "- End character: " (-> range :end :character)))
144+
:fullText (when full-text
145+
(multi-str
146+
"- Full file content"
147+
"```"
148+
full-text
149+
"```"))}))))
150+
151+
(defn init-prompt [all-tools db]
152+
(selmer/render
150153
(init-prompt-template)
151-
{:workspaceFolders (shared/workspaces-as-str db)}))
154+
(->base-selmer-ctx all-tools db)))
152155

153156
(defn title-prompt []
154157
(title-prompt-template))
155158

156-
(defn compact-prompt [additional-input config]
157-
(replace-vars
158-
(or (:compactPrompt config)
159+
(defn compact-prompt [additional-input all-tools config db]
160+
(selmer/render
161+
(or (:compactPrompt config)
159162
;; legacy
160-
(compact-prompt-template (:compactPromptFile config)))
161-
{:additionalUserInput (if additional-input
162-
(format "You MUST respect this user input in the summarization: %s." additional-input)
163-
"")}))
163+
(compact-prompt-template (:compactPromptFile config)))
164+
(merge
165+
(->base-selmer-ctx all-tools db)
166+
{:additionalUserInput (if additional-input
167+
(format "You MUST respect this user input in the summarization: %s." additional-input)
168+
"")})))
164169

165170
(defn inline-completion-prompt [config]
166171
(let [legacy-prompt-file (get-in config [:completion :systemPromptFile])

src/eca/features/rewrite.clj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[clojure.string :as string]
44
[eca.features.login :as f.login]
55
[eca.features.prompt :as f.prompt]
6+
[eca.features.tools :as f.tools]
67
[eca.llm-api :as llm-api]
78
[eca.logger :as logger]
89
[eca.messenger :as messenger]
@@ -27,7 +28,8 @@
2728
model-capabilities (get-in db [:models full-model])
2829
full-text (when path (llm-api/refine-file-context path nil))
2930
start-time (System/currentTimeMillis)
30-
instructions (f.prompt/build-rewrite-instructions text path full-text range config)
31+
all-tools (f.tools/all-tools nil nil @db* config)
32+
instructions (f.prompt/build-rewrite-instructions text path full-text range all-tools config db)
3133
ctx {:db* db*
3234
:config config
3335
:messenger messenger

0 commit comments

Comments
 (0)