answer42 0.4.64__tar.gz → 0.4.65__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.
- {answer42-0.4.64 → answer42-0.4.65}/PKG-INFO +1 -1
- {answer42-0.4.64 → answer42-0.4.65}/pyproject.toml +1 -1
- {answer42-0.4.64 → answer42-0.4.65}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form/Module.bsl +195 -52
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/server.py +159 -2
- {answer42-0.4.64 → answer42-0.4.65}/.gitignore +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/LICENSE +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/README.md +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/credentials.example.json +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/docs/agent-installation.md +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/docs/architecture.md +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/docs/assets/answer42-logo.png +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/docs/assets/platform42-logo.svg +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/docs/installation.md +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/scripts/build_cf.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/scripts/build_pages.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/scripts/e2e_http_smoke.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/scripts/e2e_stable.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/scripts/openclaw_mcp_autoreload.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/scripts/rag_cli.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/cf/ConfigDumpInfo.xml +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/cf/Configuration.xml +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/cf/DataProcessors/MCPTestManager/Ext/ObjectModule.bsl +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form.xml" +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260.xml" +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/cf/DataProcessors/MCPTestManager.xml +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/cf/Ext/ManagedApplicationModule.bsl +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/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
- {answer42-0.4.64 → answer42-0.4.65}/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
- {answer42-0.4.64 → answer42-0.4.65}/src/client_cf/ConfigDumpInfo.xml +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/client_cf/Configuration.xml +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/client_cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/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
- {answer42-0.4.64 → answer42-0.4.65}/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
- {answer42-0.4.64 → answer42-0.4.65}/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
- {answer42-0.4.64 → answer42-0.4.65}/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
- {answer42-0.4.64 → answer42-0.4.65}/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
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/__init__.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/assets/MCPTestClient.cf +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/assets/MCPTestManager.cf +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/assets/__init__.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/assets/skills/answer42/SKILL.md +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/assets/skills/answer42-rag/SKILL.md +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/assets/skills/answer42-universal-report/SKILL.md +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/auth.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/bridge.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/credentials.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/os_support.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/platform.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/protocol.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/rag/__init__.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/rag/detect.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/rag/dump.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/rag/model.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/rag/parsers.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/rag/service.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/rag/store.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/rag/summary_backend.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/rag/summary_vector.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/recorder.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/release_helper.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/runtime.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/skill_installer.py +0 -0
- {answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/window_control.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: answer42
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.65
|
|
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>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "answer42"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.65"
|
|
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"
|
|
@@ -2302,6 +2302,7 @@
|
|
|
2302
2302
|
&НаКлиенте
|
|
2303
2303
|
Функция ПоискВКомандахКомандногоИнтерфейса(Команды, СтрокаПоиска, Максимум)
|
|
2304
2304
|
Результат = Новый Массив;
|
|
2305
|
+
КлючиСовпадений = Новый Соответствие;
|
|
2305
2306
|
НормПоиск = НРег(СтрокаПоиска);
|
|
2306
2307
|
КороткийПоиск = НормПоиск;
|
|
2307
2308
|
Если СтрДлина(КороткийПоиск) > 3 Тогда
|
|
@@ -2315,13 +2316,18 @@
|
|
|
2315
2316
|
ТекстДляПоиска = НРег(Заголовок + " " + ТекстПути + " " + Ссылка);
|
|
2316
2317
|
Если СтрНайти(ТекстДляПоиска, НормПоиск) > 0
|
|
2317
2318
|
Или (КороткийПоиск <> НормПоиск И СтрНайти(ТекстДляПоиска, КороткийПоиск) > 0) Тогда
|
|
2319
|
+
Оценка = КомандныйИнтерфейсОценкаСовпадения(Заголовок, ТекстПути, Ссылка, НормПоиск);
|
|
2320
|
+
КлючСовпадения = КомандныйИнтерфейсКлючСовпадения(Заголовок, Ссылка);
|
|
2321
|
+
Если КлючиСовпадений.Получить(КлючСовпадения) <> Неопределено Тогда
|
|
2322
|
+
Продолжить;
|
|
2323
|
+
КонецЕсли;
|
|
2318
2324
|
Совпадение = Новый Структура;
|
|
2319
2325
|
Совпадение.Вставить("title", Заголовок);
|
|
2320
2326
|
Совпадение.Вставить("navigation_url", Ссылка);
|
|
2321
2327
|
Совпадение.Вставить("path", Путь);
|
|
2322
2328
|
Совпадение.Вставить("path_text", ТекстПути);
|
|
2323
|
-
Оценка = КомандныйИнтерфейсОценкаСовпадения(Заголовок, ТекстПути, Ссылка, НормПоиск);
|
|
2324
2329
|
Совпадение.Вставить("score", Оценка);
|
|
2330
|
+
КлючиСовпадений.Вставить(КлючСовпадения, Совпадение);
|
|
2325
2331
|
ИндексВставки = Результат.Количество();
|
|
2326
2332
|
Для НомерСовпадения = 0 По Результат.Количество() - 1 Цикл
|
|
2327
2333
|
Если СвойствоСтруктуры(Результат[НомерСовпадения], "score", 0) < Оценка Тогда
|
|
@@ -2331,13 +2337,23 @@
|
|
|
2331
2337
|
КонецЦикла;
|
|
2332
2338
|
Результат.Вставить(ИндексВставки, Совпадение);
|
|
2333
2339
|
Если Максимум > 0 И Результат.Количество() > Максимум Тогда
|
|
2340
|
+
УдаляемоеСовпадение = Результат[Результат.Количество() - 1];
|
|
2334
2341
|
Результат.Удалить(Результат.Количество() - 1);
|
|
2342
|
+
КлючиСовпадений.Удалить(КомандныйИнтерфейсКлючСовпадения(СвойствоСтруктуры(УдаляемоеСовпадение, "title", ""), СвойствоСтруктуры(УдаляемоеСовпадение, "navigation_url", "")));
|
|
2335
2343
|
КонецЕсли;
|
|
2336
2344
|
КонецЕсли;
|
|
2337
2345
|
КонецЦикла;
|
|
2338
2346
|
Возврат Результат;
|
|
2339
2347
|
КонецФункции
|
|
2340
2348
|
|
|
2349
|
+
&НаКлиенте
|
|
2350
|
+
Функция КомандныйИнтерфейсКлючСовпадения(Заголовок, Ссылка)
|
|
2351
|
+
Если Не ПустаяСтрока(Ссылка) Тогда
|
|
2352
|
+
Возврат НРег(Ссылка);
|
|
2353
|
+
КонецЕсли;
|
|
2354
|
+
Возврат НРег(Заголовок);
|
|
2355
|
+
КонецФункции
|
|
2356
|
+
|
|
2341
2357
|
&НаКлиенте
|
|
2342
2358
|
Функция КомандныйИнтерфейсПутьВСтроку(Путь)
|
|
2343
2359
|
Результат = "";
|
|
@@ -2352,19 +2368,26 @@
|
|
|
2352
2368
|
|
|
2353
2369
|
&НаКлиенте
|
|
2354
2370
|
Функция КомандныйИнтерфейсОценкаСовпадения(Заголовок, ТекстПути, Ссылка, НормПоиск)
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
Если
|
|
2359
|
-
|
|
2371
|
+
Оценка = 0;
|
|
2372
|
+
НормЗаголовок = НРег(Заголовок);
|
|
2373
|
+
НормСсылка = НРег(Ссылка);
|
|
2374
|
+
Если НормЗаголовок = НормПоиск Тогда
|
|
2375
|
+
Оценка = 100;
|
|
2376
|
+
ИначеЕсли СтрНайти(НормЗаголовок, НормПоиск) > 0 Тогда
|
|
2377
|
+
Оценка = 80;
|
|
2378
|
+
ИначеЕсли СтрНайти(НРег(ТекстПути), НормПоиск) > 0 Тогда
|
|
2379
|
+
Оценка = 50;
|
|
2380
|
+
ИначеЕсли СтрНайти(НормСсылка, НормПоиск) > 0 Тогда
|
|
2381
|
+
Оценка = 30;
|
|
2360
2382
|
КонецЕсли;
|
|
2361
|
-
Если СтрНайти(
|
|
2362
|
-
|
|
2383
|
+
Если СтрНайти(НормСсылка, "справочник.") > 0 Тогда
|
|
2384
|
+
Оценка = Оценка + 15;
|
|
2385
|
+
ИначеЕсли СтрНайти(НормСсылка, "документ.") > 0 Тогда
|
|
2386
|
+
Оценка = Оценка + 8;
|
|
2387
|
+
ИначеЕсли СтрНайти(НормСсылка, "отчет.") > 0 Тогда
|
|
2388
|
+
Оценка = Оценка - 5;
|
|
2363
2389
|
КонецЕсли;
|
|
2364
|
-
|
|
2365
|
-
Возврат 30;
|
|
2366
|
-
КонецЕсли;
|
|
2367
|
-
Возврат 0;
|
|
2390
|
+
Возврат Оценка;
|
|
2368
2391
|
КонецФункции
|
|
2369
2392
|
|
|
2370
2393
|
&НаКлиенте
|
|
@@ -2820,7 +2843,7 @@
|
|
|
2820
2843
|
Исключение
|
|
2821
2844
|
Ошибки.Добавить("Активизировать: " + ОписаниеОшибки());
|
|
2822
2845
|
КонецПопытки;
|
|
2823
|
-
Возврат Новый Структура("maximized,method,errors,window", Истина, "activate_only", Ошибки,
|
|
2846
|
+
Возврат Новый Структура("maximized,method,errors,window", Истина, "activate_only", Ошибки, КраткоеОписаниеОбъектаMCP(АктивноеОкно));
|
|
2824
2847
|
КонецФункции
|
|
2825
2848
|
|
|
2826
2849
|
&НаКлиенте
|
|
@@ -2831,40 +2854,65 @@
|
|
|
2831
2854
|
ПоказыватьСкрытые = СвойствоСтруктуры(Параметры, "include_hidden", Ложь);
|
|
2832
2855
|
ВключатьДанные = СвойствоСтруктуры(Параметры, "include_data", Ложь);
|
|
2833
2856
|
ВключатьКомандныеПанели = СвойствоСтруктуры(Параметры, "include_command_panels", Ложь);
|
|
2857
|
+
ВключатьСостояниеВидимости = БулевоИзЗначенияMCP(СвойствоСтруктуры(Параметры, "include_visibility_state", Истина), Истина);
|
|
2858
|
+
ВключатьСостояниеДоступности = БулевоИзЗначенияMCP(СвойствоСтруктуры(Параметры, "include_availability_state", Истина), Истина);
|
|
2859
|
+
ВключатьСостояниеТолькоПросмотр = БулевоИзЗначенияMCP(СвойствоСтруктуры(Параметры, "include_read_only_state", Истина), Истина);
|
|
2860
|
+
ВключатьТекущееСостояние = БулевоИзЗначенияMCP(СвойствоСтруктуры(Параметры, "include_current_state", Истина), Истина);
|
|
2834
2861
|
ИмяРодителя = СвойствоСтруктуры(Параметры, "parent_name", "");
|
|
2835
2862
|
ПлоскийРежим = БулевоИзЗначенияMCP(СвойствоСтруктуры(Параметры, "flat", Ложь), Ложь);
|
|
2836
2863
|
ИмяФильтра = СвойствоСтруктуры(Параметры, "name", "");
|
|
2837
2864
|
ЗаголовокФильтра = СвойствоСтруктуры(Параметры, "title", "");
|
|
2838
2865
|
ТипФильтра = СвойствоСтруктуры(Параметры, "type", "");
|
|
2839
2866
|
ТолькоКомандныеПанели = БулевоИзЗначенияMCP(СвойствоСтруктуры(Параметры, "command_panels_only", Ложь), Ложь);
|
|
2867
|
+
ВключатьТайминги = БулевоИзЗначенияMCP(СвойствоСтруктуры(Параметры, "include_timings", Ложь), Ложь);
|
|
2840
2868
|
Начало = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
2869
|
+
Тайминги = Новый Структура;
|
|
2841
2870
|
Лог("ui_tree: start include_hidden=" + Строка(ПоказыватьСкрытые) + " include_data=" + Строка(ВключатьДанные) + " parent_name='" + ИмяРодителя + "' flat=" + Строка(ПлоскийРежим));
|
|
2842
2871
|
ОтправитьСобытиеПрогрессаMCP("ui_tree", "start", Новый Структура("include_hidden,include_data,parent_name,flat", ПоказыватьСкрытые, ВключатьДанные, ИмяРодителя, ПлоскийРежим));
|
|
2872
|
+
НачалоАктивногоОкна = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
2843
2873
|
АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
|
|
2874
|
+
Тайминги.Вставить("active_window_ms", ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоАктивногоОкна);
|
|
2844
2875
|
ОтправитьСобытиеПрогрессаMCP("ui_tree", "active_window_done");
|
|
2845
2876
|
КешСериализации = НовыйКешПоискаКнопкиMCP();
|
|
2846
2877
|
СчетчикУзлов = Новый Структура("nodes", 0);
|
|
2847
2878
|
КорневойОбъект = АктивноеОкно;
|
|
2848
2879
|
Если Не ПустаяСтрока(ИмяРодителя) Тогда
|
|
2880
|
+
НачалоПоискаРодителя = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
2849
2881
|
КорневойОбъект = НайтиОбъектБыстроMCP(АктивноеОкно, ИмяРодителя, "", "", КешСериализации);
|
|
2850
2882
|
Если КорневойОбъект = Неопределено Тогда
|
|
2851
2883
|
КорневойОбъект = НайтиОбъектРекурсивно(АктивноеОкно, ИмяРодителя, "", "", 0, СчетчикУзлов, КешСериализации);
|
|
2852
2884
|
КонецЕсли;
|
|
2885
|
+
Тайминги.Вставить("parent_search_ms", ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоПоискаРодителя);
|
|
2853
2886
|
Если КорневойОбъект = Неопределено Тогда
|
|
2854
2887
|
Время = ТекущаяУниверсальнаяДатаВМиллисекундах() - Начало;
|
|
2855
2888
|
Лог("ui_tree: parent not found ms=" + Строка(Время) + " nodes=" + Строка(СчетчикУзлов.nodes));
|
|
2856
|
-
|
|
2889
|
+
РезультатНеНайден = Новый Структура("found,parent_name,reason,_tree_ms,_nodes_serialized,_nodes_visited", Ложь, ИмяРодителя, "parent_not_found", Время, СчетчикУзлов.nodes, СчетчикУзлов.nodes);
|
|
2890
|
+
Если ВключатьТайминги Тогда
|
|
2891
|
+
Тайминги.Вставить("total_ms", Время);
|
|
2892
|
+
Тайминги.Вставить("nodes_visited", СчетчикУзлов.nodes);
|
|
2893
|
+
Тайминги.Вставить("serialize_stats", КешСериализации.Статистика);
|
|
2894
|
+
РезультатНеНайден.Вставить("_timings", Тайминги);
|
|
2895
|
+
КонецЕсли;
|
|
2896
|
+
Возврат РезультатНеНайден;
|
|
2857
2897
|
КонецЕсли;
|
|
2858
2898
|
СчетчикУзлов.nodes = 0;
|
|
2859
2899
|
КонецЕсли;
|
|
2860
2900
|
Если ПлоскийРежим Тогда
|
|
2861
|
-
Возврат ПлоскоеДеревоИнтерфейсаMCP(КорневойОбъект, ИмяФильтра, ЗаголовокФильтра, ТипФильтра, ТолькоКомандныеПанели, ПоказыватьСкрытые, ВключатьДанные, ВключатьКомандныеПанели, КешСериализации, СчетчикУзлов, Начало,
|
|
2901
|
+
Возврат ПлоскоеДеревоИнтерфейсаMCP(КорневойОбъект, ИмяФильтра, ЗаголовокФильтра, ТипФильтра, ТолькоКомандныеПанели, ПоказыватьСкрытые, ВключатьДанные, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние, КешСериализации, СчетчикУзлов, Начало, ИмяРодителя, ВключатьТайминги, Тайминги);
|
|
2862
2902
|
КонецЕсли;
|
|
2863
|
-
|
|
2903
|
+
НачалоСериализации = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
2904
|
+
Результат = ОбъектВСтруктуру(КорневойОбъект, 0, ПоказыватьСкрытые, Истина, Истина, Ложь, КешСериализации, ВключатьДанные, Истина, СчетчикУзлов, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние);
|
|
2905
|
+
Тайминги.Вставить("serialize_tree_ms", ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоСериализации);
|
|
2864
2906
|
Время = ТекущаяУниверсальнаяДатаВМиллисекундах() - Начало;
|
|
2865
2907
|
Если Результат <> Неопределено И Результат <> "__skip__" Тогда
|
|
2866
2908
|
Результат.Вставить("_tree_ms", Время);
|
|
2867
2909
|
Результат.Вставить("_nodes_serialized", СчетчикУзлов.nodes);
|
|
2910
|
+
Если ВключатьТайминги Тогда
|
|
2911
|
+
Тайминги.Вставить("total_ms", Время);
|
|
2912
|
+
Тайминги.Вставить("nodes_serialized", СчетчикУзлов.nodes);
|
|
2913
|
+
Тайминги.Вставить("serialize_stats", КешСериализации.Статистика);
|
|
2914
|
+
Результат.Вставить("_timings", Тайминги);
|
|
2915
|
+
КонецЕсли;
|
|
2868
2916
|
Если Не ПустаяСтрока(ИмяРодителя) Тогда
|
|
2869
2917
|
Результат.Вставить("root_parent_name", ИмяРодителя);
|
|
2870
2918
|
КонецЕсли;
|
|
@@ -2875,21 +2923,35 @@
|
|
|
2875
2923
|
КонецФункции
|
|
2876
2924
|
|
|
2877
2925
|
&НаКлиенте
|
|
2878
|
-
Функция ПлоскоеДеревоИнтерфейсаMCP(КорневойОбъект, Имя, Заголовок, ТипОбъекта, ТолькоКомандныеПанели, ПоказыватьСкрытые, ВключатьДанные, ВключатьКомандныеПанели, КешСериализации, СчетчикУзлов, Начало,
|
|
2926
|
+
Функция ПлоскоеДеревоИнтерфейсаMCP(КорневойОбъект, Имя, Заголовок, ТипОбъекта, ТолькоКомандныеПанели, ПоказыватьСкрытые, ВключатьДанные, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние, КешСериализации, СчетчикУзлов, Начало, ИмяРодителя, ВключатьТайминги = Ложь, Тайминги = Неопределено)
|
|
2879
2927
|
Найденные = Новый Массив;
|
|
2880
2928
|
Метод = "flat_traversal";
|
|
2929
|
+
Если Тайминги = Неопределено Тогда
|
|
2930
|
+
Тайминги = Новый Структура;
|
|
2931
|
+
КонецЕсли;
|
|
2881
2932
|
Если Не ТолькоКомандныеПанели И ПустаяСтрока(Заголовок) И (Не ПустаяСтрока(Имя) Или Не ПустаяСтрока(ТипОбъекта)) Тогда
|
|
2882
|
-
|
|
2933
|
+
НачалоБыстрогоПоиска = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
2934
|
+
НайденныеБыстро = НайтиУзлыДереваИнтерфейсаБыстроMCP(КорневойОбъект, Имя, ТипОбъекта, ПоказыватьСкрытые, ВключатьДанные, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние, КешСериализации);
|
|
2935
|
+
Тайминги.Вставить("fast_search_ms", ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоБыстрогоПоиска);
|
|
2883
2936
|
Если НайденныеБыстро <> Неопределено Тогда
|
|
2884
2937
|
Найденные = НайденныеБыстро;
|
|
2885
2938
|
Метод = "fast_platform_search_objects";
|
|
2886
2939
|
КонецЕсли;
|
|
2887
2940
|
КонецЕсли;
|
|
2888
2941
|
Если Метод = "flat_traversal" Тогда
|
|
2889
|
-
|
|
2942
|
+
НачалоПлоскогоОбхода = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
2943
|
+
НайтиУзлыДереваИнтерфейсаПлоскоMCP(КорневойОбъект, Имя, Заголовок, ТипОбъекта, ТолькоКомандныеПанели, ПоказыватьСкрытые, ВключатьДанные, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние, КешСериализации, СчетчикУзлов, Найденные, 0, Ложь);
|
|
2944
|
+
Тайминги.Вставить("flat_traversal_ms", ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоПлоскогоОбхода);
|
|
2890
2945
|
КонецЕсли;
|
|
2891
2946
|
Время = ТекущаяУниверсальнаяДатаВМиллисекундах() - Начало;
|
|
2892
2947
|
Результат = Новый Структура("found,count,objects,flat,filter,method,_tree_ms,_nodes_serialized,_nodes_visited", Найденные.Количество() > 0, Найденные.Количество(), Найденные, Истина, Новый Структура("name,title,type,command_panels_only", Имя, Заголовок, ТипОбъекта, ТолькоКомандныеПанели), Метод, Время, Найденные.Количество(), СчетчикУзлов.nodes);
|
|
2948
|
+
Если ВключатьТайминги Тогда
|
|
2949
|
+
Тайминги.Вставить("total_ms", Время);
|
|
2950
|
+
Тайминги.Вставить("nodes_serialized", Найденные.Количество());
|
|
2951
|
+
Тайминги.Вставить("nodes_visited", СчетчикУзлов.nodes);
|
|
2952
|
+
Тайминги.Вставить("serialize_stats", КешСериализации.Статистика);
|
|
2953
|
+
Результат.Вставить("_timings", Тайминги);
|
|
2954
|
+
КонецЕсли;
|
|
2893
2955
|
Если Не ПустаяСтрока(ИмяРодителя) Тогда
|
|
2894
2956
|
Результат.Вставить("root_parent_name", ИмяРодителя);
|
|
2895
2957
|
КонецЕсли;
|
|
@@ -2899,7 +2961,7 @@
|
|
|
2899
2961
|
КонецФункции
|
|
2900
2962
|
|
|
2901
2963
|
&НаКлиенте
|
|
2902
|
-
Процедура НайтиУзлыДереваИнтерфейсаПлоскоMCP(Объект, Имя, Заголовок, ТипОбъекта, ТолькоКомандныеПанели, ПоказыватьСкрытые, ВключатьДанные, ВключатьКомандныеПанели, КешСериализации, СчетчикУзлов, Найденные, ТекущаяГлубина, ВнутриКоманднойПанели)
|
|
2964
|
+
Процедура НайтиУзлыДереваИнтерфейсаПлоскоMCP(Объект, Имя, Заголовок, ТипОбъекта, ТолькоКомандныеПанели, ПоказыватьСкрытые, ВключатьДанные, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние, КешСериализации, СчетчикУзлов, Найденные, ТекущаяГлубина, ВнутриКоманднойПанели)
|
|
2903
2965
|
Если Объект = Неопределено Тогда
|
|
2904
2966
|
Возврат;
|
|
2905
2967
|
КонецЕсли;
|
|
@@ -2921,17 +2983,17 @@
|
|
|
2921
2983
|
ВключитьВПлоскийРезультат = Не ТолькоКомандныеПанели Или ВнутриКоманднойПанели Или ТекущийУзелКоманднойПанели;
|
|
2922
2984
|
Если ОбъектСоответствует(ИмяТекущего, ЗаголовокТекущего, ТипТекущего, Имя, Заголовок, ТипОбъекта)
|
|
2923
2985
|
И ВключитьВПлоскийРезультат Тогда
|
|
2924
|
-
Найденные.Добавить(ОбъектВСтруктуру(Объект, 0, ПоказыватьСкрытые, Истина, Истина, Ложь, КешСериализации, ВключатьДанные, Ложь, Неопределено,
|
|
2986
|
+
Найденные.Добавить(ОбъектВСтруктуру(Объект, 0, ПоказыватьСкрытые, Истина, Истина, Ложь, КешСериализации, ВключатьДанные, Ложь, Неопределено, Ложь, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние));
|
|
2925
2987
|
КонецЕсли;
|
|
2926
2988
|
Если ВключатьКомандныеПанели Тогда
|
|
2927
2989
|
Панель = КоманднаяПанельСКешемMCP(Объект, КешСериализации);
|
|
2928
2990
|
Если Панель <> Неопределено Тогда
|
|
2929
|
-
НайтиУзлыДереваИнтерфейсаПлоскоMCP(Панель, Имя, Заголовок, ТипОбъекта, ТолькоКомандныеПанели, ПоказыватьСкрытые, ВключатьДанные, ВключатьКомандныеПанели, КешСериализации, СчетчикУзлов, Найденные, ТекущаяГлубина + 1, ВнутриКоманднойПанели Или ТекущийУзелКоманднойПанели);
|
|
2991
|
+
НайтиУзлыДереваИнтерфейсаПлоскоMCP(Панель, Имя, Заголовок, ТипОбъекта, ТолькоКомандныеПанели, ПоказыватьСкрытые, ВключатьДанные, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние, КешСериализации, СчетчикУзлов, Найденные, ТекущаяГлубина + 1, ВнутриКоманднойПанели Или ТекущийУзелКоманднойПанели);
|
|
2930
2992
|
КонецЕсли;
|
|
2931
2993
|
КонецЕсли;
|
|
2932
2994
|
Подчиненные = БезопасныеПодчиненныеСКешемMCP(Объект, КешСериализации);
|
|
2933
2995
|
Для Каждого Подчиненный Из Подчиненные Цикл
|
|
2934
|
-
НайтиУзлыДереваИнтерфейсаПлоскоMCP(Подчиненный, Имя, Заголовок, ТипОбъекта, ТолькоКомандныеПанели, ПоказыватьСкрытые, ВключатьДанные, ВключатьКомандныеПанели, КешСериализации, СчетчикУзлов, Найденные, ТекущаяГлубина + 1, ВнутриКоманднойПанели Или ТекущийУзелКоманднойПанели);
|
|
2996
|
+
НайтиУзлыДереваИнтерфейсаПлоскоMCP(Подчиненный, Имя, Заголовок, ТипОбъекта, ТолькоКомандныеПанели, ПоказыватьСкрытые, ВключатьДанные, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние, КешСериализации, СчетчикУзлов, Найденные, ТекущаяГлубина + 1, ВнутриКоманднойПанели Или ТекущийУзелКоманднойПанели);
|
|
2935
2997
|
КонецЦикла;
|
|
2936
2998
|
Исключение
|
|
2937
2999
|
Инфо = ИнформацияОбОшибке();
|
|
@@ -2940,7 +3002,7 @@
|
|
|
2940
3002
|
КонецПроцедуры
|
|
2941
3003
|
|
|
2942
3004
|
&НаКлиенте
|
|
2943
|
-
Функция НайтиУзлыДереваИнтерфейсаБыстроMCP(КорневойОбъект, Имя, ТипОбъектаСтрокой, ПоказыватьСкрытые, ВключатьДанные, КешСериализации)
|
|
3005
|
+
Функция НайтиУзлыДереваИнтерфейсаБыстроMCP(КорневойОбъект, Имя, ТипОбъектаСтрокой, ПоказыватьСкрытые, ВключатьДанные, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние, КешСериализации)
|
|
2944
3006
|
ТипОбъекта = ТипТестируемогоОбъектаMCP(ТипОбъектаСтрокой);
|
|
2945
3007
|
Если Не ПустаяСтрока(ТипОбъектаСтрокой) И ТипОбъекта = Неопределено Тогда
|
|
2946
3008
|
Возврат Неопределено;
|
|
@@ -3543,10 +3605,18 @@
|
|
|
3543
3605
|
|
|
3544
3606
|
&НаКлиенте
|
|
3545
3607
|
Функция НовыйКешПоискаКнопкиMCP()
|
|
3546
|
-
Статистика = Новый Структура("nodes,children_arrays,buttons_checked,fast_attempts,fast_found,fast_ms,method", 0, 0, 0, 0, Ложь, 0, "");
|
|
3608
|
+
Статистика = Новый Структура("nodes,children_arrays,buttons_checked,fast_attempts,fast_found,fast_ms,method,serialize_visibility_ms,serialize_type_ms,serialize_base_props_ms,serialize_data_ms,serialize_children_fetch_ms,serialize_current_page_ms,serialize_pages_ms,serialize_command_panels_ms,serialize_children_loop_ms", 0, 0, 0, 0, Ложь, 0, "", 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
3547
3609
|
Возврат Новый Структура("Методы,Свойства,Подчиненные,КомандныеПанели,ТекущиеСтраницы,Статистика", Новый Соответствие, Новый Соответствие, Новый Соответствие, Новый Соответствие, Новый Соответствие, Статистика);
|
|
3548
3610
|
КонецФункции
|
|
3549
3611
|
|
|
3612
|
+
&НаКлиенте
|
|
3613
|
+
Процедура ДобавитьТаймингСериализацииMCP(КешПоиска, ИмяПоля, Начало)
|
|
3614
|
+
Если КешПоиска = Неопределено Тогда
|
|
3615
|
+
Возврат;
|
|
3616
|
+
КонецЕсли;
|
|
3617
|
+
КешПоиска.Статистика.Вставить(ИмяПоля, СвойствоСтруктуры(КешПоиска.Статистика, ИмяПоля, 0) + (ТекущаяУниверсальнаяДатаВМиллисекундах() - Начало));
|
|
3618
|
+
КонецПроцедуры
|
|
3619
|
+
|
|
3550
3620
|
&НаКлиенте
|
|
3551
3621
|
Функция КлючСвойстваКешаMCP(ИмяСвойства)
|
|
3552
3622
|
Возврат "property:" + ИмяСвойства;
|
|
@@ -9272,7 +9342,7 @@
|
|
|
9272
9342
|
#Область Сериализация
|
|
9273
9343
|
|
|
9274
9344
|
&НаКлиенте
|
|
9275
|
-
Функция ОбъектВСтруктуру(Объект, ТекущаяГлубина, ПоказыватьСкрытые = Истина, РодительскаяВидимость = Истина, РодительскаяДоступность = Истина, РодительТолькоПросмотр = Ложь, КешСериализации = Неопределено, ВключатьДанные = Истина, СериализоватьДетей = Истина, СчетчикУзлов = Неопределено, ВключатьКомандныеПанели = Истина)
|
|
9345
|
+
Функция ОбъектВСтруктуру(Объект, ТекущаяГлубина, ПоказыватьСкрытые = Истина, РодительскаяВидимость = Истина, РодительскаяДоступность = Истина, РодительТолькоПросмотр = Ложь, КешСериализации = Неопределено, ВключатьДанные = Истина, СериализоватьДетей = Истина, СчетчикУзлов = Неопределено, ВключатьКомандныеПанели = Истина, ВключатьСостояниеВидимости = Истина, ВключатьСостояниеДоступности = Истина, ВключатьСостояниеТолькоПросмотр = Истина, ВключатьТекущееСостояние = Истина)
|
|
9276
9346
|
Если Объект = Неопределено Тогда
|
|
9277
9347
|
Возврат Неопределено;
|
|
9278
9348
|
КонецЕсли;
|
|
@@ -9285,18 +9355,56 @@
|
|
|
9285
9355
|
Если ЭтоСкрываемаяГруппа(Объект) Тогда
|
|
9286
9356
|
Возврат "__skip__";
|
|
9287
9357
|
КонецЕсли;
|
|
9288
|
-
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9358
|
+
НачалоФазыСериализации = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
9359
|
+
ТипСтрокой = Строка(ТипЗнч(Объект));
|
|
9360
|
+
ТипОбъекта = НРег(НормализованноеИмяТипа(ТипСтрокой));
|
|
9361
|
+
ЭтоДекорация = ТипОбъекта = "тестируемаядекорацияформы";
|
|
9362
|
+
ДобавитьТаймингСериализацииMCP(КешСериализации, "serialize_type_ms", НачалоФазыСериализации);
|
|
9363
|
+
|
|
9364
|
+
НачалоФазыСериализации = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
9365
|
+
Если Не РодительскаяВидимость Тогда
|
|
9366
|
+
// Невидимость родителя распространяется на всех потомков, не дергаем дорогие проверки состояния ребенка.
|
|
9367
|
+
СобственнаяВидимость = Ложь;
|
|
9368
|
+
ИначеЕсли ВключатьСостояниеВидимости Тогда
|
|
9369
|
+
СобственнаяВидимость = БезопасноеЗначениеМетодаСКешемMCP(Объект, "ТекущаяВидимость", БезопасноеСвойствоСКешемMCP(Объект, "Видимость", Истина, КешСериализации), КешСериализации);
|
|
9370
|
+
Иначе
|
|
9371
|
+
// Видимость не нужна ни для фильтрации, ни для ответа; считаем узел видимым, чтобы не блокировать другие явно запрошенные состояния.
|
|
9372
|
+
СобственнаяВидимость = Истина;
|
|
9373
|
+
КонецЕсли;
|
|
9374
|
+
Видимость = РодительскаяВидимость И СобственнаяВидимость;
|
|
9375
|
+
Если Не Видимость Тогда
|
|
9376
|
+
СобственнаяДоступность = Ложь;
|
|
9377
|
+
СобственноеТолькоПросмотр = Ложь;
|
|
9378
|
+
Доступность = Ложь;
|
|
9379
|
+
ТолькоПросмотр = Ложь;
|
|
9380
|
+
ИначеЕсли ЭтоДекорация Или Не ВключатьСостояниеДоступности Тогда
|
|
9381
|
+
// У декораций и легких профилей нет полезной доступности/только просмотра; не тратим время на platform calls.
|
|
9382
|
+
СобственнаяДоступность = РодительскаяДоступность;
|
|
9383
|
+
СобственноеТолькоПросмотр = Ложь;
|
|
9384
|
+
Доступность = РодительскаяДоступность;
|
|
9385
|
+
ТолькоПросмотр = РодительТолькоПросмотр;
|
|
9386
|
+
ИначеЕсли Не РодительскаяДоступность Тогда
|
|
9387
|
+
// Недоступность родителя распространяется на потомков, read_only не проверяем.
|
|
9388
|
+
СобственнаяДоступность = Ложь;
|
|
9389
|
+
СобственноеТолькоПросмотр = Ложь;
|
|
9390
|
+
Доступность = Ложь;
|
|
9391
|
+
ТолькоПросмотр = РодительТолькоПросмотр;
|
|
9392
|
+
Иначе
|
|
9393
|
+
СобственнаяДоступность = БезопасноеЗначениеМетодаСКешемMCP(Объект, "ТекущаяДоступность", БезопасноеСвойствоСКешемMCP(Объект, "Доступность", Истина, КешСериализации), КешСериализации);
|
|
9394
|
+
Доступность = РодительскаяДоступность И СобственнаяДоступность;
|
|
9395
|
+
Если Доступность И ВключатьСостояниеТолькоПросмотр Тогда
|
|
9396
|
+
СобственноеТолькоПросмотр = БезопасноеЗначениеМетодаСКешемMCP(Объект, "ТекущееТолькоПросмотр", БезопасноеСвойствоСКешемMCP(Объект, "ТолькоПросмотр", Ложь, КешСериализации), КешСериализации);
|
|
9397
|
+
ТолькоПросмотр = РодительТолькоПросмотр Или СобственноеТолькоПросмотр;
|
|
9398
|
+
Иначе
|
|
9399
|
+
СобственноеТолькоПросмотр = Ложь;
|
|
9400
|
+
ТолькоПросмотр = РодительТолькоПросмотр;
|
|
9401
|
+
КонецЕсли;
|
|
9402
|
+
КонецЕсли;
|
|
9403
|
+
ДобавитьТаймингСериализацииMCP(КешСериализации, "serialize_visibility_ms", НачалоФазыСериализации);
|
|
9294
9404
|
Если Не ПоказыватьСкрытые И ТекущаяГлубина > 0 И Не Видимость Тогда
|
|
9295
9405
|
Возврат Неопределено;
|
|
9296
9406
|
КонецЕсли;
|
|
9297
|
-
|
|
9298
|
-
ТипСтрокой = Строка(ТипЗнч(Объект));
|
|
9299
|
-
ТипОбъекта = НРег(НормализованноеИмяТипа(ТипСтрокой));
|
|
9407
|
+
НачалоФазыСериализации = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
9300
9408
|
Результат = Новый Структура;
|
|
9301
9409
|
Результат.Вставить("type", ТипСтрокой);
|
|
9302
9410
|
Результат.Вставить("name", БезопасноеСвойствоСКешемMCP(Объект, "Имя", "", КешСериализации));
|
|
@@ -9305,14 +9413,30 @@
|
|
|
9305
9413
|
Результат.Вставить("navigation_url", БезопасноеСвойствоСКешемMCP(Объект, "НавигационнаяСсылка", "", КешСериализации));
|
|
9306
9414
|
Результат.Вставить("main", БезопасноеСвойствоСКешемMCP(Объект, "Основное", БезопасноеСвойствоСКешемMCP(Объект, "ГлавноеОкно", Ложь, КешСериализации), КешСериализации));
|
|
9307
9415
|
Результат.Вставить("home", БезопасноеСвойствоСКешемMCP(Объект, "НачальнаяСтраница", Ложь, КешСериализации));
|
|
9308
|
-
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9416
|
+
Если ВключатьСостояниеВидимости Тогда
|
|
9417
|
+
Результат.Вставить("visible", Видимость);
|
|
9418
|
+
КонецЕсли;
|
|
9419
|
+
Если ВключатьСостояниеДоступности Тогда
|
|
9420
|
+
Результат.Вставить("available", Доступность);
|
|
9421
|
+
Результат.Вставить("enabled", Доступность);
|
|
9422
|
+
КонецЕсли;
|
|
9423
|
+
Если ВключатьСостояниеТолькоПросмотр Тогда
|
|
9424
|
+
Результат.Вставить("read_only", ТолькоПросмотр);
|
|
9425
|
+
КонецЕсли;
|
|
9426
|
+
Если ВключатьТекущееСостояние Тогда
|
|
9427
|
+
Если ВключатьСостояниеВидимости Тогда
|
|
9428
|
+
Результат.Вставить("current_visible", СобственнаяВидимость);
|
|
9429
|
+
КонецЕсли;
|
|
9430
|
+
Если ВключатьСостояниеДоступности Тогда
|
|
9431
|
+
Результат.Вставить("current_available", СобственнаяДоступность);
|
|
9432
|
+
КонецЕсли;
|
|
9433
|
+
Если ВключатьСостояниеТолькоПросмотр Тогда
|
|
9434
|
+
Результат.Вставить("current_read_only", СобственноеТолькоПросмотр);
|
|
9435
|
+
КонецЕсли;
|
|
9436
|
+
КонецЕсли;
|
|
9437
|
+
ДобавитьТаймингСериализацииMCP(КешСериализации, "serialize_base_props_ms", НачалоФазыСериализации);
|
|
9315
9438
|
|
|
9439
|
+
НачалоФазыСериализации = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
9316
9440
|
Если ВключатьДанные И (ТипОбъекта = "тестируемоеполеформы" Или ТипОбъекта = "тестируемаякнопкаформы"
|
|
9317
9441
|
Или ТипОбъекта = "тестируемаякнопкакоманднойпанели" Или ТипОбъекта = "тестируемаятаблицаформы"
|
|
9318
9442
|
Или ТипОбъекта = "тестируемыенадпись" Или ТипОбъекта = "тестируемыйпереключатель"
|
|
@@ -9330,60 +9454,78 @@
|
|
|
9330
9454
|
Иначе
|
|
9331
9455
|
Результат.Вставить("data", "");
|
|
9332
9456
|
КонецЕсли;
|
|
9457
|
+
ДобавитьТаймингСериализацииMCP(КешСериализации, "serialize_data_ms", НачалоФазыСериализации);
|
|
9333
9458
|
|
|
9334
9459
|
Если Не СериализоватьДетей Тогда
|
|
9335
9460
|
Возврат Результат;
|
|
9336
9461
|
КонецЕсли;
|
|
9337
9462
|
|
|
9463
|
+
НачалоФазыСериализации = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
9338
9464
|
Дети = БезопасныеПодчиненныеСКешемMCP(Объект, КешСериализации);
|
|
9465
|
+
ДобавитьТаймингСериализацииMCP(КешСериализации, "serialize_children_fetch_ms", НачалоФазыСериализации);
|
|
9339
9466
|
МассивДетей = Новый Массив;
|
|
9340
9467
|
ИмяТекущейСтраницы = "";
|
|
9341
9468
|
ТекущаяСтраницаГруппы = Неопределено;
|
|
9469
|
+
НачалоФазыСериализации = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
9342
9470
|
Попытка
|
|
9343
9471
|
ТекущаяСтраницаГруппы = Объект.ПолучитьТекущуюСтраницу();
|
|
9344
9472
|
ИмяТекущейСтраницы = БезопасноеСвойствоСКешемMCP(ТекущаяСтраницаГруппы, "Имя", "", КешСериализации);
|
|
9345
9473
|
Если Не ПустаяСтрока(ИмяТекущейСтраницы) Тогда
|
|
9346
9474
|
Результат.Вставить("current_page_name", ИмяТекущейСтраницы);
|
|
9347
|
-
Результат.Вставить("current_page", ОбъектВСтруктуру(ТекущаяСтраницаГруппы, ТекущаяГлубина + 1, ПоказыватьСкрытые, Видимость, Доступность, ТолькоПросмотр, КешСериализации, ВключатьДанные, Ложь, СчетчикУзлов,
|
|
9475
|
+
Результат.Вставить("current_page", ОбъектВСтруктуру(ТекущаяСтраницаГруппы, ТекущаяГлубина + 1, ПоказыватьСкрытые, Видимость, Доступность, ТолькоПросмотр, КешСериализации, ВключатьДанные, Ложь, СчетчикУзлов, Ложь, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние));
|
|
9348
9476
|
КонецЕсли;
|
|
9349
9477
|
Исключение
|
|
9350
9478
|
ИмяТекущейСтраницы = "";
|
|
9351
9479
|
ТекущаяСтраницаГруппы = Неопределено;
|
|
9352
9480
|
КонецПопытки;
|
|
9481
|
+
ДобавитьТаймингСериализацииMCP(КешСериализации, "serialize_current_page_ms", НачалоФазыСериализации);
|
|
9353
9482
|
Если Не ПустаяСтрока(ИмяТекущейСтраницы) Тогда
|
|
9483
|
+
НачалоФазыСериализации = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
9354
9484
|
Страницы = Новый Массив;
|
|
9355
9485
|
Для Каждого СтраницаГруппы Из Дети Цикл
|
|
9356
|
-
|
|
9486
|
+
СтраницаТекущая = БезопасноеСвойствоСКешемMCP(СтраницаГруппы, "Имя", "", КешСериализации) = ИмяТекущейСтраницы;
|
|
9487
|
+
ВидимостьСтраницы = Видимость И СтраницаТекущая;
|
|
9488
|
+
ДанныеСтраницы = ОбъектВСтруктуру(СтраницаГруппы, ТекущаяГлубина + 1, Истина, ВидимостьСтраницы, Доступность, ТолькоПросмотр, КешСериализации, Ложь, Ложь, СчетчикУзлов, Ложь, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние);
|
|
9357
9489
|
Если ДанныеСтраницы <> Неопределено Тогда
|
|
9358
|
-
ДанныеСтраницы.Вставить("current",
|
|
9490
|
+
ДанныеСтраницы.Вставить("current", СтраницаТекущая);
|
|
9359
9491
|
Страницы.Добавить(ДанныеСтраницы);
|
|
9360
9492
|
КонецЕсли;
|
|
9361
9493
|
КонецЦикла;
|
|
9362
9494
|
Результат.Вставить("pages", Страницы);
|
|
9495
|
+
ДобавитьТаймингСериализацииMCP(КешСериализации, "serialize_pages_ms", НачалоФазыСериализации);
|
|
9363
9496
|
КонецЕсли;
|
|
9497
|
+
НачалоФазыСериализации = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
9364
9498
|
Если ВключатьКомандныеПанели И (ТипОбъекта = "тестируемаяформа" Или ТипОбъекта = "тестируемоеокно" Или ТипОбъекта = "тестируемаятаблицаформы" Или ТипОбъекта = "тестируемаягруппаформы") Тогда
|
|
9365
9499
|
Панель = КоманднаяПанельСКешемMCP(Объект, КешСериализации);
|
|
9366
9500
|
Если Панель <> Неопределено Тогда
|
|
9367
|
-
СтруктураПанели = ОбъектВСтруктуру(Панель, ТекущаяГлубина + 1, ПоказыватьСкрытые, Видимость, Доступность, ТолькоПросмотр, КешСериализации, ВключатьДанные, Истина, СчетчикУзлов,
|
|
9501
|
+
СтруктураПанели = ОбъектВСтруктуру(Панель, ТекущаяГлубина + 1, ПоказыватьСкрытые, Видимость, Доступность, ТолькоПросмотр, КешСериализации, ВключатьДанные, Истина, СчетчикУзлов, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние);
|
|
9368
9502
|
Если СтруктураПанели <> Неопределено Тогда
|
|
9369
9503
|
МассивДетей.Добавить(СтруктураПанели);
|
|
9370
9504
|
КонецЕсли;
|
|
9371
9505
|
КонецЕсли;
|
|
9372
9506
|
КонецЕсли;
|
|
9507
|
+
ДобавитьТаймингСериализацииMCP(КешСериализации, "serialize_command_panels_ms", НачалоФазыСериализации);
|
|
9373
9508
|
СкрытыхДетей = 0;
|
|
9509
|
+
НачалоФазыСериализации = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
9374
9510
|
Для Каждого Ребенок Из Дети Цикл
|
|
9375
9511
|
ИмяРебенка = БезопасноеСвойствоСКешемMCP(Ребенок, "Имя", "", КешСериализации);
|
|
9376
|
-
|
|
9512
|
+
СтраницаРебенкаНеактивна = Не ПустаяСтрока(ИмяТекущейСтраницы) И ИмяРебенка <> ИмяТекущейСтраницы;
|
|
9513
|
+
Если Не ПоказыватьСкрытые И СтраницаРебенкаНеактивна Тогда
|
|
9377
9514
|
СкрытыхДетей = СкрытыхДетей + 1;
|
|
9378
9515
|
Продолжить;
|
|
9379
9516
|
КонецЕсли;
|
|
9380
9517
|
Если Не ПустаяСтрока(ИмяТекущейСтраницы) И ИмяРебенка = ИмяТекущейСтраницы Тогда
|
|
9381
9518
|
Продолжить;
|
|
9382
9519
|
КонецЕсли;
|
|
9383
|
-
|
|
9520
|
+
ВидимостьРебенка = Видимость;
|
|
9521
|
+
Если СтраницаРебенкаНеактивна Тогда
|
|
9522
|
+
// Дочерние элементы неактивных страниц считаем невидимыми.
|
|
9523
|
+
ВидимостьРебенка = Ложь;
|
|
9524
|
+
КонецЕсли;
|
|
9525
|
+
СтруктураРебенка = ОбъектВСтруктуру(Ребенок, ТекущаяГлубина + 1, ПоказыватьСкрытые, ВидимостьРебенка, Доступность, ТолькоПросмотр, КешСериализации, ВключатьДанные, Истина, СчетчикУзлов, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние);
|
|
9384
9526
|
Если СтруктураРебенка <> Неопределено Тогда
|
|
9385
9527
|
Если СтруктураРебенка = "__skip__" Тогда
|
|
9386
|
-
ДобавитьПодчиненныеПропущеннойГруппыMCP(МассивДетей, Ребенок, ТекущаяГлубина + 1, ПоказыватьСкрытые, Видимость, Доступность, ТолькоПросмотр, КешСериализации, ВключатьДанные, СчетчикУзлов,
|
|
9528
|
+
ДобавитьПодчиненныеПропущеннойГруппыMCP(МассивДетей, Ребенок, ТекущаяГлубина + 1, ПоказыватьСкрытые, Видимость, Доступность, ТолькоПросмотр, КешСериализации, ВключатьДанные, СчетчикУзлов, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние);
|
|
9387
9529
|
Иначе
|
|
9388
9530
|
МассивДетей.Добавить(СтруктураРебенка);
|
|
9389
9531
|
КонецЕсли;
|
|
@@ -9391,6 +9533,7 @@
|
|
|
9391
9533
|
СкрытыхДетей = СкрытыхДетей + 1;
|
|
9392
9534
|
КонецЕсли;
|
|
9393
9535
|
КонецЦикла;
|
|
9536
|
+
ДобавитьТаймингСериализацииMCP(КешСериализации, "serialize_children_loop_ms", НачалоФазыСериализации);
|
|
9394
9537
|
Результат.Вставить("children", МассивДетей);
|
|
9395
9538
|
Если СкрытыхДетей > 0 Тогда
|
|
9396
9539
|
Результат.Вставить("hidden_children_count", СкрытыхДетей);
|
|
@@ -9401,13 +9544,13 @@
|
|
|
9401
9544
|
#КонецОбласти
|
|
9402
9545
|
|
|
9403
9546
|
&НаКлиенте
|
|
9404
|
-
Процедура ДобавитьПодчиненныеПропущеннойГруппыMCP(МассивДетей, ПропущеннаяГруппа, ТекущаяГлубина, ПоказыватьСкрытые, РодительскаяВидимость, РодительскаяДоступность, РодительТолькоПросмотр, КешСериализации = Неопределено, ВключатьДанные = Истина, СчетчикУзлов = Неопределено, ВключатьКомандныеПанели = Истина)
|
|
9547
|
+
Процедура ДобавитьПодчиненныеПропущеннойГруппыMCP(МассивДетей, ПропущеннаяГруппа, ТекущаяГлубина, ПоказыватьСкрытые, РодительскаяВидимость, РодительскаяДоступность, РодительТолькоПросмотр, КешСериализации = Неопределено, ВключатьДанные = Истина, СчетчикУзлов = Неопределено, ВключатьКомандныеПанели = Истина, ВключатьСостояниеВидимости = Истина, ВключатьСостояниеДоступности = Истина, ВключатьСостояниеТолькоПросмотр = Истина, ВключатьТекущееСостояние = Истина)
|
|
9405
9548
|
ПодчиненныеПропущенной = БезопасныеПодчиненныеСКешемMCP(ПропущеннаяГруппа, КешСериализации);
|
|
9406
9549
|
Для Каждого ПодчиненныйПропущенной Из ПодчиненныеПропущенной Цикл
|
|
9407
|
-
СтруктураПодчиненного = ОбъектВСтруктуру(ПодчиненныйПропущенной, ТекущаяГлубина, ПоказыватьСкрытые, РодительскаяВидимость, РодительскаяДоступность, РодительТолькоПросмотр, КешСериализации, ВключатьДанные, Истина, СчетчикУзлов,
|
|
9550
|
+
СтруктураПодчиненного = ОбъектВСтруктуру(ПодчиненныйПропущенной, ТекущаяГлубина, ПоказыватьСкрытые, РодительскаяВидимость, РодительскаяДоступность, РодительТолькоПросмотр, КешСериализации, ВключатьДанные, Истина, СчетчикУзлов, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние);
|
|
9408
9551
|
Если СтруктураПодчиненного <> Неопределено Тогда
|
|
9409
9552
|
Если СтруктураПодчиненного = "__skip__" Тогда
|
|
9410
|
-
ДобавитьПодчиненныеПропущеннойГруппыMCP(МассивДетей, ПодчиненныйПропущенной, ТекущаяГлубина, ПоказыватьСкрытые, РодительскаяВидимость, РодительскаяДоступность, РодительТолькоПросмотр, КешСериализации, ВключатьДанные, СчетчикУзлов,
|
|
9553
|
+
ДобавитьПодчиненныеПропущеннойГруппыMCP(МассивДетей, ПодчиненныйПропущенной, ТекущаяГлубина, ПоказыватьСкрытые, РодительскаяВидимость, РодительскаяДоступность, РодительТолькоПросмотр, КешСериализации, ВключатьДанные, СчетчикУзлов, ВключатьКомандныеПанели, ВключатьСостояниеВидимости, ВключатьСостояниеДоступности, ВключатьСостояниеТолькоПросмотр, ВключатьТекущееСостояние);
|
|
9411
9554
|
Иначе
|
|
9412
9555
|
МассивДетей.Добавить(СтруктураПодчиненного);
|
|
9413
9556
|
КонецЕсли;
|
|
@@ -1907,6 +1907,28 @@ def _ui_tree_field_names(fields: str, profile: str) -> set[str] | None:
|
|
|
1907
1907
|
raise ValueError(f"Unsupported ui_tree fields: {fields!r}. Expected one of: {allowed}.")
|
|
1908
1908
|
|
|
1909
1909
|
|
|
1910
|
+
def _ui_tree_state_options(field_names: set[str] | None, *, include_hidden: bool) -> dict[str, bool]:
|
|
1911
|
+
if field_names is None:
|
|
1912
|
+
return {
|
|
1913
|
+
"include_visibility_state": True,
|
|
1914
|
+
"include_availability_state": True,
|
|
1915
|
+
"include_read_only_state": True,
|
|
1916
|
+
"include_current_state": True,
|
|
1917
|
+
}
|
|
1918
|
+
# Visibility is also a traversal/filtering input: with include_hidden=False the
|
|
1919
|
+
# 1C side must still read it even when the selected field set later omits it.
|
|
1920
|
+
include_visibility_state = not include_hidden or bool({"visible", "current_visible", "hidden_children_count"} & field_names)
|
|
1921
|
+
include_availability_state = bool({"available", "enabled", "current_available"} & field_names)
|
|
1922
|
+
include_read_only_state = bool({"read_only", "current_read_only"} & field_names)
|
|
1923
|
+
include_current_state = bool({"current_visible", "current_available", "current_read_only"} & field_names)
|
|
1924
|
+
return {
|
|
1925
|
+
"include_visibility_state": include_visibility_state,
|
|
1926
|
+
"include_availability_state": include_availability_state,
|
|
1927
|
+
"include_read_only_state": include_read_only_state,
|
|
1928
|
+
"include_current_state": include_current_state,
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
|
|
1910
1932
|
def _apply_ui_fields(value: Any, allowed: set[str] | None) -> Any:
|
|
1911
1933
|
if allowed is None:
|
|
1912
1934
|
return value
|
|
@@ -2159,6 +2181,25 @@ def _attach_ui_tree_metrics(result: Any, metrics: dict[str, Any]) -> Any:
|
|
|
2159
2181
|
return result
|
|
2160
2182
|
|
|
2161
2183
|
|
|
2184
|
+
def _build_ui_tree_timings(tree: Any, *, bridge_ms: float, stages: dict[str, float]) -> dict[str, Any]:
|
|
2185
|
+
timings: dict[str, Any] = {"bridge_ms": round(bridge_ms, 3)}
|
|
2186
|
+
if isinstance(tree, dict) and isinstance(tree.get("_timings"), dict):
|
|
2187
|
+
timings["onec"] = tree.get("_timings")
|
|
2188
|
+
for key, value in stages.items():
|
|
2189
|
+
timings[key] = round(value, 3)
|
|
2190
|
+
timings["python_total_ms"] = round(sum(stages.values()), 3)
|
|
2191
|
+
timings["total_observed_ms"] = round(bridge_ms + sum(stages.values()), 3)
|
|
2192
|
+
return timings
|
|
2193
|
+
|
|
2194
|
+
|
|
2195
|
+
def _attach_optional_timings(result: Any, timings: dict[str, Any] | None, include_timings: bool) -> Any:
|
|
2196
|
+
if include_timings and isinstance(result, dict) and timings is not None:
|
|
2197
|
+
result["_timings"] = timings
|
|
2198
|
+
elif not include_timings and isinstance(result, dict):
|
|
2199
|
+
result.pop("_timings", None)
|
|
2200
|
+
return result
|
|
2201
|
+
|
|
2202
|
+
|
|
2162
2203
|
def _outline_ui_tree(node: Any, indent: int = 0) -> str:
|
|
2163
2204
|
if not isinstance(node, dict):
|
|
2164
2205
|
return ""
|
|
@@ -2418,6 +2459,8 @@ def _ui_tree_maybe_resource_response(
|
|
|
2418
2459
|
preview_max_nodes=preview_max_nodes,
|
|
2419
2460
|
preview_format=preview_format,
|
|
2420
2461
|
)
|
|
2462
|
+
if isinstance(inline_response, dict) and isinstance(inline_response.get("_timings"), dict):
|
|
2463
|
+
response["_timings"] = inline_response["_timings"]
|
|
2421
2464
|
response["delivery_requested"] = delivery
|
|
2422
2465
|
response["delivery_reason"] = "explicit_resource" if (delivery or "").strip().lower() == "resource" else "auto_threshold_exceeded"
|
|
2423
2466
|
response["auto_threshold_tokens"] = UI_TREE_RESOURCE_AUTO_THRESHOLD_TOKENS
|
|
@@ -2906,6 +2949,51 @@ def _strip_bridge_timings(result: Any) -> Any:
|
|
|
2906
2949
|
cleaned.pop("_timings", None)
|
|
2907
2950
|
return cleaned
|
|
2908
2951
|
|
|
2952
|
+
|
|
2953
|
+
def _compact_window_summary(value: Any) -> Any:
|
|
2954
|
+
if not isinstance(value, dict):
|
|
2955
|
+
return value
|
|
2956
|
+
keep_keys = (
|
|
2957
|
+
"type", "name", "title", "form_name", "navigation_url",
|
|
2958
|
+
"visible", "available", "read_only", "active_form_title", "active_form_name",
|
|
2959
|
+
"source", "maximized", "method", "ok", "error", "geometry", "candidates",
|
|
2960
|
+
)
|
|
2961
|
+
summary = {key: _copy_compact_object(value[key]) for key in keep_keys if key in value and value.get(key) not in (None, "", [], {})}
|
|
2962
|
+
if "enabled" in value and value.get("enabled") != value.get("available"):
|
|
2963
|
+
summary["enabled"] = value.get("enabled")
|
|
2964
|
+
for key in ("main", "home"):
|
|
2965
|
+
if value.get(key) is True:
|
|
2966
|
+
summary[key] = True
|
|
2967
|
+
return summary
|
|
2968
|
+
|
|
2969
|
+
|
|
2970
|
+
def _compact_start_test_client_result(result: Any, *, include_timings: bool = False) -> Any:
|
|
2971
|
+
if not isinstance(result, dict):
|
|
2972
|
+
return result
|
|
2973
|
+
keep_keys = (
|
|
2974
|
+
"connected", "base_url", "connection_mode", "connection_value",
|
|
2975
|
+
"target_connection_mode", "port", "client_pid", "client_log",
|
|
2976
|
+
"client_stdout_log", "auto_maximize", "auto_maximize_error",
|
|
2977
|
+
)
|
|
2978
|
+
compact = {key: _copy_compact_object(result[key]) for key in keep_keys if key in result and result.get(key) not in (None, "", [], {})}
|
|
2979
|
+
if isinstance(compact.get("auto_maximize"), dict):
|
|
2980
|
+
compact["auto_maximize"] = _compact_window_summary(compact["auto_maximize"])
|
|
2981
|
+
maximized = result.get("maximized")
|
|
2982
|
+
if isinstance(maximized, dict):
|
|
2983
|
+
compact_maximized = {
|
|
2984
|
+
key: _copy_compact_object(maximized[key])
|
|
2985
|
+
for key in ("maximized", "method", "errors")
|
|
2986
|
+
if key in maximized and maximized.get(key) not in (None, "", [], {})
|
|
2987
|
+
}
|
|
2988
|
+
if maximized.get("window") not in (None, "", [], {}):
|
|
2989
|
+
compact_maximized["window"] = _compact_window_summary(maximized.get("window"))
|
|
2990
|
+
compact["maximized"] = compact_maximized
|
|
2991
|
+
elif maximized not in (None, "", [], {}):
|
|
2992
|
+
compact["maximized"] = maximized
|
|
2993
|
+
if include_timings and isinstance(result.get("_timings"), dict):
|
|
2994
|
+
compact["_timings"] = result["_timings"]
|
|
2995
|
+
return compact
|
|
2996
|
+
|
|
2909
2997
|
async def _bridge_call_recorded(
|
|
2910
2998
|
session_id: str,
|
|
2911
2999
|
method: str,
|
|
@@ -4089,8 +4177,18 @@ async def start_session(
|
|
|
4089
4177
|
command_parameter: Annotated[str, "Additional test-client /C value; when extra_args already contains /C, this value is appended with ';'"] = "",
|
|
4090
4178
|
rag_enabled: Annotated[bool, "Enable built-in RAG for this session"] = False,
|
|
4091
4179
|
summary_rag_config: Annotated[str, "Explicit Summary RAG configuration alias/code, e.g. bp, accounting30, Бухгалтерия предприятия. Enables configuration+fresh summary snapshot without live autodetection."] = "",
|
|
4180
|
+
include_timings: Annotated[bool, "Include diagnostic startup timing breakdown in the returned _timings field"] = False,
|
|
4092
4181
|
) -> dict[str, Any]:
|
|
4093
4182
|
"""One-shot session factory: detect version, start infrastructure and connect the 1C test client."""
|
|
4183
|
+
start_monotonic = time.perf_counter()
|
|
4184
|
+
stage_monotonic = start_monotonic
|
|
4185
|
+
timings: dict[str, float] = {}
|
|
4186
|
+
|
|
4187
|
+
def mark_stage(name: str) -> None:
|
|
4188
|
+
nonlocal stage_monotonic
|
|
4189
|
+
now = time.perf_counter()
|
|
4190
|
+
timings[f"{name}_seconds"] = round(now - stage_monotonic, 3)
|
|
4191
|
+
stage_monotonic = now
|
|
4094
4192
|
credential_ref = _resolve_credential_reference(base_url)
|
|
4095
4193
|
credential_account_id = _current_account_id()
|
|
4096
4194
|
saved_credentials_used = False
|
|
@@ -4134,6 +4232,7 @@ async def start_session(
|
|
|
4134
4232
|
actual_version = _platform.platform_version_from_dir(platform_dir)
|
|
4135
4233
|
_platform.require_websocket_support(actual_version)
|
|
4136
4234
|
logging.info("start_session: version=%s platform_dir=%s", actual_version, platform_dir)
|
|
4235
|
+
mark_stage("resolve_credentials_version_platform")
|
|
4137
4236
|
|
|
4138
4237
|
sid = session_id or DEFAULT_SESSION
|
|
4139
4238
|
if sid in _SESSIONS:
|
|
@@ -4171,6 +4270,7 @@ async def start_session(
|
|
|
4171
4270
|
sess.client_xvfb_process = runtime.start_xvfb(client_display)
|
|
4172
4271
|
sess.client_xvfb_pid = sess.client_xvfb_process.pid
|
|
4173
4272
|
await sess.bridge.start()
|
|
4273
|
+
mark_stage("allocate_ports_start_xvfb_bridge")
|
|
4174
4274
|
_SESSIONS[sid] = sess
|
|
4175
4275
|
_persist_sessions()
|
|
4176
4276
|
logging.info("start_session: bridge listening on ws://127.0.0.1:%s", ws_port)
|
|
@@ -4197,6 +4297,7 @@ async def start_session(
|
|
|
4197
4297
|
)
|
|
4198
4298
|
runtime.load_configuration(sess.ibcmd, sess.db_path, cf_path)
|
|
4199
4299
|
_write_cf_marker(sess.db_path, cf_path)
|
|
4300
|
+
mark_stage("prepare_manager_infobase")
|
|
4200
4301
|
except Exception:
|
|
4201
4302
|
await _cleanup_failed_start_session(sess, "infobase preparation failure")
|
|
4202
4303
|
raise
|
|
@@ -4233,6 +4334,7 @@ async def start_session(
|
|
|
4233
4334
|
runtime_state.manager_process = manager_proc
|
|
4234
4335
|
sess.manager_pid = manager_proc.pid
|
|
4235
4336
|
await _wait_for_bridge_connected(sess, timeout=60.0)
|
|
4337
|
+
mark_stage("start_manager_and_wait_bridge")
|
|
4236
4338
|
except Exception as exc:
|
|
4237
4339
|
diagnostic_error = _manager_failure_diagnostics(sess, exc)
|
|
4238
4340
|
await _cleanup_failed_start_session(sess, "manager startup failure")
|
|
@@ -4318,6 +4420,7 @@ async def start_session(
|
|
|
4318
4420
|
except Exception:
|
|
4319
4421
|
await _cleanup_failed_start_session(sess, "demo test-client preparation failure")
|
|
4320
4422
|
raise
|
|
4423
|
+
mark_stage("prepare_demo_client_if_needed")
|
|
4321
4424
|
|
|
4322
4425
|
connect_result: Any = None
|
|
4323
4426
|
connect_base_url = base_url
|
|
@@ -4336,6 +4439,7 @@ async def start_session(
|
|
|
4336
4439
|
extra_args=extra_args, execute=execute, command_parameter=command_parameter,
|
|
4337
4440
|
connection_mode=connect_connection_mode, connection_value=connect_connection_value,
|
|
4338
4441
|
)
|
|
4442
|
+
mark_stage("connect_test_client")
|
|
4339
4443
|
except Exception as exc:
|
|
4340
4444
|
enriched = await _enrich_auth_failure_for_web_base(exc, connect_base_url)
|
|
4341
4445
|
target_mode = _normalize_connection_mode(
|
|
@@ -4349,6 +4453,7 @@ async def start_session(
|
|
|
4349
4453
|
if saved_credentials_used:
|
|
4350
4454
|
_mark_credentials_verified(connect_base_url or connect_connection_value, username, password, credential_account_id)
|
|
4351
4455
|
_auto_maximize_test_client_result(connect_result, sess.client_display or sess.display)
|
|
4456
|
+
mark_stage("auto_maximize_test_client")
|
|
4352
4457
|
|
|
4353
4458
|
if effective_summary_rag_config:
|
|
4354
4459
|
sess.rag_notice = _configure_summary_rag_from_config_alias(sess, effective_summary_rag_config)
|
|
@@ -4388,12 +4493,15 @@ async def start_session(
|
|
|
4388
4493
|
enabled=False,
|
|
4389
4494
|
reason="rag_not_requested_or_no_web_base_url",
|
|
4390
4495
|
)
|
|
4496
|
+
mark_stage("configure_rag")
|
|
4391
4497
|
|
|
4392
4498
|
if sess.idle_timeout_seconds > 0:
|
|
4393
4499
|
asyncio.create_task(_idle_watch_session(sid))
|
|
4394
4500
|
|
|
4395
4501
|
_persist_sessions()
|
|
4396
|
-
|
|
4502
|
+
mark_stage("persist_session")
|
|
4503
|
+
timings["total_seconds"] = round(time.perf_counter() - start_monotonic, 3)
|
|
4504
|
+
response = {
|
|
4397
4505
|
"session_id": sid, "version": actual_version,
|
|
4398
4506
|
"platform_dir": str(platform_dir), "display": display,
|
|
4399
4507
|
"client_display": sess.client_display,
|
|
@@ -4404,8 +4512,11 @@ async def start_session(
|
|
|
4404
4512
|
"server_rag_enabled": _RAG_ENABLED,
|
|
4405
4513
|
"rag_notice": sess.rag_notice,
|
|
4406
4514
|
"idle_timeout_seconds": sess.idle_timeout_seconds,
|
|
4407
|
-
"test_client": connect_result, **pipeline_info,
|
|
4515
|
+
"test_client": _compact_start_test_client_result(connect_result, include_timings=include_timings), **pipeline_info,
|
|
4408
4516
|
}
|
|
4517
|
+
if include_timings:
|
|
4518
|
+
response["_timings"] = timings
|
|
4519
|
+
return response
|
|
4409
4520
|
|
|
4410
4521
|
|
|
4411
4522
|
async def _stop_session_impl(session_id: str = DEFAULT_SESSION, clean_data: bool = False) -> dict[str, Any]:
|
|
@@ -4991,8 +5102,19 @@ async def _connect_test_client_impl(
|
|
|
4991
5102
|
connection_value: str = "",
|
|
4992
5103
|
) -> Any:
|
|
4993
5104
|
"""Launch 1cv8c /TESTCLIENT from Python and attach the test manager to it."""
|
|
5105
|
+
start_monotonic = time.perf_counter()
|
|
5106
|
+
stage_monotonic = start_monotonic
|
|
5107
|
+
timings: dict[str, float] = {}
|
|
5108
|
+
|
|
5109
|
+
def mark_stage(name: str) -> None:
|
|
5110
|
+
nonlocal stage_monotonic
|
|
5111
|
+
now = time.perf_counter()
|
|
5112
|
+
timings[f"{name}_seconds"] = round(now - stage_monotonic, 3)
|
|
5113
|
+
stage_monotonic = now
|
|
5114
|
+
|
|
4994
5115
|
await _wait_for_bridge_connected(sess, timeout=60.0)
|
|
4995
5116
|
manager_info = await _verify_manager_protocol(sess)
|
|
5117
|
+
mark_stage("verify_manager_protocol")
|
|
4996
5118
|
r_base = _platform.normalize_infobase_url(base_url or sess.base_url)
|
|
4997
5119
|
r_value = connection_value or r_base
|
|
4998
5120
|
mode = _normalize_connection_mode(connection_mode, r_value, r_base)
|
|
@@ -5121,6 +5243,7 @@ async def _connect_test_client_impl(
|
|
|
5121
5243
|
log_name=client_stdout_log,
|
|
5122
5244
|
)
|
|
5123
5245
|
sess.test_client_pid = sess.test_client_process.pid
|
|
5246
|
+
mark_stage("spawn_test_client_process")
|
|
5124
5247
|
params = {"base_url": r_base, "username": r_user, "password": r_pass,
|
|
5125
5248
|
"port": r_port, "host": host, "client_pid": sess.test_client_process.pid,
|
|
5126
5249
|
"client_log": str(client_out_log), "client_stdout_log": str(sess.client_log_dir / client_stdout_log),
|
|
@@ -5132,6 +5255,7 @@ async def _connect_test_client_impl(
|
|
|
5132
5255
|
try:
|
|
5133
5256
|
wait_timeout = float(os.getenv("ONEC_MCP_TEST_CLIENT_READY_TIMEOUT", "55"))
|
|
5134
5257
|
await _wait_for_test_client_ready(sess, host, r_port, timeout=wait_timeout)
|
|
5258
|
+
mark_stage("wait_test_client_port")
|
|
5135
5259
|
if sess.test_client_process is not None:
|
|
5136
5260
|
monitor_task = asyncio.create_task(_wait_for_test_client_process_exit(sess.test_client_process))
|
|
5137
5261
|
attach_task = asyncio.create_task(sess.bridge.call("attach_test_client", params))
|
|
@@ -5159,6 +5283,10 @@ async def _connect_test_client_impl(
|
|
|
5159
5283
|
for pending_task in pending:
|
|
5160
5284
|
pending_task.cancel()
|
|
5161
5285
|
result = await attach_task
|
|
5286
|
+
mark_stage("attach_test_client")
|
|
5287
|
+
if isinstance(result, dict):
|
|
5288
|
+
timings["total_seconds"] = round(time.perf_counter() - start_monotonic, 3)
|
|
5289
|
+
result["_timings"] = timings
|
|
5162
5290
|
except Exception as exc:
|
|
5163
5291
|
runtime.kill_process(sess.test_client_process, "test-client")
|
|
5164
5292
|
sess.test_client_process = None
|
|
@@ -5646,6 +5774,7 @@ async def ui_tree(
|
|
|
5646
5774
|
rag_snapshot: Annotated[str, "Optional RAG snapshot name/id used for type enrichment"] = "",
|
|
5647
5775
|
delivery: Annotated[str, "Delivery mode: auto (default) returns small results inline and saves responses above token threshold as resource; inline always returns the selected JSON/outline/yaml; resource always saves full JSON and returns resource_uri + summary + preview"] = "auto",
|
|
5648
5776
|
preview_max_nodes: Annotated[int, "For delivery=auto/resource, number of top nodes/matches to include in the small inline preview when a resource is returned"] = 40,
|
|
5777
|
+
include_timings: Annotated[bool, "Include diagnostic timing breakdown in the returned _timings field"] = False,
|
|
5649
5778
|
*,
|
|
5650
5779
|
session_id: Annotated[str, "Session id"] = DEFAULT_SESSION,
|
|
5651
5780
|
) -> Any:
|
|
@@ -5679,6 +5808,11 @@ async def ui_tree(
|
|
|
5679
5808
|
`ui_tree_resource_children`, or `ui_tree_diff` instead of loading the whole
|
|
5680
5809
|
tree into the agent context.
|
|
5681
5810
|
"""
|
|
5811
|
+
stage_timings: dict[str, float] = {}
|
|
5812
|
+
|
|
5813
|
+
def timed_stage(name: str, started: float) -> None:
|
|
5814
|
+
stage_timings[name] = stage_timings.get(name, 0.0) + ((time.monotonic() - started) * 1000)
|
|
5815
|
+
|
|
5682
5816
|
delivery_key = (delivery or "auto").strip().lower()
|
|
5683
5817
|
if delivery_key not in {"auto", "inline", "resource"}:
|
|
5684
5818
|
raise ValueError(f"Unsupported ui_tree delivery: {delivery!r}. Expected auto, inline or resource.")
|
|
@@ -5687,6 +5821,7 @@ async def ui_tree(
|
|
|
5687
5821
|
group_mode_key = _validate_ui_tree_choice("group_mode", group_mode, _UI_TREE_GROUP_MODES)
|
|
5688
5822
|
fmt = _validate_ui_tree_choice("format", format, _UI_TREE_FORMATS)
|
|
5689
5823
|
field_names = _ui_tree_field_names(fields, profile_key)
|
|
5824
|
+
state_options = _ui_tree_state_options(field_names, include_hidden=include_hidden)
|
|
5690
5825
|
if profile_key in {"full", "diagnostic", "data"}:
|
|
5691
5826
|
profile_include_command_panels = True
|
|
5692
5827
|
elif profile_key == "command_panels":
|
|
@@ -5714,6 +5849,8 @@ async def ui_tree(
|
|
|
5714
5849
|
"include_hidden": include_hidden,
|
|
5715
5850
|
"include_data": include_data,
|
|
5716
5851
|
"include_command_panels": include_command_panels_effective,
|
|
5852
|
+
"include_timings": include_timings,
|
|
5853
|
+
**state_options,
|
|
5717
5854
|
}
|
|
5718
5855
|
if parent_name:
|
|
5719
5856
|
bridge_params["parent_name"] = parent_name
|
|
@@ -5726,15 +5863,20 @@ async def ui_tree(
|
|
|
5726
5863
|
bridge_ms = (time.monotonic() - bridge_start) * 1000
|
|
5727
5864
|
transform_start = time.monotonic()
|
|
5728
5865
|
if parent_name and isinstance(tree, dict) and tree.get("reason") != "parent_not_found" and tree.get("root_parent_name") != parent_name:
|
|
5866
|
+
parent_lookup_start = time.monotonic()
|
|
5729
5867
|
parent_node = _find_ui_node_by_name(tree, parent_name)
|
|
5730
5868
|
if parent_node is None:
|
|
5731
5869
|
tree = {"found": False, "parent_name": parent_name, "reason": "parent_not_found"}
|
|
5732
5870
|
else:
|
|
5733
5871
|
tree = parent_node
|
|
5734
5872
|
tree["root_parent_name"] = parent_name
|
|
5873
|
+
timed_stage("python_parent_lookup_ms", parent_lookup_start)
|
|
5874
|
+
summary_start = time.monotonic()
|
|
5735
5875
|
if isinstance(tree, dict):
|
|
5736
5876
|
tree["tree_summary"] = _summarize_ui_tree(tree, include_hidden=include_hidden)
|
|
5877
|
+
timed_stage("python_summary_ms", summary_start)
|
|
5737
5878
|
if include_rag_types:
|
|
5879
|
+
rag_start = time.monotonic()
|
|
5738
5880
|
sess = _session(session_id)
|
|
5739
5881
|
if _RAG_ENABLED and sess.rag_enabled:
|
|
5740
5882
|
tree = _enrich_ui_tree_with_rag_types(tree, snapshot=rag_snapshot or sess.rag_snapshot or None)
|
|
@@ -5742,14 +5884,18 @@ async def ui_tree(
|
|
|
5742
5884
|
tree["rag_diagnostic"] = _rag_diagnostic(session_id, rag_snapshot)
|
|
5743
5885
|
elif isinstance(tree, dict):
|
|
5744
5886
|
tree["rag_diagnostic"] = _rag_diagnostic(session_id, rag_snapshot)
|
|
5887
|
+
timed_stage("python_rag_enrich_ms", rag_start)
|
|
5745
5888
|
|
|
5746
5889
|
if parent_name and isinstance(tree, dict) and tree.get("found") is False and tree.get("reason") == "parent_not_found":
|
|
5747
5890
|
tree["tree_summary"] = _summarize_ui_tree(tree, include_hidden=include_hidden)
|
|
5748
5891
|
python_transform_ms = (time.monotonic() - transform_start) * 1000
|
|
5892
|
+
stage_timings["python_transform_ms"] = python_transform_ms
|
|
5893
|
+
ui_timings = _build_ui_tree_timings(tree, bridge_ms=bridge_ms, stages=stage_timings)
|
|
5749
5894
|
if fmt == "outline":
|
|
5750
5895
|
response = {"format": "outline", "text": "", "tree_summary": tree.get("tree_summary"), "profile": profile_key, "parent_name": parent_name, "found": False, "reason": "parent_not_found"}
|
|
5751
5896
|
response = _apply_ui_fields(response, field_names)
|
|
5752
5897
|
response = _attach_ui_tree_metrics(response, _ui_tree_metrics(tree, bridge_ms=bridge_ms, python_transform_ms=python_transform_ms, result=response))
|
|
5898
|
+
response = _attach_optional_timings(response, ui_timings, include_timings)
|
|
5753
5899
|
return _ui_tree_maybe_resource_response(
|
|
5754
5900
|
response,
|
|
5755
5901
|
inline_response=response,
|
|
@@ -5763,6 +5909,7 @@ async def ui_tree(
|
|
|
5763
5909
|
if fmt == "yaml":
|
|
5764
5910
|
response = {"format": "yaml", "yaml": _to_simple_yaml(tree), "tree_summary": tree.get("tree_summary"), "profile": profile_key, "parent_name": parent_name}
|
|
5765
5911
|
response = _attach_ui_tree_metrics(response, _ui_tree_metrics(tree, bridge_ms=bridge_ms, python_transform_ms=python_transform_ms, result=response))
|
|
5912
|
+
response = _attach_optional_timings(response, ui_timings, include_timings)
|
|
5766
5913
|
return _ui_tree_maybe_resource_response(
|
|
5767
5914
|
tree,
|
|
5768
5915
|
inline_response=response,
|
|
@@ -5775,6 +5922,7 @@ async def ui_tree(
|
|
|
5775
5922
|
)
|
|
5776
5923
|
tree = _apply_ui_fields(tree, field_names)
|
|
5777
5924
|
tree = _attach_ui_tree_metrics(tree, _ui_tree_metrics(tree, bridge_ms=bridge_ms, python_transform_ms=python_transform_ms, result=tree))
|
|
5925
|
+
tree = _attach_optional_timings(tree, ui_timings, include_timings)
|
|
5778
5926
|
return _ui_tree_maybe_resource_response(
|
|
5779
5927
|
tree,
|
|
5780
5928
|
inline_response=tree,
|
|
@@ -5788,6 +5936,7 @@ async def ui_tree(
|
|
|
5788
5936
|
|
|
5789
5937
|
summary = tree.get("tree_summary") if isinstance(tree, dict) else None
|
|
5790
5938
|
|
|
5939
|
+
result_build_start = time.monotonic()
|
|
5791
5940
|
if filtered:
|
|
5792
5941
|
if isinstance(tree, dict) and isinstance(tree.get("objects"), list):
|
|
5793
5942
|
objects = [obj for obj in tree["objects"] if isinstance(obj, dict)]
|
|
@@ -5846,8 +5995,13 @@ async def ui_tree(
|
|
|
5846
5995
|
compact_tree["rag_diagnostic"] = tree["rag_diagnostic"]
|
|
5847
5996
|
result = compact_tree
|
|
5848
5997
|
|
|
5998
|
+
timed_stage("python_result_build_ms", result_build_start)
|
|
5999
|
+
field_filter_start = time.monotonic()
|
|
5849
6000
|
result = _apply_ui_fields(result, field_names)
|
|
6001
|
+
timed_stage("python_field_filter_ms", field_filter_start)
|
|
5850
6002
|
python_transform_ms = (time.monotonic() - transform_start) * 1000
|
|
6003
|
+
stage_timings["python_transform_ms"] = python_transform_ms
|
|
6004
|
+
ui_timings = _build_ui_tree_timings(tree, bridge_ms=bridge_ms, stages=stage_timings)
|
|
5851
6005
|
if fmt == "outline":
|
|
5852
6006
|
format_start = time.monotonic()
|
|
5853
6007
|
text = _outline_ui_nodes(result.get("objects", [])) if isinstance(result, dict) and "objects" in result else _outline_ui_tree(result)
|
|
@@ -5856,6 +6010,7 @@ async def ui_tree(
|
|
|
5856
6010
|
response["parent_name"] = parent_name
|
|
5857
6011
|
metrics = _ui_tree_metrics(tree, bridge_ms=bridge_ms, python_transform_ms=python_transform_ms, format_ms=(time.monotonic() - format_start) * 1000, result=response)
|
|
5858
6012
|
response = _attach_ui_tree_metrics(response, metrics)
|
|
6013
|
+
response = _attach_optional_timings(response, ui_timings, include_timings)
|
|
5859
6014
|
return _ui_tree_maybe_resource_response(
|
|
5860
6015
|
result,
|
|
5861
6016
|
inline_response=response,
|
|
@@ -5873,6 +6028,7 @@ async def ui_tree(
|
|
|
5873
6028
|
response["parent_name"] = parent_name
|
|
5874
6029
|
metrics = _ui_tree_metrics(tree, bridge_ms=bridge_ms, python_transform_ms=python_transform_ms, format_ms=(time.monotonic() - format_start) * 1000, result=response)
|
|
5875
6030
|
response = _attach_ui_tree_metrics(response, metrics)
|
|
6031
|
+
response = _attach_optional_timings(response, ui_timings, include_timings)
|
|
5876
6032
|
return _ui_tree_maybe_resource_response(
|
|
5877
6033
|
result,
|
|
5878
6034
|
inline_response=response,
|
|
@@ -5885,6 +6041,7 @@ async def ui_tree(
|
|
|
5885
6041
|
)
|
|
5886
6042
|
metrics = _ui_tree_metrics(tree, bridge_ms=bridge_ms, python_transform_ms=python_transform_ms, result=result)
|
|
5887
6043
|
result = _attach_ui_tree_metrics(result, metrics)
|
|
6044
|
+
result = _attach_optional_timings(result, ui_timings, include_timings)
|
|
5888
6045
|
return _ui_tree_maybe_resource_response(
|
|
5889
6046
|
result,
|
|
5890
6047
|
inline_response=result,
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{answer42-0.4.64 → answer42-0.4.65}/src/cf/DataProcessors/MCPTestManager/Ext/ObjectModule.bsl
RENAMED
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
{answer42-0.4.64 → answer42-0.4.65}/src/mcp_1c/assets/skills/answer42-universal-report/SKILL.md
RENAMED
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|