(user_id: str, item_type: str, value: str, action: str)
| 1814 | def list_must_read(user_id: str) -> Dict[str, Any]: |
| 1815 | profile = db_ops.get_profile(user_id) or {} |
| 1816 | must_read = profile.get("must_read") or {"authors": [], "institutions": [], "keywords": []} |
| 1817 | return { |
| 1818 | "must_read": { |
| 1819 | "authors": list(must_read.get("authors") or []), |
| 1820 | "institutions": list(must_read.get("institutions") or []), |
| 1821 | "keywords": list(must_read.get("keywords") or []), |
| 1822 | } |
| 1823 | } |
| 1824 | |
| 1825 | |
| 1826 | def update_must_read(user_id: str, item_type: str, value: str, action: str) -> Dict[str, Any]: |
| 1827 | normalized_type = (item_type or "").strip().lower() |
| 1828 | normalized_action = (action or "").strip().lower() |
| 1829 | if normalized_type not in {"author", "institution", "keyword"}: |
| 1830 | raise ValueError("item_type must be author, institution, or keyword") |
| 1831 | if normalized_action not in {"add", "remove"}: |
| 1832 | raise ValueError("action must be add or remove") |
| 1833 | cleaned_value = str(value or "").strip() |
| 1834 | if not cleaned_value: |
| 1835 | raise ValueError("value is required") |
| 1836 | |
| 1837 | profile = db_ops.get_profile(user_id) |
| 1838 | if not profile: |
| 1839 | raise ValueError(f"Profile not found: {user_id}") |
| 1840 | |
| 1841 | if normalized_action == "add": |
| 1842 | result = must_read_agent.add_must_read(profile, normalized_type, cleaned_value) |
| 1843 | else: |
| 1844 | result = must_read_agent.remove_must_read(profile, normalized_type, cleaned_value) |
| 1845 | |
| 1846 | if result.get("success"): |
| 1847 | db_ops.update_profile(user_id, profile) |
| 1848 | db_ops.log_behavior( |
| 1849 | user_id=user_id, |
| 1850 | push_id="desktop_gui", |
| 1851 | paper_id=None, |
| 1852 | action=f"{normalized_action}_{normalized_type}", |
| 1853 | action_type="must_read_update", |
| 1854 | category="desktop_gui", |
| 1855 | metadata={"value": cleaned_value, "item_type": normalized_type}, |
nothing calls this directly
no test coverage detected