- Introduced `card_language` attribute in ProjectRecord and Workspace classes to handle multiple languages for project cards. - Updated project creation and renaming methods to accept and store the card language. - Enhanced ZoteroReader to read and return attachment metadata, including language-specific summaries and claims. - Modified LLM client to generate card content based on the specified language, supporting both English and Chinese. - Updated tests to cover new functionality, ensuring correct handling of multilingual card generation and retrieval. - Adjusted UI tests to verify the presence of language selection options and proper rendering of multilingual content.
81 lines
3.2 KiB
Python
81 lines
3.2 KiB
Python
from pathlib import Path
|
|
|
|
from zotero_kb.cards import CardBuilder
|
|
from zotero_kb.config import AppConfig
|
|
from zotero_kb.projects import ProjectService
|
|
from zotero_kb.workspace import Workspace
|
|
from zotero_kb.writing import WritingService
|
|
from zotero_kb.zotero_reader import ZoteroItemRecord
|
|
|
|
|
|
class FakeLlmClient:
|
|
def generate_card(self, source_bundle: dict[str, object]) -> dict[str, object]:
|
|
title = str(source_bundle["title"])
|
|
if "Scoped" in title:
|
|
summary = "Project-scoped retrieval improves drafting support."
|
|
claims = ["Project scoping improves citation precision."]
|
|
hints = ["Use for scoped retrieval arguments."]
|
|
else:
|
|
summary = "Broad retrieval baseline for comparison."
|
|
claims = ["Baseline retrieval may drift."]
|
|
hints = ["Use as a contrast only."]
|
|
return {
|
|
"summary": summary,
|
|
"core_claims": claims,
|
|
"methods": ["Method details."],
|
|
"evidence": ["Evidence details."],
|
|
"quotable_passages": claims,
|
|
"writing_hints": hints,
|
|
"keywords": ["retrieval", "writing"],
|
|
}
|
|
|
|
|
|
def _build_item(item_key: str, title: str) -> ZoteroItemRecord:
|
|
return ZoteroItemRecord(
|
|
item_key=item_key,
|
|
title=title,
|
|
creators=["Alice Smith"],
|
|
year="2024",
|
|
item_type="journalArticle",
|
|
abstract=title,
|
|
tags=["retrieval"],
|
|
collection_paths=[["Theory", "Drafting"]],
|
|
notes=[title],
|
|
attachments=[],
|
|
attachment_texts=[title],
|
|
)
|
|
|
|
|
|
def test_recommend_citations_only_reads_project_items(tmp_path: Path) -> None:
|
|
config = AppConfig(workspace_dir=tmp_path / "workspace", zotero_data_dir=tmp_path / "zotero")
|
|
workspace = Workspace(config)
|
|
workspace.create_project("thesis-ch2", "Thesis Chapter 2", "openai", "gpt-5-mini", "en")
|
|
builder = CardBuilder(config.workspace_dir, FakeLlmClient())
|
|
builder.build_or_update(_build_item("PAPER0001", "Scoped Retrieval for Drafting"))
|
|
builder.build_or_update(_build_item("PAPER0002", "Broad Retrieval Baseline"))
|
|
|
|
project_service = ProjectService(config.workspace_dir)
|
|
project_service.add_items("thesis-ch2", ["PAPER0001"])
|
|
|
|
service = WritingService(config.workspace_dir)
|
|
result = service.recommend_citations("thesis-ch2", "support scoped retrieval during drafting")
|
|
|
|
assert [item["item_key"] for item in result["results"]] == ["PAPER0001"]
|
|
|
|
|
|
def test_generate_plan_returns_structured_sections(tmp_path: Path) -> None:
|
|
config = AppConfig(workspace_dir=tmp_path / "workspace", zotero_data_dir=tmp_path / "zotero")
|
|
workspace = Workspace(config)
|
|
workspace.create_project("thesis-ch2", "Thesis Chapter 2", "openai", "gpt-5-mini", "en")
|
|
builder = CardBuilder(config.workspace_dir, FakeLlmClient())
|
|
builder.build_or_update(_build_item("PAPER0001", "Scoped Retrieval for Drafting"))
|
|
|
|
project_service = ProjectService(config.workspace_dir)
|
|
project_service.add_items("thesis-ch2", ["PAPER0001"])
|
|
|
|
service = WritingService(config.workspace_dir)
|
|
plan = service.generate_plan("thesis-ch2", "argue that project scoping improves drafting")
|
|
|
|
assert "sections" in plan
|
|
assert plan["sections"][0]["citations"][0]["item_key"] == "PAPER0001"
|