Skip to content
Open
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
1 change: 0 additions & 1 deletion .aiignore
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ htmlcov/
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ htmlcov/
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
Expand Down
2 changes: 1 addition & 1 deletion agents/canvas/src/canvas/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ async def canvas_agent(

if edit_request:
original_content = _get_text(edit_request.artifact)
selected_text = original_content[edit_request.start_index:edit_request.end_index]
selected_text = original_content[edit_request.start_index : edit_request.end_index]
system_prompt = f"""You are an expert content editor. The user has selected a part of a larger text and wants to edit it.

The user's instruction is: "{edit_request.description}"
Expand Down
1 change: 1 addition & 0 deletions agents/chat/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ ARG UV_VERSION=0.10.7
FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv
FROM python:3.14-alpine3.23@sha256:faee120f7885a06fcc9677922331391fa690d911c020abb9e8025ff3d908e510
ARG RELEASE_VERSION="main"
RUN apk add bash git nodejs npm curl
COPY ./agents/chat/ /app/agents/chat
COPY ./apps/agentstack-sdk-py/ /app/apps/agentstack-sdk-py/
WORKDIR /app/agents/chat
Expand Down
10 changes: 5 additions & 5 deletions agents/chat/src/chat/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
LLMServiceExtensionSpec,
TrajectoryExtensionServer,
TrajectoryExtensionSpec,
)
from agentstack_sdk.a2a.extensions.services.platform import (
PlatformApiExtensionServer,
PlatformApiExtensionSpec,
)
Expand Down Expand Up @@ -259,15 +257,17 @@ async def chat(
input=last_step.input, output=last_step.output, error=last_step.error
)
metadata = trajectory.trajectory_metadata(
title=last_step.tool.name if last_step.tool else None, content=trajectory_content.model_dump_json(), group_id=last_step.id
title=last_step.tool.name if last_step.tool else None,
content=trajectory_content.model_dump_json(),
group_id=last_step.id,
)
yield metadata
await context.store(AgentMessage(metadata=metadata))

if isinstance(last_step.output, FileCreatorToolOutput):
for file_info in last_step.output.result.files:
part = file_info.file.to_file_part()
part.file.name = file_info.display_filename
part = file_info.file.to_part()
part.filename = file_info.display_filename
artifact = AgentArtifact(name=file_info.display_filename, parts=[part])
yield artifact
await context.store(artifact)
Expand Down
6 changes: 3 additions & 3 deletions agents/chat/src/chat/tools/files/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ class OriginType(StrEnum):


ORIGIN_TYPE_BY_ROLE = {
Role.user: OriginType.UPLOADED,
Role.agent: OriginType.GENERATED,
Role.ROLE_USER: OriginType.UPLOADED,
Role.ROLE_AGENT: OriginType.GENERATED,
}


class FileChatInfo(BaseModel):
class FileChatInfo(BaseModel, arbitrary_types_allowed=True):
file: File
display_filename: str # A sanitized version of the filename used for display, in case of naming conflicts.
role: Role
Expand Down
21 changes: 10 additions & 11 deletions agents/chat/src/chat/tools/files/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Iterable

import pydantic
from a2a.types import FilePart, FileWithUri, Message, Role
from a2a.types import Message, Role
from beeai_framework.backend import AnyMessage, AssistantMessage, UserMessage

from agentstack_sdk.platform import File
Expand All @@ -17,14 +17,14 @@


def to_framework_message(message: Message, all_attachments: list[FileChatInfo]) -> AnyMessage:
message_text = "".join(part.root.text for part in message.parts if part.root.kind == "text")
message_text = "".join(part.text for part in message.parts if part.HasField("text"))
if attachments := [file for file in all_attachments if file.message_id == message.message_id]:
message_text += "\nAttached files:\n" + "\n".join([file.description for file in attachments])

match message.role:
case Role.agent:
case Role.ROLE_AGENT:
return AssistantMessage(message_text)
case Role.user:
case Role.ROLE_USER:
return UserMessage(message_text)
case _:
raise ValueError(f"Invalid message role: {message.role}")
Expand All @@ -46,13 +46,12 @@ async def extract_files(history: list[Message]) -> list[FileChatInfo]:

for item in history:
for part in item.parts:
match part.root:
case FilePart(file=FileWithUri(uri=uri)):
with suppress(ValueError):
url = pydantic.type_adapter.TypeAdapter(PlatformFileUrl).validate_python(uri)
if url.file_id not in seen:
seen.add(url.file_id)
files[url.file_id] = item
if part.HasField("url"):
with suppress(ValueError):
url = pydantic.type_adapter.TypeAdapter(PlatformFileUrl).validate_python(part.url)
if url.file_id not in seen:
seen.add(url.file_id)
files[url.file_id] = item

# TODO: N+1 query issue, add bulk endpoint
file_objects = await asyncio.gather(*(File.get(file_id) for file_id in files))
Expand Down
Loading