|
305 | 305 | :text #"(?s)Failed.*servers are currently overloaded.*Error type: overloaded.*Request ID: req_overloaded.*Partial result.*Partial findings"}]} |
306 | 306 | result)))))) |
307 | 307 |
|
| 308 | + (testing "rate-limited error includes reset time and retry guidance" |
| 309 | + (let [db* (atom {:chats {"chat-1" {:id "chat-1" :model "test/model"}}}) |
| 310 | + subagent-chat-id "subagent-tc-rate-limited"] |
| 311 | + (with-redefs [requiring-resolve |
| 312 | + (fn [sym] |
| 313 | + (case sym |
| 314 | + eca.features.chat/prompt |
| 315 | + (fn [_params _db* _messenger _config _metrics] |
| 316 | + (swap! db* assoc-in [:chats subagent-chat-id :status] :idle) |
| 317 | + (swap! db* assoc-in [:chats subagent-chat-id :prompt-error] |
| 318 | + {:message "Anthropic rate_limit_error: This request would exceed your rate limit" |
| 319 | + :error-type :rate-limited |
| 320 | + :status 429 |
| 321 | + :code "rate_limit_error" |
| 322 | + :rate-limit-resets-at 1756204800000})) |
| 323 | + (clojure.lang.RT/var (namespace sym) (name sym))))] |
| 324 | + (let [result ((spawn-handler) |
| 325 | + {"agent" "explorer" "task" "find files"} |
| 326 | + {:db* db* |
| 327 | + :config test-config |
| 328 | + :messenger (h/messenger) |
| 329 | + :metrics (h/metrics) |
| 330 | + :chat-id "chat-1" |
| 331 | + :tool-call-id "tc-rate-limited" |
| 332 | + :call-state-fn (constantly {:status :executing})})] |
| 333 | + (is (match? {:error true |
| 334 | + :contents [{:type :text |
| 335 | + :text #"(?s)Failed.*rate limit.*Error type: rate-limited.*Status: 429.*Code: rate_limit_error.*Rate limit resets at: 2025-08-26T10:40:00Z.*transient provider error\. Prefer spawning this agent again"}]} |
| 336 | + result)))))) |
| 337 | + |
| 338 | + (testing "non-retryable error advises against retrying the same way" |
| 339 | + (let [db* (atom {:chats {"chat-1" {:id "chat-1" :model "test/model"}}}) |
| 340 | + subagent-chat-id "subagent-tc-auth"] |
| 341 | + (with-redefs [requiring-resolve |
| 342 | + (fn [sym] |
| 343 | + (case sym |
| 344 | + eca.features.chat/prompt |
| 345 | + (fn [_params _db* _messenger _config _metrics] |
| 346 | + (swap! db* assoc-in [:chats subagent-chat-id :status] :idle) |
| 347 | + (swap! db* assoc-in [:chats subagent-chat-id :prompt-error] |
| 348 | + {:message "Invalid API key" |
| 349 | + :error-type :auth |
| 350 | + :status 401})) |
| 351 | + (clojure.lang.RT/var (namespace sym) (name sym))))] |
| 352 | + (let [result ((spawn-handler) |
| 353 | + {"agent" "explorer" "task" "find files"} |
| 354 | + {:db* db* |
| 355 | + :config test-config |
| 356 | + :messenger (h/messenger) |
| 357 | + :metrics (h/metrics) |
| 358 | + :chat-id "chat-1" |
| 359 | + :tool-call-id "tc-auth" |
| 360 | + :call-state-fn (constantly {:status :executing})})] |
| 361 | + (is (match? {:error true |
| 362 | + :contents [{:type :text |
| 363 | + :text #"(?s)Failed.*Invalid API key.*Error type: auth.*Status: 401.*unlikely to help"}]} |
| 364 | + result)))))) |
| 365 | + |
308 | 366 | (testing "an error status without structured details still returns failure" |
309 | 367 | (let [db* (atom {:chats {"chat-1" {:id "chat-1" :model "test/model"}}}) |
310 | 368 | subagent-chat-id "subagent-tc-error-status"] |
|
0 commit comments