errorMessageFromBody extracts the user-facing string from a non-2xx body. hamrpass wraps errors as `{"error":{"message":...,"provider_hint":...}}`; we prefer provider_hint (providers stash the human diagnostic there), fall back to message, then to the raw first line so non-hamrpass backends still su
(b []byte)
| 443 | }) |
| 444 | if err != nil { |
| 445 | return nil, &Event{Kind: EventError, Err: err, Budget: budget} |
| 446 | } |
| 447 | return resp, nil |
| 448 | } |
| 449 | |
| 450 | // postChat dispatches via doPost; on a 400 rejecting reasoning it drops |
| 451 | // reasoning_effort for this Client's lifetime and retries once. |
| 452 | // Probe never sets ReasoningEffort, so its 400 can't trip the flag. |
| 453 | func (c *Client) postChat(parent context.Context, body chatRequest) (*http.Response, cloud.BudgetStatus, error) { |
| 454 | if c.noReasoningEffort.Load() { |
| 455 | body.ReasoningEffort = "" |
| 456 | } |
| 457 | resp, budget, errBody, err := c.doPost(parent, body) |
| 458 | if err != nil && body.ReasoningEffort != "" && rejectsReasoning(errBody) { |
| 459 | c.noReasoningEffort.Store(true) |
| 460 | body.ReasoningEffort = "" |
| 461 | resp, budget, _, err = c.doPost(parent, body) |
| 462 | } |
| 463 | return resp, budget, err |
| 464 | } |