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
8 changes: 2 additions & 6 deletions faigate/adaptation.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,16 +206,12 @@ def to_dict(self) -> dict[str, Any]:
"cooldown_window_s": cooldown_window_s,
"cooldown_remaining_s": cooldown_remaining_s,
"cooldown_until": (
round(self.last_issue_at + cooldown_window_s, 3)
if cooldown_window_s and self.last_issue_at
else 0.0
round(self.last_issue_at + cooldown_window_s, 3) if cooldown_window_s and self.last_issue_at else 0.0
),
"degraded_window_s": degraded_window_s,
"degraded_remaining_s": degraded_remaining_s,
"degraded_until": (
round(self.last_issue_at + degraded_window_s, 3)
if degraded_window_s and self.last_issue_at
else 0.0
round(self.last_issue_at + degraded_window_s, 3) if degraded_window_s and self.last_issue_at else 0.0
),
"window_state": self.window_state(),
"request_blocked": self.cooldown_active(),
Expand Down
4 changes: 1 addition & 3 deletions faigate/api/anthropic/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,7 @@ def _parse_system_prompt(raw: Any) -> str | list[str] | None:
if isinstance(raw, str):
return raw
if not isinstance(raw, list):
raise AnthropicBridgeError(
"'system' must be a string, a list of strings, a list of text blocks, or null"
)
raise AnthropicBridgeError("'system' must be a string, a list of strings, a list of text blocks, or null")

normalized: list[str] = []
for item in raw:
Expand Down
35 changes: 8 additions & 27 deletions faigate/bridges/anthropic/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,7 @@ def anthropic_request_to_canonical(
"""Map an Anthropic messages request to the internal gateway model."""

normalized_headers = {str(key): str(value) for key, value in (headers or {}).items()}
source = (
normalized_headers.get("x-faigate-client")
or normalized_headers.get("anthropic-client")
or "claude-code"
)
source = normalized_headers.get("x-faigate-client") or normalized_headers.get("anthropic-client") or "claude-code"
client = source
metadata = dict(request.metadata)
metadata.setdefault("source", source)
Expand Down Expand Up @@ -204,9 +200,7 @@ def approximate_anthropic_input_tokens(
total += 12
total += _estimate_text_tokens(tool.name)
total += _estimate_text_tokens(tool.description)
total += _estimate_text_tokens(
json.dumps(tool.input_schema, sort_keys=True, separators=(",", ":"))
)
total += _estimate_text_tokens(json.dumps(tool.input_schema, sort_keys=True, separators=(",", ":")))

return max(total, 1), "estimated-char-v1"

Expand Down Expand Up @@ -264,9 +258,7 @@ def _user_message_to_canonical(message: AnthropicMessage) -> list[CanonicalMessa
pending_text.append(block)
continue
if block.type != "tool_result":
raise AnthropicBridgeError(
"Anthropic bridge v1 supports only text and tool_result blocks in user messages"
)
raise AnthropicBridgeError("Anthropic bridge v1 supports only text and tool_result blocks in user messages")
if not block.tool_use_id:
# Claude-native clients can emit tool_result-like user blocks without a
# stable tool_use_id. Falling back to user text keeps the session
Expand All @@ -289,9 +281,7 @@ def _user_message_to_canonical(message: AnthropicMessage) -> list[CanonicalMessa
# OpenAI-style tool continuity requires tool messages to follow the
# assistant tool_calls immediately. Preserve any surrounding user text
# as a trailing user turn once all tool_result blocks are emitted.
canonical_messages.append(
CanonicalMessage(role="user", content=_text_blocks_to_string(pending_text))
)
canonical_messages.append(CanonicalMessage(role="user", content=_text_blocks_to_string(pending_text)))
return canonical_messages


Expand Down Expand Up @@ -402,11 +392,7 @@ def _canonical_content_to_anthropic_blocks(
content = message.content
blocks: list[AnthropicContentBlock]
if isinstance(content, str):
blocks = (
[]
if (not content and message.tool_calls)
else [AnthropicContentBlock(type="text", text=content)]
)
blocks = [] if (not content and message.tool_calls) else [AnthropicContentBlock(type="text", text=content)]
elif isinstance(content, list):
blocks = []
for item in content:
Expand Down Expand Up @@ -457,9 +443,7 @@ def _canonical_content_to_anthropic_blocks(
return blocks


def map_stop_reason_to_anthropic(
stop_reason: str | None, *, has_tool_calls: bool = False
) -> str | None:
def map_stop_reason_to_anthropic(stop_reason: str | None, *, has_tool_calls: bool = False) -> str | None:
"""Translate OpenAI-style finish reasons into Anthropic stop reasons."""

normalized = str(stop_reason or "").strip().lower()
Expand Down Expand Up @@ -567,8 +551,7 @@ async def openai_sse_to_anthropic(
"error",
{
"type": "error",
"error": payload.get("error")
or {"type": "api_error", "message": "Upstream error"},
"error": payload.get("error") or {"type": "api_error", "message": "Upstream error"},
},
)
return
Expand Down Expand Up @@ -639,9 +622,7 @@ async def openai_sse_to_anthropic(
if not isinstance(tool_delta, dict):
continue
raw_index = int(tool_delta.get("index") or 0)
state = tool_states.setdefault(
raw_index, _AnthropicStreamToolState(index=raw_index)
)
state = tool_states.setdefault(raw_index, _AnthropicStreamToolState(index=raw_index))
function = tool_delta.get("function") or {}
if tool_delta.get("id"):
state.tool_use_id = str(tool_delta["id"])
Expand Down
5 changes: 1 addition & 4 deletions faigate/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,7 @@ def _bar(ratio: float, width: int = 20, char: str = "█") -> str:
def _table(headers: list[str], rows: list[list[str]], col_widths: list[int] | None = None):
"""Print a simple aligned table."""
if not col_widths:
col_widths = [
max(len(h), max((len(str(r[i])) for r in rows), default=0)) + 2
for i, h in enumerate(headers)
]
col_widths = [max(len(h), max((len(str(r[i])) for r in rows), default=0)) + 2 for i, h in enumerate(headers)]

# Header
hdr = ""
Expand Down
Loading
Loading