Files
kompas3d-mcp/docs/OPEN_QUESTIONS.md
T
mikhail 60cf26f739 refactor(core): правки по код-ревью (COM-утечки, безопасный shutdown, типобезопасность)
- PartModeler: ResetAsync/Dispose освобождают RCW и чистят реестр эскизов/операций;
  Editor освобождается после EndEdit (C1)
- DocumentTools: сброс реестра при create/open/close — нет устаревших id (C2)
- DocumentService: освобождение транзитных IDocuments/IKompasDocument (m9)
- KompasSession.Dispose: ограниченное ожидание 5с вместо вечного блока (M3)
- PartModeler.ExtrudeAsync: убран dynamic -> конкретные definition-типы;
  throughAll только для cut (M4)
- FeatureTools.extrude_cut: дефолт throughAll=false, без подмены depth (m7)
- tests: регрессия на сброс реестра (старый id недействителен)
- docs/OPEN_QUESTIONS.md: итоги ревью (исправлено/отложено)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 09:18:52 +03:00

78 lines
6.7 KiB
Markdown

# Открытые вопросы для проработки
Журнал спорных моментов и решений, принятых автономно (ночная сессия 2026-05-25/26).
Помечено: ⚠️ = требует вашего решения; ✅ = решено по умолчанию, можно пересмотреть.
---
## ⚠️ 1. API5 vs API7 для построения 3D
**Контекст.** Примеры SDK строят 3D через **API5** (`ksPart.NewEntity(o3d_*)`
`ksBossExtrusionDefinition``Create()`). API7 предлагает `IPart7``IModelContainer`
`IExtrusions.Add()`.
**Решение по умолчанию (✅ в коде):** в v1 строю 3D через **API5 `ksPart`** (надёжно, повторяет
рабочие примеры Step3d1). API7 использую для приложения/документов/версии.
**На проработку:** переводить ли операции на чистый API7 позже (плюс — единообразие, минус — риск).
## ✅ 2. Точка входа подключения — API5
Для построения 3D нужен `KompasObject` (API5), а для снимка — `ksDocument3D` (API5).
Поэтому `KompasSession` подключается через `KOMPAS.Application.5``KompasObject`, затем
`ksGetApplication7()``IApplication`. Держит обе ссылки. (Ранее в спайке заходили через `.7`.)
## ✅ 3. Состав проектов v1
Вместо 4 проектов (Host/Tools/Core/Interop) сделано компактно: **Core** (COM + сервисы) +
**Host** (MCP + определения инструментов) + **Tests**. Interop — вендорские DLL в `libs/`.
Разнести на больше проектов можно позже.
## ✅ 4. Тестовые артефакты
Тестовые документы КОМПАС сохраняю в `.scratch/` (gitignore). Снимки рендера — туда же,
для визуальной проверки.
---
## Само-ревью кода (ночная сессия) — итоги
**Исправлено сразу:**
- C1/C2 — утечки COM и устаревшие id: `PartModeler` освобождает RCW и сбрасывает реестр
(`ResetAsync`/`Dispose`), `DocumentTools` сбрасывает реестр при create/open/close;
`DocumentService` освобождает транзитные `IDocuments`/`IKompasDocument`.
- M3 — `KompasSession.Dispose`: ограниченное ожидание (5 c) вместо вечного блока.
- M4 — `ExtrudeAsync`: убран `dynamic`, конкретные `ksBossExtrusionDefinition`/
`ksCutExtrusionDefinition`; `throughAll` разрешён только для выреза.
- m7 — `extrude_cut`: дефолт `throughAll=false`, без молчаливой подмены `depth`.
- Регрессионный тест: после `ResetAsync` старый id эскиза недействителен.
**⚠️ Отложено на проработку (из ревью):**
- M5 — отмена/насос сообщений: `CancellationToken` не прерывает уже идущий COM-вызов; зависший
вызов (модальный диалог КОМПАС) блокирует всю очередь. Возможное решение — диспетчер с насосом
сообщений + подавление диалогов. Связано с [конкурентностью MCP].
- m6 — `colorBPP=24` для снимка: для GIF (палитра) может не подойти; снимок по умолчанию PNG.
- m8 — приведения enum к `short` для `GetPart/NewEntity/GetDefaultEntity`: на v24 работает
(тесты зелёные), но стоит сверить точные типы параметров в interop.
- m10 — `_app/_kompas` читаются из `IsConnected/Status()` вне STA-потока без `volatile`
(доброкачественное устаревшее чтение).
- m11 — трансляция `COMException`/HRESULT в понятные сообщения (сейчас понятны только наши
`InvalidOperationException`); добавить текст последней ошибки КОМПАС.
## Журнал решений по ходу
(дополняется автоматически во время работы)
### ⚠️ Конкурентность вызовов 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` остаётся **пустым**. Поэтому
`SnapshotService` рендерит во временный файл и читает байты обратно (надёжно проверено на v24 Home).
**На проработку:** пустое имя файла + `returnResultAsArrayBytes=true` для чистого in-memory —
не проверено; текущий путь через temp-файл работает.