Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions acp_adapter/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -769,8 +769,8 @@ def _build_patch_mode_content(patch_text: str) -> List[Any]:
old_chunks: list[str] = []
new_chunks: list[str] = []
for hunk in op.hunks:
old_lines = [line.content for line in hunk.lines if line.prefix in (" ", "-")]
new_lines = [line.content for line in hunk.lines if line.prefix in (" ", "+")]
old_lines = [line.content for line in hunk.lines if line.prefix in {" ", "-"}]
new_lines = [line.content for line in hunk.lines if line.prefix in {" ", "+"}]
if old_lines or new_lines:
old_chunks.append("\n".join(old_lines))
new_chunks.append("\n".join(new_lines))
Expand Down
2 changes: 1 addition & 1 deletion agent/account_usage.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _title_case_slug(value: Optional[str]) -> Optional[str]:


def _parse_dt(value: Any) -> Optional[datetime]:
if value in (None, ""):
if value in {None, ""}:
return None
if isinstance(value, (int, float)):
return datetime.fromtimestamp(float(value), tz=timezone.utc)
Expand Down
4 changes: 2 additions & 2 deletions agent/anthropic_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1537,7 +1537,7 @@ def convert_messages_to_anthropic(
# downgraded to a spurious text block on the last assistant message.
reasoning_content = m.get("reasoning_content")
_already_has_thinking = any(
isinstance(b, dict) and b.get("type") in ("thinking", "redacted_thinking")
isinstance(b, dict) and b.get("type") in {"thinking", "redacted_thinking"}
for b in blocks
)
if isinstance(reasoning_content, str) and not _already_has_thinking:
Expand Down Expand Up @@ -1688,7 +1688,7 @@ def convert_messages_to_anthropic(
if isinstance(m["content"], list):
m["content"] = [
b for b in m["content"]
if not (isinstance(b, dict) and b.get("type") in ("thinking", "redacted_thinking"))
if not (isinstance(b, dict) and b.get("type") in {"thinking", "redacted_thinking"})
]
prev_blocks = fixed[-1]["content"]
curr_blocks = m["content"]
Expand Down
34 changes: 17 additions & 17 deletions agent/auxiliary_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def _normalize_aux_provider(provider: Optional[str]) -> str:
# Resolve to the user's actual main provider so named custom providers
# and non-aggregator providers (DeepSeek, Alibaba, etc.) work correctly.
main_prov = (_read_main_provider() or "").strip().lower()
if main_prov and main_prov not in ("auto", "main", ""):
if main_prov and main_prov not in {"auto", "main", ""}:
normalized = main_prov
else:
return "custom"
Expand Down Expand Up @@ -578,7 +578,7 @@ def _convert_content_for_responses(content: Any) -> Any:
if detail:
entry["detail"] = detail
converted.append(entry)
elif ptype in ("input_text", "input_image"):
elif ptype in {"input_text", "input_image"}:
# Already in Responses format — pass through
converted.append(part)
else:
Expand Down Expand Up @@ -798,7 +798,7 @@ def _item_get(obj: Any, key: str, default: Any = None) -> Any:
if item_type == "message":
for part in (_item_get(item, "content") or []):
ptype = _item_get(part, "type")
if ptype in ("output_text", "text"):
if ptype in {"output_text", "text"}:
text_parts.append(_item_get(part, "text", ""))
elif item_type == "function_call":
tool_calls_raw.append(SimpleNamespace(
Expand Down Expand Up @@ -1949,7 +1949,7 @@ def _is_payment_error(exc: Exception) -> bool:
err_lower = str(exc).lower()
# OpenRouter and other providers include "credits" or "afford" in 402 bodies,
# but sometimes wrap them in 429 or other codes.
if status in (402, 429, None):
if status in {402, 429, None}:
if any(kw in err_lower for kw in ("credits", "insufficient funds",
"can only afford", "billing",
"payment required")):
Expand Down Expand Up @@ -2142,7 +2142,7 @@ def _pool_cache_hint(
if normalized == "auto":
runtime = _normalize_main_runtime(main_runtime)
normalized = _normalize_aux_provider(runtime.get("provider") or _read_main_provider())
if normalized in ("", "auto", "custom"):
if normalized in {"", "auto", "custom"}:
return ""
entry = _peek_pool_entry(normalized)
if entry is None:
Expand All @@ -2164,7 +2164,7 @@ def _pool_error_context(exc: Exception) -> Dict[str, Any]:
def _recoverable_pool_provider(resolved_provider: str, client: Any) -> Optional[str]:
"""Infer which provider pool can recover the current auxiliary client."""
normalized = _normalize_aux_provider(resolved_provider)
if normalized not in ("", "auto", "custom"):
if normalized not in {"", "auto", "custom"}:
return normalized
base = str(getattr(client, "base_url", "") or "")
if base_url_host_matches(base, "chatgpt.com"):
Expand Down Expand Up @@ -2481,7 +2481,7 @@ def _resolve_auto(main_runtime: Optional[Dict[str, Any]] = None) -> Tuple[Option
main_provider = runtime_provider or _read_main_provider()
main_model = runtime_model or _read_main_model()
if (main_provider and main_model
and main_provider not in ("auto", "")):
and main_provider not in {"auto", ""}):
resolved_provider = main_provider
explicit_base_url = None
explicit_api_key = None
Expand Down Expand Up @@ -3142,7 +3142,7 @@ def _wrap_if_needed(client_obj, final_model_str: str, base_url_str: str = "",
return (_to_async_client(client, final_model, is_vision=is_vision) if async_mode
else (client, final_model))

elif pconfig.auth_type in ("oauth_device_code", "oauth_external"):
elif pconfig.auth_type in {"oauth_device_code", "oauth_external"}:
# OAuth providers — route through their specific try functions
if provider == "nous":
return resolve_provider_client("nous", model, async_mode)
Expand Down Expand Up @@ -3251,7 +3251,7 @@ def get_available_vision_backends() -> List[str]:
available: List[str] = []
# 1. Active provider — if the user configured a provider, try it first.
main_provider = _read_main_provider()
if main_provider and main_provider not in ("auto", ""):
if main_provider and main_provider not in {"auto", ""}:
if main_provider in _VISION_AUTO_PROVIDER_ORDER:
if _strict_vision_backend_available(main_provider):
available.append(main_provider)
Expand Down Expand Up @@ -3297,7 +3297,7 @@ def _finalize(resolved_provider: str, sync_client: Any, default_model: Optional[

if resolved_base_url:
provider_for_base_override = (
requested if requested and requested not in ("", "auto") else "custom"
requested if requested and requested not in {"", "auto"} else "custom"
)
client, final_model = resolve_provider_client(
provider_for_base_override,
Expand Down Expand Up @@ -3325,7 +3325,7 @@ def _finalize(resolved_provider: str, sync_client: Any, default_model: Optional[
# 4. Stop
main_provider = _read_main_provider()
main_model = _read_main_model()
if main_provider and main_provider not in ("auto", ""):
if main_provider and main_provider not in {"auto", ""}:
vision_model = _PROVIDER_VISION_MODELS.get(main_provider, main_model)
if main_provider == "nous":
sync_client, default_model = _resolve_strict_vision_backend(
Expand Down Expand Up @@ -4131,7 +4131,7 @@ def call_llm(
# credentials were found, fail fast instead of silently routing
# through OpenRouter (which causes confusing 404s).
_explicit = (resolved_provider or "").strip().lower()
if _explicit and _explicit not in ("auto", "openrouter", "custom"):
if _explicit and _explicit not in {"auto", "openrouter", "custom"}:
raise RuntimeError(
f"Provider '{_explicit}' is set in config.yaml but no API key "
f"was found. Set the {_explicit.upper()}_API_KEY environment "
Expand Down Expand Up @@ -4261,7 +4261,7 @@ def call_llm(

# ── Auth refresh retry ───────────────────────────────────────
if (_is_auth_error(first_err)
and resolved_provider not in ("auto", "", None)
and resolved_provider not in {"auto", "", None}
and not client_is_nous):
if _refresh_provider_credentials(resolved_provider):
logger.info(
Expand Down Expand Up @@ -4344,7 +4344,7 @@ def call_llm(
# Only try alternative providers when the user didn't explicitly
# configure this task's provider. Explicit provider = hard constraint;
# auto (the default) = best-effort fallback chain. (#7559)
is_auto = resolved_provider in ("auto", "", None)
is_auto = resolved_provider in {"auto", "", None}
if should_fallback and is_auto:
if _is_payment_error(first_err):
reason = "payment error"
Expand Down Expand Up @@ -4500,7 +4500,7 @@ async def async_call_llm(
)
if client is None:
_explicit = (resolved_provider or "").strip().lower()
if _explicit and _explicit not in ("auto", "openrouter", "custom"):
if _explicit and _explicit not in {"auto", "openrouter", "custom"}:
raise RuntimeError(
f"Provider '{_explicit}' is set in config.yaml but no API key "
f"was found. Set the {_explicit.upper()}_API_KEY environment "
Expand Down Expand Up @@ -4611,7 +4611,7 @@ async def async_call_llm(

# ── Auth refresh retry (mirrors sync call_llm) ───────────────
if (_is_auth_error(first_err)
and resolved_provider not in ("auto", "", None)
and resolved_provider not in {"auto", "", None}
and not client_is_nous):
if _refresh_provider_credentials(resolved_provider):
logger.info(
Expand Down Expand Up @@ -4673,7 +4673,7 @@ async def async_call_llm(
or _is_connection_error(first_err)
or _is_rate_limit_error(first_err)
)
is_auto = resolved_provider in ("auto", "", None)
is_auto = resolved_provider in {"auto", "", None}
if should_fallback and is_auto:
if _is_payment_error(first_err):
reason = "payment error"
Expand Down
14 changes: 7 additions & 7 deletions agent/context_compressor.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def _strip_image_parts_from_parts(parts: Any) -> Any:
out.append(part)
continue
ptype = part.get("type")
if ptype in ("image", "image_url", "input_image"):
if ptype in {"image", "image_url", "input_image"}:
had_image = True
out.append({"type": "text", "text": "[screenshot removed to save context]"})
else:
Expand Down Expand Up @@ -274,8 +274,8 @@ def _summarize_tool_result(tool_name: str, tool_args: str, tool_content: str) ->
mode = args.get("mode", "replace")
return f"[patch] {mode} in {path} ({content_len:,} chars result)"

if tool_name in ("browser_navigate", "browser_click", "browser_snapshot",
"browser_type", "browser_scroll", "browser_vision"):
if tool_name in {"browser_navigate", "browser_click", "browser_snapshot",
"browser_type", "browser_scroll", "browser_vision"}:
url = args.get("url", "")
ref = args.get("ref", "")
detail = f" {url}" if url else (f" ref={ref}" if ref else "")
Expand Down Expand Up @@ -304,7 +304,7 @@ def _summarize_tool_result(tool_name: str, tool_args: str, tool_content: str) ->
code_preview += "..."
return f"[execute_code] `{code_preview}` ({line_count} lines output)"

if tool_name in ("skill_view", "skills_list", "skill_manage"):
if tool_name in {"skill_view", "skills_list", "skill_manage"}:
name = args.get("name", "?")
return f"[{tool_name}] name={name} ({content_len:,} chars)"

Expand Down Expand Up @@ -979,13 +979,13 @@ def _generate_summary(self, turns_to_summarize: List[Dict[str, Any]], focus_topi
_status = getattr(e, "status_code", None) or getattr(getattr(e, "response", None), "status_code", None)
_err_str = str(e).lower()
_is_model_not_found = (
_status in (404, 503)
_status in {404, 503}
or "model_not_found" in _err_str
or "does not exist" in _err_str
or "no available channel" in _err_str
)
_is_timeout = (
_status in (408, 429, 502, 504)
_status in {408, 429, 502, 504}
or "timeout" in _err_str
)
# Non-JSON / malformed-body responses from misconfigured providers
Expand Down Expand Up @@ -1479,7 +1479,7 @@ def compress(self, messages: List[Dict[str, Any]], current_tokens: int = None, f
first_tail_role = messages[compress_end].get("role", "user") if compress_end < n_messages else "user"
# Pick a role that avoids consecutive same-role with both neighbors.
# Priority: avoid colliding with head (already committed), then tail.
if last_head_role in ("assistant", "tool"):
if last_head_role in {"assistant", "tool"}:
summary_role = "user"
else:
summary_role = "assistant"
Expand Down
2 changes: 1 addition & 1 deletion agent/credential_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def to_dict(self) -> Dict[str, Any]:
}
result: Dict[str, Any] = {}
for field_def in fields(self):
if field_def.name in ("provider", "extra"):
if field_def.name in {"provider", "extra"}:
continue
value = getattr(self, field_def.name)
if value is not None or field_def.name in _ALWAYS_EMIT:
Expand Down
16 changes: 8 additions & 8 deletions agent/error_classifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class ClassifiedError:

@property
def is_auth(self) -> bool:
return self.reason in (FailoverReason.auth, FailoverReason.auth_permanent)
return self.reason in {FailoverReason.auth, FailoverReason.auth_permanent}



Expand Down Expand Up @@ -688,10 +688,10 @@ def _classify_by_status(
result_fn=result_fn,
)

if status_code in (500, 502):
if status_code in {500, 502}:
return result_fn(FailoverReason.server_error, retryable=True)

if status_code in (503, 529):
if status_code in {503, 529}:
return result_fn(FailoverReason.overloaded, retryable=True)

# Other 4xx — non-retryable
Expand Down Expand Up @@ -810,7 +810,7 @@ def _classify_400(
# Responses API (and some providers) use flat body: {"message": "..."}
if not err_body_msg:
err_body_msg = str(body.get("message") or "").strip().lower()
is_generic = len(err_body_msg) < 30 or err_body_msg in ("error", "")
is_generic = len(err_body_msg) < 30 or err_body_msg in {"error", ""}
# Absolute token/message-count thresholds are only a proxy for smaller
# context windows. Large-context sessions can have many messages while
# still being far below their actual token budget.
Expand Down Expand Up @@ -841,29 +841,29 @@ def _classify_by_error_code(
"""Classify by structured error codes from the response body."""
code_lower = error_code.lower()

if code_lower in ("resource_exhausted", "throttled", "rate_limit_exceeded"):
if code_lower in {"resource_exhausted", "throttled", "rate_limit_exceeded"}:
return result_fn(
FailoverReason.rate_limit,
retryable=True,
should_rotate_credential=True,
)

if code_lower in ("insufficient_quota", "billing_not_active", "payment_required"):
if code_lower in {"insufficient_quota", "billing_not_active", "payment_required"}:
return result_fn(
FailoverReason.billing,
retryable=False,
should_rotate_credential=True,
should_fallback=True,
)

if code_lower in ("model_not_found", "model_not_available", "invalid_model"):
if code_lower in {"model_not_found", "model_not_available", "invalid_model"}:
return result_fn(
FailoverReason.model_not_found,
retryable=False,
should_fallback=True,
)

if code_lower in ("context_length_exceeded", "max_tokens_exceeded"):
if code_lower in {"context_length_exceeded", "max_tokens_exceeded"}:
return result_fn(
FailoverReason.context_overflow,
retryable=True,
Expand Down
2 changes: 1 addition & 1 deletion agent/gemini_cloudcode_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def _coerce_content_to_text(content: Any) -> str:
if p.get("type") == "text" and isinstance(p.get("text"), str):
pieces.append(p["text"])
# Multimodal (image_url, etc.) — stub for now; log and skip
elif p.get("type") in ("image_url", "input_audio"):
elif p.get("type") in {"image_url", "input_audio"}:
logger.debug("Dropping multimodal part (not yet supported): %s", p.get("type"))
return "\n".join(pieces)
return str(content)
Expand Down
8 changes: 4 additions & 4 deletions agent/image_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def _explicit_aux_vision_override(cfg: Optional[Dict[str, Any]]) -> bool:
base_url = str(vision.get("base_url") or "").strip()

# "auto" / "" / blank = not explicit
if provider in ("", "auto") and not model and not base_url:
if provider in {"", "auto"} and not model and not base_url:
return False
return True

Expand Down Expand Up @@ -163,7 +163,7 @@ def _sniff_mime_from_bytes(raw: bytes) -> Optional[str]:
if raw.startswith(b"\xff\xd8\xff"):
return "image/jpeg"
# GIF87a / GIF89a
if raw[:6] in (b"GIF87a", b"GIF89a"):
if raw[:6] in {b"GIF87a", b"GIF89a"}:
return "image/gif"
# WEBP: "RIFF" .... "WEBP"
if len(raw) >= 12 and raw[:4] == b"RIFF" and raw[8:12] == b"WEBP":
Expand All @@ -172,9 +172,9 @@ def _sniff_mime_from_bytes(raw: bytes) -> Optional[str]:
if raw.startswith(b"BM"):
return "image/bmp"
# HEIC/HEIF: ftypheic / ftypheix / ftypmif1 / ftypmsf1 etc.
if len(raw) >= 12 and raw[4:8] == b"ftyp" and raw[8:12] in (
if len(raw) >= 12 and raw[4:8] == b"ftyp" and raw[8:12] in {
b"heic", b"heix", b"hevc", b"hevx", b"mif1", b"msf1", b"heim", b"heis",
):
}:
return "image/heic"
return None

Expand Down
4 changes: 2 additions & 2 deletions agent/memory_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,11 +470,11 @@ def _provider_memory_write_metadata_mode(provider: MemoryProvider) -> str:

accepted = [
p for p in params
if p.kind in (
if p.kind in {
inspect.Parameter.POSITIONAL_ONLY,
inspect.Parameter.POSITIONAL_OR_KEYWORD,
inspect.Parameter.KEYWORD_ONLY,
)
}
]
if len(accepted) >= 4:
return "positional"
Expand Down
Loading
Loading