(user_id: str, updates: Dict[str, Any])
| 1905 | "keywords": list(must_read.get("keywords") or []), |
| 1906 | } |
| 1907 | } |
| 1908 | |
| 1909 | |
| 1910 | def update_must_read(user_id: str, item_type: str, value: str, action: str) -> Dict[str, Any]: |
| 1911 | normalized_type = (item_type or "").strip().lower() |
| 1912 | normalized_action = (action or "").strip().lower() |
| 1913 | if normalized_type not in {"author", "institution", "keyword"}: |
| 1914 | raise ValueError("item_type must be author, institution, or keyword") |
| 1915 | if normalized_action not in {"add", "remove"}: |
| 1916 | raise ValueError("action must be add or remove") |
| 1917 | cleaned_value = str(value or "").strip() |
| 1918 | if not cleaned_value: |
| 1919 | raise ValueError("value is required") |
| 1920 | |
| 1921 | profile = db_ops.get_profile(user_id) |
| 1922 | if not profile: |
| 1923 | raise ValueError(f"Profile not found: {user_id}") |
| 1924 | |
| 1925 | if normalized_action == "add": |
| 1926 | result = must_read_agent.add_must_read(profile, normalized_type, cleaned_value) |
| 1927 | else: |
| 1928 | result = must_read_agent.remove_must_read(profile, normalized_type, cleaned_value) |
| 1929 | |
| 1930 | if result.get("success"): |
| 1931 | db_ops.update_profile(user_id, profile) |
| 1932 | db_ops.log_behavior( |
| 1933 | user_id=user_id, |
| 1934 | push_id="desktop_gui", |
| 1935 | paper_id=None, |
| 1936 | action=f"{normalized_action}_{normalized_type}", |
| 1937 | action_type="must_read_update", |
| 1938 | category="desktop_gui", |
no test coverage detected