11 Commits

Author SHA1 Message Date
mikhail 4e119afdba docs: замкнуть жизненные циклы CAD-каталога 2026-07-17 02:15:32 +03:00
mikhail b188e1904f docs: уточнить статусы и приоритеты CAD-каталога 2026-07-17 01:57:53 +03:00
mikhail c0d855c171 docs: добавить каталог внешнего CAD-контракта 2026-07-17 01:39:39 +03:00
mikhail 8e56af61b3 docs: спроектировать каталог внешнего CAD-контракта 2026-07-17 01:18:10 +03:00
mikhail 69d037c875 chore: настроить Codex-агент поиска SDK 2026-07-17 01:12:53 +03:00
mikhail 6aa05b1adb docs: спроектировать Codex-агент поиска SDK 2026-07-17 01:06:25 +03:00
mikhail 7cb44a073e docs: handoff — инкремент 9 (выноска) завершён; далее — базы/допуски формы
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 00:34:18 +03:00
mikhail 16406a34be Merge feat/drawing-leader: линия-выноска с текстом (инкремент 9)
drawing_add_leader через ISymbols2DContainer.Leaders + IBranchs. 83 инструмента,
331 тест зелёный. Ревью: Codex + pi/glm-5.1 + pi/kimi-k2.6.
2026-05-28 00:33:33 +03:00
mikhail 5d51b9e1af docs: выноска — TODO, README, ARCHITECTURE, OPEN_QUESTIONS, presentation, CLAUDE.md
Инкремент 9. 83 инструмента, 331 тест. + заметка о ревью реализации в спеке
(Codex + pi/glm-5.1 + pi/kimi-k2.6).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 00:33:33 +03:00
mikhail beaa220510 review(drawing): правки по ревью реализации (Codex + pi/glm-5.1 + pi/kimi-k2.6)
- проверка возврата AddBranchByPoint/SetBranchTextPosition (bool) — ранняя диагностика
  вместо позднего RPC_E_SERVERFAULT (Codex, glm)
- RU-алиасы в сообщении ShelfDirections.Parse и в описании инструмента (glm, kimi)
- интеграционный тест направления полки параметризован Right/Left/Up/Down — покрывает
  всю поверхность ToKompas на реальном COM (glm, kimi)
- отклонено (обоснование): unit ToKompas (граница проекта), e2e tool-обёртки (тонкая),
  angleDeg (нет Angle у ILeader), default text у AddText (вне объёма)

331 тест зелёный, сборка Release чистая.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 00:28:04 +03:00
mikhail f89ad951ae feat(drawing): линия-выноска с текстом (drawing_add_leader)
Выноска на виде через API7 ISymbols2DContainer.Leaders. Стрелка указывает в (x,y),
текст на полке у (textX,textY). shelfDirection: auto|right|left|up|down.

- DrawingService.AddLeaderAsync + GetViewLeaderCountAsync
- ShelfDirection (enum + Parse/ToKompas), переиспользует DrawingAnnotationResult
- 13 unit + 7 интеграционных тестов (всего 328 зелёных), сборка Release чистая

