mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-05 15:22:11 +00:00
refactor: keep image URLs in text and centralize image auth
This commit is contained in:
parent
bec99b106e
commit
446b659c54
3 changed files with 40 additions and 56 deletions
|
|
@ -27,6 +27,28 @@ class LinearNotifyState(AgentState):
|
||||||
linear_messages_sent_count: int
|
linear_messages_sent_count: int
|
||||||
|
|
||||||
|
|
||||||
|
async def _build_blocks_from_payload(
|
||||||
|
payload: dict[str, Any],
|
||||||
|
) -> list[dict[str, Any]]:
|
||||||
|
text = payload.get("text", "")
|
||||||
|
image_urls = payload.get("image_urls", []) or []
|
||||||
|
blocks: list[dict[str, Any]] = []
|
||||||
|
if text:
|
||||||
|
blocks.append({"type": "text", "text": text})
|
||||||
|
|
||||||
|
if not image_urls:
|
||||||
|
return blocks
|
||||||
|
linear_api_key = os.environ.get("LINEAR_API_KEY", "")
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
for image_url in image_urls:
|
||||||
|
image_block = await fetch_image_block(
|
||||||
|
image_url, client, linear_api_key=linear_api_key
|
||||||
|
)
|
||||||
|
if image_block:
|
||||||
|
blocks.append(image_block)
|
||||||
|
return blocks
|
||||||
|
|
||||||
|
|
||||||
@before_model(state_schema=LinearNotifyState)
|
@before_model(state_schema=LinearNotifyState)
|
||||||
async def check_message_queue_before_model( # noqa: PLR0911
|
async def check_message_queue_before_model( # noqa: PLR0911
|
||||||
state: LinearNotifyState, # noqa: ARG001
|
state: LinearNotifyState, # noqa: ARG001
|
||||||
|
|
@ -84,36 +106,6 @@ async def check_message_queue_before_model( # noqa: PLR0911
|
||||||
thread_id,
|
thread_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _build_blocks_from_payload(
|
|
||||||
payload: dict[str, Any],
|
|
||||||
) -> list[dict[str, Any]]:
|
|
||||||
text = payload.get("text", "")
|
|
||||||
image_urls = payload.get("image_urls", []) or []
|
|
||||||
blocks: list[dict[str, Any]] = []
|
|
||||||
if text:
|
|
||||||
blocks.append({"type": "text", "text": text})
|
|
||||||
|
|
||||||
if not image_urls:
|
|
||||||
return blocks
|
|
||||||
linear_api_key = os.environ.get("LINEAR_API_KEY", "")
|
|
||||||
async with httpx.AsyncClient() as client:
|
|
||||||
for image_url in image_urls:
|
|
||||||
headers = None
|
|
||||||
if "uploads.linear.app" in image_url:
|
|
||||||
if linear_api_key:
|
|
||||||
headers = {"Authorization": linear_api_key}
|
|
||||||
else:
|
|
||||||
logger.warning(
|
|
||||||
"LINEAR_API_KEY not set; cannot authenticate image fetch for %s",
|
|
||||||
image_url,
|
|
||||||
)
|
|
||||||
image_block = await fetch_image_block(
|
|
||||||
image_url, client, headers=headers
|
|
||||||
)
|
|
||||||
if image_block:
|
|
||||||
blocks.append(image_block)
|
|
||||||
return blocks
|
|
||||||
|
|
||||||
content_blocks: list[dict[str, Any]] = []
|
content_blocks: list[dict[str, Any]] = []
|
||||||
for msg in queued_messages:
|
for msg in queued_messages:
|
||||||
content = msg.get("content")
|
content = msg.get("content")
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ from __future__ import annotations
|
||||||
import base64
|
import base64
|
||||||
import logging
|
import logging
|
||||||
import mimetypes
|
import mimetypes
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
|
@ -35,26 +36,27 @@ def extract_image_urls(text: str) -> list[str]:
|
||||||
return deduped
|
return deduped
|
||||||
|
|
||||||
|
|
||||||
def strip_image_urls(text: str, image_urls: list[str]) -> str:
|
|
||||||
"""Remove markdown image links and direct image URLs from text."""
|
|
||||||
if not text or not image_urls:
|
|
||||||
return text
|
|
||||||
|
|
||||||
logger.debug("Stripping %d image URL(s) from text", len(image_urls))
|
|
||||||
text = IMAGE_MARKDOWN_RE.sub("", text)
|
|
||||||
for url in image_urls:
|
|
||||||
text = text.replace(url, "")
|
|
||||||
return text
|
|
||||||
|
|
||||||
|
|
||||||
async def fetch_image_block(
|
async def fetch_image_block(
|
||||||
image_url: str,
|
image_url: str,
|
||||||
client: httpx.AsyncClient,
|
client: httpx.AsyncClient,
|
||||||
headers: dict[str, str] | None = None,
|
*,
|
||||||
|
linear_api_key: str | None = None,
|
||||||
) -> dict[str, Any] | None:
|
) -> dict[str, Any] | None:
|
||||||
"""Fetch image bytes and build an image content block."""
|
"""Fetch image bytes and build an image content block."""
|
||||||
try:
|
try:
|
||||||
logger.debug("Fetching image from %s", image_url)
|
logger.debug("Fetching image from %s", image_url)
|
||||||
|
headers = None
|
||||||
|
if "uploads.linear.app" in image_url:
|
||||||
|
if linear_api_key is None:
|
||||||
|
linear_api_key = os.environ.get("LINEAR_API_KEY", "")
|
||||||
|
if linear_api_key:
|
||||||
|
headers = {"Authorization": linear_api_key}
|
||||||
|
else:
|
||||||
|
logger.warning(
|
||||||
|
"LINEAR_API_KEY not set; cannot authenticate image fetch for %s",
|
||||||
|
image_url,
|
||||||
|
)
|
||||||
response = await client.get(image_url, headers=headers)
|
response = await client.get(image_url, headers=headers)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
content_type = response.headers.get("Content-Type", "").split(";")[0].strip()
|
content_type = response.headers.get("Content-Type", "").split(";")[0].strip()
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ from langgraph_sdk import get_client
|
||||||
|
|
||||||
# Local import for encryption
|
# Local import for encryption
|
||||||
from .encryption import encrypt_token
|
from .encryption import encrypt_token
|
||||||
from .utils.multimodal import extract_image_urls, fetch_image_block, strip_image_urls
|
from .utils.multimodal import extract_image_urls, fetch_image_block
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -581,7 +581,6 @@ async def process_linear_issue( # noqa: PLR0912, PLR0915
|
||||||
description_image_urls = extract_image_urls(description)
|
description_image_urls = extract_image_urls(description)
|
||||||
if description_image_urls:
|
if description_image_urls:
|
||||||
image_urls.extend(description_image_urls)
|
image_urls.extend(description_image_urls)
|
||||||
description = strip_image_urls(description, description_image_urls)
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Found %d image URL(s) in issue description",
|
"Found %d image URL(s) in issue description",
|
||||||
len(description_image_urls),
|
len(description_image_urls),
|
||||||
|
|
@ -643,7 +642,6 @@ async def process_linear_issue( # noqa: PLR0912, PLR0915
|
||||||
body_image_urls = extract_image_urls(body)
|
body_image_urls = extract_image_urls(body)
|
||||||
if body_image_urls:
|
if body_image_urls:
|
||||||
image_urls.extend(body_image_urls)
|
image_urls.extend(body_image_urls)
|
||||||
body = strip_image_urls(body, body_image_urls)
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Found %d image URL(s) in comment by %s",
|
"Found %d image URL(s) in comment by %s",
|
||||||
len(body_image_urls),
|
len(body_image_urls),
|
||||||
|
|
@ -661,7 +659,6 @@ async def process_linear_issue( # noqa: PLR0912, PLR0915
|
||||||
trigger_image_urls = extract_image_urls(trigger_body)
|
trigger_image_urls = extract_image_urls(trigger_body)
|
||||||
if trigger_image_urls:
|
if trigger_image_urls:
|
||||||
image_urls.extend(trigger_image_urls)
|
image_urls.extend(trigger_image_urls)
|
||||||
trigger_body = strip_image_urls(trigger_body, trigger_image_urls)
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Found %d image URL(s) in triggering comment by %s",
|
"Found %d image URL(s) in triggering comment by %s",
|
||||||
len(trigger_image_urls),
|
len(trigger_image_urls),
|
||||||
|
|
@ -696,16 +693,9 @@ async def process_linear_issue( # noqa: PLR0912, PLR0915
|
||||||
|
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
for image_url in image_urls:
|
for image_url in image_urls:
|
||||||
headers = None
|
image_block = await fetch_image_block(
|
||||||
if "uploads.linear.app" in image_url:
|
image_url, client, linear_api_key=LINEAR_API_KEY
|
||||||
if LINEAR_API_KEY:
|
)
|
||||||
headers = {"Authorization": LINEAR_API_KEY}
|
|
||||||
else:
|
|
||||||
logger.warning(
|
|
||||||
"LINEAR_API_KEY not set; cannot authenticate image fetch for %s",
|
|
||||||
image_url,
|
|
||||||
)
|
|
||||||
image_block = await fetch_image_block(image_url, client, headers=headers)
|
|
||||||
if image_block:
|
if image_block:
|
||||||
content_blocks.append(image_block)
|
content_blocks.append(image_block)
|
||||||
logger.info("Built %d content block(s) for prompt", len(content_blocks))
|
logger.info("Built %d content block(s) for prompt", len(content_blocks))
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue