|
55 | 55 |
|
56 | 56 | (defn ^:private send-step-progress! |
57 | 57 | "Send a toolCallRunning notification with current step progress to the parent chat." |
58 | | - [messenger chat-id tool-call-id agent-name activity subagent-chat-id step max-steps model arguments] |
| 58 | + [messenger chat-id tool-call-id agent-name activity subagent-chat-id step max-steps model variant arguments] |
59 | 59 | (messenger/chat-content-received |
60 | 60 | messenger |
61 | 61 | {:chat-id chat-id |
|
67 | 67 | :origin "native" |
68 | 68 | :summary (format "%s: %s" agent-name activity) |
69 | 69 | :arguments arguments |
70 | | - :details {:type :subagent |
71 | | - :subagent-chat-id subagent-chat-id |
72 | | - :model model |
73 | | - :agent-name agent-name |
74 | | - :step step |
75 | | - :max-steps max-steps}}})) |
| 70 | + :details (cond-> {:type :subagent |
| 71 | + :subagent-chat-id subagent-chat-id |
| 72 | + :model model |
| 73 | + :agent-name agent-name |
| 74 | + :step step |
| 75 | + :max-steps max-steps} |
| 76 | + variant (assoc :variant variant))}})) |
76 | 77 |
|
77 | 78 | (defn ^:private stop-subagent-chat! |
78 | 79 | "Stop a running subagent chat silently (parent already shows 'Prompt stopped')." |
|
150 | 151 | ;; Create subagent chat session using deterministic id based on tool-call-id |
151 | 152 | subagent-chat-id (->subagent-chat-id tool-call-id) |
152 | 153 |
|
153 | | - user-model (get arguments "model") |
| 154 | + user-model (tools.util/normalize-optional-string (get arguments "model")) |
154 | 155 | _ (when user-model |
155 | 156 | (let [available-models (:models db)] |
156 | 157 | (when (and (seq available-models) |
|
167 | 168 | ;; Variant validation: reject only when the resolved model has configured |
168 | 169 | ;; variants and the user-specified one isn't among them. Models with no |
169 | 170 | ;; configured variants accept any variant (the LLM API will reject if invalid). |
170 | | - user-variant (get arguments "variant") |
| 171 | + user-variant (tools.util/normalize-optional-string (get arguments "variant")) |
171 | 172 | _ (when user-variant |
172 | 173 | (let [valid-variants (model-variant-names config subagent-model)] |
173 | 174 | (when (and (seq valid-variants) |
|
224 | 225 | ;; Send step progress when step advances |
225 | 226 | (when (> current-step last-step) |
226 | 227 | (send-step-progress! messenger chat-id tool-call-id agent-name activity |
227 | | - subagent-chat-id current-step max-steps-limit subagent-model arguments)) |
| 228 | + subagent-chat-id current-step max-steps-limit subagent-model user-variant arguments)) |
228 | 229 | (cond |
229 | 230 | ;; Parent chat stopped — propagate stop to subagent |
230 | 231 | (= :stopping (:status (call-state-fn))) |
|
259 | 260 | (throw e)))))) |
260 | 261 |
|
261 | 262 | (defn ^:private build-description |
262 | | - "Build tool description with available agents listed." |
| 263 | + "Build tool description with available agents and models listed." |
263 | 264 | [config] |
264 | 265 | (let [base-description (tools.util/read-tool-description "spawn_agent") |
265 | 266 | agents (all-agents config) |
|
280 | 281 | :properties {"agent" {:type "string" |
281 | 282 | :description "Name of the agent to spawn"} |
282 | 283 | "task" {:type "string" |
283 | | - :description "Clear description of what the agent should accomplish"} |
| 284 | + :description "The detailed instructions for the agent"} |
284 | 285 | "activity" {:type "string" |
285 | 286 | :description "Concise label (max 3-4 words) shown in the UI while the agent runs, e.g. \"exploring codebase\", \"reviewing changes\", \"analyzing tests\"."} |
286 | 287 | "model" {:type "string" |
287 | | - :description (multi-str |
288 | | - "If user specified a model to use." |
289 | | - "DO NOT pass this arg if user didn't request it." |
290 | | - "Known models: " |
291 | | - model-names)} |
292 | | - "variant" (cond-> {:type "string" |
293 | | - :description (str "Variant (Usually reasoning related) for the subagent, only pass if user specify." |
294 | | - "Available variants are model-dependent; pick the closest match when the user asks informally (e.g. \"high reasoning\" → \"high\").")} |
295 | | - (seq variant-names) (assoc :enum variant-names))} |
| 288 | + :description (cond-> "Optional model override. Include this key ONLY when the user explicitly asked for a specific model. Otherwise omit the key entirely; never send an empty string." |
| 289 | + (and (seq model-names) (> (count model-names) 1)) |
| 290 | + (multi-str "One of these models can be used if the user explicitely requests it: " model-names))} |
| 291 | + "variant" {:type "string" |
| 292 | + :description (cond-> "Optional variant override. Include this key ONLY when the user explicitly asked for a specific variant." |
| 293 | + (seq variant-names) (multi-str "One of these variants can be used if the user requests it: " |
| 294 | + variant-names))}} |
296 | 295 | :required ["agent" "task" "activity"]} |
297 | 296 | :handler #'spawn-agent |
298 | 297 | :summary-fn (fn [{:keys [args]}] |
|
304 | 303 | (defmethod tools.util/tool-call-details-before-invocation :spawn_agent |
305 | 304 | [_name arguments _server {:keys [db config chat-id tool-call-id]}] |
306 | 305 | (let [agent-name (get arguments "agent") |
307 | | - user-model (get arguments "model") |
308 | | - user-variant (get arguments "variant") |
| 306 | + user-model (tools.util/normalize-optional-string (get arguments "model")) |
| 307 | + user-variant (tools.util/normalize-optional-string (get arguments "variant")) |
309 | 308 | subagent (when agent-name |
310 | 309 | (get-agent agent-name config)) |
311 | 310 | parent-model (get-in db [:chats chat-id :model]) |
|
0 commit comments