Skip to content

Файлы и слой S3 ​

Где физически лежат файлы чатов, как устроен доступ к ним в стиле S3, как инструменты MCP получают временные ключи и какие действуют ограничения.

Главное, что нужно понять ​

Объектного хранилища в платформе нет. Ни MinIO, ни AWS S3, ни другого сервиса хранения. Файлы лежат в обычном каталоге на диске, а сведения о них в базе данных.

При этом API отдаёт эти файлы через набор адресов, повторяющих часть протокола S3. Сделано это для инструментов MCP: любой сервер, умеющий работать с S3, подключается к EVA без доработки.

Что из этого следует

API и Runtime должны видеть один и тот же каталог. Развести их на разные машины без общего диска нельзя. Репликации между хранилищами тоже нет, резервное копирование это копирование каталога вместе с базой данных.

Схема движения файла ​

Где лежат файлы ​

Каталог задаётся переменной SESSION_FILES_DIR, по умолчанию .data/session-files рядом с API. Внутри одна папка на чат:

{SESSION_FILES_DIR}/{идентификатор чата}/{идентификатор файла}__{имя файла}

Этот же путь передаётся рабочим процессам Runtime, поэтому инструменты работы с файлами читают их напрямую с диска. Выход за пределы каталога заблокирован.

Имя файла приводится к безопасному виду. Сохраняются буквы и цифры любого алфавита, включая русский, а также точка, дефис, пробел, круглые и квадратные скобки. Всё остальное заменяется на подчёркивание.

Сведения о файле ​

В базе на каждый файл хранится: чат, вид файла, имя, тип содержимого, размер, путь на диске и признак того, кто последним менял файл, пользователь или ИИ.

Вид файла бывает трёх значений: загруженный пользователем, рабочий и результат работы. Вид это только пометка, на путь к файлу он не влияет.

Одно имя на чат

В одном чате не может быть двух файлов с одинаковым именем. Повторная загрузка или запись файла с тем же именем перезаписывает прежний.

Адреса слоя S3 ​

Все обращения идут на /api/chat-s3 и требуют временный ключ в параметре token.

ОперацияЗапросЧто возвращает
Список объектовGET /api/chat-s3/{bucket}?list-type=2&prefix=...&token=...XML в формате ListBucketResult
Получить объектGET /api/chat-s3/{bucket}/{key}?token=...Содержимое файла, тип, размер, ETag
Проверить объектHEAD на тот же адресТолько заголовки
Записать объектPUT /api/chat-s3/{bucket}/{key}?token=...Пустое тело, ETag и заголовки с именем файла
Удалить объектDELETE /api/chat-s3/{bucket}/{key}?token=...Код 204, повторное удаление ошибкой не считается

Параметр list-type должен быть равен ровно 2, иначе запрос будет отклонён.

Имя корзины ​

Корзина одна, её имя берётся из CHAT_S3_BUCKET, по умолчанию chat-files. Обращение к любой другой корзине вернёт ошибку. Создавать и удалять корзины нельзя.

Ключ объекта ​

Ключ объекта:

sessions/<идентификатор чата>/<имя файла>

Имя файла в ключе закодировано по правилам URL.

Заголовки с русскими именами ​

При записи объекта API возвращает заголовки с ключом объекта и именем файла. Значения закодированы через encodeURIComponent, потому что в заголовках HTTP нельзя передавать неанглийские символы. Клиент обязан раскодировать их обратно.

Чего в слое нет ​

Многочастной загрузки, версий объектов, копирования, подписанных ссылок, подписи SigV4, запросов по диапазону байтов и постраничного перебора. Это подмножество, а не полноценный S3.

Временные ключи доступа ​

Ключ выглядит так:

base64url(JSON с чатом, пользователем и временем истечения) + "." + base64url(подпись HMAC-SHA256)

Это не JWT. Подпись считается на общем секрете платформы.

СвойствоЗначение
Как передаётсяПараметр запроса token
Время жизниCHAT_S3_TOKEN_TTL_SEC, по умолчанию 900 секунд
Когда выдаётсяНа каждое сообщение, если хотя бы один подключённый сервер MCP имеет доступ к файлам чата
Как попадает к серверу MCPТолько внутри вызова init_eva_session
Видит ли ключ модельНет, никогда

Поскольку привязка сессии выполняется заново перед вызовами инструментов, сервер MCP получает обновлённый ключ по ходу работы чата.

Адрес, который передаётся серверу MCP, зависит от настройки конкретного источника: внутренний адрес платформы, внешний адрес или собственный адрес для этого источника. К выбранному адресу добавляется /api/chat-s3.

Адрес должен быть доступен из контейнера MCP

Если сервер MCP работает в своём контейнере, адрес 127.0.0.1 для него бесполезен. Нужно указывать адрес, по которому API виден этому контейнеру.

Изоляция чатов ​

Проверка простая и строгая:

  • чат в ключе доступа должен совпадать с чатом в ключе объекта, иначе запрос отклоняется;
  • при запросе списка объектов префикс обязан начинаться с sessions/<чат из ключа доступа>/, иначе запрос отклоняется, а результат ещё раз фильтруется по префиксу.

Прочитать файлы другого чата по действующему ключу невозможно.

Ограничения на файлы ​

ОграничениеЗначение
Максимальный размер одного файла1 ГиБ
Максимум файлов за одну загрузку10
Таймаут загрузки1 час
Исполняемые файлыЗапрещены по расширению, по типу содержимого и по первым байтам файла
Загрузка по ссылкеТолько http и https, без данных для входа в ссылке, не больше 5 переадресаций, таймаут 20 секунд, тот же предел 1 ГиБ
Аватар и значок агентаИзображение в виде data-URL, не больше 400 000 символов
Чтение текста инструментомНе больше 200 000 символов за раз
Поиск по файлам чатаНе больше 50 совпадений

Проверка по первым байтам означает, что переименовать исполняемый файл в документ и загрузить его не получится.

Другие пути к файлам ​

Кроме слоя S3 есть обычные адреса для интерфейса:

  • скачивание файла пользователем;
  • запись файла из встроенного редактора, при этом файл помечается как изменённый пользователем;
  • отдельный предпросмотр HTML: платформа выдаёт временный ключ со временем жизни PREVIEW_TOKEN_TTL_SEC, по умолчанию 1200 секунд, и обслуживает файлы по имени, чтобы сгенерированная страница могла подключить свои стили.

Что стоит учитывать ​

Удаление чата удаляет записи в базе, но не удаляет каталог с файлами на диске. Автоматической очистки осиротевших файлов нет, кроме удаления конкретного файла при его удалении или перезаписи.

Документация платформы EVA