answer42 0.2.2__tar.gz → 0.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {answer42-0.2.2 → answer42-0.2.4}/PKG-INFO +2 -2
  2. {answer42-0.2.2 → answer42-0.2.4}/README.md +1 -1
  3. {answer42-0.2.2 → answer42-0.2.4}/pyproject.toml +1 -1
  4. {answer42-0.2.2 → answer42-0.2.4}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form/Module.bsl +350 -6
  5. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/assets/MCPTestManager.cf +0 -0
  6. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/server.py +45 -1
  7. {answer42-0.2.2 → answer42-0.2.4}/.gitignore +0 -0
  8. {answer42-0.2.2 → answer42-0.2.4}/LICENSE +0 -0
  9. {answer42-0.2.2 → answer42-0.2.4}/credentials.example.json +0 -0
  10. {answer42-0.2.2 → answer42-0.2.4}/docs/agent-installation.md +0 -0
  11. {answer42-0.2.2 → answer42-0.2.4}/docs/architecture.md +0 -0
  12. {answer42-0.2.2 → answer42-0.2.4}/docs/assets/answer42-logo.png +0 -0
  13. {answer42-0.2.2 → answer42-0.2.4}/docs/assets/platform42-logo.svg +0 -0
  14. {answer42-0.2.2 → answer42-0.2.4}/docs/installation.md +0 -0
  15. {answer42-0.2.2 → answer42-0.2.4}/scripts/build_cf.py +0 -0
  16. {answer42-0.2.2 → answer42-0.2.4}/scripts/build_pages.py +0 -0
  17. {answer42-0.2.2 → answer42-0.2.4}/scripts/e2e_stable.py +0 -0
  18. {answer42-0.2.2 → answer42-0.2.4}/scripts/openclaw_mcp_autoreload.py +0 -0
  19. {answer42-0.2.2 → answer42-0.2.4}/scripts/rag_cli.py +0 -0
  20. {answer42-0.2.2 → answer42-0.2.4}/src/cf/ConfigDumpInfo.xml +0 -0
  21. {answer42-0.2.2 → answer42-0.2.4}/src/cf/Configuration.xml +0 -0
  22. {answer42-0.2.2 → answer42-0.2.4}/src/cf/DataProcessors/MCPTestManager/Ext/ObjectModule.bsl +0 -0
  23. {answer42-0.2.2 → answer42-0.2.4}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form.xml" +0 -0
  24. {answer42-0.2.2 → answer42-0.2.4}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260.xml" +0 -0
  25. {answer42-0.2.2 → answer42-0.2.4}/src/cf/DataProcessors/MCPTestManager.xml +0 -0
  26. {answer42-0.2.2 → answer42-0.2.4}/src/cf/Ext/ManagedApplicationModule.bsl +0 -0
  27. {answer42-0.2.2 → answer42-0.2.4}/src/cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
  28. {answer42-0.2.2 → answer42-0.2.4}/src/client_cf/Catalogs//320/237/320/241_/320/222/320/273/320/260/320/264/320/265/320/273/320/265/321/206.xml" +0 -0
  29. {answer42-0.2.2 → answer42-0.2.4}/src/client_cf/Catalogs//320/237/320/241_/320/241/320/277/321/200/320/260/320/262/320/276/321/207/320/275/320/270/320/2721.xml" +0 -0
  30. {answer42-0.2.2 → answer42-0.2.4}/src/client_cf/ConfigDumpInfo.xml +0 -0
  31. {answer42-0.2.2 → answer42-0.2.4}/src/client_cf/Configuration.xml +0 -0
  32. {answer42-0.2.2 → answer42-0.2.4}/src/client_cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
  33. {answer42-0.2.2 → answer42-0.2.4}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Ext/ManagerModule.bsl" +0 -0
  34. {answer42-0.2.2 → answer42-0.2.4}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Ext/ObjectModule.bsl" +0 -0
  35. {answer42-0.2.2 → answer42-0.2.4}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Templates//320/236/321/201/320/275/320/276/320/262/320/275/320/260/321/217/320/241/321/205/320/265/320/274/320/260/320/232/320/276/320/274/320/277/320/276/320/275/320/276/320/262/320/272/320/270/320/224/320/260/320/275/320/275/321/213/321/205/Ext/Template.xml" +0 -0
  36. {answer42-0.2.2 → answer42-0.2.4}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Templates//320/236/321/201/320/275/320/276/320/262/320/275/320/260/321/217/320/241/321/205/320/265/320/274/320/260/320/232/320/276/320/274/320/277/320/276/320/275/320/276/320/262/320/272/320/270/320/224/320/260/320/275/320/275/321/213/321/205.xml" +0 -0
  37. {answer42-0.2.2 → answer42-0.2.4}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262.xml" +0 -0
  38. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/__init__.py +0 -0
  39. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/assets/MCPTestClient.cf +0 -0
  40. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/assets/__init__.py +0 -0
  41. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/assets/skills/answer42/SKILL.md +0 -0
  42. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/assets/skills/answer42-rag/SKILL.md +0 -0
  43. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/bridge.py +0 -0
  44. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/credentials.py +0 -0
  45. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/os_support.py +0 -0
  46. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/platform.py +0 -0
  47. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/protocol.py +0 -0
  48. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/rag/__init__.py +0 -0
  49. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/rag/detect.py +0 -0
  50. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/rag/model.py +0 -0
  51. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/rag/parsers.py +0 -0
  52. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/rag/service.py +0 -0
  53. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/rag/store.py +0 -0
  54. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/recorder.py +0 -0
  55. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/release_helper.py +0 -0
  56. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/runtime.py +0 -0
  57. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/skill_installer.py +0 -0
  58. {answer42-0.2.2 → answer42-0.2.4}/src/mcp_1c/window_control.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: answer42
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Answer42 — The Answer to Life, Universe, and 1C — UI Driver. MCP-powered 1C:Enterprise UI automation: click, fill, navigate, test, and introspect managed forms through the test-client API
5
5
  Author: Marvin (AI Assistant), 42Clouds, and contributors
