Skip to content
Draft
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
14 changes: 13 additions & 1 deletion src/backend/chat/streaming/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,19 @@ async def stream_conversation(
else:
working_arguments = dict(arguments)
if session_id and _tool_requires_session_id(tool_name):
working_arguments.setdefault("session_id", session_id)
existing_session = working_arguments.get("session_id")
if (
isinstance(existing_session, str)
and existing_session.strip()
and existing_session.strip() != session_id
):
logger.debug(
"Overriding tool-provided session_id '%s' with active session '%s' for tool %s",
existing_session,
session_id,
tool_name,
)
working_arguments["session_id"] = session_id
try:
result_obj = await self._tool_client.call_tool(
tool_name, working_arguments
Expand Down
58 changes: 44 additions & 14 deletions src/backend/chat/streaming/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,54 @@


def parse_attachment_references(text: str) -> tuple[str, list[str]]:
"""Extract inline attachment references from tool output text."""
"""Extract attachment IDs from plain text markers or JSON payloads."""

if "attachment_id:" not in text:
if not isinstance(text, str):
return text, []

original_text = text
attachment_ids: list[str] = []
lines: list[str] = []

for line in text.split("\n"):
if line.strip().startswith("attachment_id:"):
attachment_id = line.strip().split(":", 1)[1].strip()
if attachment_id:
attachment_ids.append(attachment_id)
else:
lines.append(line)

cleaned_text = "\n".join(lines).strip()
return cleaned_text, attachment_ids

if "attachment_id:" in text:
lines: list[str] = []
for line in text.split("\n"):
if line.strip().startswith("attachment_id:"):
attachment_id = line.strip().split(":", 1)[1].strip()
if attachment_id:
attachment_ids.append(attachment_id)
else:
lines.append(line)
text = "\n".join(lines).strip()

if not attachment_ids:
attachment_ids = _extract_attachment_ids_from_json(original_text)

return text, attachment_ids


def _extract_attachment_ids_from_json(text: str) -> list[str]:
"""Parse JSON text to locate attachment_id fields."""

try:
payload = json.loads(text)
except (TypeError, ValueError):
return []

found: list[str] = []

def _walk(value: Any) -> None:
if isinstance(value, dict):
attachment_id = value.get("attachment_id")
if isinstance(attachment_id, str) and attachment_id.strip():
found.append(attachment_id.strip())
for child in value.values():
_walk(child)
elif isinstance(value, list):
for item in value:
_walk(item)

_walk(payload)
return found


def prepare_messages_for_model(
Expand Down
Loading