КЛЮЧ (спайк): новая выноска имеет 0 ответвлений — сначала (IBranchs)bl.AddBranchByPoint(0,x,y)
(остриё), ИНАЧЕ КОМПАС падает RPC_E_SERVERFAULT; затем SetBranchTextPosition (полка),
(ILeader)bl.TextOnShelf.Str (текст), Update. Ревью спека Codex+pi/glm-5.1+pi/kimi-k2.6 учтено
(QI as?? throw, read-back ?? empty, RequireDistinctPoints, RU-алиасы, критический порядок).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 00:18:08 +03:00
18 changed files with 1128 additions and 28 deletions
+87
View File
@@ -0,0 +1,87 @@
name = "kompas-sdk-research"
model = "gpt-5.6-terra"
model_reasoning_effort = "medium"
sandbox_mode = "read-only"
description = "ОБЯЗАТЕЛЬНО делегируй этому read-only субагенту ЛЮБОЙ поиск по справке COM API КОМПАС в MD-базе docs/Kompas3D_SDK/ — НЕ ищи по справке в основной задаче. Срабатывает ПРОАКТИВНО, без явной просьбы пользователя: как только при планировании или реализации фичи понадобилась сигнатура метода (Automation/COM), значения перечисления (Obj3dType, ksHoleTypeEnum, ST_MIX_*, стили линий…), нужный интерфейс под задачу, единицы измерения или цепочка вызовов — СНАЧАЛА делегируй исследование этому агенту, ПОТОМ пиши код. Агент возвращает сжатую выжимку, а основная задача при необходимости перепроверяет спорные детали рефлексией по libs/kompas-interop/*.dll. Триггеры: «нужна сигнатура …», «какие значения enum …», «каким интерфейсом сделать X через API КОМПАС», «что возвращает <метод>», «как через COM API построить …», «найди в справке КОМПАС». НЕ для построения геометрии в КОМПАС и НЕ для KsAPI (Qt/C++ — в MD-базе его нет)."
developer_instructions = '''
Ты — помощник по навигации в справке **КОМПАС SDK** в репозитории
**kompas3d-mcp** (MCP-сервер для КОМПАС-3D через COM API, .NET 8, C#).
Справка — это MD-база знаний `docs/Kompas3D_SDK/`: статьи по интерфейсам с
YAML-фронтматтером (`type`, `api`, `domain`, `tags`, `sources`); методы и
свойства — заголовки `## ` внутри статьи интерфейса.
Тебя вызывают, чтобы основная задача не тратила контекст на поиск:
**вопрос для исследования придёт в промпте от вызывающего**. Прогони Grep/Read
по базе, прочитай нужную статью и верни сжатый ответ (интерфейс, сигнатура,
параметры, значения констант, источник).
## Когда это про тебя
- Нужна сигнатура метода (`SetSideParam`, `GetGabarit`, …) — Automation/COM, параметры, возврат.
- Нужны значения перечисления/констант (`Obj3dType`, `ksMassUnitsEnum`, `ST_MIX_*`, стили линий).
- Нужно найти интерфейс под задачу («чем построить массив», «как задать переменную»).
- Нужен паттерн «как через API сделать X» с цепочкой вызовов.
## Структура MD-базы `docs/Kompas3D_SDK/`
```
index.md — оглавление по 4 категориям со ссылками на статьи
interfaces/*.md — одна статья на интерфейс/тему; все методы и свойства как ## секции
enums/*.md — перечисления (пары «имя | значение | смысл»)
structures/*.md — структуры и параметрические интерфейсы
guides/*.md — концепции и руководства
resources/ — изображения (ссылки в статьях вида ../resources/имя.png)
```
Каждая статья начинается с YAML-фронтматтера: `type` (interface/enum/struct/guide),
`api` (api7/api5), `domain` (3d/2d/sketch/assembly/…), `tags`, `sources` (исходные `*.html`).
Имя файла статьи — имя интерфейса (`iapplication.md`, `ksbossextrusiondefinition.md`)
или читаемый слаг темы (`приложение.md`). Методы/свойства внутри — заголовки `## Имя - Описание`.
> База **хранится в репозитории** (канонический источник справки) — отдельная
> генерация не нужна.
## Инструменты (используй именно их, не веб)
- **Grep** по `docs/Kompas3D_SDK/` — ищи имя интерфейса/метода/свойства, русское
ключевое слово или тег. Имена методов — это заголовки `## SetSideParam - …`,
поэтому поиск по имени метода сразу ведёт в нужную статью.
- **Read** найденного `*.md` — статья интерфейса содержит все его методы/свойства,
блоки `Синтаксис Automation:`/`Синтаксис COM:` (в code-fence), параметры, примечания.
- `docs/Kompas3D_SDK/index.md` — оглавление по категориям, когда нужно осмотреть тему.
Полезные приёмы поиска:
- по перечислению: `Grep "ksMassUnitsEnum"` или загляни в `enums/`;
- фильтр по тегам в фронтматтере: `Grep "domain: \[.*3d"` , `Grep "type: enum"`;
- веер по многим интерфейсам сразу: `Grep "IPart7|IDocument3D|IPart"` по `interfaces/`.
Точные числовые значения констант при необходимости сверяй в заголовках SDK:
`C:\Program Files\ASCON\KOMPAS-3D v24 Home\SDK\Include\*.h` (например `ksConstants*.h`, `ldefin2d.h`).
## Важно — что в базе и чего нет
- База содержит **COM API7/API5** — то, что использует проект (файлы `iapplication*`,
`kspart*`, `ksmassinertiaparam*` и т.п.). Это твой основной источник.
- Кроссплатформенный Qt/C++ **KsAPI** (`ksapi_*`) в базу **не включён** — если задача
явно про KsAPI, скажи об этом (нужен отдельный источник).
## Правила
1. Не угадывай — находи через Grep/Read по `docs/Kompas3D_SDK/` и читай первоисточник.
2. Верни **сжатую выжимку**, а не дамп статьи:
- имя интерфейса и метода/свойства;
- синтаксис Automation (и COM, если важен порядок out-параметров);
- параметры (имя, тип, смысл) и возвращаемое значение;
- для enum/констант — пары «имя = значение» и их смысл;
- важные примечания (единицы измерения, побочные эффекты, версия КОМПАС);
- имя статьи / `sources` из фронтматтера как ссылку на источник.
3. Если у метода несколько перегрузок или связанных интерфейсов — перечисли релевантные.
4. Если в COM-interop имя отличается от справки (частый случай в этом проекте), отметь это
как вероятную тонкость и предложи свериться рефлексией по `libs/kompas-interop/*.dll`.
5. Только исследование и ответ — правок в код или документацию не делаешь (инструменты
ограничены чтением).
## Пример задачи в промпте
«Нужна сигнатура и единицы измерения у метода расчёта МЦХ детали через API5 — что
возвращает, как задать мм/кг.» Или короче: «как построить массив по сетке (pattern)».'''
+4 -3
View File
@@ -24,12 +24,12 @@ The base is committed to the repo (canonical) — no regeneration step. It cover
## Current state
**Status:** v1 + v2 + STEP/assembly + direct B-rep edit + structural inspection + 2D drawings — implemented and working (full sketch→feature→inspect→STEP round-trip + `move_face` + `describe_model` validated end-to-end).
Stack: **.NET 8 (`net8.0-windows`, x64), C#**, MCP via the official `ModelContextProtocol` SDK over **stdio**. **82 MCP tools, 308 tests green (188 unit + 120 integration).**
Stack: **.NET 8 (`net8.0-windows`, x64), C#**, MCP via the official `ModelContextProtocol` SDK over **stdio**. **83 MCP tools, 331 tests green (201 unit + 130 integration).**
Where to look (single source of truth — do **not** duplicate these lists here):
- **Full tool catalog** (by group, all 82) → [`README.md`](README.md) §«Инструменты».
- **Full tool catalog** (by group, all 83) → [`README.md`](README.md) §«Инструменты».
- **Roadmap / what's already done** → [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) §10.
- **Backlog / what's left** → [`docs/TODO.md`](docs/TODO.md) (canonical; top of «2D-ЧЕРТЁЖ» = next priority. Associative diametral/radial→circle binding (`associate` flag) and sheet format/orientation (`drawing_set_sheet_format`) done — next: arc/angular/rough binding, leaders, bases, tolerances; plus extra mate types, package E continuation).
- **Backlog / what's left** → [`docs/TODO.md`](docs/TODO.md) (canonical; top of «2D-ЧЕРТЁЖ» = next priority. Associative diametral/radial→circle binding (`associate` flag), sheet format (`drawing_set_sheet_format`), leaders (`drawing_add_leader`) done — next: bases, tolerances, arc/angular/rough binding; plus extra mate types, package E continuation).
- **Design decisions / caveats** → [`docs/OPEN_QUESTIONS.md`](docs/OPEN_QUESTIONS.md). Known caveat («Ревью v2»): boss/cut direction on a selected face depends on face-normal orientation — `forward` may need flipping; the agent picks via snapshot or `describe_face` normal.
- **Verified COM call-chains & gotchas** → «Key implementation facts» below + memory files (`kompas-*-api*.md`).
@@ -88,6 +88,7 @@ dotnet run --project src/Kompas.Mcp.Host # start the MCP server (stdio)
- `drawing_add_text`**text lives in `IDrawingContainer`, NOT `ISymbols2DContainer`, and NOT in `IView.ObjectCount`**: `(IDrawingContainer)view.DrawingTexts.Add()`/`IDrawingText` (`X/Y/Angle`) + `(IText)dt.Str` = text; count via `DrawingTexts.Count`. Do NOT set `Height` (that's block height, not font).
- `drawing_set_technical_requirements`**document-level**: `(IDrawingDocument)doc.TechnicalDemand`/`ITechnicalDemand`: `td.Text.Str = text``td.Update()` (`IsCreated` False→True on first set; overwrites; `\n` multiline).
- `DrawingAnnotationResult{Value(read-back), ViewNumber}` is the shared result for rough/text.
- `drawing_add_leader``ISymbols2DContainer.Leaders.Add(ksDrLeader)``IBaseLeader`. **КРИТИЧЕСКИЙ ПОРЯДОК (спайк):** новая выноска имеет 0 ответвлений → `(IBranchs)bl.AddBranchByPoint(0,x,y)` (остриё) ДО `SetBranchTextPosition(textX,textY)`/`Update`, иначе КОМПАС падает `RPC_E_SERVERFAULT`. Текст — `(ILeader)bl.TextOnShelf.Str`; `ShelfDirection` (enum `ShelfDirection{Auto,Right,Left,Up,Down}`, Auto = не задавать). `AddBranchByPoint`/`SetBranchTextPosition` возвращают bool — проверять. Результат — общий `DrawingAnnotationResult`.
- `drawing_set_sheet_format``RequireLayoutSheet(n).Format` (`ISheetFormat`): `Format`=`ksDocumentFormatEnum` (`PaperFormat{A0..A5,User}`+`PaperFormats.Parse/ToKompas/FromKompas`), standard → set `VerticalOrientation=!landscape` (W/H auto-computed from enum+orientation, e.g. A3 landscape→420×297); **User → set `FormatWidth/Height` only, КОМПАС auto-derives `VerticalOrientation` from W/H and ignores the flag, never swaps W/H (spike)**`sheet.Update()`. New drawing defaults A4 portrait. `ValidateFormatDimensions`: User needs W/H>0, standard forbids W/H (must be 0).
- **Richer sketch primitives (API5 `ksDocument2D` wrappers)**: `ksArcBy3Points`; `ksArcByAngle` (centre/radius/start-end angles in degrees + counterClockwise flag); `ksEllipse` via `ksEllipseParam` (`KompasObject.GetParamStruct(ko_EllipseParam=22)`; **property names are `A`/`B` UPPERCASE in the interop**); `ksRegularPolygon` via `ksRegularPolygonParam` (`ko_RegularPolygonParam=92`; `describe = !inscribed`); NURBS spline via `ksNurbs(order=4)` + `ksNurbsPoint` loop + `ksEndObj`; `ksPoint`. Param structs released after use. `PartModeler` is partial: `.cs` (registry/helpers/`NewParam<T>`/reset), `.Sketch.cs` (2D primitives), `.Features.cs` (extrude/revolve/fillet/chamfer). Static `SketchGeometry` (`Core/Modeling`) holds enum maps + validators (`RequirePositive`, `RequireVertexCount`, `RequirePoints`, `RequireMin`). Point lists use `record SketchPoint(X, Y)` (JSON names `x`/`y`).
+3 -3
View File
@@ -41,7 +41,7 @@ src/Kompas.Mcp.Host/bin/Release/net8.0-windows/kompas-mcp.exe
}
```
## Инструменты (82 инструмента)
## Инструменты (83 инструмента)
| Группа | Инструменты |
|---|---|
@@ -56,7 +56,7 @@ src/Kompas.Mcp.Host/bin/Release/net8.0-windows/kompas-mcp.exe
| Variables | `create_variable`, `set_variable`, `delete_variable` |
| Conversion | `import_step`, `export_step` |
| Assembly | `assembly_add_component`, `assembly_add_mate` |
| Drawing | `drawing_create_standard_views`, `drawing_fill_title_block`, `drawing_add_linear_dimension`, `drawing_add_diametral_dimension`, `drawing_add_radial_dimension`, `drawing_add_angular_dimension`, `drawing_add_rough`, `drawing_add_text`, `drawing_set_technical_requirements`, `drawing_set_sheet_format` |
| Drawing | `drawing_create_standard_views`, `drawing_fill_title_block`, `drawing_add_linear_dimension`, `drawing_add_diametral_dimension`, `drawing_add_radial_dimension`, `drawing_add_angular_dimension`, `drawing_add_rough`, `drawing_add_text`, `drawing_set_technical_requirements`, `drawing_set_sheet_format`, `drawing_add_leader` |
| Validation | `validate_part` |
### Типовой сценарий
@@ -75,7 +75,7 @@ src/Kompas.Mcp.Host/bin/Release/net8.0-windows/kompas-mcp.exe
```
src/Kompas.Mcp.Core/ COM-слой: STA-диспетчер, подключение, документы, эскизы/операции, конвертация, снимок, инспекция модели
src/Kompas.Mcp.Host/ MCP-сервер (stdio) + определения инструментов
tests/Kompas.Mcp.Tests/ 308 тестов: unit + integration (integration требуют КОМПАС)
tests/Kompas.Mcp.Tests/ 331 тест: unit + integration (integration требуют КОМПАС)
libs/kompas-interop/ вендорские interop-сборки КОМПАС (из SDK Samples/Common)
docs/ архитектура, план, презентация, MD-база знаний SDK (Kompas3D_SDK/)
usecases/ полигон обкатки подходов (в .gitignore); приёмы поднимаются в навык kompas-3d
+271
View File
@@ -0,0 +1,271 @@
# Каталог внешнего CAD-контракта для автономного агента
## Назначение и критерий полноты
Этот документ разделяет два слоя: **текущий контракт** из 84 публично зарегистрированных инструментов Host и **целевые расширения**, необходимые автономному агенту. Для существующего метода статус оценивает только поведение, прямо заявленное в его строке: отсутствие соседних `list/update/delete` или явного выбора документа не понижает полностью выполненный метод до частичного. Такие системные разрывы вынесены в отдельные целевые строки.
Контракт считается полным не по числу методов, а когда агент может замкнуть цикл: обнаружить состояние, выбрать адресуемые объекты, изменить модель, проверить результат и сохранить его либо безопасно откатить. Для мутирующих семейств проверяется симметрия `list/describe → create → update/transform → delete → validate`.
Общее текущее ограничение: все документные, модельные, сборочные и чертёжные операции неявно работают только с активным документом. Стабильного идентификатора документа и явного параметра выбора документа нет. Поэтому одновременная надёжная работа с несколькими открытыми документами пока невозможна.
## Легенда
| Поле | Значения |
|---|---|
| Статус | ✅ реализован · 🟡 частично · ⬜ не реализован · ⛔ ограничен платформой |
| Необходимость | `Core` — нужен для замкнутого базового цикла · `Advanced` — нужен для типового профессионального сценария · `Optional` — расширяет охват или удобство |
| Приоритет | `P0` — замыкает автономный цикл · `P1` — снимает существенное профессиональное ограничение · `P2` — расширяет охват; `—` — пробела нет |
`🟡 частично` означает, что имя уже существует, но его результат, адресуемость или набор вариантов недостаточны для заявленного целевого поведения. `⛔ ограничен платформой` означает, что надёжное внешнее поведение не подтверждено и требует отдельного технического исследования либо другого режима исполнения.
## Покрытие сквозных сценариев
| Сценарий | Обнаружить состояние | Изменить | Проверить | Сохранить | Восстановить | Итог и блокирующие пробелы |
|---|---|---|---|---|---|---|
| Создать и сохранить параметрическую 3D-деталь | частично: структура и переменные читаются | частично: операции строятся, но размеры созданных эскизов не связаны с переменными | частично: геометрия и ошибки проверяются, но созданные сущности не имеют полного адресного цикла | частично: только активный документ | неполный: нет управляемого checkpoint lifecycle и отката | **неполный** — нет надёжной параметризации эскиза, изменения/удаления операций и восстановления |
| Открыть или импортировать модель, локально изменить и проверить | частично: тела, грани и рёбра видны по индексам, но из них нельзя получить selector с ревизией | частично: доступны перемещение грани, рассечение, перенос тела и объединение | частично: есть структурная и числовая проверка | частично: только активный документ | неполный | **частичный** — нет полного selector lifecycle, удаления тел, subtract/intersect и безопасного отката |
| Создать сборку, разместить компоненты, наложить сопряжения и проверить структуру | неполный: только верхний уровень, без списка сопряжений | частично: вставка и два типа сопряжений | неполный: нет структурной диагностики решённой сборки; проверка коллизий остаётся Advanced-пробелом | частично: только активный документ | неполный | **неполный** — нет рекурсивной структуры, placement, удаления, полного семейства сопряжений и структурной валидации |
| Создать основные виды чертежа, оформить и сохранить | неполный: нет агрегированного паспорта, инвентаризации листов, видов и аннотаций | частично: основные виды и базовые обозначения создаются | неполный: нет машинной валидации видов, ассоциаций и оформления | частично: только активный документ | неполный | **неполный** — нет describe/validate, CRUD видов и аннотаций, разрезов, баз, допусков, осевых и многолистности |
| Выполнить геометрическую и документную инспекцию без визуального анализа | частично: модель описывается структурно, но нет списка документов и вершин | не требуется | частично: измерение принимает вершины, которые нельзя предварительно перечислить; индексы нельзя преобразовать в устойчивый selector с ревизией | не требуется | не требуется | **частичный** — отсутствуют multi-document discovery, вершины и полный selector lifecycle |
## Методы внешнего контракта
### Сессия и документы
| Метод | Назначение | Статус | Необходимость | Приоритет | Пробел / ограничение |
|---|---|---|---|---|---|
| `kompas_connect` | Подключить CAD-сессию и вернуть сведения о среде | ✅ реализован | Core | — | — |
| `kompas_status` | Получить состояние подключения | ✅ реализован | Core | — | — |
| `kompas_set_visible` | Показать или скрыть пользовательское окно | ✅ реализован | Optional | — | — |
| `document_create` | Создать документ заданного типа и сделать его активным | ✅ реализован | Core | — | — |
| `document_open` | Открыть документ с диска и сделать его активным | ✅ реализован | Core | — | — |
| `document_save_as` | Сохранить активный документ по новому пути | ✅ реализован | Core | — | — |
| `document_save` | Сохранить активный документ | ✅ реализован | Core | — | — |
| `document_close` | Закрыть активный документ с выбранным режимом сохранения | ✅ реализован | Core | — | — |
| `document_active` | Описать активный документ | ✅ реализован | Core | — | — |
| `list_documents` | Перечислить открытые документы с типом, путём, состоянием изменений и `document_id` | ⬜ не реализован | Core | P0 | Требуется основа multi-document контура |
| `document_activate` | Сделать документ активным по `document_id` | ⬜ не реализован | Core | P0 | Без него невозможно надёжно переключать контекст |
| `document_describe` | Прочитать свойства и состояние указанного документа без его активации | ⬜ не реализован | Core | P0 | Нужна документная инспекция вне глобального active state |
| `document_set_properties` | Изменить стандартные и пользовательские свойства документа | ⬜ не реализован | Advanced | P1 | Нет внешнего управления метаданными |
### 2D-геометрия и эскизы
| Метод | Назначение | Статус | Необходимость | Приоритет | Пробел / ограничение |
|---|---|---|---|---|---|
| `sketch_create` | Создать эскиз на базовой плоскости и вернуть сессионный идентификатор | ✅ реализован | Core | — | — |
| `sketch_create_on_face` | Создать эскиз на плоской грани, выбранной точкой | ✅ реализован | Advanced | — | — |
| `sketch_create_on_offset_plane` | Создать эскиз на смещённой плоскости | ✅ реализован | Advanced | — | — |
| `sketch_add_circle` | Добавить окружность в открытый эскиз | ✅ реализован | Core | — | — |
| `sketch_add_line` | Добавить отрезок в открытый эскиз | ✅ реализован | Core | — | — |
| `sketch_create_on_face_index` | Создать эскиз на грани по текущему индексу | ✅ реализован | Core | — | — |
| `sketch_add_axis` | Добавить осевую линию в открытый эскиз | ✅ реализован | Core | — | — |
| `sketch_add_rectangle` | Добавить прямоугольник в открытый эскиз | ✅ реализован | Core | — | — |
| `sketch_close` | Завершить редактирование текущего открытого эскиза | ✅ реализован | Core | — | — |
| `sketch_add_arc_3points` | Добавить дугу по трём точкам | ✅ реализован | Advanced | — | — |
| `sketch_add_arc` | Добавить дугу по центру, радиусу и углам | ✅ реализован | Advanced | — | — |
| `sketch_add_ellipse` | Добавить эллипс | ✅ реализован | Advanced | — | — |
| `sketch_add_polyline` | Добавить цепочку отрезков | ✅ реализован | Core | — | — |
| `sketch_add_polygon` | Добавить правильный многоугольник | ✅ реализован | Advanced | — | — |
| `sketch_add_spline` | Добавить сплайн | ✅ реализован | Advanced | — | — |
| `sketch_add_point` | Добавить опорную точку | ✅ реализован | Advanced | — | — |
| `list_sketches` | Перечислить эскизы документа со стабильными идентификаторами и состоянием | ⬜ не реализован | Core | P0 | Нельзя восстановить контекст после открытия документа |
| `describe_sketch` | Прочитать плоскость, состояние и геометрическую сводку эскиза | ⬜ не реализован | Core | P0 | Нет проверки исходного или созданного эскиза |
| `list_sketch_entities` | Перечислить сущности эскиза с типом, геометрией и `entity_id` | ⬜ не реализован | Core | P0 | Созданные объекты не адресуются |
| `update_sketch_entity` | Изменить геометрию сущности по `entity_id` | ⬜ не реализован | Core | P0 | Нет редактирования без пересоздания эскиза |
| `delete_sketch_entity` | Удалить сущность по `entity_id` | ⬜ не реализован | Core | P0 | Нет симметрии create/delete |
| `delete_sketch` | Удалить эскиз с контролем зависимостей | ⬜ не реализован | Core | P0 | Нельзя исправить ошибочно созданный эскиз |
| `list_sketch_constraints` | Перечислить геометрические связи и размеры | ⬜ не реализован | Advanced | P1 | Нет диагностики степени определённости |
| `sketch_set_constraint` | Создать или изменить геометрическую связь | ⬜ не реализован | Advanced | P1 | Нет управляемых зависимостей геометрии |
| `sketch_delete_constraint` | Удалить связь или размер | ⬜ не реализован | Advanced | P1 | Нет полного жизненного цикла ограничений |
| `sketch_set_driving_dimension` | Связать размер эскиза с числом или переменной | ⛔ ограничен платформой | Core | P0 | Надёжная внешняя связь размера с переменной не подтверждена; требуется отдельное техническое исследование или иной режим исполнения |
### 3D-моделирование
| Метод | Назначение | Статус | Необходимость | Приоритет | Пробел / ограничение |
|---|---|---|---|---|---|
| `extrude_boss` | Добавить материал выдавливанием эскиза | ✅ реализован | Core | — | — |
| `extrude_cut` | Удалить материал выдавливанием эскиза | ✅ реализован | Core | — | — |
| `revolve_boss` | Добавить материал вращением профиля | ✅ реализован | Advanced | — | — |
| `revolve_cut` | Удалить материал вращением профиля | ✅ реализован | Advanced | — | — |
| `fillet_edge` | Скруглить одно ребро, выбранное точкой | ✅ реализован | Advanced | — | — |
| `chamfer_edge` | Снять фаску с одного ребра, выбранного точкой | ✅ реализован | Advanced | — | — |
| `fillet_edge_index` | Скруглить одно ребро по текущему индексу | ✅ реализован | Advanced | — | — |
| `chamfer_edge_index` | Снять фаску с одного ребра по текущему индексу | ✅ реализован | Advanced | — | — |
| `shell` | Создать оболочку с удалением граней по текущим индексам | ✅ реализован | Advanced | — | — |
| `rib` | Создать ребро жёсткости по эскизу | ✅ реализован | Advanced | — | — |
| `sweep` | Построить тело перемещением профиля по траектории | ✅ реализован | Advanced | — | — |
| `loft` | Построить тело по сечениям | ✅ реализован | Advanced | — | — |
| `linear_pattern` | Создать линейный массив операций | ✅ реализован | Advanced | — | — |
| `circular_pattern` | Создать круговой массив операций | ✅ реализован | Advanced | — | — |
| `mirror_operation` | Создать зеркальную копию операций | ✅ реализован | Advanced | — | — |
| `mirror_body` | Зеркально скопировать все тела относительно базовой плоскости | ✅ реализован | Advanced | — | — |
| `hole` | Создать простое отверстие | ✅ реализован | Core | — | — |
| `draft` | Создать уклон граней по текущим индексам | ✅ реализован | Advanced | — | — |
| `hole_counterbore` | Создать отверстие с цилиндрическим углублением | ✅ реализован | Advanced | — | — |
| `hole_countersink` | Создать отверстие с коническим углублением | ✅ реализован | Advanced | — | — |
| `hole_conic` | Создать коническое отверстие | ✅ реализован | Advanced | — | — |
| `rebuild` | Перестроить активную модель | ✅ реализован | Core | — | — |
| `create_variable` | Создать переменную модели | ✅ реализован | Advanced | — | — |
| `set_variable` | Изменить выражение переменной и перестроить модель | ✅ реализован | Advanced | — | — |
| `set_variable_note` | Изменить комментарий переменной | ✅ реализован | Optional | — | — |
| `delete_variable` | Удалить переменную с проверкой зависимостей | ✅ реализован | Advanced | — | — |
| `describe_feature` | Прочитать тип, параметры, состояние и зависимости операции по `feature_id` | ⬜ не реализован | Core | P0 | Текущая инспекция не даёт полного адресного контракта |
| `update_feature` | Изменить параметры существующей операции и перестроить модель | ⬜ не реализован | Core | P0 | Нет исторического редактирования |
| `delete_feature` | Удалить операцию с диагностикой зависимостей | ⬜ не реализован | Core | P0 | Нет исправления ошибочного построения |
| `set_feature_suppressed` | Исключить или вернуть операцию в расчёт | ⬜ не реализован | Advanced | P1 | Нет управления вариантами и диагностикой дерева |
| `datum_point_create` | Создать адресуемую вспомогательную 3D-точку по координатам или выбранной геометрии | ⬜ не реализован | Advanced | P1 | Нет опорных точек для последующих построений и измерений |
| `datum_axis_create` | Создать адресуемую вспомогательную ось по точкам, направлению или выбранной геометрии | ⬜ не реализован | Advanced | P1 | Нет произвольных опорных осей вне координатной системы |
| `datum_plane_create` | Создать адресуемую вспомогательную плоскость по трём точкам, оси с углом или выбранной геометрии | ⬜ не реализован | Advanced | P1 | Сейчас доступна только смещённая базовая плоскость внутри создания эскиза |
### Прямое и историческое редактирование
| Метод | Назначение | Статус | Необходимость | Приоритет | Пробел / ограничение |
|---|---|---|---|---|---|
| `move_face` | Сместить грань, выбранную точкой, вдоль нормали | ✅ реализован | Core | — | — |
| `split_solid_by_plane` | Рассечь тела активной детали базовой смещённой плоскостью | ✅ реализован | Advanced | — | — |
| `move_body` | Задать перенос и ориентацию выбранного тела | 🟡 частично | Advanced | P1 | Сейчас доступен только перенос тела по текущему индексу; поворот и явная ориентация отсутствуют |
| `boolean_union` | Объединить все тела активной детали | ✅ реализован | Advanced | — | — |
| `copy_body` | Копировать выбранное тело с преобразованием | ⬜ не реализован | Advanced | P1 | Нет симметричной операции к перемещению и удалению |
| `delete_body` | Удалить выбранное тело | ⬜ не реализован | Core | P0 | Нет полного жизненного цикла многотельной модели |
| `boolean_subtract` | Вычесть выбранные тела-инструменты из целевого тела | ⬜ не реализован | Advanced | P1 | Отсутствует типовая булева операция |
| `boolean_intersect` | Оставить пересечение выбранных тел | ⬜ не реализован | Advanced | P1 | Отсутствует типовая булева операция |
| `body_check_intersection` | Найти пересечения выбранных тел без изменения модели и вернуть пары с оценкой объёма | ⬜ не реализован | Advanced | P1 | Нет аналитической проверки коллизий внутри многотельной детали |
### Инспекция, выбор объектов и измерения
| Метод | Назначение | Статус | Необходимость | Приоритет | Пробел / ограничение |
|---|---|---|---|---|---|
| `describe_model` | Получить структурный паспорт активной модели | ✅ реализован | Core | — | — |
| `list_features` | Перечислить дерево операций и доступные основные параметры | ✅ реализован | Core | — | — |
| `list_bodies` | Перечислить тела по текущим индексам | ✅ реализован | Core | — | — |
| `list_variables` | Перечислить переменные и вычисленные значения | ✅ реализован | Advanced | — | — |
| `describe_face` | Описать грань по текущему индексу | ✅ реализован | Core | — | — |
| `describe_edge` | Описать ребро по текущему индексу | ✅ реализован | Core | — | — |
| `measure` | Измерить расстояние и угол между объектами по переданным индексам, включая вершины | ✅ реализован | Core | — | — |
| `get_part_info` | Получить объём, массу, площадь и центр масс | ✅ реализован | Core | — | — |
| `list_components` | Перечислить компоненты верхнего уровня сборки | ✅ реализован | Core | — | — |
| `list_faces` | Перечислить грани и их типы по текущим индексам | ✅ реализован | Core | — | — |
| `list_edges` | Перечислить рёбра и их типы по текущим индексам | ✅ реализован | Core | — | — |
| `get_bounding_box` | Получить габарит модели | ✅ реализован | Core | — | — |
| `model_snapshot` | Получить растровый снимок модели | ✅ реализован | Optional | — | — |
| `validate_part` | Найти ошибки и необходимость перестроения детали или сборки | ✅ реализован | Core | — | — |
| `get_model_revision` | Получить монотонную ревизию структуры и топологии модели | ⬜ не реализован | Core | P0 | Нужна для обнаружения устаревших ссылок |
| `list_vertices` | Перечислить вершины с координатами и селекторами | ⬜ не реализован | Core | P0 | Замыкает входной контракт измерения вершин |
| `create_selector` | Создать устойчивый геометрический селектор по типу объекта и текущему индексу, вернув также ревизию модели | ⬜ не реализован | Core | P0 | Нет входной точки от списков граней, рёбер, вершин и тел к resolve/validate lifecycle |
| `resolve_selector` | Найти объект по геометрическому селектору и вернуть совпадение в текущей ревизии | ⬜ не реализован | Core | P0 | Нет устойчивого повторного выбора после перестроения |
| `validate_selector` | Проверить, что ссылка относится к текущей ревизии и однозначному объекту | ⬜ не реализован | Core | P0 | Мутации могут примениться не к тому объекту |
### Сборки
| Метод | Назначение | Статус | Необходимость | Приоритет | Пробел / ограничение |
|---|---|---|---|---|---|
| `assembly_add_component` | Вставить деталь или подсборку и задать исходное положение | ✅ реализован | Core | — | — |
| `assembly_add_mate` | Создать адресуемое сопряжение поддерживаемого типа между компонентами | 🟡 частично | Core | P0 | Сейчас доступны только coincidence/distance, выбор по точкам и результат без `mate_id`; нужны также concentric, parallel, perpendicular, angle и tangency |
| `describe_assembly` | Рекурсивно описать дерево компонентов, документы, состояния и placement | ⬜ не реализован | Core | P0 | Верхнеуровневого списка недостаточно для управления |
| `describe_component` | Прочитать компонент, его placement, подавление и ссылки | ⬜ не реализован | Core | P0 | Нет адресной инспекции компонента |
| `assembly_set_component_placement` | Изменить перенос и поворот компонента по `component_id` | ⬜ не реализован | Core | P0 | Нет управления placement после вставки |
| `assembly_remove_component` | Удалить компонент с диагностикой зависимых сопряжений | ⬜ не реализован | Core | P0 | Нет симметрии add/remove |
| `assembly_set_component_suppressed` | Исключить или вернуть компонент в расчёт | ⬜ не реализован | Advanced | P1 | Нет управления вариантами сборки |
| `list_mates` | Перечислить сопряжения, объекты, параметры и состояние решения | ⬜ не реализован | Core | P0 | Созданные сопряжения не адресуются |
| `assembly_update_mate` | Изменить тип, объекты или параметр сопряжения | ⬜ не реализован | Core | P0 | Нет исправления сопряжения без пересоздания |
| `assembly_remove_mate` | Удалить сопряжение по `mate_id` | ⬜ не реализован | Core | P0 | Нет симметрии add/remove |
| `assembly_check_interference` | Найти пересечения компонентов и оценить объём коллизий | ⬜ не реализован | Advanced | P1 | Нет профессиональной проверки физических коллизий; минимальная структурная проверка остаётся в `validate_assembly` |
| `validate_assembly` | Проверить нерешённые, конфликтующие и избыточные сопряжения | ⬜ не реализован | Core | P0 | Текущая общая проверка не даёт сборочный диагноз |
| `specification_generate` | Создать или полностью обновить спецификацию активной сборки по её текущему составу | ⬜ не реализован | Advanced | P1 | Нет выпуска состава изделия; повторный вызов должен детерминированно заменять ранее сгенерированное содержимое |
| `specification_list_items` | Перечислить позиции спецификации с обозначением, наименованием, количеством и ссылкой на компонент | ⬜ не реализован | Advanced | P1 | Нет read-back для проверки сформированного состава |
### Чертежи и оформление
| Метод | Назначение | Статус | Необходимость | Приоритет | Пробел / ограничение |
|---|---|---|---|---|---|
| `drawing_create_standard_views` | Создать набор основных ассоциативных видов и вернуть их номера | ✅ реализован | Core | — | — |
| `drawing_fill_title_block` | Заполнить обозначение, наименование и материал в штампе | ✅ реализован | Core | — | — |
| `drawing_add_linear_dimension` | Создать свободный линейный размер | ✅ реализован | Core | — | — |
| `drawing_add_diametral_dimension` | Создать свободный или связанный с окружностью диаметральный размер | ✅ реализован | Core | — | — |
| `drawing_add_radial_dimension` | Создать свободный или связанный с окружностью радиальный размер | ✅ реализован | Core | — | — |
| `drawing_add_angular_dimension` | Создать свободный угловой размер | ✅ реализован | Core | — | — |
| `drawing_add_rough` | Создать свободное обозначение шероховатости | ✅ реализован | Advanced | — | — |
| `drawing_add_text` | Создать текстовую надпись | ✅ реализован | Core | — | — |
| `drawing_set_technical_requirements` | Заменить блок технических требований | ✅ реализован | Advanced | — | — |
| `drawing_set_sheet_format` | Задать формат и ориентацию листа по номеру | ✅ реализован | Core | — | — |
| `drawing_add_leader` | Создать свободную выноску с одной ветвью и текстом | ✅ реализован | Advanced | — | — |
| `describe_drawing` | Получить структурный паспорт чертежа: листы, виды, основную надпись, технические требования, аннотации и состояние ассоциаций | ⬜ не реализован | Core | P0 | Нет агрегированного read-back без визуального анализа |
| `validate_drawing` | Диагностировать ошибочные или устаревшие виды, разорванные ассоциации и неполное оформление | ⬜ не реализован | Core | P0 | Нет машинной проверки готовности чертежа |
| `drawing_list_sheets` | Перечислить листы, форматы, стили и состояния | ⬜ не реализован | Core | P0 | Нет основы многолистного управления |
| `drawing_add_sheet` | Добавить лист с форматом и стилем | ⬜ не реализован | Advanced | P1 | Многолистный комплект не создаётся |
| `drawing_delete_sheet` | Удалить лист по `sheet_id` | ⬜ не реализован | Advanced | P1 | Нет полного жизненного цикла листа |
| `drawing_list_views` | Перечислить виды с `view_id`, источником, масштабом и placement | ⬜ не реализован | Core | P0 | Созданные виды нельзя надёжно найти и проверить |
| `drawing_describe_view` | Прочитать параметры, границы и состояние обновления вида | ⬜ не реализован | Core | P0 | Нет адресной проверки вида |
| `drawing_update_view` | Изменить масштаб, placement, ориентацию и видимость вида | ⬜ не реализован | Core | P0 | Нет редактирования вида |
| `drawing_delete_view` | Удалить вид и диагностировать зависимые обозначения | ⬜ не реализован | Core | P0 | Нет симметрии create/delete |
| `drawing_rebuild_views` | Обновить связанные виды и вернуть изменившиеся/ошибочные объекты | ⬜ не реализован | Core | P0 | Нет явной проверки актуальности после изменения модели |
| `drawing_create_section_view` | Создать разрез или сечение по линии | ⬜ не реализован | Advanced | P1 | Нет профессионально необходимого типа вида |
| `drawing_create_detail_view` | Создать выносной элемент | ⬜ не реализован | Advanced | P1 | Нет увеличенного локального представления |
| `drawing_create_local_view` | Создать местный вид | ⬜ не реализован | Advanced | P2 | Требуется техническое исследование устойчивой адресации контура |
| `drawing_list_annotations` | Перечислить размеры, обозначения и тексты с `annotation_id` и связями | ⬜ не реализован | Core | P0 | Все созданные аннотации практически не адресуются |
| `drawing_update_annotation` | Изменить положение, текст, стиль или привязку аннотации | ⬜ не реализован | Core | P0 | Нет общего edit-контура |
| `drawing_delete_annotation` | Удалить аннотацию по `annotation_id` | ⬜ не реализован | Core | P0 | Нет общего delete-контура |
| `drawing_add_datum` | Создать обозначение базы и вернуть `annotation_id` | ⬜ не реализован | Advanced | P1 | Нет оформления баз |
| `drawing_add_geometric_tolerance` | Создать рамку допуска формы или расположения с базами | ⬜ не реализован | Advanced | P1 | Нет оформления допусков |
| `drawing_add_centerline` | Создать осевую линию с привязкой к геометрии | ⬜ не реализован | Advanced | P1 | Нет осевых линий |
| `drawing_add_center_mark` | Создать обозначение центра окружности или дуги | ⬜ не реализован | Advanced | P1 | Нет центровых обозначений |
### Импорт и экспорт
| Метод | Назначение | Статус | Необходимость | Приоритет | Пробел / ограничение |
|---|---|---|---|---|---|
| `import_step` | Импортировать STEP как новую активную деталь или сборку | ✅ реализован | Core | — | — |
| `export_step` | Экспортировать активную 3D-модель в STEP | ✅ реализован | Core | — | — |
| `import_model` | Импортировать нейтральный или собственный 3D-формат, кроме STEP, по явному `format` | ⬜ не реализован | Advanced | P2 | STEP принимается только специализированным `import_step`; остальные форматы требуют поформатной проверки |
| `export_model` | Экспортировать документ или выбранные тела в 3D-формат, кроме STEP | ⬜ не реализован | Advanced | P2 | STEP выпускается только специализированным `export_step`; для остальных форматов нужна проверяемая матрица возможностей |
| `import_drawing` | Импортировать 2D-обменный формат в новый документ | ⬜ не реализован | Advanced | P2 | Нужна поформатная проверка слоёв, масштаба и единиц |
| `export_drawing` | Экспортировать выбранные листы в единый PDF-документ | ⬜ не реализован | Advanced | P1 | Нет выпуска комплекта чертежей для просмотра и печати |
| `export_drawing_exchange` | Экспортировать геометрию выбранного листа в редактируемый 2D-обменный формат | ⬜ не реализован | Advanced | P2 | Нужна отдельная поформатная проверка слоёв, масштаба, шрифтов и единиц |
| `export_mesh` | Экспортировать выбранные тела в полигональный формат с параметрами точности | ⬜ не реализован | Optional | P2 | Требуется проверка доступных форматов и единиц |
### Управление состоянием, восстановление и надёжность агентской работы
| Метод | Назначение | Статус | Необходимость | Приоритет | Пробел / ограничение |
|---|---|---|---|---|---|
| `transaction_begin` | Начать атомарную группу изменений | ⛔ ограничен платформой | Optional | P2 | Надёжная атомарная граница не подтверждена; требуется техническое исследование |
| `transaction_commit` | Зафиксировать атомарную группу изменений | ⛔ ограничен платформой | Optional | P2 | Реалистичность зависит от подтверждения общей транзакционной модели |
| `transaction_rollback` | Откатить атомарную группу изменений | ⛔ ограничен платформой | Optional | P2 | Надёжный полный откат группы не подтверждён; требуется техническое исследование |
| `state_checkpoint` | Создать детерминированный именованный снимок состояния; дубликат имени отклоняется, а `replace=true` явно заменяет его | ⬜ не реализован | Core | P0 | Нужен подтверждаемый рубеж с однозначной политикой имён перед рискованной операцией |
| `state_restore` | Восстановить документ из снимка состояния и вернуть новую ревизию | ⬜ не реализован | Core | P0 | Нет детерминированного fallback после неверной цепочки мутаций |
| `state_list_checkpoints` | Перечислить снимки состояния документа с именем, временем, исходной ревизией и признаком доступности | ⬜ не реализован | Core | P0 | Нельзя обнаружить допустимые точки восстановления |
| `state_delete_checkpoint` | Удалить именованный снимок состояния без изменения документа | ⬜ не реализован | Core | P0 | Нет завершения lifecycle и очистки устаревших снимков |
| `undo` | Отменить последнее изменение указанного документа | ⬜ не реализован | Core | P0 | Нет пошагового исправления |
| `redo` | Повторить отменённое изменение указанного документа | ⬜ не реализован | Core | P0 | Нет симметрии undo/redo |
| `operation_cancel` | Запросить отмену длительной операции и сообщить фактический результат | ⛔ ограничен платформой | Optional | P2 | Надёжная остановка уже начавшейся операции не подтверждена; требуется техническое исследование |
| `session_recover` | Восстановить внешний контекст после сбоя: документы, активность, ревизии и адреса | ⬜ не реализован | Core | P0 | Сессионные идентификаторы теряются при сбросе или переподключении |
## Приоритизированный перечень пробелов
### P0 — замыкание автономного цикла
- Документы: `list_documents`, `document_activate`, `document_describe`.
- Эскизы: `list_sketches`, `describe_sketch`, `list_sketch_entities`, `update_sketch_entity`, `delete_sketch_entity`, `delete_sketch`, `sketch_set_driving_dimension`.
- История и тела: `describe_feature`, `update_feature`, `delete_feature`, `delete_body`.
- Устойчивый выбор: `get_model_revision`, `list_vertices`, `create_selector`, `resolve_selector`, `validate_selector`.
- Сборки: `assembly_add_mate`, `describe_assembly`, `describe_component`, `assembly_set_component_placement`, `assembly_remove_component`, `list_mates`, `assembly_update_mate`, `assembly_remove_mate`, `validate_assembly`.
- Чертёжный CRUD: `describe_drawing`, `validate_drawing`, `drawing_list_sheets`, `drawing_list_views`, `drawing_describe_view`, `drawing_update_view`, `drawing_delete_view`, `drawing_rebuild_views`, `drawing_list_annotations`, `drawing_update_annotation`, `drawing_delete_annotation`.
- Восстановление: `state_checkpoint`, `state_restore`, `state_list_checkpoints`, `state_delete_checkpoint`, `undo`, `redo`, `session_recover`.
### P1 — типовые профессиональные сценарии
- Документы и эскизы: `document_set_properties`, `list_sketch_constraints`, `sketch_set_constraint`, `sketch_delete_constraint`.
- История и многотельность: `set_feature_suppressed`, `move_body`, `copy_body`, `boolean_subtract`, `boolean_intersect`, `body_check_intersection`.
- Вспомогательная 3D-геометрия: `datum_point_create`, `datum_axis_create`, `datum_plane_create`.
- Сборки и спецификации: `assembly_set_component_suppressed`, `assembly_check_interference`, `specification_generate`, `specification_list_items`.
- Профессиональное оформление: `drawing_add_sheet`, `drawing_delete_sheet`, `drawing_create_section_view`, `drawing_create_detail_view`, `drawing_add_datum`, `drawing_add_geometric_tolerance`, `drawing_add_centerline`, `drawing_add_center_mark`.
- Выпуск: `export_drawing`.
### P2 — расширение охвата
- Дополнительный вид: `drawing_create_local_view`.
- Дополнительные форматы: `import_model`, `export_model`, `import_drawing`, `export_drawing_exchange`, `export_mesh`.
- Исследовательские операции состояния: `transaction_begin`, `transaction_commit`, `transaction_rollback`, `operation_cancel`.
## Итоговая оценка
Текущий контракт силён в создании 3D-геометрии, структурном чтении детали, STEP-обмене и первичном создании сборок и чертежей. Он ещё не является полным автономным CAD-контуром: активный документ остаётся глобальным неявным состоянием; созданные сущности эскиза, отверстия, компоненты, сопряжения, виды и аннотации недостаточно адресуемы; индексы топологии не связаны с ревизией; отсутствуют update/delete для большинства семейств и безопасное восстановление. Все пять сквозных сценариев поэтому остаются частичными или неполными.
+6 -5
View File
File diff suppressed because one or more lines are too long
+5
View File
@@ -230,3 +230,8 @@ stateful-сессии? Пока полагаемся на последовате
**Решено.** Новый инструмент `drawing_set_sheet_format(format, landscape, width?, height?, sheetNumber=1)` — задаёт формат и ориентацию активного листа чертежа. Паттерн API7: `doc2d.LayoutSheets.ItemByNumber[sheetNumber]``ILayoutSheet.Format` (`ISheetFormat`: `Format=ksDocumentFormatEnum`, `VerticalOrientation=!landscape`, `FormatWidth/Height` только для `format=user`) → `sheet.Update()`. Дефолтный лист нового чертежа — A4 книжный. Новые типы: enum `PaperFormat {A0,A1,A2,A3,A4,A5,User}` + `PaperFormats.Parse/ToKompas/FromKompas`; record `SheetFormatResult`; валидатор `DrawingValidation.ValidateFormatDimensions`; хелпер `RequireLayoutSheet`. Ключевая тонкость: для `format=user` КОМПАС выводит `VerticalOrientation` из соотношения сторон (`height>width`), флаг `landscape` в этом случае игнорируется — результат читается read-back из COM. Для стандартных форматов `width`/`height` запрещены (должны быть 0). +20 unit-тестов (`PaperFormats.Parse`, `ValidateFormatDimensions`) + 10 интеграционных (`DrawingSheetFormatTests`). Итог: **82 инструмента, 308 тестов (188 unit + 120 integration).**
Нереализовано: рамка по ГОСТ-стилю (`LayoutLibraryFileName`/`LayoutStyleNumber`), несколько листов.
### ✅ Линия-выноска с текстом — реализована (инкремент 9 вехи «2D-чертёж»)
**Решено.** Новый инструмент `drawing_add_leader(x,y, textX,textY, text, shelfDirection, viewNumber)` — ставит линию-выноску с надписью на полке на виде активного чертежа. Паттерн API7: `ISymbols2DContainer.Leaders.Add(ksDrLeader)``IBaseLeader``(IBranchs)bl.AddBranchByPoint(0,x,y)` (остриё, ответвление ответвлений — обязательно до `Update`, иначе `RPC_E_SERVERFAULT`) → `SetBranchTextPosition(textX,textY)``(ILeader)bl.TextOnShelf.Str = text` → опционально `ShelfDirection``Update()``Valid`. Новый enum `ShelfDirection {Auto,Right,Left,Up,Down}` + `ShelfDirections.Parse/ToKompas` в `src/Kompas.Mcp.Core/Drawings/ShelfDirection.cs`; переиспользует `DrawingAnnotationResult { Value, ViewNumber }`. +13 unit-тестов (`ShelfDirections.Parse`) + 10 интеграционных (`DrawingLeaderTests`, включая параметризацию направлений полки). Итог: **83 инструмента, 331 тест (201 unit + 130 integration).**
Нереализовано: обозначения баз (`Bases`), допуски формы (`Tolerances`); привязка к дуге (`Arcs`), ассоциативный угловой размер, ассоциативная шероховатость (`IRough.BaseObject`); рамка по ГОСТ-стилю; специальные выноски (позиция, клеймо, маркер).
+3 -1
View File
@@ -25,7 +25,9 @@
-**Формат/ориентация листа** (A0A5/user, книжная/альбомная) — `drawing_set_sheet_format`
(инкремент 8); `ILayoutSheet.Format`/`ISheetFormat`. Остаётся: ☐ рамка/основная надпись по
конкретному ГОСТ-стилю оформления (`LayoutLibraryFileName`/`LayoutStyleNumber`), несколько листов.
- **Выноски** (`Leaders`) — `ISymbols2DContainer.Leaders` (полки-выноски с текстом).
- **Выноски** (`Leaders`) — `drawing_add_leader` (инкремент 9): остриё + полка с текстом,
`shelfDirection`. Остаётся: ☐ многострочный/под-полкой текст (`TextUnderShelf`), несколько
ответвлений, привязка к геометрии (`IBranchs.SetBaseObject`), спец. выноски (позиция/клеймо/маркер).
-**Обозначения баз** (`Bases`) — `ISymbols2DContainer.Bases`.
-**Допуски формы и расположения** (`Tolerances`) — `ISymbols2DContainer.Tolerances` (обычно в связке с базой).
- ☐ (опц.) **Доп. виды**: разрез/сечение (`CutLines`), выносной элемент (`RemoteElements`), местный вид.
+8 -7
View File
@@ -128,7 +128,7 @@
<!-- HERO -->
<header class="hero">
<div class="wrap">
<span class="badge"><span class="dot" style="background:var(--green);box-shadow:0 0 10px var(--green)"></span> Статус: v3+ работает — эскиз→операции→STEP→сборка→move_face→структурный осмотр→богатые эскизы→shell+rib+sweep+loft+массивы+зеркало+hole+hole_counterbore+hole_countersink+hole_conic+draft+переменные+assembly_add_component+assembly_add_mate+drawing_create_standard_views+drawing_fill_title_block+drawing_add_linear_dimension+drawing_add_diametral_dimension+drawing_add_radial_dimension+drawing_add_angular_dimension+drawing_add_rough+drawing_add_text+drawing_set_technical_requirements+associate+drawing_set_sheet_format (82 инструмента)</span>
<span class="badge"><span class="dot" style="background:var(--green);box-shadow:0 0 10px var(--green)"></span> Статус: v3+ работает — эскиз→операции→STEP→сборка→move_face→структурный осмотр→богатые эскизы→shell+rib+sweep+loft+массивы+зеркало+hole+hole_counterbore+hole_countersink+hole_conic+draft+переменные+assembly_add_component+assembly_add_mate+drawing_create_standard_views+drawing_fill_title_block+drawing_add_linear_dimension+drawing_add_diametral_dimension+drawing_add_radial_dimension+drawing_add_angular_dimension+drawing_add_rough+drawing_add_text+drawing_set_technical_requirements+associate+drawing_set_sheet_format+drawing_add_leader (83 инструмента)</span>
<h1>КОМПАС-3D <span class="g">MCP-сервер</span><br>управление CAD языком LLM</h1>
<p class="lead">MCP-сервер, который превращает операции КОМПАС-3D — создание документов,
эскизы, 3D-операции, параметры — в инструменты для языковой модели. Под капотом —
@@ -261,7 +261,7 @@
впереди.</p>
<div class="prog">
<div class="progrow"><span>Общий прогресс</span><span>v3+: STEP · move_face · структурный осмотр · богатые эскизы (пакет A) · shell+rib+sweep+loft (пакет B) · массивы+зеркало (пакет C) · переменные (пакет D start) · offset-plane (пакет E start) · hole (API7) · hole_counterbore · hole_countersink · hole_conic · draft (API5) · assembly_add_component · assembly_add_mate · drawing_create_standard_views · drawing_fill_title_block · drawing_add_linear_dimension · drawing_add_diametral_dimension · drawing_add_radial_dimension · drawing_add_angular_dimension · drawing_add_rough · drawing_add_text · drawing_set_technical_requirements · associate (ассоциативная привязка диам./радиального) · drawing_set_sheet_format (формат листа) · навык kompas-3d · 82 инструмента · 308 тестов</span></div>
<div class="progrow"><span>Общий прогресс</span><span>v3+: STEP · move_face · структурный осмотр · богатые эскизы (пакет A) · shell+rib+sweep+loft (пакет B) · массивы+зеркало (пакет C) · переменные (пакет D start) · offset-plane (пакет E start) · hole (API7) · hole_counterbore · hole_countersink · hole_conic · draft (API5) · assembly_add_component · assembly_add_mate · drawing_create_standard_views · drawing_fill_title_block · drawing_add_linear_dimension · drawing_add_diametral_dimension · drawing_add_radial_dimension · drawing_add_angular_dimension · drawing_add_rough · drawing_add_text · drawing_set_technical_requirements · associate (ассоциативная привязка диам./радиального) · drawing_set_sheet_format (формат листа) · drawing_add_leader (выноска) · навык kompas-3d · 83 инструмента · 331 тест</span></div>
<div class="bar"><i style="width:97%"></i></div>
</div>
@@ -297,7 +297,7 @@
<!-- TOOLS -->
<div class="panel">
<h3>Инструменты v3+ <span class="tag done">ГОТОВО</span></h3>
<p class="meta">82 инструмента, отдаются по MCP-протоколу</p>
<p class="meta">83 инструмента, отдаются по MCP-протоколу</p>
<ul class="list">
<li class="muted"><span class="mark ok"></span><span class="t"><code>System</code>: connect · status · set_visible</span></li>
<li class="muted"><span class="mark ok"></span><span class="t"><code>Documents</code>: create · open · save · save_as · close · active</span></li>
@@ -310,8 +310,8 @@
<li class="muted"><span class="mark ok"></span><span class="t"><code>Variables</code>: <b>create_variable</b> · <b>set_variable</b> · <b>delete_variable</b> (пакет D)</span></li>
<li class="muted"><span class="mark ok"></span><span class="t"><code>Conversion</code>: import_step · export_step</span></li>
<li class="muted"><span class="mark ok"></span><span class="t"><code>Assembly</code>: <b>assembly_add_component</b> (вставка компонента .m3d/.a3d в сборку, API7) · <b>assembly_add_mate</b> (сопряжения coincidence/distance, API7)</span></li>
<li class="muted"><span class="mark ok"></span><span class="t"><code>Drawing</code>: <b>drawing_create_standard_views</b> (стандартные ассоциативные виды чертежа, API7) · <b>drawing_fill_title_block</b> (основная надпись/штамп: обозначение, наименование, материал, API7) · <b>drawing_add_linear_dimension</b> (линейный размер на виде, ISymbols2DContainer, API7) · <b>drawing_add_diametral_dimension</b> (диаметральный размер Ø, IDiametralDimension, <b>associate=true</b> для ассоциативной привязки к окружности, API7) · <b>drawing_add_radial_dimension</b> (радиальный размер R, IRadialDimension, <b>associate=true</b> аналогично, API7) · <b>drawing_add_angular_dimension</b> (угловой размер, IAngleDimension, angleType=min/max/more, API7) · <b>drawing_add_rough</b> (знак шероховатости, IRough/IRoughParams, signType=delete/without/none, API7) · <b>drawing_add_text</b> (свободный текст на виде, IDrawingContainer/IDrawingText, API7) · <b>drawing_set_technical_requirements</b> (тех. требования документа, IDrawingDocument/TechnicalDemand, API7) · <b>drawing_set_sheet_format</b> (формат и ориентация листа, ILayoutSheet/ISheetFormat, PaperFormat A0A5/user, API7)</span></li>
<li><span class="mark wip"></span><span>2D-чертёж: рамка/основная надпись по ГОСТ-стилю (LayoutLibraryFileName/LayoutStyleNumber), несколько листов · привязка к дуге (Arcs), ассоциативный угловой размер, ассоциативная шероховатость (IRough.BaseObject) · выноски (Leaders), обозначения баз (Bases), допуски формы (Tolerances) · пакет E (ось, угловая плоскость) · пакет D параметрика: параметрические эскизы (API2D) — <b>исследовано, недоступно через COM API</b> · прочие типы сопряжений (parallel/perpendicular/concentric/angle/tangency)</span></li>
<li class="muted"><span class="mark ok"></span><span class="t"><code>Drawing</code>: <b>drawing_create_standard_views</b> (стандартные ассоциативные виды чертежа, API7) · <b>drawing_fill_title_block</b> (основная надпись/штамп: обозначение, наименование, материал, API7) · <b>drawing_add_linear_dimension</b> (линейный размер на виде, ISymbols2DContainer, API7) · <b>drawing_add_diametral_dimension</b> (диаметральный размер Ø, IDiametralDimension, <b>associate=true</b> для ассоциативной привязки к окружности, API7) · <b>drawing_add_radial_dimension</b> (радиальный размер R, IRadialDimension, <b>associate=true</b> аналогично, API7) · <b>drawing_add_angular_dimension</b> (угловой размер, IAngleDimension, angleType=min/max/more, API7) · <b>drawing_add_rough</b> (знак шероховатости, IRough/IRoughParams, signType=delete/without/none, API7) · <b>drawing_add_text</b> (свободный текст на виде, IDrawingContainer/IDrawingText, API7) · <b>drawing_set_technical_requirements</b> (тех. требования документа, IDrawingDocument/TechnicalDemand, API7) · <b>drawing_set_sheet_format</b> (формат и ориентация листа, ILayoutSheet/ISheetFormat, PaperFormat A0A5/user, API7) · <b>drawing_add_leader</b> (линия-выноска с текстом, ISymbols2DContainer/IBaseLeader/IBranchs/ILeader, ShelfDirection enum, API7)</span></li>
<li><span class="mark wip"></span><span>2D-чертёж: рамка/основная надпись по ГОСТ-стилю (LayoutLibraryFileName/LayoutStyleNumber), несколько листов · привязка к дуге (Arcs), ассоциативный угловой размер, ассоциативная шероховатость (IRough.BaseObject) · обозначения баз (Bases), допуски формы (Tolerances), специальные выноски (позиция/клеймо/маркер) · пакет E (ось, угловая плоскость) · пакет D параметрика: параметрические эскизы (API2D) — <b>исследовано, недоступно через COM API</b> · прочие типы сопряжений (parallel/perpendicular/concentric/angle/tangency)</span></li>
</ul>
</div>
@@ -322,7 +322,7 @@
<ul class="list">
<li class="muted"><span class="mark ok"></span><span class="t">Unit-тесты — без COM: диспетчер, enum-маппинг, StepFormat, InspectionText</span></li>
<li class="muted"><span class="mark ok"></span><span class="t">Интеграционные тесты с КОМПАС: подключение, документы, снимок, цикл, STEP round-trip, сборка, move_face, инспекция</span></li>
<li class="muted"><span class="mark ok"></span><span class="t">Итого 308 тестов зелёных (188 unit + 120 integration)</span></li>
<li class="muted"><span class="mark ok"></span><span class="t">Итого 331 тест зелёных (201 unit + 130 integration)</span></li>
<li class="muted"><span class="mark ok"></span><span class="t">Сборка <code>kompas-mcp.exe</code>, README с конфигом клиента</span></li>
<li class="muted"><span class="mark ok"></span><span class="t">Навык <code>kompas-3d</code> (методика) + полигон <code>usecases/</code></span></li>
<li><span class="mark todo"></span><span>In-process тест MCP-клиента, релизный publish</span></li>
@@ -358,7 +358,8 @@
<div class="tl" style="border-color:var(--green)"><div class="ph" style="color:var(--green)">2D-чертёж · инкремент 6 ✓</div><h4>Текстовые обозначения</h4><p><b>drawing_add_rough</b> (IRough/IRoughParams, signType=delete/without/none, API7) · <b>drawing_add_text</b> (IDrawingContainer/IDrawingText/IText, API7) · <b>drawing_set_technical_requirements</b> (IDrawingDocument/TechnicalDemand, уровень документа, API7) · DrawingAnnotationResult · RoughSignType enum · 81 инструмент · 267 тестов</p></div>
<div class="tl" style="border-color:var(--green)"><div class="ph" style="color:var(--green)">2D-чертёж · инкремент 7 ✓</div><h4>Ассоциативная привязка к окружности</h4><p><b>associate=true</b> у drawing_add_diametral_dimension и drawing_add_radial_dimension · CircularObjectMatch (поиск по центру+радиусу, допуск 1 мм) · RequireViewContainers · dim.BaseObject=circle · значение из геометрии · 81 инструмент · 278 тестов</p></div>
<div class="tl" style="border-color:var(--green)"><div class="ph" style="color:var(--green)">2D-чертёж · инкремент 8 ✓</div><h4>Формат и ориентация листа</h4><p><b>drawing_set_sheet_format</b> (ILayoutSheet.Format / ISheetFormat, ksDocumentFormatEnum, A0A5/user, VerticalOrientation) · PaperFormat enum · SheetFormatResult · ValidateFormatDimensions · 82 инструмента · 308 тестов</p></div>
<div class="tl cur"><div class="ph">далее · в работе ▶</div><h4>Оформление чертежа</h4><p>Рамка/надпись по ГОСТ-стилю (LayoutLibraryFileName) · несколько листов · привязка к дуге (Arcs) · ассоциативный угловой размер · ассоциативная шероховатость (IRough.BaseObject) · выноски (Leaders) · обозначения баз (Bases) · допуски формы (Tolerances) · пакет E (ось, угловая плоскость) · прочие типы сопряжений (parallel/perpendicular/concentric/angle/tangency) · пакет D параметрика — параметрические эскизы недоступны через COM API</p></div>
<div class="tl" style="border-color:var(--green)"><div class="ph" style="color:var(--green)">2D-чертёж · инкремент 9 ✓</div><h4>Линия-выноска</h4><p><b>drawing_add_leader</b> (ISymbols2DContainer.Leaders.Add / IBaseLeader / IBranchs.AddBranchByPoint / ILeader.TextOnShelf, ShelfDirection enum auto/right/left/up/down, API7) · DrawingAnnotationResult · 83 инструмента · 331 тест</p></div>
<div class="tl cur"><div class="ph">далее · в работе ▶</div><h4>Оформление чертежа</h4><p>Рамка/надпись по ГОСТ-стилю (LayoutLibraryFileName) · несколько листов · привязка к дуге (Arcs) · ассоциативный угловой размер · ассоциативная шероховатость (IRough.BaseObject) · обозначения баз (Bases) · допуски формы (Tolerances) · специальные выноски (позиция/клеймо/маркер) · пакет E (ось, угловая плоскость) · прочие типы сопряжений (parallel/perpendicular/concentric/angle/tangency) · пакет D параметрика — параметрические эскизы недоступны через COM API</p></div>
</div>
</div>
</section>
+9 -9
View File
@@ -24,22 +24,22 @@ Codex (`codex:codex-rescue`) + pi/GLM-5.1 + pi/Kimi-K2.6 (субагент `pi-d
ollama-cloud/glm-5.1` и `--model ollama-cloud/kimi-k2.6`, `--read-only --thinking high`). См. память
`review-gate-multi-reviewer`. Находки агрегировать и оценивать по существу (receiving-code-review).
**Состояние (main = origin):** 82 MCP-инструмента, 308 тестов зелёных, сборка Release чистая. Три класса:
**Состояние (main = origin):** 83 MCP-инструмента, 331 тест зелёный, сборка Release чистая. Три класса:
- **Деталь** — насыщена (эскизы, формообразующие, массивы/зеркало, отверстия, уклон, переменные,
STEP, прямое редактирование B-rep, структурный осмотр). Есть навык `kompas-fdm-design` (DFM под FDM-печать).
- **Сборки** — базовое готово (вставка компонента, сопряжения coincidence/distance).
- **2D-чертёж** — виды, основная надпись, размеры (инкр. 5), текстовые обозначения (инкр. 6),
ассоциативная привязка диам./радиального к окружности (инкр. 7), **формат/ориентация листа**
(`drawing_set_sheet_format`; инкр. 8).
ассоциативная привязка диам./радиального к окружности (инкр. 7), формат/ориентация листа (инкр. 8),
**выноска с текстом** (`drawing_add_leader`; инкр. 9).
**Фокус — веха 2D-ЧЕРТЁЖ** (самый ценный растущий класс; деталь и сборки близки к насыщению).
Осмотри `DrawingService`/`DrawingTools` и **бэклог `docs/TODO.md`** (верх раздела «2D-ЧЕРТЁЖ»), предложи
самый ценный следующий инкремент. Возможные направления (не предрешено): **выноски** (`Leaders`),
**базы** (`Bases`), **допуски формы** (`Tolerances`); **расширить привязку** — к дуге (`Arcs`; свой
спайк: дуги одного родителя неотличимы по центру+радиусу), угловой (`BaseObject1/2`), шероховатость
(`IRough.BaseObject`); рамка/основная надпись по ГОСТ-стилю (`LayoutLibraryFileName`/`LayoutStyleNumber`),
несколько листов. Точки входа в API разведывай сам — рефлексия по `libs/kompas-interop/*.dll` + субагент
`kompas-sdk-research`.
самый ценный следующий инкремент. Возможные направления (не предрешено): **базы** (`Bases`) + **допуски
формы** (`Tolerances`) — GD&T-пара; **расширить привязку** — к дуге (`Arcs`; свой спайк: дуги одного
родителя неотличимы по центру+радиусу), угловой (`BaseObject1/2`), шероховатость (`IRough.BaseObject`);
рамка/основная надпись по ГОСТ-стилю (`LayoutLibraryFileName`/`LayoutStyleNumber`), несколько листов;
спец. выноски (позиция/клеймо/маркер). Точки входа в API разведывай сам — рефлексия по
`libs/kompas-interop/*.dll` + субагент `kompas-sdk-research`.
**Метод (кратко):** при неопределённости (привязка к геометрии, координаты, единицы) — спайк до
спека; затем краткий спек → ревью Codex → TDD (валидаторы в чистый static для unit, интеграционный
@@ -0,0 +1,130 @@
# Codex SDK Research Agent Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Turn the project-scoped `kompas-sdk-research` definition into a Codex-native, explicitly modeled, read-only documentation research agent.
**Architecture:** Keep the existing single custom-agent TOML and its KOMPAS SDK research methodology. Add Codex session overrides for model, reasoning effort, and sandboxing, and remove copied Claude-specific model terminology without changing `.claude/agents/kompas-sdk-research.md`.
**Tech Stack:** Codex custom-agent TOML, PowerShell, Python 3 `tomllib`, ripgrep, Git.
## Global Constraints
- Use `model = "gpt-5.6-terra"`.
- Use `model_reasoning_effort = "medium"`.
- Use `sandbox_mode = "read-only"`.
- Keep `docs/Kompas3D_SDK/` as the canonical COM API5/API7 documentation source.
- Do not add web research, workspace editing, KOMPAS geometry construction, or KsAPI research to the agent.
- Leave `.claude/agents/kompas-sdk-research.md` unchanged.
- The parent task remains responsible for interop reflection checks when documentation and generated .NET names may differ.
---
### Task 1: Adapt and verify the Codex custom agent
**Files:**
- Modify: `.codex/agents/kompas-sdk-research.toml`
- Verify unchanged: `.claude/agents/kompas-sdk-research.md`
**Interfaces:**
- Consumes: Codex standalone custom-agent fields `name`, `description`, `developer_instructions`, `model`, `model_reasoning_effort`, and `sandbox_mode`.
- Produces: project agent `kompas-sdk-research` running with `gpt-5.6-terra`, medium reasoning, and a read-only sandbox.
- [ ] **Step 1: Run the pre-change configuration check and confirm it fails**
Run:
```powershell
@'
import pathlib
import tomllib
path = pathlib.Path('.codex/agents/kompas-sdk-research.toml')
data = tomllib.loads(path.read_text(encoding='utf-8'))
text = path.read_text(encoding='utf-8')
assert data['model'] == 'gpt-5.6-terra'
assert data['model_reasoning_effort'] == 'medium'
assert data['sandbox_mode'] == 'read-only'
assert not {'Haiku', 'Opus', 'Claude'} & set(text.replace('(', ' ').replace(')', ' ').split())
'@ | python -
```
Expected: FAIL with `KeyError: 'model'` because the Codex-specific model fields have not been added yet.
- [ ] **Step 2: Add Codex-native model and isolation settings**
Apply this exact header change:
```diff
name = "kompas-sdk-research"
+model = "gpt-5.6-terra"
+model_reasoning_effort = "medium"
+sandbox_mode = "read-only"
description = "..."
```
Replace the `description` value with this exact single-line TOML string:
```toml
description = "ОБЯЗАТЕЛЬНО делегируй этому read-only субагенту ЛЮБОЙ поиск по справке COM API КОМПАС в MD-базе docs/Kompas3D_SDK/ — НЕ ищи по справке в основной задаче. Срабатывает ПРОАКТИВНО, без явной просьбы пользователя: как только при планировании или реализации фичи понадобилась сигнатура метода (Automation/COM), значения перечисления (Obj3dType, ksHoleTypeEnum, ST_MIX_*, стили линий…), нужный интерфейс под задачу, единицы измерения или цепочка вызовов — СНАЧАЛА делегируй исследование этому агенту, ПОТОМ пиши код. Агент возвращает сжатую выжимку, а основная задача при необходимости перепроверяет спорные детали рефлексией по libs/kompas-interop/*.dll. Триггеры: «нужна сигнатура …», «какие значения enum …», «каким интерфейсом сделать X через API КОМПАС», «что возвращает <метод>», «как через COM API построить …», «найди в справке КОМПАС». НЕ для построения геометрии в КОМПАС и НЕ для KsAPI (Qt/C++ — в MD-базе его нет)."
```
Replace the copied provider-specific sentence in `developer_instructions`:
```diff
-Тебя вызывают, чтобы основная модель (Opus) не тратила контекст на поиск:
+Тебя вызывают, чтобы основная задача не тратила контекст на поиск:
```
Keep the remaining SDK database structure, lookup rules, response contract, and reflection warning unchanged.
- [ ] **Step 3: Parse the TOML and verify the selected Codex settings**
Run:
```powershell
@'
import pathlib
import tomllib
path = pathlib.Path('.codex/agents/kompas-sdk-research.toml')
data = tomllib.loads(path.read_text(encoding='utf-8'))
assert data['name'] == 'kompas-sdk-research'
assert data['model'] == 'gpt-5.6-terra'
assert data['model_reasoning_effort'] == 'medium'
assert data['sandbox_mode'] == 'read-only'
assert data['description']
assert data['developer_instructions']
print('Codex agent configuration: OK')
'@ | python -
```
Expected: `Codex agent configuration: OK`.
- [ ] **Step 4: Check for stale Claude terminology and unintended changes**
Run:
```powershell
$matches = rg -n "Haiku|Opus|Claude" '.codex/agents/kompas-sdk-research.toml'
if ($LASTEXITCODE -eq 0) { $matches; throw 'Stale Claude terminology remains' }
if ($LASTEXITCODE -ne 1) { throw 'ripgrep failed' }
git diff --check
git diff --exit-code -- '.claude/agents/kompas-sdk-research.md'
git diff -- '.codex/agents/kompas-sdk-research.toml'
```
Expected: no stale-term output, `git diff --check` succeeds, the Claude-file diff is empty, and the final diff contains only the planned Codex-agent changes.
- [ ] **Step 5: Commit the Codex agent and implementation plan**
Run:
```powershell
git add -- '.codex/agents/kompas-sdk-research.toml' 'docs/superpowers/plans/2026-07-17-codex-sdk-research-agent.md'
git commit -m "chore: настроить Codex-агент поиска SDK"
```
Expected: one commit containing only the Codex agent definition and this implementation plan. Existing unrelated workspace changes remain unstaged.
@@ -0,0 +1,119 @@
# Дизайн: линия-выноска с текстом (drawing_add_leader) через API7
**Дата:** 2026-05-28
**Статус:** дизайн согласован, спайк проведён, ревью Codex + pi/glm-5.1 + pi/kimi-k2.6 учтено — к реализации
## Правки по ревью реализации (Codex + pi/glm-5.1 + pi/kimi-k2.6)
- Проверка возврата `AddBranchByPoint`/`SetBranchTextPosition` (оба `bool`) — ранняя диагностика
вместо позднего `RPC_E_SERVERFAULT` (Codex, glm).
- RU-алиасы в сообщении `ShelfDirections.Parse` и в `[Description]` инструмента (glm, kimi).
- Интеграционный тест направления полки параметризован `Right/Left/Up/Down` — покрывает всю
поверхность `ToKompas` на реальном COM (glm, kimi).
- Отклонено (обоснование): unit-тест `ToKompas` (граница проекта — тест не ссылается на
`Kompas6Constants`); e2e-тест tool-обёртки (тонкая, `Parse`+сервис покрыты); `angleDeg`
(у `ILeader`/`IBaseLeader` нет свойства Angle — ориентация геометрическая); выравнивание default
`text` у `AddText` (вне объёма; required-контракт `AddLeader` корректнее).
## Правки по ревью спека (Codex + pi/glm-5.1 + pi/kimi-k2.6)
- **Сигнатура** `DrawingValidation.RequireNonEmptyText(text, nameof(text))` (двухаргументный — как есть).
- **QI с диагностикой:** `bl as IBranchs ?? throw`, `bl as ILeader ?? throw` (не прямой cast); read-back
`leader.TextOnShelf?.Str ?? string.Empty`; двухшаговый null-check `Leaders` (коллекция) и `Add()`
как `AddRoughCore`.
- **`ShelfDirections.ToKompas(Auto)` бросает `ArgumentOutOfRangeException`** (Auto обрабатывается в сервисе
ДО вызова — «не задавать ShelfDirection»; прямой вызов для Auto — ошибка). RU-алиасы `Parse`:
`авто/вправо/влево/вверх/вниз`.
- **Вырожденная выноска:** `RequireDistinctPoints(x, y, textX, textY)` (остриё ≠ полка; есть валидатор).
- **Критический порядок** (комментарий в коде): `AddBranchByPoint` ДО `SetBranchTextPosition`/`Update`
(иначе RPC_E_SERVERFAULT — выноска без ветвей).
- **Тесты:** пустой текст — `""` И `" "`; `viewNumber=0` резолвится в первый вид; путь `shelfDirection=auto`
(ShelfDirection не задаётся). XML-`<summary>` членов `ShelfDirection` — «в ЛОКАЛЬНОЙ СК вида».
- Нейминг COM-объекта — `baseLeader` (не `bl`). `GetViewLeaderCountAsync` считает ВСЕ подтипы выносок
(для v1 ок; фильтр — при добавлении ksDrPosLeader/… — в «Дальнейшее»).
## Цель
Веха 2D-ЧЕРТЁЖ, инкремент 9. Поставить на виде **линию-выноску** (leader) с текстовой надписью на полке —
поясняющее обозначение, указывающее стрелкой на элемент (примечание, материал детали, и т.п.).
## Спайк: последовательность подтверждена вживую (НЕ разучивать)
Спайк (`_SpikeLeader`, прогнан на реальном КОМПАС, затем удалён). **Ключ:** только что созданная
выноска имеет **0 ответвлений** — любые операции над ответвлением (`SetSignPosition`) и `Update` на
выноске без ветвей падают с `RPC_E_SERVERFAULT`; сначала нужно добавить ответвление через `IBranchs`.
```
IBaseLeader bl = symbols.Leaders.Add(DrawingObjectTypeEnum.ksDrLeader); // ksDrLeader=20
((IBranchs)bl).AddBranchByPoint(0, x, y); // QI; ответвление 0 — остриё (куда указывает стрелка)
bl.SetBranchTextPosition(textX, textY); // положение полки/текста
((ILeader)bl).TextOnShelf.Str = text; // надпись на полке (.Str — наш interop)
// опц.: ((ILeader)bl).ShelfDirection = ksShelfDirectionEnum.ksLSRight;
bl.Update(); // True, bl.Valid == True
```
**Проверено:** `AddBranchByPoint(0,x,y)``BranchCount=1`; `Update=True`, `Valid=True`,
`TextOnShelf.Str` round-trip; `Leaders.Count` +1. Работает с явной `ShelfDirection` и без неё.
`BaseLeader` реализует `IBaseLeader`/`IDrawingObject`; `IBranchs` и `ILeader` — COM-QI от него.
Интерфейсы: `ILeaders.Add(DrawingObjectTypeEnum)``BaseLeader` (для обычной выноски `ksDrLeader=20`);
`IBranchs.AddBranchByPoint(int index, double x, double y)`; `IBaseLeader.SetBranchTextPosition(x,y)` /
`Update` / `Valid` / `Delete` / `ArrowType` (`ksArrowEnum`); `ILeader.TextOnShelf` (`IText`),
`ShelfDirection` (`ksShelfDirectionEnum`: `ksLSNone=0`/`ksLSRight=1`/`ksLSUp=2`/`ksLSDown=3`/`ksLSLeft=-1`).
## MCP-инструмент
| Инструмент | Параметры | Поведение |
|---|---|---|
| `drawing_add_leader` | `x,y` (остриё — куда указывает стрелка), `textX,textY` (полка/якорь текста), `text`, `shelfDirection="auto"` (auto\|right\|left\|up\|down), `viewNumber=0` | Поставить выноску на виде: стрелка из полки указывает в (x,y), текст `text` на полке у (textX,textY). Координаты — ЛОКАЛЬНАЯ СК вида (мм). `shelfDirection` — направление полки (auto = по умолчанию КОМПАС). Возвращает текст (read-back) и номер вида. |
## Архитектура
В `DrawingService` (namespace `Kompas.Mcp.Core.Drawings`).
- `AddLeaderAsync(viewNumber, x, y, textX, textY, text, shelfDirection, ct)``DrawingAnnotationResult`
(переиспользуем: `Value`=read-back текст, `ViewNumber`).
- Использует существующий `RequireSymbols2DContainer(viewNumber)` (выноски в `ISymbols2DContainer.Leaders`).
- Новый файл `src/Kompas.Mcp.Core/Drawings/ShelfDirection.cs`: `enum ShelfDirection {Auto,Right,Left,Up,Down}`
(XML-`<summary>` на членах) + `ShelfDirections.Parse(string)` / `ToKompas(ShelfDirection)→ksShelfDirectionEnum`
по образцу `AngleDimensionTypes`. `Auto` → не задавать `ShelfDirection` (оставить дефолт КОМПАС).
- Счётчик `GetViewLeaderCountAsync(viewNumber)` (для теста попадания в вид).
## Реализация
`AddLeaderCore`: `RequireNonEmptyText(text)` + `RequireFiniteCoords(x,y,textX,textY)`
`RequireSymbols2DContainer``symbols.Leaders` (null-check) → `.Add(ksDrLeader)` (null-check) →
**внутри `try/catch`+`Delete`**: `((IBranchs)bl).AddBranchByPoint(0, x, y)` (QI null-check),
`bl.SetBranchTextPosition(textX, textY)`, `((ILeader)bl).TextOnShelf` (null-check) `.Str = text`,
если `shelfDirection != Auto`: `((ILeader)bl).ShelfDirection = ShelfDirections.ToKompas(...)`
`bl.Update()` (FALSE → откат) → `bl.Valid` (false → откат) → read-back `((ILeader)bl).TextOnShelf.Str`
`DrawingAnnotationResult{Value=read-back, ViewNumber}`.
RCW точечно не освобождаем (консистентно; долг v2-2).
## Валидация (чистые static, unit)
- `RequireNonEmptyText(text, nameof(text))`, `RequireFiniteCoords(x,y,textX,textY)`,
`RequireDistinctPoints(x, y, textX, textY)` (остриё ≠ полка) — все уже есть.
- `ShelfDirections.Parse``auto/right/left/up/down` (+ рус. `авто/вправо/влево/вверх/вниз`, регистр/пробелы);
неизвестное → `ArgumentException`; null → `ArgumentNullException`. `ToKompas` (→ `ksShelfDirectionEnum`)
НЕ покрываем unit (граница проекта); бросает `ArgumentOutOfRangeException` на `Auto`.
## Тестирование
### Unit (`ShelfDirectionsTests`)
- `Parse`: `auto/right/left/up/down` (+ регистр, рус.) → enum; неизвестное → `ArgumentException`; null → `ArgumentNullException`.
### Integration (`DrawingLeaderTests`; модель — коробка + стандартные виды)
1. **Ставится + round-trip + viewNumber=0**: `text="Примечание 1"`, `shelfDirection=auto`, `viewNumber=0`
`Value=="Примечание 1"` (read-back), `viewNumber=0` резолвится в первый вид (`r.ViewNumber` совпал),
`Leaders.Count` целевого вида +1.
2. **shelfDirection=left** (не-auto путь) на целевом виде → ставится, `Leaders.Count` +1.
3. **Пустой текст** (`""` и `" "`) → `ArgumentException` (до Add).
4. **Вырожденная** (остриё совпадает с полкой) → `ArgumentException` (до Add).
5. **Нет видов** → понятная ошибка. 6. **Несуществующий `viewNumber>0`** → понятная ошибка.
## Дальнейшее (вне спека)
- Многострочный текст полки / текст под полкой (`TextUnderShelf`); несколько ответвлений
(`AddBranchByPoint` с разными индексами); привязка к геометрии (`IBranchs.SetBaseObject`); тип стрелки
(`ArrowType`); специальные выноски (позиция/клеймо/маркер: `ksDrPosLeader/ksDrBrandLeader/ksDrMarkerLeader`).
Базы (`Bases`), допуски формы (`Tolerances`).
@@ -0,0 +1,96 @@
# Каталог внешнего CAD-контракта для агента — дизайн
## Цель
Создать отдельный документ `docs/AGENT_CAD_TOOL_CATALOG.md`, который описывает желаемый внешний MCP-контракт управления CAD с точки зрения автономного агента, показывает все реализованные и необходимые нереализованные методы и позволяет оценить полноту контракта по сквозным CAD-сценариям.
## Границы
- Каталог описывает внешний контракт, а не внутреннюю реализацию.
- COM-интерфейсы, вызовы API5/API7 и другие детали SDK КОМПАС-3D в итоговую таблицу не включаются.
- SDK разрешено использовать только для внутренней оценки реалистичности предлагаемых методов и выявления платформенных ограничений.
- Методы формулируются как общие CAD-операции, а не как инструменты под отдельную пользовательскую задачу.
- В каталог входят все существующие MCP-инструменты и все выявленные методы, необходимые для полноты агентского контура.
## Структура итогового документа
1. Назначение документа и определение полноты внешнего контракта.
2. Легенда статусов и приоритетов.
3. Сводная матрица покрытия сквозных сценариев.
4. Таблицы методов по функциональным доменам.
5. Приоритизированный перечень пробелов.
6. Общий вывод о текущей полноте контракта.
Функциональные домены:
- сессия и документы;
- 2D-геометрия и эскизы;
- 3D-моделирование;
- прямое и историческое редактирование;
- инспекция, выбор объектов и измерения;
- сборки;
- чертежи и оформление;
- импорт и экспорт;
- управление состоянием, восстановление и надёжность агентской работы.
## Формат таблиц методов
Каждая строка описывает один метод внешнего контракта. Обязательные столбцы:
| Столбец | Содержание |
|---|---|
| Метод | Стабильное имя MCP-метода в `snake_case` |
| Назначение | Краткое описание результата метода с позиции вызывающего агента |
| Статус | `✅ реализован`, `🟡 частично`, `⬜ не реализован` или `⛔ ограничен платформой` |
| Необходимость | `Core`, `Advanced` или `Optional` |
| Пробел / ограничение | Что отсутствует в контракте или какая часть поведения не покрыта |
SDK-интерфейсы, классы сервисов и другие детали реализации в эти таблицы не добавляются.
## Критерии классификации
### Статус
- `✅ реализован` — метод существует в текущем MCP-каталоге и предоставляет заявленное внешнее поведение.
- `🟡 частично` — метод существует, но покрывает только часть необходимого внешнего поведения или поддерживает ограниченный набор вариантов.
- `⬜ не реализован` — метод нужен целевому контракту, но отсутствует как MCP-инструмент.
- `⛔ ограничен платформой` — желаемое поведение невозможно или ненадёжно в доступном Automation API; ограничение должно быть сформулировано на уровне внешнего результата без SDK-подробностей.
### Необходимость
- `Core` — без метода агент не может надёжно завершить базовый сквозной сценарий либо проверить результат мутации.
- `Advanced` — метод нужен для промышленно значимого расширенного сценария, но не блокирует минимальный цикл моделирования.
- `Optional` — повышает удобство, производительность или широту применения, сохраняя работоспособность основного контура без него.
### Приоритет пробела
- `P0` — разрыв базового сквозного сценария или отсутствие необходимой обратной связи/управления состоянием.
- `P1` — существенное ограничение распространённого профессионального сценария.
- `P2` — расширение охвата или удобства без разрыва основных сценариев.
## Оценка полноты
Полнота оценивается не числом методов, а способностью агента выполнить замкнутый цикл `обнаружить состояние → изменить модель → проверить результат → сохранить или безопасно откатить`.
Сводная матрица должна проверить минимум следующие сценарии:
1. Создать и сохранить параметрическую 3D-деталь.
2. Открыть или импортировать модель, локально изменить геометрию и проверить результат.
3. Создать сборку, разместить компоненты, наложить сопряжения и проверить структуру.
4. Создать комплект основных видов чертежа, оформить размеры и обозначения, сохранить результат.
5. Выполнить геометрическую и документную инспекцию без обязательного визуального анализа.
Для каждого сценария фиксируются покрытые этапы, блокирующие пробелы и итоговая оценка: `полный`, `частичный` или `неполный`.
## Проверка реалистичности
Перед включением нереализованного метода в контракт проверяется, что требуемое поведение в принципе доступно в установленной версии КОМПАС-3D либо может быть составлено из надёжных операций. Если реалистичность не подтверждена, метод получает статус `⛔ ограничен платформой` или явную пометку о необходимости технического исследования; детали исследования остаются вне итогового каталога.
## Критерии готовности
- Все текущие MCP-инструменты представлены ровно по одному разу.
- Для каждого домена перечислены необходимые отсутствующие методы.
- Частично реализованные методы не ошибочно помечены как полностью реализованные.
- Сквозные сценарии позволяют увидеть блокирующие пробелы независимо от общего количества методов.
- Итоговый список `P0P2` согласован с доменными таблицами и не содержит методов, отсутствующих в основном каталоге.
- Документ не содержит внутренних COM/SDK-деталей.
@@ -0,0 +1,75 @@
# Codex SDK Research Agent Design
## Goal
Adapt the project-scoped `kompas-sdk-research` custom agent for Codex while
leaving the Claude Code agent unchanged. The Codex agent must be optimized for
fast, read-heavy searches in the local KOMPAS SDK Markdown knowledge base and
must not modify the workspace.
## Configuration
The Codex agent remains in `.codex/agents/kompas-sdk-research.toml` and uses:
```toml
name = "kompas-sdk-research"
model = "gpt-5.6-terra"
model_reasoning_effort = "medium"
sandbox_mode = "read-only"
```
`gpt-5.6-terra` fits exploration, documentation scans, and distilled support
work. Medium reasoning is used because SDK questions can require correlating
several interfaces, overloads, constants, and COM call-chain details.
## Agent Responsibilities
The agent searches only local project and installed SDK reference material:
- `docs/Kompas3D_SDK/` is the canonical source for COM API5/API7 documentation.
- SDK headers under the installed KOMPAS SDK may be read when exact constant
values need confirmation.
- The agent must not browse the web, edit files, implement features, or build
geometry in KOMPAS-3D.
- KsAPI is outside the Markdown knowledge base and must be reported as outside
scope instead of guessed.
The parent agent delegates non-trivial SDK lookups before implementation. It
remains responsible for validating interop-specific discrepancies through
reflection over `libs/kompas-interop/*.dll` when needed.
## Prompt Adaptation
Remove Claude-specific references to Haiku and Opus from the Codex TOML. Keep
the existing domain guidance, but express it in provider-neutral Codex terms.
The description must make proactive delegation triggers clear without claiming
that the agent uses tools or model behavior specific to Claude Code.
The response contract remains concise and evidence-oriented:
1. Relevant interface, method, property, enum, or constant.
2. Automation syntax and COM syntax when parameter ordering matters.
3. Parameter and return-value meanings, including units and side effects.
4. Related overloads or interfaces when relevant.
5. Source article path and its `sources` frontmatter entry.
6. A warning when generated .NET interop names may differ from SDK docs.
## Isolation and Compatibility
The Claude definition in `.claude/agents/kompas-sdk-research.md` is not changed.
The two versions intentionally use different configuration formats and model
selection while sharing the same research methodology.
The Codex agent's read-only behavior is enforced by `sandbox_mode`, not merely
requested in prose. No exact Claude-style tool allowlist is copied into the
Codex configuration.
## Verification
After editing the TOML:
- parse it as TOML;
- confirm the required fields and selected model settings;
- confirm `sandbox_mode = "read-only"`;
- search the Codex file for stale `Haiku`, `Opus`, and Claude-specific wording;
- confirm the Claude agent file is unchanged.
@@ -482,6 +482,66 @@ public sealed class DrawingService
public Task<int> GetViewTextCountAsync(int viewNumber, CancellationToken ct = default)
=> _dispatcher.InvokeAsync(() => RequireDrawingContainer(viewNumber).Container.DrawingTexts?.Count ?? 0, ct);
/// <summary>
/// Поставить линию-выноску на виде: стрелка из полки указывает в (<paramref name="x"/>,<paramref name="y"/>),
/// текст <paramref name="text"/> на полке у (<paramref name="textX"/>,<paramref name="textY"/>) — всё в
/// ЛОКАЛЬНОЙ СК вида (мм). <paramref name="shelfDirection"/> — направление полки (Auto = по умолчанию КОМПАС).
/// Возвращает текст (read-back) и номер вида.
/// </summary>
public Task<DrawingAnnotationResult> AddLeaderAsync(int viewNumber, double x, double y, double textX,
double textY, string text, ShelfDirection shelfDirection, CancellationToken ct = default)
=> _dispatcher.InvokeAsync(() => AddLeaderCore(viewNumber, x, y, textX, textY, text, shelfDirection), ct);
private DrawingAnnotationResult AddLeaderCore(int viewNumber, double x, double y, double textX,
double textY, string text, ShelfDirection shelfDirection)
{
DrawingValidation.RequireNonEmptyText(text, nameof(text));
DrawingValidation.RequireFiniteCoords(x, y, textX, textY);
DrawingValidation.RequireDistinctPoints(x, y, textX, textY); // остриё ≠ полка (иначе вырождение)
var (view, symbols) = RequireSymbols2DContainer(viewNumber);
var leaders = symbols.Leaders
?? throw new InvalidOperationException("Коллекция Leaders недоступна на виде.");
var baseLeader = leaders.Add(DrawingObjectTypeEnum.ksDrLeader)
?? throw new InvalidOperationException("Leaders.Add вернул null.");
try
{
// КРИТИЧЕСКИЙ ПОРЯДОК: AddBranchByPoint ДОЛЖЕН предшествовать SetBranchTextPosition/Update —
// выноска без ответвлений валит КОМПАС (RPC_E_SERVERFAULT). Проверено спайком.
var branches = baseLeader as IBranchs
?? throw new InvalidOperationException("Выноска не приводится к IBranchs.");
if (!branches.AddBranchByPoint(0, x, y)) // остриё ответвления 0 (куда указывает стрелка)
throw new InvalidOperationException("AddBranchByPoint вернул FALSE — ответвление выноски не создано.");
if (!baseLeader.SetBranchTextPosition(textX, textY)) // положение полки/текста
throw new InvalidOperationException("SetBranchTextPosition вернул FALSE — полка выноски не задана.");
var leader = baseLeader as ILeader
?? throw new InvalidOperationException("Выноска не приводится к ILeader.");
var shelf = leader.TextOnShelf
?? throw new InvalidOperationException("Текст полки выноски недоступен (TextOnShelf == null).");
shelf.Str = text;
if (shelfDirection != ShelfDirection.Auto)
leader.ShelfDirection = ShelfDirections.ToKompas(shelfDirection);
if (!baseLeader.Update())
throw new InvalidOperationException("ILeader.Update вернул FALSE — выноска не построена.");
if (!baseLeader.Valid)
throw new InvalidOperationException("Выноска построена невалидной.");
var readBack = leader.TextOnShelf?.Str ?? string.Empty; // read-back из COM
return new DrawingAnnotationResult { Value = readBack, ViewNumber = view.Number };
}
catch
{
try { baseLeader.Delete(); } catch { /* лучшее усилие */ }
throw;
}
}
/// <summary>Число выносок на виде (для проверки попадания в вид; считает все подтипы выносок).</summary>
public Task<int> GetViewLeaderCountAsync(int viewNumber, CancellationToken ct = default)
=> _dispatcher.InvokeAsync(() => RequireSymbols2DContainer(viewNumber).Symbols.Leaders?.Count ?? 0, ct);
/// <summary>
/// Задать технические требования активного чертежа (единый блок над основной надписью; перезаписывает
/// прежние). <paramref name="text"/> — строки через \n. Возвращает число строк.
@@ -0,0 +1,52 @@
using Kompas6Constants;
namespace Kompas.Mcp.Core.Drawings;
/// <summary>Направление полки выноски (обёртка над <see cref="ksShelfDirectionEnum"/>).</summary>
public enum ShelfDirection
{
/// <summary>Авто — направление полки оставляет КОМПАС (свойство не задаётся).</summary>
Auto,
/// <summary>Полка вправо (в ЛОКАЛЬНОЙ СК вида).</summary>
Right,
/// <summary>Полка влево (в ЛОКАЛЬНОЙ СК вида).</summary>
Left,
/// <summary>Полка вверх (в ЛОКАЛЬНОЙ СК вида).</summary>
Up,
/// <summary>Полка вниз (в ЛОКАЛЬНОЙ СК вида).</summary>
Down,
}
/// <summary>Маппинг направления полки ↔ перечисление КОМПАС и разбор строки.</summary>
public static class ShelfDirections
{
/// <summary>В <see cref="ksShelfDirectionEnum"/>. Бросает на <see cref="ShelfDirection.Auto"/> —
/// «авто» обрабатывается в сервисе (свойство не задаётся), сюда передавать нельзя.</summary>
public static ksShelfDirectionEnum ToKompas(ShelfDirection direction) => direction switch
{
ShelfDirection.Right => ksShelfDirectionEnum.ksLSRight,
ShelfDirection.Left => ksShelfDirectionEnum.ksLSLeft,
ShelfDirection.Up => ksShelfDirectionEnum.ksLSUp,
ShelfDirection.Down => ksShelfDirectionEnum.ksLSDown,
_ => throw new ArgumentOutOfRangeException(nameof(direction), direction,
"ShelfDirection.Auto не имеет COM-значения (направление не задаётся)."),
};
/// <summary>Разобрать строку направления (англ./рус., регистр/пробелы) в <see cref="ShelfDirection"/>.</summary>
public static ShelfDirection Parse(string value)
{
ArgumentNullException.ThrowIfNull(value);
return value.Trim().ToLowerInvariant() switch
{
"auto" or "авто" => ShelfDirection.Auto,
"right" or "вправо" => ShelfDirection.Right,
"left" or "влево" => ShelfDirection.Left,
"up" or "вверх" => ShelfDirection.Up,
"down" or "вниз" => ShelfDirection.Down,
_ => throw new ArgumentException(
$"Неизвестное направление полки '{value}'. Допустимо: auto/авто, right/вправо, " +
"left/влево, up/вверх, down/вниз.",
nameof(value)),
};
}
}
+22
View File
@@ -207,4 +207,26 @@ public sealed class DrawingTools(KompasSession session, DrawingService drawing)
var orient = r.Landscape ? "альбомная" : "книжная";
return $"Формат листа {sheetNumber}: {r.Format}, {r.Width:0.#}×{r.Height:0.#} мм, {orient}.";
}
[McpServerTool(Name = "drawing_add_leader")]
[Description("Поставить линию-выноску с текстом на виде активного чертежа. Стрелка выноски указывает " +
"в точку (x,y); текст text размещается на полке у точки (textX,textY) — всё в ЛОКАЛЬНОЙ СК вида (мм). " +
"shelfDirection: auto/авто (по умолчанию — КОМПАС сам) | right/вправо | left/влево | up/вверх | " +
"down/вниз — направление полки. " +
"viewNumber — номер вида из drawing_create_standard_views (0 = первый/главный). Точка острия (x,y) " +
"должна отличаться от точки полки (textX,textY). Возвращает поставленный текст и номер вида.")]
public async Task<string> AddLeader(
[Description("X острия — куда указывает стрелка (СК вида, мм)")] double x,
[Description("Y острия")] double y,
[Description("X полки/якоря текста")] double textX,
[Description("Y полки/якоря текста")] double textY,
[Description("Текст надписи на полке")] string text,
[Description("Направление полки: auto | right | left | up | down")] string shelfDirection = "auto",
[Description("Номер вида (0 = первый/главный)")] int viewNumber = 0)
{
await session.ConnectAsync();
var dir = ShelfDirections.Parse(shelfDirection);
var r = await drawing.AddLeaderAsync(viewNumber, x, y, textX, textY, text, dir);
return $"Выноска поставлена на виде {r.ViewNumber}: «{r.Value}».";
}
}
@@ -0,0 +1,146 @@
using Kompas.Mcp.Core.Documents;
using Kompas.Mcp.Core.Drawings;
using Kompas.Mcp.Core.Modeling;
namespace Kompas.Mcp.Tests.Integration;
/// <summary>Интеграция: линия-выноска с текстом на виде (API7 ISymbols2DContainer.Leaders + IBranchs).</summary>
[Trait("Category", "Integration")]
[Collection(KompasCollection.Name)]
public sealed class DrawingLeaderTests : IntegrationTestBase
{
private readonly DocumentService _docs;
private readonly PartModeler _modeler;
private readonly DrawingService _drawing;
public DrawingLeaderTests(KompasFixture fx) : base(fx)
{
_docs = new DocumentService(fx.Session, fx.Dispatcher);
_modeler = new PartModeler(fx.Session, fx.Dispatcher);
_drawing = new DrawingService(fx.Session, fx.Dispatcher);
}
private async Task<string> BuildAndSaveBoxAsync()
{
var path = TestPaths.NewFile(".m3d");
await _docs.CreateAsync(KompasDocumentType.Part);
try
{
var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
await _modeler.AddRectangleAsync(s, 0, 0, 40, 30);
await _modeler.CloseSketchAsync(s);
await _modeler.ExtrudeAsync(s, depth: 20);
await _modeler.RebuildAsync();
await _docs.SaveAsAsync(path);
}
finally { await _docs.CloseAsync(save: false); }
return path;
}
[Fact]
public async Task Leader_is_placed_round_trip_and_resolves_default_view()
{
var partFile = await BuildAndSaveBoxAsync();
await _docs.CreateAsync(KompasDocumentType.Drawing);
try
{
var views = await _drawing.CreateStandardViewsAsync(partFile, 1.0, 100, 150);
var first = views.ViewNumbers[0];
var before = await _drawing.GetViewLeaderCountAsync(first);
// viewNumber=0 → первый несистемный вид (= first)
var r = await _drawing.AddLeaderAsync(0, x: 5, y: 5, textX: 25, textY: 20,
text: "Примечание 1", shelfDirection: ShelfDirection.Auto);
var after = await _drawing.GetViewLeaderCountAsync(first);
Assert.Equal(first, r.ViewNumber);
Assert.Equal("Примечание 1", r.Value); // read-back из COM
Assert.Equal(before + 1, after);
}
finally { await _docs.CloseAsync(save: false); }
}
[Theory]
[InlineData(ShelfDirection.Right)]
[InlineData(ShelfDirection.Left)]
[InlineData(ShelfDirection.Up)]
[InlineData(ShelfDirection.Down)]
public async Task Leader_with_explicit_shelf_direction(ShelfDirection dir)
{
var partFile = await BuildAndSaveBoxAsync();
await _docs.CreateAsync(KompasDocumentType.Drawing);
try
{
var views = await _drawing.CreateStandardViewsAsync(partFile, 1.0, 100, 150);
var target = views.ViewNumbers[0];
var before = await _drawing.GetViewLeaderCountAsync(target);
// Покрывает всю поверхность ShelfDirections.ToKompas (Right/Left/Up/Down) на реальном COM.
var r = await _drawing.AddLeaderAsync(target, x: 10, y: 8, textX: 30, textY: 25,
text: "Полка", shelfDirection: dir);
var after = await _drawing.GetViewLeaderCountAsync(target);
Assert.Equal(before + 1, after);
Assert.Equal("Полка", r.Value);
}
finally { await _docs.CloseAsync(save: false); }
}
[Theory]
[InlineData("")]
[InlineData(" ")]
public async Task Empty_text_throws(string text)
{
var partFile = await BuildAndSaveBoxAsync();
await _docs.CreateAsync(KompasDocumentType.Drawing);
try
{
await _drawing.CreateStandardViewsAsync(partFile, 1.0, 100, 150);
await Assert.ThrowsAsync<ArgumentException>(() =>
_drawing.AddLeaderAsync(0, x: 5, y: 5, textX: 25, textY: 20, text: text,
shelfDirection: ShelfDirection.Auto));
}
finally { await _docs.CloseAsync(save: false); }
}
[Fact]
public async Task Degenerate_tip_equals_shelf_throws()
{
var partFile = await BuildAndSaveBoxAsync();
await _docs.CreateAsync(KompasDocumentType.Drawing);
try
{
await _drawing.CreateStandardViewsAsync(partFile, 1.0, 100, 150);
await Assert.ThrowsAsync<ArgumentException>(() =>
_drawing.AddLeaderAsync(0, x: 5, y: 5, textX: 5, textY: 5, text: "X",
shelfDirection: ShelfDirection.Auto));
}
finally { await _docs.CloseAsync(save: false); }
}
[Fact]
public async Task No_views_throws()
{
await _docs.CreateAsync(KompasDocumentType.Drawing);
try
{
await Assert.ThrowsAsync<InvalidOperationException>(() =>
_drawing.AddLeaderAsync(0, x: 5, y: 5, textX: 25, textY: 20, text: "X",
shelfDirection: ShelfDirection.Auto));
}
finally { await _docs.CloseAsync(save: false); }
}
[Fact]
public async Task Unknown_view_number_throws()
{
var partFile = await BuildAndSaveBoxAsync();
await _docs.CreateAsync(KompasDocumentType.Drawing);
try
{
await _drawing.CreateStandardViewsAsync(partFile, 1.0, 100, 150);
await Assert.ThrowsAsync<InvalidOperationException>(() =>
_drawing.AddLeaderAsync(999, x: 5, y: 5, textX: 25, textY: 20, text: "X",
shelfDirection: ShelfDirection.Auto));
}
finally { await _docs.CloseAsync(save: false); }
}
}
@@ -0,0 +1,32 @@
using Kompas.Mcp.Core.Drawings;
namespace Kompas.Mcp.Tests;
[Trait("Category", "Unit")]
public sealed class ShelfDirectionsTests
{
[Theory]
[InlineData("auto", ShelfDirection.Auto)]
[InlineData("right", ShelfDirection.Right)]
[InlineData("left", ShelfDirection.Left)]
[InlineData("up", ShelfDirection.Up)]
[InlineData("down", ShelfDirection.Down)]
[InlineData(" RIGHT ", ShelfDirection.Right)]
[InlineData("авто", ShelfDirection.Auto)]
[InlineData("вправо", ShelfDirection.Right)]
[InlineData("влево", ShelfDirection.Left)]
[InlineData("вверх", ShelfDirection.Up)]
[InlineData("вниз", ShelfDirection.Down)]
public void Parse_maps_known(string value, ShelfDirection expected)
=> Assert.Equal(expected, ShelfDirections.Parse(value));
[Fact]
public void Parse_throws_on_unknown()
=> Assert.Throws<ArgumentException>(() => ShelfDirections.Parse("diagonal"));
[Fact]
public void Parse_throws_on_null()
=> Assert.Throws<ArgumentNullException>(() => ShelfDirections.Parse(null!));
// ToKompas (→ ksShelfDirectionEnum) — граница проекта; для Auto бросает (проверяется косвенно).
}