#15 Файловые вложения к сообщениям от юзера #16
4 changed files with 30 additions and 4 deletions
|
|
@ -9,6 +9,7 @@ WebSocket API SDK для взаимодействия с AI-агентом.
|
||||||
- Добавлен параметр `chat_id` в конструктор `AgentAPI`. Нужен для разделения истории сообщений по чатам/веткам.
|
- Добавлен параметр `chat_id` в конструктор `AgentAPI`. Нужен для разделения истории сообщений по чатам/веткам.
|
||||||
- `AgentAPI.connect()` вызывает `AgentBusyException`, если выбранный чат уже занят другим API клиентом.
|
- `AgentAPI.connect()` вызывает `AgentBusyException`, если выбранный чат уже занят другим API клиентом.
|
||||||
- Добавлен новый тип события `MsgEventSendFile` для отправки файлов пользователю. Поле `path` — путь к файлу относительно `/workspace`.
|
- Добавлен новый тип события `MsgEventSendFile` для отправки файлов пользователю. Поле `path` — путь к файлу относительно `/workspace`.
|
||||||
|
- `send_message(text, attachments)` теперь принимает `attachments` — список путей к файлам относительно `/workspace`.
|
||||||
|
|
||||||
## Установка
|
## Установка
|
||||||
В `master` всегда будет актуальная рабочая версия.
|
В `master` всегда будет актуальная рабочая версия.
|
||||||
|
|
|
||||||
|
|
@ -164,11 +164,17 @@ class AgentApi:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in on_disconnect: {e}")
|
logger.error(f"Error in on_disconnect: {e}")
|
||||||
|
|
||||||
async def send_message(self, text: str) -> AsyncIterator[AgentEventUnion]:
|
async def send_message(
|
||||||
|
self, text: str, attachments: list[str] | None = None
|
||||||
|
) -> AsyncIterator[AgentEventUnion]:
|
||||||
"""
|
"""
|
||||||
Нативный асинхронный генератор.
|
Нативный асинхронный генератор.
|
||||||
Не требует отдельного класса ResponseIterator.
|
Не требует отдельного класса ResponseIterator.
|
||||||
Гарантированно освобождает блокировку.
|
Гарантированно освобождает блокировку.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text: Текст сообщения.
|
||||||
|
attachments: Список путей к файлам относительно /workspace.
|
||||||
"""
|
"""
|
||||||
if not self._connected or not self._ws:
|
if not self._connected or not self._ws:
|
||||||
raise AgentException(
|
raise AgentException(
|
||||||
|
|
@ -185,7 +191,11 @@ class AgentApi:
|
||||||
try:
|
try:
|
||||||
self._current_queue = asyncio.Queue()
|
self._current_queue = asyncio.Queue()
|
||||||
|
|
||||||
message = MsgUserMessage(type=EClientMessage.USER_MESSAGE, text=text)
|
message = MsgUserMessage(
|
||||||
|
type=EClientMessage.USER_MESSAGE,
|
||||||
|
text=text,
|
||||||
|
attachments=attachments or [],
|
||||||
|
)
|
||||||
|
|
||||||
await self._ws.send_str(message.model_dump_json())
|
await self._ws.send_str(message.model_dump_json())
|
||||||
logger.debug(f"[{self.id}] Sent message: {text[:50]}...")
|
logger.debug(f"[{self.id}] Sent message: {text[:50]}...")
|
||||||
|
|
@ -248,7 +258,7 @@ class AgentApi:
|
||||||
self._request_lock.release()
|
self._request_lock.release()
|
||||||
|
|
||||||
async def _listen(self):
|
async def _listen(self):
|
||||||
""""
|
"""
|
||||||
Прослушивание вебсокета.
|
Прослушивание вебсокета.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,12 @@ class MsgUserMessage(BaseModel):
|
||||||
"""
|
"""
|
||||||
Текст сообщения.
|
Текст сообщения.
|
||||||
"""
|
"""
|
||||||
|
attachments: list[str] = Field(default_factory=list)
|
||||||
|
"""
|
||||||
|
Список вложений (файлов) к сообщению.
|
||||||
|
Передается путь до файла относительно /workspace .
|
||||||
|
Файлы уже должны быть загружены в директорию.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
ClientMessage = TypeAdapter(Annotated[
|
ClientMessage = TypeAdapter(Annotated[
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,18 @@ async def main():
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
prompt = await asyncio.get_event_loop().run_in_executor(None, input, ">>> ")
|
prompt = await asyncio.get_event_loop().run_in_executor(None, input, ">>> ")
|
||||||
|
attachments_input = await asyncio.get_event_loop().run_in_executor(
|
||||||
|
None, input, "Attachments (comma-separated, empty for none): "
|
||||||
|
)
|
||||||
|
attachments = (
|
||||||
|
[a.strip() for a in attachments_input.split(",") if a.strip()]
|
||||||
|
if attachments_input.strip()
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
print("Agent: ", end="")
|
print("Agent: ", end="")
|
||||||
is_tool = False
|
is_tool = False
|
||||||
async for chunk in api.send_message(prompt):
|
async for chunk in api.send_message(prompt, attachments):
|
||||||
match chunk:
|
match chunk:
|
||||||
case MsgEventTextChunk():
|
case MsgEventTextChunk():
|
||||||
is_tool = False
|
is_tool = False
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue