80 lines
3.2 KiB
Python
80 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],
|
|
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")
|
|
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")
|
|
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"
|