6
6
  Author-email: "Kosolapov Stanislav (proDOOMman)" <prodoomman@gmail.com>
@@ -34,7 +34,7 @@ Description-Content-Type: text/markdown
34
34
 
35
35
  # Answer42
36
36
 
37
- ![Answer42 logo](docs/assets/answer42-logo.png)
37
+ ![Answer42 logo](https://gitlab.com/platform42/answer42-mcp/-/raw/v0.2.4/docs/assets/answer42-logo.png)
38
38
 
39
39
  **Answer42** — MCP-инструмент для интерактивного управления UI **1С:Предприятия** через клиент тестирования. Он позволяет AI-агенту открывать формы 1С, нажимать кнопки, заполнять поля, выбирать ссылки из форм выбора, работать с таблицами, динамическими списками и табличными документами.
40
40
 
@@ -1,6 +1,6 @@
1
1
  # Answer42
2
2
 
3
- ![Answer42 logo](docs/assets/answer42-logo.png)
3
+ ![Answer42 logo](https://gitlab.com/platform42/answer42-mcp/-/raw/v0.2.4/docs/assets/answer42-logo.png)
4
4
 
5
5
  **Answer42** — MCP-инструмент для интерактивного управления UI **1С:Предприятия** через клиент тестирования. Он позволяет AI-агенту открывать формы 1С, нажимать кнопки, заполнять поля, выбирать ссылки из форм выбора, работать с таблицами, динамическими списками и табличными документами.
6
6
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "answer42"
3
- version = "0.2.2"
3
+ version = "0.2.4"
4
4
  description = "Answer42 — The Answer to Life, Universe, and 1C — UI Driver. MCP-powered 1C:Enterprise UI automation: click, fill, navigate, test, and introspect managed forms through the test-client API"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -355,7 +355,13 @@
355
355
  ИначеЕсли Метод = "object_context_menu" Тогда
356
356
  Возврат КонтекстноеМенюОбъектаMCP(Параметры);
357
357
  ИначеЕсли Метод = "window_command_interface" Тогда
358
- Возврат КомандныйИнтерфейсОкнаMCP();
358
+ Возврат КомандныйИнтерфейсОкнаMCP(Параметры);
359
+ ИначеЕсли Метод = "command_interface_sections" Тогда
360
+ Возврат РазделыКомандногоИнтерфейсаMCP(Параметры);
361
+ ИначеЕсли Метод = "command_interface_commands" Тогда
362
+ Возврат КомандыКомандногоИнтерфейсаMCP(Параметры);
363
+ ИначеЕсли Метод = "command_interface_search" Тогда
364
+ Возврат ПоискКомандногоИнтерфейсаMCP(Параметры);
359
365
  ИначеЕсли Метод = "group_expand" Тогда
360
366
  Возврат РазвернутьГруппуMCP(Параметры);
361
367
  ИначеЕсли Метод = "group_collapse" Тогда
@@ -1322,25 +1328,363 @@
1322
1328
  КонецФункции
1323
1329
 
1324
1330
  &НаКлиенте
1325
- Функция КомандныйИнтерфейсОкнаMCP()
1331
+ Функция КомандныйИнтерфейсОкнаMCP(Параметры)
1326
1332
  Если ТестируемоеПриложение = Неопределено Тогда
1327
1333
  ВызватьИсключение "Тестируемое приложение не подключено.";
1328
1334
  КонецЕсли;
1329
1335
 
1330
1336
  Попытка
1331
- АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
1337
+ Глубина = СвойствоСтруктуры(Параметры, "max_depth", 4);
1338
+ АктивноеОкно = КомандныйИнтерфейсЦелевоеОкно(Параметры);
1332
1339
  Интерфейс = АктивноеОкно.ПолучитьКомандныйИнтерфейс();
1333
1340
  Если Интерфейс = Неопределено Тогда
1334
- Возврат Новый Структура("available,reason", Ложь, "not_available");
1341
+ Возврат Новый Структура("available,reason,window", Ложь, "not_available", ОбъектВСтруктуру(АктивноеОкно, 0, 0));
1335
1342
  Иначе
1336
- Дерево = ОбъектВСтруктуру(Интерфейс, 0, 2);
1337
- Возврат Новый Структура("available,interface", Истина, Дерево);
1343
+ Дерево = КомандныйИнтерфейсОбъектВСтруктуру(Интерфейс, 0, Глубина);
1344
+ Возврат Новый Структура("available,interface,window", Истина, Дерево, ОбъектВСтруктуру(АктивноеОкно, 0, 0));
1338
1345
  КонецЕсли;
1339
1346
  Исключение
1340
1347
  Возврат Новый Структура("available,reason,error", Ложь, "not_supported", ОписаниеОшибки());
1341
1348
  КонецПопытки;
1342
1349
  КонецФункции
1343
1350
 
1351
+ &НаКлиенте
1352
+ Функция РазделыКомандногоИнтерфейсаMCP(Параметры)
1353
+ Если ТестируемоеПриложение = Неопределено Тогда
1354
+ ВызватьИсключение "Тестируемое приложение не подключено.";
1355
+ КонецЕсли;
1356
+
1357
+ Попытка
1358
+ АктивноеОкно = КомандныйИнтерфейсЦелевоеОкно(Параметры);
1359
+ Интерфейс = АктивноеОкно.ПолучитьКомандныйИнтерфейс();
1360
+ Если Интерфейс = Неопределено Тогда
1361
+ Возврат Новый Структура("available,reason,window", Ложь, "not_available", ОбъектВСтруктуру(АктивноеОкно, 0, 0));
1362
+ КонецЕсли;
1363
+
1364
+ Разделы = РазделыКомандногоИнтерфейса(Интерфейс);
1365
+ Возврат Новый Структура("available,sections,window", Истина, Разделы, ОбъектВСтруктуру(АктивноеОкно, 0, 0));
1366
+ Исключение
1367
+ Возврат Новый Структура("available,reason,error", Ложь, "not_supported", ОписаниеОшибки());
1368
+ КонецПопытки;
1369
+ КонецФункции
1370
+
1371
+ &НаКлиенте
1372
+ Функция КомандыКомандногоИнтерфейсаMCP(Параметры)
1373
+ Если ТестируемоеПриложение = Неопределено Тогда
1374
+ ВызватьИсключение "Тестируемое приложение не подключено.";
1375
+ КонецЕсли;
1376
+
1377
+ Попытка
1378
+ Глубина = СвойствоСтруктуры(Параметры, "max_depth", 4);
1379
+ ЗаголовокРаздела = СвойствоСтруктуры(Параметры, "section", "");
1380
+ АктивноеОкно = КомандныйИнтерфейсЦелевоеОкно(Параметры);
1381
+ Интерфейс = АктивноеОкно.ПолучитьКомандныйИнтерфейс();
1382
+ Если Интерфейс = Неопределено Тогда
1383
+ Возврат Новый Структура("available,reason,window", Ложь, "not_available", ОбъектВСтруктуру(АктивноеОкно, 0, 0));
1384
+ КонецЕсли;
1385
+
1386
+ Корень = Интерфейс;
1387
+ Если Не ПустаяСтрока(ЗаголовокРаздела) Тогда
1388
+ КнопкаРаздела = КомандныйИнтерфейсНайтиРаздел(Интерфейс, ЗаголовокРаздела);
1389
+ Если КнопкаРаздела = Неопределено Тогда
1390
+ Возврат Новый Структура("available,found,reason,section,window", Истина, Ложь, "section_not_found", ЗаголовокРаздела, ОбъектВСтруктуру(АктивноеОкно, 0, 0));
1391
+ КонецЕсли;
1392
+ КнопкаРаздела.Нажать();
1393
+ Интерфейс = АктивноеОкно.ПолучитьКомандныйИнтерфейс();
1394
+ Корень = Интерфейс;
1395
+ КонецЕсли;
1396
+
1397
+ Дерево = КомандныйИнтерфейсОбъектВСтруктуру(Корень, 0, Глубина);
1398
+ ЛокКоманды = КомандыКомандногоИнтерфейса(Корень, Истина);
1399
+ Возврат Новый Структура("available,found,section,tree,commands,window", Истина, Истина, ЗаголовокРаздела, Дерево, ЛокКоманды, ОбъектВСтруктуру(АктивноеОкно, 0, 0));
1400
+ Исключение
1401
+ Возврат Новый Структура("available,reason,error", Ложь, "not_supported", ОписаниеОшибки());
1402
+ КонецПопытки;
1403
+ КонецФункции
1404
+
1405
+ &НаКлиенте
1406
+ Функция ПоискКомандногоИнтерфейсаMCP(Параметры)
1407
+ Если ТестируемоеПриложение = Неопределено Тогда
1408
+ ВызватьИсключение "Тестируемое приложение не подключено.";
1409
+ КонецЕсли;
1410
+
1411
+ Попытка
1412
+ СтрокаПоиска = СокрЛП(СвойствоСтруктуры(Параметры, "query", ""));
1413
+ Если ПустаяСтрока(СтрокаПоиска) Тогда
1414
+ ВызватьИсключение "Параметр query обязателен.";
1415
+ КонецЕсли;
1416
+
1417
+ ЗаголовокРаздела = СвойствоСтруктуры(Параметры, "section", "");
1418
+ Максимум = СвойствоСтруктуры(Параметры, "max_results", 20);
1419
+ АктивноеОкно = КомандныйИнтерфейсЦелевоеОкно(Параметры);
1420
+ Интерфейс = АктивноеОкно.ПолучитьКомандныйИнтерфейс();
1421
+ Если Интерфейс = Неопределено Тогда
1422
+ Возврат Новый Структура("available,reason,window", Ложь, "not_available", ОбъектВСтруктуру(АктивноеОкно, 0, 0));
1423
+ КонецЕсли;
1424
+
1425
+ Если Не ПустаяСтрока(ЗаголовокРаздела) Тогда
1426
+ КнопкаРаздела = КомандныйИнтерфейсНайтиРаздел(Интерфейс, ЗаголовокРаздела);
1427
+ Если КнопкаРаздела = Неопределено Тогда
1428
+ Возврат Новый Структура("available,found,reason,query,section,matches,window", Истина, Ложь, "section_not_found", СтрокаПоиска, ЗаголовокРаздела, Новый Массив, ОбъектВСтруктуру(АктивноеОкно, 0, 0));
1429
+ КонецЕсли;
1430
+ КнопкаРаздела.Нажать();
1431
+ Интерфейс = АктивноеОкно.ПолучитьКомандныйИнтерфейс();
1432
+ КонецЕсли;
1433
+
1434
+ ВсеКоманды = КомандыКомандногоИнтерфейса(Интерфейс, Истина);
1435
+ Совпадения = ПоискВКомандахКомандногоИнтерфейса(ВсеКоманды, СтрокаПоиска, Максимум);
1436
+ Возврат Новый Структура("available,found,query,section,count,matches,window", Истина, Совпадения.Количество() > 0, СтрокаПоиска, ЗаголовокРаздела, Совпадения.Количество(), Совпадения, ОбъектВСтруктуру(АктивноеОкно, 0, 0));
1437
+ Исключение
1438
+ Возврат Новый Структура("available,reason,error", Ложь, "not_supported", ОписаниеОшибки());
1439
+ КонецПопытки;
1440
+ КонецФункции
1441
+
1442
+ &НаКлиенте
1443
+ Функция КомандныйИнтерфейсЦелевоеОкно(Параметры)
1444
+ ОкноЗаголовок = СвойствоСтруктуры(Параметры, "window_title", "");
1445
+ Если ПустаяСтрока(ОкноЗаголовок) Тогда
1446
+ АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
1447
+ Если КомандныйИнтерфейсОкнаПоддерживается(АктивноеОкно) Тогда
1448
+ Возврат АктивноеОкно;
1449
+ КонецЕсли;
1450
+ Для Каждого ТекущееОкно Из ОкнаТестируемогоПриложения() Цикл
1451
+ Если КомандныйИнтерфейсОкнаПоддерживается(ТекущееОкно) Тогда
1452
+ ТекущееОкно.Активизировать();
1453
+ Возврат ТекущееОкно;
1454
+ КонецЕсли;
1455
+ КонецЦикла;
1456
+ Возврат АктивноеОкно;
1457
+ КонецЕсли;
1458
+
1459
+ Для Каждого ТекущееОкно Из ОкнаТестируемогоПриложения() Цикл
1460
+ ЗаголовокТекущегоОкна = БезопасноеСвойство(ТекущееОкно, "Заголовок", "");
1461
+ Если СтрНайти(НРег(ЗаголовокТекущегоОкна), НРег(ОкноЗаголовок)) > 0
1462
+ И КомандныйИнтерфейсОкнаПоддерживается(ТекущееОкно) Тогда
1463
+ ТекущееОкно.Активизировать();
1464
+ Возврат ТекущееОкно;
1465
+ КонецЕсли;
1466
+ КонецЦикла;
1467
+ ВызватьИсключение "Окно не найдено: " + ОкноЗаголовок;
1468
+ КонецФункции
1469
+
1470
+ &НаКлиенте
1471
+ Функция КомандныйИнтерфейсОкнаПоддерживается(Окно)
1472
+ Попытка
1473
+ Окно.ПолучитьКомандныйИнтерфейс();
1474
+ Возврат Истина;
1475
+ Исключение
1476
+ Возврат Ложь;
1477
+ КонецПопытки;
1478
+ КонецФункции
1479
+
1480
+ &НаКлиенте
1481
+ Функция КомандныйИнтерфейсНайтиРаздел(Интерфейс, ЗаголовокРаздела)
1482
+ Для Каждого Раздел Из КомандныйИнтерфейсПодчиненныеРекурсивно(Интерфейс, "тестируемаякнопкакомандногоинтерфейса") Цикл
1483
+ ЗаголовокРазделаТекущий = БезопасныйЗаголовок(Раздел);
1484
+ Если СтрНайти(НРег(ЗаголовокРазделаТекущий), НРег(ЗаголовокРаздела)) > 0 Тогда
1485
+ Возврат Раздел;
1486
+ КонецЕсли;
1487
+ КонецЦикла;
1488
+ Возврат Неопределено;
1489
+ КонецФункции
1490
+
1491
+ &НаКлиенте
1492
+ Функция РазделыКомандногоИнтерфейса(Интерфейс)
1493
+ Результат = Новый Массив;
1494
+ Для Каждого Группа Из КомандныйИнтерфейсПодчиненныеРекурсивно(Интерфейс, "тестируемаягруппакомандногоинтерфейса") Цикл
1495
+ Если СтрНайти(НРег(БезопасныйЗаголовок(Группа)), "панель разделов") = 0 Тогда
1496
+ Продолжить;
1497
+ КонецЕсли;
1498
+ Для Каждого Раздел Из БезопасныеПодчиненные(Группа) Цикл
1499
+ Если НормализованноеИмяТипа(Строка(ТипЗнч(Раздел))) <> "тестируемаякнопкакомандногоинтерфейса" Тогда
1500
+ Продолжить;
1501
+ КонецЕсли;
1502
+ ДанныеРаздела = КомандныйИнтерфейсОбъектВСтруктуру(Раздел, 0, 0);
1503
+ ДанныеРаздела.Вставить("panel", БезопасныйЗаголовок(Группа));
1504
+ Результат.Добавить(ДанныеРаздела);
1505
+ КонецЦикла;
1506
+ КонецЦикла;
1507
+ Возврат Результат;
1508
+ КонецФункции
1509
+
1510
+ &НаКлиенте
1511
+ Функция КомандныйИнтерфейсПодчиненныеРекурсивно(Объект, ИскомыйТип)
1512
+ Результат = Новый Массив;
1513
+ КомандныйИнтерфейсПодчиненныеРекурсивноВнутр(Объект, ИскомыйТип, Результат);
1514
+ Возврат Результат;
1515
+ КонецФункции
1516
+
1517
+ &НаКлиенте
1518
+ Процедура КомандныйИнтерфейсПодчиненныеРекурсивноВнутр(Объект, ИскомыйТип, Результат)
1519
+ Если Объект = Неопределено Тогда
1520
+ Возврат;
1521
+ КонецЕсли;
1522
+ Для Каждого Подчиненный Из БезопасныеПодчиненные(Объект) Цикл
1523
+ Если НормализованноеИмяТипа(Строка(ТипЗнч(Подчиненный))) = ИскомыйТип Тогда
1524
+ Результат.Добавить(Подчиненный);
1525
+ КонецЕсли;
1526
+ КомандныйИнтерфейсПодчиненныеРекурсивноВнутр(Подчиненный, ИскомыйТип, Результат);
1527
+ КонецЦикла;
1528
+ КонецПроцедуры
1529
+
1530
+ &НаКлиенте
1531
+ Функция КомандныйИнтерфейсОбъектВСтруктуру(Объект, ТекущаяГлубина, МаксимальнаяГлубина)
1532
+ Если Объект = Неопределено Тогда
1533
+ Возврат Неопределено;
1534
+ КонецЕсли;
1535
+
1536
+ Результат = Новый Структура;
1537
+ ТипОбъекта = Строка(ТипЗнч(Объект));
1538
+ НормТип = НормализованноеИмяТипа(ТипОбъекта);
1539
+ Результат.Вставить("type", ТипОбъекта);
1540
+ Результат.Вставить("kind", НормТип);
1541
+ Результат.Вставить("title", БезопасныйЗаголовок(Объект));
1542
+ Результат.Вставить("navigation_url", БезопасноеСвойство(Объект, "НавигационнаяСсылка", ""));
1543
+
1544
+ Если НормТип = "тестируемыйкомандныйинтерфейс" Тогда
1545
+ Результат.Вставить("role", "root");
1546
+ ИначеЕсли НормТип = "тестируемаягруппакомандногоинтерфейса" Тогда
1547
+ Результат.Вставить("role", "section");
1548
+ ИначеЕсли НормТип = "тестируемаякнопкакомандногоинтерфейса" Тогда
1549
+ Результат.Вставить("role", "command");
1550
+ Иначе
1551
+ Результат.Вставить("role", "object");
1552
+ КонецЕсли;
1553
+
1554
+ Попытка
1555
+ Результат.Вставить("visible", Объект.ТекущаяВидимость());
1556
+ Исключение
1557
+ Результат.Вставить("visible", Истина);
1558
+ КонецПопытки;
1559
+ Попытка
1560
+ Результат.Вставить("available", Объект.ТекущаяДоступность());
1561
+ Исключение
1562
+ Результат.Вставить("available", Истина);
1563
+ КонецПопытки;
1564
+
1565
+ Если ТекущаяГлубина < МаксимальнаяГлубина Тогда
1566
+ Дети = Новый Массив;
1567
+ Для Каждого Подчиненный Из БезопасныеПодчиненные(Объект) Цикл
1568
+ ДанныеПодчиненного = КомандныйИнтерфейсОбъектВСтруктуру(Подчиненный, ТекущаяГлубина + 1, МаксимальнаяГлубина);
1569
+ Если ДанныеПодчиненного <> Неопределено Тогда
1570
+ Дети.Добавить(ДанныеПодчиненного);
1571
+ КонецЕсли;
1572
+ КонецЦикла;
1573
+ Результат.Вставить("children", Дети);
1574
+ КонецЕсли;
1575
+
1576
+ Возврат Результат;
1577
+ КонецФункции
1578
+
1579
+ &НаКлиенте
1580
+ Функция КомандыКомандногоИнтерфейса(Корень, ИсключатьСлужебныеПанели = Ложь)
1581
+ Результат = Новый Массив;
1582
+ КомандыКомандногоИнтерфейсаРекурсивно(Корень, Результат, Новый Массив, ИсключатьСлужебныеПанели);
1583
+ Возврат Результат;
1584
+ КонецФункции
1585
+
1586
+ &НаКлиенте
1587
+ Процедура КомандыКомандногоИнтерфейсаРекурсивно(Объект, Результат, Путь, ИсключатьСлужебныеПанели)
1588
+ Если Объект = Неопределено Тогда
1589
+ Возврат;
1590
+ КонецЕсли;
1591
+
1592
+ ТипОбъекта = НормализованноеИмяТипа(Строка(ТипЗнч(Объект)));
1593
+ Заголовок = БезопасныйЗаголовок(Объект);
1594
+ СлужебнаяПанель = ИсключатьСлужебныеПанели И КомандныйИнтерфейсПутьСодержитСлужебнуюПанель(Путь);
1595
+ Если ТипОбъекта = "тестируемаякнопкакомандногоинтерфейса" И Не СлужебнаяПанель Тогда
1596
+ Команда = Новый Структура;
1597
+ Команда.Вставить("title", Заголовок);
1598
+ Команда.Вставить("navigation_url", БезопасноеСвойство(Объект, "НавигационнаяСсылка", ""));
1599
+ Команда.Вставить("path", Путь);
1600
+ Результат.Добавить(Команда);
1601
+ КонецЕсли;
1602
+
1603
+ НовыйПуть = Новый Массив;
1604
+ Для Каждого ЭлементПути Из Путь Цикл
1605
+ НовыйПуть.Добавить(ЭлементПути);
1606
+ КонецЦикла;
1607
+ Если ТипОбъекта = "тестируемаягруппакомандногоинтерфейса" И Не ПустаяСтрока(Заголовок) Тогда
1608
+ НовыйПуть.Добавить(Заголовок);
1609
+ КонецЕсли;
1610
+
1611
+ Для Каждого Подчиненный Из БезопасныеПодчиненные(Объект) Цикл
1612
+ КомандыКомандногоИнтерфейсаРекурсивно(Подчиненный, Результат, НовыйПуть, ИсключатьСлужебныеПанели);
1613
+ КонецЦикла;
1614
+ КонецПроцедуры
1615
+
1616
+ &НаКлиенте
1617
+ Функция КомандныйИнтерфейсПутьСодержитСлужебнуюПанель(Путь)
1618
+ Для Каждого ЭлементПути Из Путь Цикл
1619
+ НормЭлемент = НРег(ЭлементПути);
1620
+ Если СтрНайти(НормЭлемент, "панель разделов") > 0
1621
+ Или СтрНайти(НормЭлемент, "панель открытых") > 0 Тогда
1622
+ Возврат Истина;
1623
+ КонецЕсли;
1624
+ КонецЦикла;
1625
+ Возврат Ложь;
1626
+ КонецФункции
1627
+
1628
+ &НаКлиенте
1629
+ Функция ПоискВКомандахКомандногоИнтерфейса(Команды, СтрокаПоиска, Максимум)
1630
+ Результат = Новый Массив;
1631
+ НормПоиск = НРег(СтрокаПоиска);
1632
+ КороткийПоиск = НормПоиск;
1633
+ Если СтрДлина(КороткийПоиск) > 3 Тогда
1634
+ КороткийПоиск = Лев(КороткийПоиск, СтрДлина(КороткийПоиск) - 1);
1635
+ КонецЕсли;
1636
+ Для Каждого Команда Из Команды Цикл
1637
+ Заголовок = СвойствоСтруктуры(Команда, "title", "");
1638
+ Ссылка = СвойствоСтруктуры(Команда, "navigation_url", "");
1639
+ Путь = СвойствоСтруктуры(Команда, "path", Новый Массив);
1640
+ ТекстПути = КомандныйИнтерфейсПутьВСтроку(Путь);
1641
+ ТекстДляПоиска = НРег(Заголовок + " " + ТекстПути + " " + Ссылка);
1642
+ Если СтрНайти(ТекстДляПоиска, НормПоиск) > 0
1643
+ Или (КороткийПоиск <> НормПоиск И СтрНайти(ТекстДляПоиска, КороткийПоиск) > 0) Тогда
1644
+ Совпадение = Новый Структура;
1645
+ Совпадение.Вставить("title", Заголовок);
1646
+ Совпадение.Вставить("navigation_url", Ссылка);
1647
+ Совпадение.Вставить("path", Путь);
1648
+ Совпадение.Вставить("path_text", ТекстПути);
1649
+ Совпадение.Вставить("score", КомандныйИнтерфейсОценкаСовпадения(Заголовок, ТекстПути, Ссылка, НормПоиск));
1650
+ Результат.Добавить(Совпадение);
1651
+ Если Максимум > 0 И Результат.Количество() >= Максимум Тогда
1652
+ Прервать;
1653
+ КонецЕсли;
1654
+ КонецЕсли;
1655
+ КонецЦикла;
1656
+ Возврат Результат;
1657
+ КонецФункции
1658
+
1659
+ &НаКлиенте
1660
+ Функция КомандныйИнтерфейсПутьВСтроку(Путь)
1661
+ Результат = "";
1662
+ Для Каждого ЭлементПути Из Путь Цикл
1663
+ Если Не ПустаяСтрока(Результат) Тогда
1664
+ Результат = Результат + " / ";
1665
+ КонецЕсли;
1666
+ Результат = Результат + ЭлементПути;
1667
+ КонецЦикла;
1668
+ Возврат Результат;
1669
+ КонецФункции
1670
+
1671
+ &НаКлиенте
1672
+ Функция КомандныйИнтерфейсОценкаСовпадения(Заголовок, ТекстПути, Ссылка, НормПоиск)
1673
+ Если НРег(Заголовок) = НормПоиск Тогда
1674
+ Возврат 100;
1675
+ КонецЕсли;
1676
+ Если СтрНайти(НРег(Заголовок), НормПоиск) > 0 Тогда
1677
+ Возврат 80;
1678
+ КонецЕсли;
1679
+ Если СтрНайти(НРег(ТекстПути), НормПоиск) > 0 Тогда
1680
+ Возврат 50;
1681
+ КонецЕсли;
1682
+ Если СтрНайти(НРег(Ссылка), НормПоиск) > 0 Тогда
1683
+ Возврат 30;
1684
+ КонецЕсли;
1685
+ Возврат 0;
1686
+ КонецФункции
1687
+
1344
1688
  &НаКлиенте
1345
1689
  Функция РазвернутьГруппуMCP(Параметры)
1346
1690
  Если ТестируемоеПриложение = Неопределено Тогда
@@ -2455,11 +2455,55 @@ async def object_context_menu(
2455
2455
  @mcp.tool()
2456
2456
  async def window_command_interface(
2457
2457
  max_depth: Annotated[int, "Serialization depth for returned command interface"] = 2,
2458
+ window_title: Annotated[str, "Optional window title substring to activate before reading command interface"] = "",
2458
2459
  *,
2459
2460
  session_id: Annotated[str, "Session id"] = DEFAULT_SESSION,
2460
2461
  ) -> Any:
2461
2462
  """Return active window command interface, when supported."""
2462
- return await _bridge_call_recorded(session_id, "window_command_interface", {"max_depth": max_depth})
2463
+ return await _bridge_call_recorded(session_id, "window_command_interface", {"max_depth": max_depth, "window_title": window_title})
2464
+
2465
+
2466
+ @mcp.tool()
2467
+ async def command_interface_sections(
2468
+ window_title: Annotated[str, "Optional window title substring to activate before reading command interface"] = "",
2469
+ *,
2470
+ session_id: Annotated[str, "Session id"] = DEFAULT_SESSION,
2471
+ ) -> Any:
2472
+ """Return top-level sections of the active window command interface."""
2473
+ return await _bridge_call_recorded(session_id, "command_interface_sections", {"window_title": window_title})
2474
+
2475
+
2476
+ @mcp.tool()
2477
+ async def command_interface_commands(
2478
+ section: Annotated[str, "Optional top-level section title substring, e.g. 'Главное' or 'Администрирование'"] = "",
2479
+ max_depth: Annotated[int, "Serialization depth for returned command tree"] = 4,
2480
+ window_title: Annotated[str, "Optional window title substring to activate before reading command interface"] = "",
2481
+ *,
2482
+ session_id: Annotated[str, "Session id"] = DEFAULT_SESSION,
2483
+ ) -> Any:
2484
+ """Return command-interface command tree and flattened command list, optionally filtered by section."""
2485
+ return await _bridge_call_recorded(
2486
+ session_id,
2487
+ "command_interface_commands",
2488
+ {"section": section, "max_depth": max_depth, "window_title": window_title},
2489
+ )
2490
+
2491
+
2492
+ @mcp.tool()
2493
+ async def command_interface_search(
2494
+ query: Annotated[str, "Search text to match against command title, path and navigation URL"],
2495
+ section: Annotated[str, "Optional top-level section title substring to activate before searching"] = "",
2496
+ max_results: Annotated[int, "Maximum number of matches to return; 0 means no limit"] = 20,
2497
+ window_title: Annotated[str, "Optional window title substring to activate before reading command interface"] = "",
2498
+ *,
2499
+ session_id: Annotated[str, "Session id"] = DEFAULT_SESSION,
2500
+ ) -> Any:
2501
+ """Search live command-interface commands by title, path or navigation URL."""
2502
+ return await _bridge_call_recorded(
2503
+ session_id,
2504
+ "command_interface_search",
2505
+ {"query": query, "section": section, "max_results": max_results, "window_title": window_title},
2506
+ )
2463
2507
 
2464
2508
 
2465
2509
  @mcp.tool()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes