diff --git a/dev-api.py b/dev-api.py index 8746ef0..f11259c 100644 --- a/dev-api.py +++ b/dev-api.py @@ -4541,8 +4541,13 @@ You must ALWAYS respond with valid JSON in this exact format: Only include fields in extracted_fields that you are confident about from the conversation. Do not include fields the user hasn't mentioned. Infer complete=true when all required fields (name, email, career_summary) are gathered or when user explicitly says done.""" +class HistoryMessage(BaseModel): + role: str # "user" or "assistant" + content: str + + class WizardInterviewRequest(BaseModel): - history: list[dict] # [{"role": "user"|"assistant", "content": "..."}] + history: list[HistoryMessage] = [] profile_so_far: dict = {} @@ -4574,8 +4579,8 @@ def wizard_ai_interview(request: WizardInterviewRequest): # Build conversation prompt from history conversation_lines = [] for msg in request.history: - role = msg.get("role", "user") - content = msg.get("content", "") + role = msg.role + content = msg.content.replace("\n", " ").replace("\r", "") if role == "user": conversation_lines.append(f"User: {content}") else: @@ -4600,7 +4605,7 @@ def wizard_ai_interview(request: WizardInterviewRequest): from scripts.llm_router import LLMRouter response_text = LLMRouter().complete(prompt, system=_AI_WIZARD_SYSTEM_PROMPT) except Exception as exc: - raise HTTPException(500, detail={"error": "llm_error", "message": str(exc)}) + raise HTTPException(503, detail={"error": "llm_error", "message": str(exc)}) try: parsed = json.loads(response_text) @@ -4617,15 +4622,14 @@ def wizard_ai_interview(request: WizardInterviewRequest): def wizard_ai_finalize(request: WizardFinalizeRequest): """Merge AI-collected wizard fields into user.yaml. Only allowed fields are written.""" yaml_path = _user_yaml_path() - current = load_user_profile(yaml_path) - - merged_keys = [] - for key, value in request.profile.items(): - if key in _WIZARD_ALLOWED_FIELDS: - current[key] = value - merged_keys.append(key) - - save_user_profile(yaml_path, current) + try: + current = load_user_profile(yaml_path) + updates = {k: v for k, v in request.profile.items() if k in _WIZARD_ALLOWED_FIELDS} + merged = {**current, **updates} + save_user_profile(yaml_path, merged) + except Exception as exc: + raise HTTPException(500, detail={"error": "write_error", "message": str(exc)}) + merged_keys = list(updates.keys()) return {"saved": True, "fields": merged_keys} diff --git a/tests/test_wizard_ai.py b/tests/test_wizard_ai.py index 74c4850..cd8ebef 100644 --- a/tests/test_wizard_ai.py +++ b/tests/test_wizard_ai.py @@ -226,8 +226,8 @@ class TestWizardAIInterviewLLM: assert "Alex Rivera" in prompt assert "alex@example.com" in prompt - def test_llm_error_returns_500(self, client): - """If LLM raises, the endpoint returns 500.""" + def test_llm_error_returns_503(self, client): + """If LLM raises, the endpoint returns 503.""" with patch("dev_api._get_effective_tier", return_value="paid"): with patch("app.wizard.tiers.has_configured_llm", return_value=True): with patch("scripts.llm_router.LLMRouter") as mock_cls: @@ -236,7 +236,7 @@ class TestWizardAIInterviewLLM: "/api/wizard/ai/interview", json={"history": [{"role": "user", "content": "hi"}]}, ) - assert r.status_code == 500 + assert r.status_code == 503 # ── POST /api/wizard/ai/finalize ──────────────────────────────────────────────