|
5 | 5 | [integration.eca :as eca] |
6 | 6 | [integration.fixture :as fixture] |
7 | 7 | [integration.helper :refer [match-content] :as h] |
| 8 | + [llm-mock.mocks :as llm.mocks] |
8 | 9 | [matcher-combinators.matchers :as m] |
9 | 10 | [matcher-combinators.test :refer [match?]])) |
10 | 11 |
|
|
100 | 101 | :commands (m/embeds |
101 | 102 | [{:name "mcpServerSample:my-prompt" :arguments [{:name "some-arg-1"}]}])} |
102 | 103 | resp))))) |
| 104 | + |
| 105 | +(deftest compact-command |
| 106 | + (eca/start-process!) |
| 107 | + |
| 108 | + (eca/request! (fixture/initialize-request)) |
| 109 | + (eca/notify! (fixture/initialized-notification)) |
| 110 | + |
| 111 | + (let [chat-id* (atom nil)] |
| 112 | + (testing "Setup: send an initial message to create chat history" |
| 113 | + (llm.mocks/set-case! :simple-text-0) |
| 114 | + (let [resp (eca/request! (fixture/chat-prompt-request |
| 115 | + {:model "anthropic/claude-sonnet-4-6" |
| 116 | + :message "Tell me a joke!"})) |
| 117 | + chat-id (reset! chat-id* (:chatId resp))] |
| 118 | + (match-content chat-id "user" {:type "text" :text "Tell me a joke!\n"}) |
| 119 | + (match-content chat-id "system" {:type "metadata" :title "Some Cool Title"}) |
| 120 | + (match-content chat-id "system" {:type "progress" :state "running" :text "Waiting model"}) |
| 121 | + (match-content chat-id "system" {:type "progress" :state "running" :text "Generating"}) |
| 122 | + (match-content chat-id "assistant" {:type "text" :text "Knock"}) |
| 123 | + (match-content chat-id "assistant" {:type "text" :text " knock!"}) |
| 124 | + (match-content chat-id "system" {:type "usage"}) |
| 125 | + (match-content chat-id "system" {:type "progress" :state "finished"}))) |
| 126 | + |
| 127 | + (testing "Compact calls the tool and finishes cleanly without a second LLM request" |
| 128 | + (llm.mocks/set-case! :compact-0) |
| 129 | + (let [resp (eca/request! (fixture/chat-prompt-request |
| 130 | + {:chat-id @chat-id* |
| 131 | + :model "anthropic/claude-sonnet-4-6" |
| 132 | + :message "/compact"})) |
| 133 | + chat-id (:chatId resp)] |
| 134 | + |
| 135 | + (is (match? {:chatId (m/pred string?) |
| 136 | + :model "anthropic/claude-sonnet-4-6" |
| 137 | + :status "prompting"} |
| 138 | + resp)) |
| 139 | + |
| 140 | + ;; User message |
| 141 | + (match-content chat-id "user" {:type "text" :text "/compact\n"}) |
| 142 | + ;; Progress |
| 143 | + (match-content chat-id "system" {:type "progress" :state "running" :text "Waiting model"}) |
| 144 | + (match-content chat-id "system" {:type "progress" :state "running" :text "Generating"}) |
| 145 | + ;; Tool call preparation (streaming) |
| 146 | + (match-content chat-id "assistant" {:type "toolCallPrepare" |
| 147 | + :origin "native" |
| 148 | + :id "compact-1" |
| 149 | + :name "compact_chat" |
| 150 | + :argumentsText "" |
| 151 | + :summary "Compacting..."}) |
| 152 | + (match-content chat-id "assistant" {:type "toolCallPrepare" |
| 153 | + :origin "native" |
| 154 | + :id "compact-1" |
| 155 | + :name "compact_chat" |
| 156 | + :argumentsText "{\"summary\":\"Test summary of the conversation\"}" |
| 157 | + :summary "Compacting..."}) |
| 158 | + ;; Usage from LLM response |
| 159 | + (match-content chat-id "system" {:type "usage"}) |
| 160 | + ;; Tool execution |
| 161 | + (match-content chat-id "assistant" {:type "toolCallRun" |
| 162 | + :origin "native" |
| 163 | + :id "compact-1" |
| 164 | + :name "compact_chat" |
| 165 | + :arguments {:summary "Test summary of the conversation"} |
| 166 | + :manualApproval false |
| 167 | + :summary "Compacting..."}) |
| 168 | + (match-content chat-id "assistant" {:type "toolCallRunning" |
| 169 | + :origin "native" |
| 170 | + :id "compact-1" |
| 171 | + :name "compact_chat" |
| 172 | + :summary "Compacting..."}) |
| 173 | + (match-content chat-id "system" {:type "progress" :state "running" :text "Calling tool"}) |
| 174 | + (match-content chat-id "assistant" {:type "toolCalled" |
| 175 | + :origin "native" |
| 176 | + :id "compact-1" |
| 177 | + :name "compact_chat" |
| 178 | + :error false |
| 179 | + :totalTimeMs (m/pred number?) |
| 180 | + :outputs [{:type "text" :text "Compacted successfully!"}]}) |
| 181 | + ;; Chat finishes, then compact side-effect sends summary messages |
| 182 | + (match-content chat-id "system" {:type "progress" :state "finished"}) |
| 183 | + (match-content chat-id "system" {:type "text" :text "Compacted chat"}) |
| 184 | + (match-content chat-id "system" {:type "usage"}) |
| 185 | + |
| 186 | + ;; Key assertion: only one LLM request was made (no tool_result continuation). |
| 187 | + ;; Before the fix, the continue-fn would trigger a second LLM call whose |
| 188 | + ;; request body would overwrite this one and contain tool_result messages. |
| 189 | + (is (not-any? (fn [{:keys [content]}] |
| 190 | + (and (sequential? content) |
| 191 | + (some #(= "tool_result" (:type %)) content))) |
| 192 | + (:messages (llm.mocks/get-req-body :compact-0))) |
| 193 | + "Only one LLM request should be made - no tool_result continuation"))))) |
0 commit comments