from __future__ import annotations from copy import deepcopy from dataclasses import dataclass from typing import Any from .fsm import FSMError, assistant_turn, component from .models import ComposerMode, Stage from .services import ExtractedExperience @dataclass(slots=True) class RewriteConfirmationTransition: stage: Stage profile: dict[str, Any] turn: dict[str, Any] lifecycle: str = "submitted" create_draft: bool = False resume_content: dict[str, Any] | None = None def prepare_rewrite_confirmation( profile: dict[str, Any], extraction: ExtractedExperience, rewritten: dict[str, Any], ) -> tuple[dict[str, Any], dict[str, Any]]: updated = deepcopy(profile) updated["pending_experience"] = extraction.to_dict() updated["pending_resume_content"] = rewritten summary = _confirmation_summary(extraction, rewritten) turn = assistant_turn( "我已把这段事实整理成正式简历语言,请确认后再写入简历。", [ component( "ExperienceConfirmCard", title="确认 AI 改写", description="只在内容准确时加入简历;需要调整可返回继续描述。", value=summary, confirmation_kind="rewrite", ) ], mode=ComposerMode.UI_ONLY, ) return updated, turn def process_rewrite_confirmation( profile: dict[str, Any], action: str ) -> RewriteConfirmationTransition: updated = deepcopy(profile) normalized = action.strip().lower() if normalized in {"edit", "revise", "edit_anchor"}: updated.pop("pending_experience", None) updated.pop("pending_resume_content", None) return RewriteConfirmationTransition( Stage.RESUME_ENRICHING, updated, assistant_turn( "这版暂不写入。请补充或纠正事实,我会重新整理。", [], mode=ComposerMode.CHAT, ), ) if normalized not in {"confirm", "confirm_anchor", "confirm_rewrite"}: raise FSMError("invalid_action", "Confirm or revise the proposed rewrite") experience = updated.pop("pending_experience", None) resume_content = updated.pop("pending_resume_content", None) if not isinstance(experience, dict) or not isinstance(resume_content, dict): raise FSMError("rewrite_not_pending", "No proposed rewrite is waiting for confirmation") updated.setdefault("experiences", []).append(experience) updated["ai_rewrites_confirmed"] = True return RewriteConfirmationTransition( Stage.CONTENT_READY, updated, assistant_turn( "已确认并写入简历。", [ component( "ContentReadyCard", formal_content_ready=True, actions=["continue_enriching", "finish_enrichment"], ) ], mode=ComposerMode.HYBRID, ), lifecycle="confirmed", resume_content=resume_content, ) def _confirmation_summary( extraction: ExtractedExperience, rewritten: dict[str, Any] ) -> dict[str, Any]: bullets: list[str] = [] section = next( ( item for item in rewritten.get("sections", []) if item.get("kind") == "additional_experience" ), None, ) if section and section.get("items"): bullets = section["items"][-1].get("resume_bullets") or [] return { "title": extraction.title, "organization": extraction.organization, "role": extraction.role, "highlights": bullets or extraction.highlights, }