(self, messages: list[dict[str, Any]])
| 461 | raise RuntimeError("Exceeded retry budget without exception or success.") |
| 462 | |
| 463 | async def _query_async(self, messages: list[dict[str, Any]]) -> dict[str, Any]: |
| 464 | last_error: ValueError | None = None |
| 465 | raw_text = "" |
| 466 | request_messages = list(messages) |
| 467 | for attempt_index in range(MAX_JSON_PARSE_RETRIES + 1): |
| 468 | payload = self._build_payload(request_messages) |
| 469 | request_metrics = _request_metrics_from_serialized_input(self._request_metrics_input(payload)) |
| 470 | self._last_request_metrics = dict(request_metrics) |
| 471 | for key, value in request_metrics.items(): |
| 472 | self._cumulative_request_metrics[key] += value |
| 473 | |
| 474 | response_payload = await self._post_with_retries(payload) |
| 475 | |
| 476 | usage_metrics = self._usage_metrics_from_payload(response_payload) |
| 477 | self._last_usage_metrics = dict(usage_metrics) |
| 478 | for key, value in usage_metrics.items(): |
| 479 | self._cumulative_usage_metrics[key] += value |
| 480 | |
| 481 | raw_text = self._extract_text(response_payload) |
| 482 | append_runtime_log( |
| 483 | self._raw_response_log_path(), |
| 484 | source="model", |
| 485 | event="raw_text", |
| 486 | attempt=attempt_index + 1, |
| 487 | raw_text=raw_text, |
| 488 | ) |
| 489 | try: |
| 490 | parsed = parse_json_output(raw_text, action_field=self.config.action_field) |
| 491 | break |
| 492 | except ValueError as exc: |
| 493 | last_error = exc |
| 494 | if attempt_index < MAX_JSON_PARSE_RETRIES: |
| 495 | request_messages.append( |
| 496 | self._format_repair_message(raw_text=raw_text, error=str(exc)) |
| 497 | ) |
| 498 | else: |
| 499 | raise self._format_error( |
| 500 | raw_text=raw_text, |
| 501 | error=str(last_error or ValueError("Unable to parse model output.")), |
| 502 | ) |
| 503 | |
| 504 | actions: list[dict[str, Any]] = [] |
| 505 | action_field = self.config.action_field |
| 506 | action_text = str(parsed.get(action_field, "") or "").strip() |
| 507 | if action_text: |
| 508 | action = {action_field: action_text, "command": action_text} |
| 509 | if action_field == "bash_command": |
| 510 | action["bash_command"] = action_text |
| 511 | try: |
| 512 | _validate_bash_command(action_text) |
| 513 | except ValueError as exc: |
| 514 | raise self._format_error(raw_text=raw_text, error=str(exc)) |
| 515 | else: |
| 516 | action["python_code"] = action_text |
| 517 | actions.append(action) |
| 518 | |
| 519 | return self.format_message( |
| 520 | role="assistant", |
no test coverage detected