diff --git a/web/api.py b/web/api.py index 4c245f2..5ff0214 100644 --- a/web/api.py +++ b/web/api.py @@ -1228,7 +1228,15 @@ def patch_environment(project_id: str, env_id: int, body: EnvironmentPatch): if body.is_installed is not None: fields["is_installed"] = int(body.is_installed) - updated = models.update_environment(conn, env_id, **fields) + try: + updated = models.update_environment(conn, env_id, **fields) + except Exception as e: + conn.close() + if "UNIQUE constraint" in str(e): + raise HTTPException(409, f"Environment name already exists for this project") + if "KIN_SECRET_KEY" in str(e): + raise HTTPException(503, "Server misconfiguration: KIN_SECRET_KEY is not set. Contact admin.") + raise HTTPException(500, str(e)) scan_task_id = None if body.is_installed is True and not was_installed: diff --git a/web/frontend/src/views/ChatView.vue b/web/frontend/src/views/ChatView.vue index 1ef0613..0d2b151 100644 --- a/web/frontend/src/views/ChatView.vue +++ b/web/frontend/src/views/ChatView.vue @@ -12,6 +12,7 @@ const input = ref('') const sending = ref(false) const loading = ref(true) const error = ref('') +const consecutiveErrors = ref(0) const projectName = ref('') const messagesEl = ref(null) @@ -37,8 +38,17 @@ function checkAndPoll() { try { const updated = await api.chatHistory(props.projectId) messages.value = updated + consecutiveErrors.value = 0 + error.value = '' if (!hasRunningTasks(updated)) stopPoll() - } catch {} + } catch (e: any) { + consecutiveErrors.value++ + console.warn(`[polling] ошибка #${consecutiveErrors.value}:`, e) + if (consecutiveErrors.value >= 3) { + error.value = 'Сервер недоступен. Проверьте подключение.' + stopPoll() + } + } }, 3000) } @@ -46,6 +56,7 @@ async function load() { stopPoll() loading.value = true error.value = '' + consecutiveErrors.value = 0 try { const [msgs, project] = await Promise.all([ api.chatHistory(props.projectId),