Skip to content

Commit c70e814

Browse files
committed
Improve json output for tools that output json.
1 parent 8e0d395 commit c70e814

File tree

3 files changed

+69
-19
lines changed

3 files changed

+69
-19
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Added ability to cancel tool calls. Only the shell tool currently. #145
66
- Bump mcp java sdk to 0.14.1.
7+
- Improve json output for tools that output json.
78

89
## 0.64.1
910

src/eca/features/tools.clj

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"This ns centralizes all available tools for LLMs including
33
eca native tools and MCP servers."
44
(:require
5+
[cheshire.core :as json]
56
[clojure.string :as string]
67
[eca.features.tools.chat :as f.tools.chat]
78
[eca.features.tools.custom :as f.tools.custom]
@@ -74,6 +75,27 @@
7475
(mapv #(assoc % :origin :native) (native-tools db config))
7576
(mapv #(assoc % :origin :mcp) (f.mcp/all-tools db))))))
7677

78+
(defn ^:private pretty-format-any-json-output
79+
[result]
80+
(update result
81+
:contents
82+
(fn [contents]
83+
(mapv (fn [content]
84+
(if (= :text (:type content))
85+
(let [text (string/trim (:text content))]
86+
(if (or (and (string/starts-with? text "{")
87+
(string/ends-with? text "}"))
88+
(and (string/starts-with? text "[")
89+
(string/ends-with? text "]")))
90+
(try
91+
(update content :text #(json/generate-string (json/parse-string %) {:pretty true}))
92+
(catch Exception e
93+
(println e)
94+
content))
95+
content))
96+
content))
97+
contents))))
98+
7799
(defn call-tool! [^String name ^Map arguments chat-id tool-call-id behavior db* config messenger metrics
78100
call-state-fn ; thunk
79101
state-transition-fn ; params: event & event-data
@@ -82,25 +104,26 @@
82104
(let [arguments (update-keys arguments clojure.core/name)
83105
db @db*]
84106
(try
85-
(let [result (if-let [native-tool-handler (get-in (native-definitions db config) [name :handler])]
86-
(native-tool-handler arguments {:db db
87-
:db* db*
88-
:config config
89-
:messenger messenger
90-
:behavior behavior
91-
:chat-id chat-id
92-
:tool-call-id tool-call-id
93-
:call-state-fn call-state-fn
94-
:state-transition-fn state-transition-fn})
95-
(f.mcp/call-tool! name arguments {:db db
96-
:db* db*
97-
:config config
98-
:messenger messenger
99-
:behavior behavior
100-
:chat-id chat-id
101-
:tool-call-id tool-call-id
102-
:call-state-fn call-state-fn
103-
:state-transition-fn state-transition-fn}))]
107+
(let [result (-> (if-let [native-tool-handler (get-in (native-definitions db config) [name :handler])]
108+
(native-tool-handler arguments {:db db
109+
:db* db*
110+
:config config
111+
:messenger messenger
112+
:behavior behavior
113+
:chat-id chat-id
114+
:tool-call-id tool-call-id
115+
:call-state-fn call-state-fn
116+
:state-transition-fn state-transition-fn})
117+
(f.mcp/call-tool! name arguments {:db db
118+
:db* db*
119+
:config config
120+
:messenger messenger
121+
:behavior behavior
122+
:chat-id chat-id
123+
:tool-call-id tool-call-id
124+
:call-state-fn call-state-fn
125+
:state-transition-fn state-transition-fn}))
126+
(pretty-format-any-json-output))]
104127
(logger/debug logger-tag "Tool call result: " result)
105128
(metrics/count-up! "tool-called" {:name name :error (:error result)} metrics)
106129
result)

test/eca/features/tools_test.clj

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
[eca.config :as config]
55
[eca.features.tools :as f.tools]
66
[eca.features.tools.filesystem :as f.tools.filesystem]
7+
[eca.features.tools.mcp :as f.mcp]
8+
[eca.shared :refer [multi-str]]
79
[eca.test-helper :as h]
810
[matcher-combinators.matchers :as m]
911
[matcher-combinators.test :refer [match?]]))
@@ -188,3 +190,27 @@
188190
;; Test safe commands that should NOT be denied
189191
(is (= :ask (f.tools/approval all-tools "eca_shell_command" {"command" "ls -la"} {} config "plan")))
190192
(is (= :ask (f.tools/approval all-tools "eca_shell_command" {"command" "git status"} {} config "plan")))))))
193+
194+
(deftest call-tool!-test
195+
(testing "We adapt output if json"
196+
(is (match?
197+
{:contents [{:type :text
198+
:text (multi-str "{"
199+
" \"foo\" : \"123\","
200+
" \"bar\" : 234"
201+
"}")}]
202+
:error false}
203+
(with-redefs [f.mcp/call-tool! (constantly {:contents [{:type :text
204+
:text "{\"foo\": \"123\", \"bar\": 234}"}]
205+
:error false})]
206+
(f.tools/call-tool! "my-json-tool"
207+
{}
208+
"chat-123"
209+
"tool-234"
210+
"agent"
211+
(h/db*)
212+
(h/config)
213+
(h/messenger)
214+
(h/metrics)
215+
identity
216+
identity))))))

0 commit comments

Comments
 (0)