fix(host): корректный возврат снимка через ImageContentBlock.FromBytes

- Data хранит base64-байты; сырые PNG-байты надо отдавать через FromBytes,
  иначе изображение портится на проводе (0x89 -> U+FFFD)
- проверено сквозным прогоном по MCP-протоколу: connect -> document_create ->
  sketch_create -> add_circle -> close -> extrude_boss -> model_snapshot,
  получен валидный PNG (~19 КБ) цилиндра
- docs/OPEN_QUESTIONS.md: конкурентность вызовов MCP и нюанс FromBytes

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 00:04:31 +03:00
parent 68855c218e
commit 230c534403
2 changed files with 15 additions and 5 deletions
+13
View File
@@ -32,6 +32,19 @@
## Журнал решений по ходу
(дополняется автоматически во время работы)
### ⚠️ Конкурентность вызовов MCP и состояние сессии
MCP-сервер обрабатывает запросы **конкурентно**. Цикл моделирования с реестром эскизов по id
(`sketch_create``sketch_add_*`) предполагает, что клиент **ждёт ответа** на каждый вызов перед
следующим (нормальное поведение LLM-клиентов). При «конвейерной» отправке зависимых вызовов
возможна гонка (id ещё не зарегистрирован). STA-диспетчер сериализует COM, но не порядок постановки задач.
**На проработку:** нужна ли серверная сериализация вызовов инструментов (очередь) для надёжности
stateful-сессии? Пока полагаемся на последовательное поведение клиента.
### ✅ Возврат изображения: ImageContentBlock.FromBytes
Поле `ImageContentBlock.Data` хранит **base64-байты**, а не сырые. Сырые байты PNG нужно
передавать через `ImageContentBlock.FromBytes(bytes, mimeType)` — он сам кодирует. Прямое
присваивание `Data = rawBytes` портит изображение на проводе. Исправлено в VisionTools.
### ✅ Снимок 3D: рендер через файл, а не resultArrayBytes
`ksDocument3D.SaveAsToRasterFormat(fileName, param)` при **непустом** `fileName` возвращает TRUE,
пишет корректный PNG на диск, но `param.resultArrayBytes` остаётся **пустым**. Поэтому