diff --git a/DOCS/sonnet-response-v1.1.11.md b/DOCS/sonnet-response-v1.1.11.md new file mode 100644 index 0000000..a933a14 --- /dev/null +++ b/DOCS/sonnet-response-v1.1.11.md @@ -0,0 +1,42 @@ +# Sonnet 4.6 — Code Review v1.1.11 + +Дата: 2026-07-29 +Модель: Claude Sonnet 4.6 + +## Ответ + +### 🔴 Критично: NameError в api_test.py + +Строки 159, 178, 180 вызывают: +- `get_params_with_current_values(...)` +- `_normalize_value_list(...)` + +Оба символа определены в `operations/get_params.py`, но **не импортированы** в `routes/api_test.py`. + +Цепочка падения: +1. `startCreate()` → `fetch('/api/params/{opId}')` +2. Сервер: `_normalize_value_list(p.get("valueList"))` → `NameError` +3. `except` → `{"error": "name '_normalize_value_list' is not defined"}`, HTTP 500 +4. JS: `data.params` = undefined → fallback к `data` = `{"error": "..."}` +5. `params.map(...)` → `TypeError: params.map is not a function` +6. Нет `.catch()` → промис падает молча + +Также сломаны MODIFY-запросы (строка 159 — `get_params_with_current_values`). + +**Фикс:** одна строка импорта. + +### 🟡 Вторичные баги в JS + +1. `showParams()` — нет `.catch()` на fetch-цепочке → ошибки скрыты +2. `data.params||data` без `Array.isArray()` → TypeError при ошибке API + +### ⚪ Косметика + +`create-btn-area` после `params-area` в DOM — неудобно, но не ломает. + +## Действия + +- [x] Добавить импорт в api_test.py +- [x] Исправить клиентский код +- [x] Добавить `.catch()` в showParams +- [x] Проверить Array.isArray перед .map() diff --git a/site/app.py b/site/app.py index dd13f7e..b98992b 100644 --- a/site/app.py +++ b/site/app.py @@ -18,7 +18,7 @@ from routes.api import bp as api_bp from routes.api_test import bp as api_test_bp # Версия — меняется при КАЖДОМ изменении кода. Показывается в топбаре UI. -VERSION = "1.1.11" +VERSION = "1.1.12" app = Flask(__name__, template_folder="templates", static_folder="static") app.config["NUBES_API_ENDPOINT"] = os.getenv("NUBES_API_ENDPOINT", "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc") diff --git a/site/routes/api_test.py b/site/routes/api_test.py index 736b49f..2800547 100644 --- a/site/routes/api_test.py +++ b/site/routes/api_test.py @@ -32,6 +32,7 @@ from api.http_client import HttpClient, detect_endpoint, stand_name from api.auth import get_token, get_client, get_client_id, get_stand, get_token_info from operations.get_services import get_services, get_service_detail from operations.get_instances import get_instances +from operations.get_params import get_params_with_current_values, _normalize_value_list from operations.tracker import add as tracker_add, list_all as tracker_list from operations.tracker import remove as tracker_remove diff --git a/site/static/app.js b/site/static/app.js index 999a7fd..3582205 100644 --- a/site/static/app.js +++ b/site/static/app.js @@ -137,7 +137,9 @@ function showParams(opId,opName){ const isCreate=opName==='create'; const qs=isCreate?'' : `?instanceUid=${selectedInst}`; fetch('/api/params/'+opId+qs).then(r=>r.json()).then(async data=>{ + if(data.error){document.getElementById('params-form').innerHTML=`Ошибка: ${_esc(data.error)}`;return;} const params=data.params||data; + if(!Array.isArray(params)){document.getElementById('params-form').innerHTML=`Неверный формат параметров`;return;} // Заранее загрузить все инстансы для refSvcId-параметров let allInst=[]; const needRefs=params.some(p=>p.refSvcId); @@ -237,6 +239,8 @@ function showParams(opId,opName){ for(const pk in nested) pp[pk]=JSON.stringify(nested[pk]); executeOp(pp); }; + }).catch(e=>{ + document.getElementById('params-form').innerHTML=`Ошибка загрузки: ${_esc(e.message)}`; }); }