test_memory_bootstrap.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from data_modules.config import DataModulesConfig
  4. from data_modules.index_manager import EntityMeta, RelationshipMeta, StateChangeMeta, IndexManager
  5. from data_modules.memory.bootstrap import bootstrap_from_index
  6. from data_modules.memory.store import ScratchpadManager
  7. def _cfg(tmp_path):
  8. cfg = DataModulesConfig.from_project_root(tmp_path)
  9. cfg.ensure_dirs()
  10. return cfg
  11. def test_bootstrap_from_index_includes_state_changes_and_open_loops(tmp_path):
  12. cfg = _cfg(tmp_path)
  13. idx = IndexManager(cfg)
  14. idx.upsert_entity(
  15. EntityMeta(
  16. id="xiaoyan",
  17. type="角色",
  18. canonical_name="萧炎",
  19. current={"realm": "斗者"},
  20. first_appearance=1,
  21. last_appearance=2,
  22. )
  23. )
  24. idx.record_state_change(
  25. StateChangeMeta(
  26. entity_id="xiaoyan",
  27. field="realm",
  28. old_value="斗者",
  29. new_value="斗师",
  30. reason="突破",
  31. chapter=3,
  32. )
  33. )
  34. idx.record_state_change(
  35. StateChangeMeta(
  36. entity_id="xiaoyan",
  37. field="realm",
  38. old_value="斗师",
  39. new_value="大斗师",
  40. reason="再突破",
  41. chapter=8,
  42. )
  43. )
  44. idx.upsert_relationship(
  45. RelationshipMeta(
  46. from_entity="xiaoyan",
  47. to_entity="yaolao",
  48. type="师徒",
  49. description="授艺",
  50. chapter=2,
  51. )
  52. )
  53. summaries_dir = cfg.webnovel_dir / "summaries"
  54. summaries_dir.mkdir(parents=True, exist_ok=True)
  55. (summaries_dir / "ch0008.md").write_text(
  56. "## 剧情摘要\n内容\n\n## 伏笔\n- 三年之约\n- 神秘玉佩的来历\n",
  57. encoding="utf-8",
  58. )
  59. result = bootstrap_from_index(cfg)
  60. assert result["items_created"] > 0
  61. assert result["categories"].get("character_state", 0) >= 2
  62. assert result["categories"].get("open_loop", 0) >= 2
  63. store = ScratchpadManager(cfg)
  64. active_realm = store.query(category="character_state", subject="xiaoyan", status="active")
  65. assert any(item.field == "realm" and item.value == "大斗师" for item in active_realm)
  66. outdated_realm = store.query(category="character_state", subject="xiaoyan", status="outdated")
  67. assert any(item.field == "realm" and item.value == "斗师" for item in outdated_realm)
  68. loops = store.query(category="open_loop", status="active")
  69. assert any("三年之约" in item.value for item in loops)