chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping, Sequence
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class URLCitation:
|
||||
title: str
|
||||
url: str
|
||||
|
||||
|
||||
def get_field(obj: Any, key: str) -> Any:
|
||||
if isinstance(obj, Mapping):
|
||||
return obj.get(key)
|
||||
return getattr(obj, key, None)
|
||||
|
||||
|
||||
def extract_url_citations(items: Sequence[Any]) -> list[URLCitation]:
|
||||
citations: list[URLCitation] = []
|
||||
seen: set[str] = set()
|
||||
|
||||
for item in items:
|
||||
raw_item = get_field(item, "raw_item")
|
||||
if get_field(raw_item, "type") != "message":
|
||||
continue
|
||||
|
||||
content = get_field(raw_item, "content")
|
||||
if not isinstance(content, list):
|
||||
continue
|
||||
|
||||
for part in content:
|
||||
if get_field(part, "type") != "output_text":
|
||||
continue
|
||||
annotations = get_field(part, "annotations")
|
||||
if not isinstance(annotations, list):
|
||||
continue
|
||||
|
||||
for annotation in annotations:
|
||||
if get_field(annotation, "type") != "url_citation":
|
||||
continue
|
||||
url = get_field(annotation, "url")
|
||||
title = get_field(annotation, "title")
|
||||
if not isinstance(url, str) or url in seen:
|
||||
continue
|
||||
seen.add(url)
|
||||
citations.append(
|
||||
URLCitation(
|
||||
title=title if isinstance(title, str) else url,
|
||||
url=url,
|
||||
)
|
||||
)
|
||||
|
||||
return citations
|
||||
|
||||
|
||||
def extract_web_search_source_urls(items: Sequence[Any]) -> list[str]:
|
||||
urls: list[str] = []
|
||||
seen: set[str] = set()
|
||||
|
||||
for item in items:
|
||||
raw_item = get_field(item, "raw_item")
|
||||
if get_field(raw_item, "type") != "web_search_call":
|
||||
continue
|
||||
|
||||
action = get_field(raw_item, "action")
|
||||
sources = get_field(action, "sources") if action else None
|
||||
if not isinstance(sources, list):
|
||||
continue
|
||||
|
||||
for source in sources:
|
||||
url = get_field(source, "url")
|
||||
if not isinstance(url, str) or url in seen:
|
||||
continue
|
||||
seen.add(url)
|
||||
urls.append(url)
|
||||
|
||||
return urls
|
||||
Reference in New Issue
Block a user