|
83 | 83 | {:effort "medium" |
84 | 84 | :summary "detailed"}) |
85 | 85 | :stream true |
| 86 | + ;; :verbosity "medium" |
86 | 87 | :max_output_tokens max-output-tokens} |
87 | | - mcp-call-by-item-id* (atom {}) |
| 88 | + tool-call-by-item-id* (atom {}) |
88 | 89 | on-response-fn |
89 | 90 | (fn handle-response [event data] |
90 | 91 | (case event |
|
93 | 94 | (on-message-received {:type :text |
94 | 95 | :text (:delta data)}) |
95 | 96 | ;; tools |
96 | | - "response.function_call_arguments.delta" (let [call (get @mcp-call-by-item-id* (:item_id data))] |
| 97 | + "response.function_call_arguments.delta" (let [call (get @tool-call-by-item-id* (:item_id data))] |
97 | 98 | (on-prepare-tool-call {:id (:id call) |
98 | 99 | :name (:name call) |
99 | 100 | :arguments-text (:delta data)})) |
100 | 101 |
|
101 | 102 | "response.output_item.done" |
102 | 103 | (case (:type (:item data)) |
103 | | - "function_call" (let [function-name (-> data :item :name) |
104 | | - function-args (-> data :item :arguments) |
105 | | - {:keys [new-messages]} (on-tool-called {:id (-> data :item :call_id) |
106 | | - :name function-name |
107 | | - :arguments (json/parse-string function-args)}) |
108 | | - input (normalize-messages new-messages)] |
109 | | - (base-completion-request! |
110 | | - {:rid (llm-util/gen-rid) |
111 | | - :body (assoc body :input input) |
112 | | - :api-url api-url |
113 | | - :api-key api-key |
114 | | - :on-error on-error |
115 | | - :on-response handle-response}) |
116 | | - (swap! mcp-call-by-item-id* dissoc (-> data :item :id))) |
117 | 104 | "reasoning" (on-reason {:status :finished |
118 | 105 | :id (-> data :item :id) |
119 | 106 | :external-id (-> data :item :id)}) |
|
140 | 127 | :id (-> data :item :id)}) |
141 | 128 | "function_call" (let [call-id (-> data :item :call_id) |
142 | 129 | item-id (-> data :item :id) |
143 | | - name (-> data :item :name)] |
144 | | - (swap! mcp-call-by-item-id* assoc item-id {:name name :id call-id}) |
145 | | - (on-prepare-tool-call {:id (-> data :item :call_id) |
146 | | - :name (-> data :item :name) |
147 | | - :arguments-text (-> data :item :arguments)})) |
| 130 | + function-name (-> data :item :name) |
| 131 | + function-args (-> data :item :arguments)] |
| 132 | + (swap! tool-call-by-item-id* assoc item-id {:name function-name :id call-id}) |
| 133 | + (on-prepare-tool-call {:id call-id |
| 134 | + :name function-name |
| 135 | + :arguments-text function-args})) |
148 | 136 | nil) |
149 | 137 |
|
150 | 138 | ;; done |
151 | 139 | "response.completed" |
152 | | - (do |
| 140 | + (let [last-output (-> data :response :output last)] |
153 | 141 | (on-usage-updated {:input-tokens (-> data :response :usage :input_tokens) |
154 | 142 | :output-tokens (-> data :response :usage :output_tokens)}) |
155 | | - (when-not (= "function_call" (-> data :response :output last :type)) |
156 | | - (on-message-received {:type :finish |
| 143 | + (case (:type last-output) |
| 144 | + "function_call" |
| 145 | + (let [function-name (:name last-output) |
| 146 | + function-args (:arguments last-output) |
| 147 | + call-id (:call_id last-output) |
| 148 | + item-id (:id last-output)] |
| 149 | + ;; Fallback case when the tool call was not prepared before when |
| 150 | + ;; some models/apis respond only with response.completed (skipping streaming). |
| 151 | + (when-not (get @tool-call-by-item-id* item-id) |
| 152 | + (swap! tool-call-by-item-id* assoc item-id {:name function-name :id call-id}) |
| 153 | + (on-prepare-tool-call {:id call-id |
| 154 | + :name function-name |
| 155 | + :arguments-text function-args})) |
| 156 | + (let [{:keys [new-messages]} (on-tool-called {:id call-id |
| 157 | + :name function-name |
| 158 | + :arguments (json/parse-string function-args)}) |
| 159 | + input (normalize-messages new-messages)] |
| 160 | + (base-completion-request! |
| 161 | + {:rid (llm-util/gen-rid) |
| 162 | + :body (assoc body :input input) |
| 163 | + :api-url api-url |
| 164 | + :api-key api-key |
| 165 | + :on-error on-error |
| 166 | + :on-response handle-response}) |
| 167 | + (swap! tool-call-by-item-id* dissoc item-id))) |
157 | 168 |
|
| 169 | + ;; else |
| 170 | + (on-message-received {:type :finish |
158 | 171 | :finish-reason (-> data :response :status)}))) |
| 172 | + |
159 | 173 | nil))] |
160 | 174 | (base-completion-request! |
161 | 175 | {:rid (llm-util/gen-rid) |
|
0 commit comments