b4fbd6fe9f
Deploy Site / deploy-vercel (push) Has been skipped
Deploy Site / deploy-docs (push) Has been skipped
Build Skills Index / build-index (push) Has been skipped
Build Skills Index / trigger-deploy (push) Waiting to run
CI / Deny unrelated histories (push) Has been skipped
CI / CI timing report (push) Blocked by required conditions
CI / Detect affected areas (push) Successful in 27m35s
CI / OSV scan (push) Failing after 4s
CI / Build&Test Docker image (push) Successful in 9s
CI / Supply-chain scan (push) Has been skipped
CI / Lint Docker scripts (push) Failing after 5m13s
CI / Check contributors (push) Failing after 12m8s
CI / Docs Site (push) Failing after 12m8s
CI / TypeScript (push) Failing after 12m8s
CI / Python lints (push) Failing after 12m9s
CI / Python tests (push) Failing after 12m9s
CI / Check uv.lock (push) Failing after 23m22s
CI / All required checks pass (push) Waiting to run
51 lines
1.3 KiB
Python
51 lines
1.3 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Mapping
|
|
from typing import Any
|
|
|
|
|
|
_NON_TEXT_PART_TYPES = {"image", "image_url", "input_image", "audio", "input_audio"}
|
|
_TEXT_KEYS = ("text", "content", "input_text", "output_text", "summary_text")
|
|
|
|
|
|
def _field(value: Any, key: str) -> Any:
|
|
if isinstance(value, Mapping):
|
|
return value.get(key)
|
|
return getattr(value, key, None)
|
|
|
|
|
|
def _text_from_part(part: Any) -> str:
|
|
if part is None:
|
|
return ""
|
|
if isinstance(part, str):
|
|
return part
|
|
|
|
part_type = str(_field(part, "type") or "").strip().lower()
|
|
if part_type in _NON_TEXT_PART_TYPES:
|
|
return ""
|
|
|
|
for key in _TEXT_KEYS:
|
|
text = _field(part, key)
|
|
if isinstance(text, str):
|
|
return text
|
|
return ""
|
|
|
|
|
|
def flatten_message_text(content: Any, *, sep: str = "\n") -> str:
|
|
"""Return the visible text from common chat/Responses message content shapes."""
|
|
if content is None:
|
|
return ""
|
|
if isinstance(content, str):
|
|
return content
|
|
if isinstance(content, list):
|
|
chunks = [_text_from_part(part) for part in content]
|
|
return sep.join(chunk for chunk in chunks if chunk)
|
|
|
|
text = _text_from_part(content)
|
|
if text:
|
|
return text
|
|
try:
|
|
return str(content)
|
|
except Exception:
|
|
return ""
|