diff --git a/backend/app.py b/backend/app.py index a98df6d..98e47d1 100644 --- a/backend/app.py +++ b/backend/app.py @@ -3962,7 +3962,7 @@ async def _chat_background(mid: str, sid: str, msg: ChatMsg, user: dict, genai_c log.info(f"RAG: filtering by tenancy '{rag_tenancy}'") rag_context = "" - adb_cfgs = _get_active_adb_configs(user["id"]) + adb_cfgs = _get_active_adb_configs(user["id"]) if agent_type != "terraform" else [] if adb_cfgs: all_documents = [] for adb_cfg in adb_cfgs: @@ -5176,8 +5176,8 @@ async def _terraform_exec(wid: str, action: str, user: dict): ) log.warning(f"Workspace {wid}: missing variable 'region' — blocking plan") with db() as c: - c.execute("UPDATE terraform_workspaces SET status='failed', error=?, updated_at=datetime('now') WHERE id=?", - (error_msg, wid)) + c.execute("UPDATE terraform_workspaces SET status='failed', plan_output=?, error=?, updated_at=datetime('now') WHERE id=?", + (error_msg, error_msg, wid)) return region_value = 'var.region' diff --git a/frontend/index.html b/frontend/index.html index 02d1151..5f93530 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1401,12 +1401,13 @@ function _tfBadge(st){ function rTfActions(){ if(S.tfRunning)return''; const st=S.tfStatus;let btns=''; - if(S.tfCode&&(st==='draft'||st==='failed'||st==='destroyed'))btns+=``; + const canPlan=S.tfCode&&['draft','failed','destroyed','planning','applying','destroying'].includes(st); + const canReplan=S.tfCode&&['planned','failed','applied'].includes(st); + if(canPlan&&!canReplan)btns+=``; + if(canReplan)btns+=``; if(st==='failed'&&S.tfPlanOut&&S.tfFiles.length&&S.tfModel)btns+=``; if(st==='failed'&&(S.tfApplyOut||S.tfHadApply))btns+=''; - if(st==='planned'||st==='failed')btns+=``; if(st==='planned')btns+=''; - if(st==='applied')btns+=``; if(st==='applied'||st==='planned')btns+=''; return btns; } @@ -1786,13 +1787,14 @@ async function tfPollExec(){ S.tfPlanOut=r.plan_output||S.tfPlanOut; S.tfApplyOut=r.apply_output||S.tfApplyOut; S.tfDestroyOut=r.destroy_output||S.tfDestroyOut; + S.tfError=r.error||''; S.tfStatus=r.status; const done=!['planning','applying','destroying'].includes(r.status); if(done){S.tfRunning=false;if(r.status==='destroyed')S.tfHadApply=false;} // Update only the terminal body without full re-render const t=document.getElementById('tfTermOut'); if(t){ - const content=S.tfDestroyOut||S.tfApplyOut||S.tfPlanOut||''; + const content=S.tfDestroyOut||S.tfApplyOut||S.tfPlanOut||(done&&S.tfError?'ERROR: '+S.tfError:'')||''; t.innerHTML=content?escHtml(content):'Aguardando execução...'; t.scrollTop=t.scrollHeight; }