contextweave 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (545) hide show
  1. contextweave-0.2.0/.github/workflows/release.yml +396 -0
  2. contextweave-0.2.0/.gitignore +59 -0
  3. contextweave-0.2.0/AGENTS.md +58 -0
  4. contextweave-0.2.0/LICENSE +674 -0
  5. contextweave-0.2.0/Makefile +146 -0
  6. contextweave-0.2.0/PKG-INFO +185 -0
  7. contextweave-0.2.0/README.md +136 -0
  8. contextweave-0.2.0/README_ZH.md +136 -0
  9. contextweave-0.2.0/cat-ui.spec +292 -0
  10. contextweave-0.2.0/context_aware_translation/AGENTS.md +134 -0
  11. contextweave-0.2.0/context_aware_translation/__init__.py +114 -0
  12. contextweave-0.2.0/context_aware_translation/adapters/__init__.py +1 -0
  13. contextweave-0.2.0/context_aware_translation/adapters/files/__init__.py +3 -0
  14. contextweave-0.2.0/context_aware_translation/adapters/files/glossary_io.py +203 -0
  15. contextweave-0.2.0/context_aware_translation/adapters/qt/__init__.py +1 -0
  16. contextweave-0.2.0/context_aware_translation/adapters/qt/application_event_bridge.py +78 -0
  17. contextweave-0.2.0/context_aware_translation/adapters/qt/task_engine.py +392 -0
  18. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/__init__.py +1 -0
  19. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/base_worker.py +61 -0
  20. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/batch_task_overlap_guard.py +57 -0
  21. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/batch_translation_task_worker.py +228 -0
  22. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/chunk_retranslation_task_worker.py +136 -0
  23. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/export_worker.py +75 -0
  24. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/glossary_export_task_worker.py +119 -0
  25. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/glossary_extraction_task_worker.py +102 -0
  26. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/glossary_review_task_worker.py +98 -0
  27. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/glossary_translation_task_worker.py +97 -0
  28. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/image_reembedding_task_worker.py +114 -0
  29. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/import_worker.py +49 -0
  30. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/ocr_task_worker.py +149 -0
  31. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/operation_tracker.py +94 -0
  32. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/translate_and_export_task_worker.py +394 -0
  33. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/translation_manga_task_worker.py +133 -0
  34. contextweave-0.2.0/context_aware_translation/adapters/qt/workers/translation_text_task_worker.py +158 -0
  35. contextweave-0.2.0/context_aware_translation/app_identity.py +33 -0
  36. contextweave-0.2.0/context_aware_translation/application/__init__.py +7 -0
  37. contextweave-0.2.0/context_aware_translation/application/composition.py +104 -0
  38. contextweave-0.2.0/context_aware_translation/application/contracts/__init__.py +57 -0
  39. contextweave-0.2.0/context_aware_translation/application/contracts/app_setup.py +188 -0
  40. contextweave-0.2.0/context_aware_translation/application/contracts/common.py +193 -0
  41. contextweave-0.2.0/context_aware_translation/application/contracts/document.py +235 -0
  42. contextweave-0.2.0/context_aware_translation/application/contracts/project_setup.py +19 -0
  43. contextweave-0.2.0/context_aware_translation/application/contracts/projects.py +36 -0
  44. contextweave-0.2.0/context_aware_translation/application/contracts/queue.py +35 -0
  45. contextweave-0.2.0/context_aware_translation/application/contracts/terms.py +148 -0
  46. contextweave-0.2.0/context_aware_translation/application/contracts/work.py +111 -0
  47. contextweave-0.2.0/context_aware_translation/application/errors.py +35 -0
  48. contextweave-0.2.0/context_aware_translation/application/events.py +146 -0
  49. contextweave-0.2.0/context_aware_translation/application/runtime.py +1302 -0
  50. contextweave-0.2.0/context_aware_translation/application/services/__init__.py +19 -0
  51. contextweave-0.2.0/context_aware_translation/application/services/_export_support.py +281 -0
  52. contextweave-0.2.0/context_aware_translation/application/services/app_setup.py +532 -0
  53. contextweave-0.2.0/context_aware_translation/application/services/document.py +2309 -0
  54. contextweave-0.2.0/context_aware_translation/application/services/project_setup.py +161 -0
  55. contextweave-0.2.0/context_aware_translation/application/services/projects.py +152 -0
  56. contextweave-0.2.0/context_aware_translation/application/services/queue.py +118 -0
  57. contextweave-0.2.0/context_aware_translation/application/services/terms.py +582 -0
  58. contextweave-0.2.0/context_aware_translation/application/services/work.py +525 -0
  59. contextweave-0.2.0/context_aware_translation/cli/__init__.py +1 -0
  60. contextweave-0.2.0/context_aware_translation/cli/config_file.py +337 -0
  61. contextweave-0.2.0/context_aware_translation/cli/main.py +362 -0
  62. contextweave-0.2.0/context_aware_translation/cli/output.py +91 -0
  63. contextweave-0.2.0/context_aware_translation/cli/runtime.py +26 -0
  64. contextweave-0.2.0/context_aware_translation/cli/wait.py +51 -0
  65. contextweave-0.2.0/context_aware_translation/config.py +1354 -0
  66. contextweave-0.2.0/context_aware_translation/core/AGENTS.md +133 -0
  67. contextweave-0.2.0/context_aware_translation/core/__init__.py +1 -0
  68. contextweave-0.2.0/context_aware_translation/core/cancellation.py +17 -0
  69. contextweave-0.2.0/context_aware_translation/core/context_extractor.py +68 -0
  70. contextweave-0.2.0/context_aware_translation/core/context_manager.py +2257 -0
  71. contextweave-0.2.0/context_aware_translation/core/manga_document_handler.py +253 -0
  72. contextweave-0.2.0/context_aware_translation/core/models.py +211 -0
  73. contextweave-0.2.0/context_aware_translation/core/progress.py +42 -0
  74. contextweave-0.2.0/context_aware_translation/core/term_memory.py +14 -0
  75. contextweave-0.2.0/context_aware_translation/core/term_memory_builder.py +246 -0
  76. contextweave-0.2.0/context_aware_translation/core/translation_strategies.py +202 -0
  77. contextweave-0.2.0/context_aware_translation/documents/AGENTS.md +139 -0
  78. contextweave-0.2.0/context_aware_translation/documents/__init__.py +0 -0
  79. contextweave-0.2.0/context_aware_translation/documents/base.py +377 -0
  80. contextweave-0.2.0/context_aware_translation/documents/content/AGENTS.md +162 -0
  81. contextweave-0.2.0/context_aware_translation/documents/content/__init__.py +0 -0
  82. contextweave-0.2.0/context_aware_translation/documents/content/ocr_content.py +235 -0
  83. contextweave-0.2.0/context_aware_translation/documents/content/ocr_items.py +940 -0
  84. contextweave-0.2.0/context_aware_translation/documents/epub.py +2669 -0
  85. contextweave-0.2.0/context_aware_translation/documents/epub_container.py +23 -0
  86. contextweave-0.2.0/context_aware_translation/documents/epub_support/AGENTS.md +183 -0
  87. contextweave-0.2.0/context_aware_translation/documents/epub_support/__init__.py +1 -0
  88. contextweave-0.2.0/context_aware_translation/documents/epub_support/container_model.py +75 -0
  89. contextweave-0.2.0/context_aware_translation/documents/epub_support/container_patch.py +43 -0
  90. contextweave-0.2.0/context_aware_translation/documents/epub_support/container_reader.py +579 -0
  91. contextweave-0.2.0/context_aware_translation/documents/epub_support/container_shared.py +109 -0
  92. contextweave-0.2.0/context_aware_translation/documents/epub_support/container_writer.py +413 -0
  93. contextweave-0.2.0/context_aware_translation/documents/epub_support/inline_markers.py +285 -0
  94. contextweave-0.2.0/context_aware_translation/documents/epub_support/nav_ops.py +384 -0
  95. contextweave-0.2.0/context_aware_translation/documents/epub_support/slot_lines.py +61 -0
  96. contextweave-0.2.0/context_aware_translation/documents/epub_support/xml_utils.py +38 -0
  97. contextweave-0.2.0/context_aware_translation/documents/epub_xhtml_utils.py +1457 -0
  98. contextweave-0.2.0/context_aware_translation/documents/manga.py +695 -0
  99. contextweave-0.2.0/context_aware_translation/documents/manga_alignment.py +88 -0
  100. contextweave-0.2.0/context_aware_translation/documents/manga_reembed_planner.py +476 -0
  101. contextweave-0.2.0/context_aware_translation/documents/pdf.py +757 -0
  102. contextweave-0.2.0/context_aware_translation/documents/scanned_book.py +408 -0
  103. contextweave-0.2.0/context_aware_translation/documents/subtitle.py +334 -0
  104. contextweave-0.2.0/context_aware_translation/documents/text.py +265 -0
  105. contextweave-0.2.0/context_aware_translation/llm/AGENTS.md +144 -0
  106. contextweave-0.2.0/context_aware_translation/llm/__init__.py +1 -0
  107. contextweave-0.2.0/context_aware_translation/llm/batch_jobs/AGENTS.md +148 -0
  108. contextweave-0.2.0/context_aware_translation/llm/batch_jobs/__init__.py +21 -0
  109. contextweave-0.2.0/context_aware_translation/llm/batch_jobs/base.py +101 -0
  110. contextweave-0.2.0/context_aware_translation/llm/batch_jobs/gemini_gateway.py +668 -0
  111. contextweave-0.2.0/context_aware_translation/llm/client.py +430 -0
  112. contextweave-0.2.0/context_aware_translation/llm/epub_ocr.py +131 -0
  113. contextweave-0.2.0/context_aware_translation/llm/extractor.py +341 -0
  114. contextweave-0.2.0/context_aware_translation/llm/glossary_translator.py +254 -0
  115. contextweave-0.2.0/context_aware_translation/llm/image_backend_base.py +94 -0
  116. contextweave-0.2.0/context_aware_translation/llm/image_backends/AGENTS.md +199 -0
  117. contextweave-0.2.0/context_aware_translation/llm/image_backends/__init__.py +1 -0
  118. contextweave-0.2.0/context_aware_translation/llm/image_backends/gemini_backend.py +169 -0
  119. contextweave-0.2.0/context_aware_translation/llm/image_backends/openai_backend.py +139 -0
  120. contextweave-0.2.0/context_aware_translation/llm/image_backends/qwen_backend.py +172 -0
  121. contextweave-0.2.0/context_aware_translation/llm/image_generator.py +109 -0
  122. contextweave-0.2.0/context_aware_translation/llm/language_detector.py +162 -0
  123. contextweave-0.2.0/context_aware_translation/llm/manga_ocr.py +302 -0
  124. contextweave-0.2.0/context_aware_translation/llm/manga_translator.py +127 -0
  125. contextweave-0.2.0/context_aware_translation/llm/ocr.py +205 -0
  126. contextweave-0.2.0/context_aware_translation/llm/reviewer.py +173 -0
  127. contextweave-0.2.0/context_aware_translation/llm/session_trace.py +38 -0
  128. contextweave-0.2.0/context_aware_translation/llm/summarizor.py +352 -0
  129. contextweave-0.2.0/context_aware_translation/llm/token_tracker.py +170 -0
  130. contextweave-0.2.0/context_aware_translation/llm/translation_strategies.py +280 -0
  131. contextweave-0.2.0/context_aware_translation/llm/translator.py +771 -0
  132. contextweave-0.2.0/context_aware_translation/resources/opencc/config/hk2s.json +33 -0
  133. contextweave-0.2.0/context_aware_translation/resources/opencc/config/jp2s.json +33 -0
  134. contextweave-0.2.0/context_aware_translation/resources/opencc/config/s2hk.json +27 -0
  135. contextweave-0.2.0/context_aware_translation/resources/opencc/config/s2t.json +22 -0
  136. contextweave-0.2.0/context_aware_translation/resources/opencc/config/s2tw.json +27 -0
  137. contextweave-0.2.0/context_aware_translation/resources/opencc/config/s2twp.json +32 -0
  138. contextweave-0.2.0/context_aware_translation/resources/opencc/config/t2hk.json +16 -0
  139. contextweave-0.2.0/context_aware_translation/resources/opencc/config/t2s.json +22 -0
  140. contextweave-0.2.0/context_aware_translation/resources/opencc/config/t2tw.json +16 -0
  141. contextweave-0.2.0/context_aware_translation/resources/opencc/config/tw2s.json +33 -0
  142. contextweave-0.2.0/context_aware_translation/resources/opencc/config/tw2sp.json +36 -0
  143. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/HKVariants.txt +63 -0
  144. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/HKVariantsPhrases.txt +17 -0
  145. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/HKVariantsRev.txt +70 -0
  146. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/HKVariantsRevPhrases.txt +156 -0
  147. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/JPVariants.txt +367 -0
  148. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/JPVariantsRev.txt +367 -0
  149. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/STCharacters.txt +3980 -0
  150. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/STPhrases.txt +49051 -0
  151. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/TSCharacters.txt +4113 -0
  152. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/TSPhrases.txt +277 -0
  153. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/TWPhrases.txt +509 -0
  154. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/TWPhrasesRev.txt +518 -0
  155. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/TWVariants.txt +39 -0
  156. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/TWVariantsRev.txt +39 -0
  157. contextweave-0.2.0/context_aware_translation/resources/opencc/dictionary/TWVariantsRevPhrases.txt +68 -0
  158. contextweave-0.2.0/context_aware_translation/resources/tokenizers/deepseek-v3/special_tokens_map.json +23 -0
  159. contextweave-0.2.0/context_aware_translation/resources/tokenizers/deepseek-v3/tokenizer.json +646418 -0
  160. contextweave-0.2.0/context_aware_translation/resources/tokenizers/deepseek-v3/tokenizer_config.json +6562 -0
  161. contextweave-0.2.0/context_aware_translation/storage/AGENTS.md +192 -0
  162. contextweave-0.2.0/context_aware_translation/storage/__init__.py +3 -0
  163. contextweave-0.2.0/context_aware_translation/storage/library/__init__.py +3 -0
  164. contextweave-0.2.0/context_aware_translation/storage/library/book_manager.py +670 -0
  165. contextweave-0.2.0/context_aware_translation/storage/models/__init__.py +3 -0
  166. contextweave-0.2.0/context_aware_translation/storage/models/book.py +85 -0
  167. contextweave-0.2.0/context_aware_translation/storage/models/config_profile.py +67 -0
  168. contextweave-0.2.0/context_aware_translation/storage/models/endpoint_profile.py +97 -0
  169. contextweave-0.2.0/context_aware_translation/storage/repositories/__init__.py +80 -0
  170. contextweave-0.2.0/context_aware_translation/storage/repositories/document_repository.py +325 -0
  171. contextweave-0.2.0/context_aware_translation/storage/repositories/llm_batch_store.py +165 -0
  172. contextweave-0.2.0/context_aware_translation/storage/repositories/task_store.py +295 -0
  173. contextweave-0.2.0/context_aware_translation/storage/repositories/term_repository.py +431 -0
  174. contextweave-0.2.0/context_aware_translation/storage/repositories/translation_batch_task_store.py +315 -0
  175. contextweave-0.2.0/context_aware_translation/storage/schema/__init__.py +17 -0
  176. contextweave-0.2.0/context_aware_translation/storage/schema/book_db.py +1958 -0
  177. contextweave-0.2.0/context_aware_translation/storage/schema/registry_db.py +949 -0
  178. contextweave-0.2.0/context_aware_translation/storage/sqlite_locking.py +17 -0
  179. contextweave-0.2.0/context_aware_translation/ui/AGENTS.md +115 -0
  180. contextweave-0.2.0/context_aware_translation/ui/__init__.py +0 -0
  181. contextweave-0.2.0/context_aware_translation/ui/chrome_sizing.py +21 -0
  182. contextweave-0.2.0/context_aware_translation/ui/constants.py +104 -0
  183. contextweave-0.2.0/context_aware_translation/ui/features/app_settings_pane.py +585 -0
  184. contextweave-0.2.0/context_aware_translation/ui/features/app_setup_view.py +921 -0
  185. contextweave-0.2.0/context_aware_translation/ui/features/document_images_view.py +725 -0
  186. contextweave-0.2.0/context_aware_translation/ui/features/document_ocr_tab.py +1038 -0
  187. contextweave-0.2.0/context_aware_translation/ui/features/document_translation_view.py +1401 -0
  188. contextweave-0.2.0/context_aware_translation/ui/features/document_workspace_view.py +806 -0
  189. contextweave-0.2.0/context_aware_translation/ui/features/library_view.py +401 -0
  190. contextweave-0.2.0/context_aware_translation/ui/features/project_settings_pane.py +448 -0
  191. contextweave-0.2.0/context_aware_translation/ui/features/queue_drawer_view.py +472 -0
  192. contextweave-0.2.0/context_aware_translation/ui/features/terms_table_widget.py +599 -0
  193. contextweave-0.2.0/context_aware_translation/ui/features/terms_view.py +1149 -0
  194. contextweave-0.2.0/context_aware_translation/ui/features/work_view.py +697 -0
  195. contextweave-0.2.0/context_aware_translation/ui/features/workflow_profile_editor.py +1312 -0
  196. contextweave-0.2.0/context_aware_translation/ui/i18n.py +954 -0
  197. contextweave-0.2.0/context_aware_translation/ui/json_utils.py +23 -0
  198. contextweave-0.2.0/context_aware_translation/ui/main.py +140 -0
  199. contextweave-0.2.0/context_aware_translation/ui/main_window.py +585 -0
  200. contextweave-0.2.0/context_aware_translation/ui/qml/BootstrapProbe.qml +10 -0
  201. contextweave-0.2.0/context_aware_translation/ui/qml/app/AppShellChrome.qml +161 -0
  202. contextweave-0.2.0/context_aware_translation/ui/qml/dialogs/app_settings/AppSettingsDialogChrome.qml +77 -0
  203. contextweave-0.2.0/context_aware_translation/ui/qml/dialogs/app_settings/AppSettingsPane.qml +131 -0
  204. contextweave-0.2.0/context_aware_translation/ui/qml/dialogs/project_settings/ProjectSettingsDialogChrome.qml +77 -0
  205. contextweave-0.2.0/context_aware_translation/ui/qml/dialogs/project_settings/ProjectSettingsPane.qml +205 -0
  206. contextweave-0.2.0/context_aware_translation/ui/qml/document/DocumentShellChrome.qml +205 -0
  207. contextweave-0.2.0/context_aware_translation/ui/qml/document/export/DocumentExportPaneChrome.qml +89 -0
  208. contextweave-0.2.0/context_aware_translation/ui/qml/document/images/DocumentImagesPaneChrome.qml +457 -0
  209. contextweave-0.2.0/context_aware_translation/ui/qml/document/ocr/DocumentOCRPaneChrome.qml +416 -0
  210. contextweave-0.2.0/context_aware_translation/ui/qml/document/translation/DocumentTranslationPaneChrome.qml +136 -0
  211. contextweave-0.2.0/context_aware_translation/ui/qml/project/ProjectShellChrome.qml +175 -0
  212. contextweave-0.2.0/context_aware_translation/ui/qml/project/terms/TermsPaneChrome.qml +143 -0
  213. contextweave-0.2.0/context_aware_translation/ui/qml/project/work_home/WorkHomeChrome.qml +331 -0
  214. contextweave-0.2.0/context_aware_translation/ui/qml/queue/QueueShellChrome.qml +70 -0
  215. contextweave-0.2.0/context_aware_translation/ui/qml_resources.py +57 -0
  216. contextweave-0.2.0/context_aware_translation/ui/resources/__init__.py +0 -0
  217. contextweave-0.2.0/context_aware_translation/ui/resources/styles.qss +283 -0
  218. contextweave-0.2.0/context_aware_translation/ui/shell_hosts/__init__.py +11 -0
  219. contextweave-0.2.0/context_aware_translation/ui/shell_hosts/app_settings_dialog_host.py +55 -0
  220. contextweave-0.2.0/context_aware_translation/ui/shell_hosts/app_shell_host.py +77 -0
  221. contextweave-0.2.0/context_aware_translation/ui/shell_hosts/document_shell_host.py +190 -0
  222. contextweave-0.2.0/context_aware_translation/ui/shell_hosts/hybrid.py +156 -0
  223. contextweave-0.2.0/context_aware_translation/ui/shell_hosts/project_settings_dialog_host.py +55 -0
  224. contextweave-0.2.0/context_aware_translation/ui/shell_hosts/project_shell_host.py +144 -0
  225. contextweave-0.2.0/context_aware_translation/ui/shell_hosts/queue_shell_host.py +60 -0
  226. contextweave-0.2.0/context_aware_translation/ui/sleep_inhibitor.py +135 -0
  227. contextweave-0.2.0/context_aware_translation/ui/startup.py +78 -0
  228. contextweave-0.2.0/context_aware_translation/ui/tips.py +16 -0
  229. contextweave-0.2.0/context_aware_translation/ui/translations/zh_CN.qm +0 -0
  230. contextweave-0.2.0/context_aware_translation/ui/translations/zh_CN.ts +4351 -0
  231. contextweave-0.2.0/context_aware_translation/ui/viewmodels/__init__.py +30 -0
  232. contextweave-0.2.0/context_aware_translation/ui/viewmodels/app_settings_dialog.py +53 -0
  233. contextweave-0.2.0/context_aware_translation/ui/viewmodels/app_settings_pane.py +63 -0
  234. contextweave-0.2.0/context_aware_translation/ui/viewmodels/app_shell.py +87 -0
  235. contextweave-0.2.0/context_aware_translation/ui/viewmodels/base.py +114 -0
  236. contextweave-0.2.0/context_aware_translation/ui/viewmodels/document_export_pane.py +65 -0
  237. contextweave-0.2.0/context_aware_translation/ui/viewmodels/document_images_pane.py +338 -0
  238. contextweave-0.2.0/context_aware_translation/ui/viewmodels/document_ocr_pane.py +261 -0
  239. contextweave-0.2.0/context_aware_translation/ui/viewmodels/document_shell.py +122 -0
  240. contextweave-0.2.0/context_aware_translation/ui/viewmodels/document_translation_pane.py +113 -0
  241. contextweave-0.2.0/context_aware_translation/ui/viewmodels/project_settings_dialog.py +51 -0
  242. contextweave-0.2.0/context_aware_translation/ui/viewmodels/project_settings_pane.py +194 -0
  243. contextweave-0.2.0/context_aware_translation/ui/viewmodels/project_shell.py +98 -0
  244. contextweave-0.2.0/context_aware_translation/ui/viewmodels/queue_shell.py +51 -0
  245. contextweave-0.2.0/context_aware_translation/ui/viewmodels/router.py +202 -0
  246. contextweave-0.2.0/context_aware_translation/ui/viewmodels/terms_pane.py +230 -0
  247. contextweave-0.2.0/context_aware_translation/ui/viewmodels/work_home.py +250 -0
  248. contextweave-0.2.0/context_aware_translation/ui/widgets/AGENTS.md +90 -0
  249. contextweave-0.2.0/context_aware_translation/ui/widgets/hybrid_controls.py +153 -0
  250. contextweave-0.2.0/context_aware_translation/ui/widgets/image_viewer.py +343 -0
  251. contextweave-0.2.0/context_aware_translation/ui/widgets/progress_widget.py +136 -0
  252. contextweave-0.2.0/context_aware_translation/ui/widgets/table_support.py +59 -0
  253. contextweave-0.2.0/context_aware_translation/ui/window_controllers.py +310 -0
  254. contextweave-0.2.0/context_aware_translation/utils/AGENTS.md +157 -0
  255. contextweave-0.2.0/context_aware_translation/utils/__init__.py +3 -0
  256. contextweave-0.2.0/context_aware_translation/utils/chunking.py +147 -0
  257. contextweave-0.2.0/context_aware_translation/utils/cjk_normalize.py +141 -0
  258. contextweave-0.2.0/context_aware_translation/utils/compression_marker.py +18 -0
  259. contextweave-0.2.0/context_aware_translation/utils/file_utils.py +34 -0
  260. contextweave-0.2.0/context_aware_translation/utils/hard_wrap.py +87 -0
  261. contextweave-0.2.0/context_aware_translation/utils/hashing.py +20 -0
  262. contextweave-0.2.0/context_aware_translation/utils/image_utils.py +79 -0
  263. contextweave-0.2.0/context_aware_translation/utils/llm_json_cleaner.py +91 -0
  264. contextweave-0.2.0/context_aware_translation/utils/markdown_escape.py +195 -0
  265. contextweave-0.2.0/context_aware_translation/utils/pandoc_export.py +52 -0
  266. contextweave-0.2.0/context_aware_translation/utils/semantic_chunker.py +92 -0
  267. contextweave-0.2.0/context_aware_translation/utils/string_similarity.py +33 -0
  268. contextweave-0.2.0/context_aware_translation/utils/symbol_check.py +29 -0
  269. contextweave-0.2.0/context_aware_translation/workflow/AGENTS.md +171 -0
  270. contextweave-0.2.0/context_aware_translation/workflow/__init__.py +1 -0
  271. contextweave-0.2.0/context_aware_translation/workflow/bootstrap.py +123 -0
  272. contextweave-0.2.0/context_aware_translation/workflow/image_fetcher.py +53 -0
  273. contextweave-0.2.0/context_aware_translation/workflow/ops/__init__.py +1 -0
  274. contextweave-0.2.0/context_aware_translation/workflow/ops/bootstrap_ops.py +202 -0
  275. contextweave-0.2.0/context_aware_translation/workflow/ops/export_ops.py +234 -0
  276. contextweave-0.2.0/context_aware_translation/workflow/ops/glossary_ops.py +116 -0
  277. contextweave-0.2.0/context_aware_translation/workflow/ops/import_ops.py +108 -0
  278. contextweave-0.2.0/context_aware_translation/workflow/ops/import_support.py +209 -0
  279. contextweave-0.2.0/context_aware_translation/workflow/ops/ocr_ops.py +118 -0
  280. contextweave-0.2.0/context_aware_translation/workflow/ops/translation_ops.py +156 -0
  281. contextweave-0.2.0/context_aware_translation/workflow/runtime.py +27 -0
  282. contextweave-0.2.0/context_aware_translation/workflow/session.py +69 -0
  283. contextweave-0.2.0/context_aware_translation/workflow/task_runtime.py +89 -0
  284. contextweave-0.2.0/context_aware_translation/workflow/tasks/AGENTS.md +176 -0
  285. contextweave-0.2.0/context_aware_translation/workflow/tasks/__init__.py +0 -0
  286. contextweave-0.2.0/context_aware_translation/workflow/tasks/claims.py +83 -0
  287. contextweave-0.2.0/context_aware_translation/workflow/tasks/engine_core.py +740 -0
  288. contextweave-0.2.0/context_aware_translation/workflow/tasks/exceptions.py +13 -0
  289. contextweave-0.2.0/context_aware_translation/workflow/tasks/execution/AGENTS.md +126 -0
  290. contextweave-0.2.0/context_aware_translation/workflow/tasks/execution/__init__.py +0 -0
  291. contextweave-0.2.0/context_aware_translation/workflow/tasks/execution/batch_translation_executor.py +819 -0
  292. contextweave-0.2.0/context_aware_translation/workflow/tasks/execution/batch_translation_ops.py +1190 -0
  293. contextweave-0.2.0/context_aware_translation/workflow/tasks/glossary_preflight.py +138 -0
  294. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/AGENTS.md +245 -0
  295. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/__init__.py +0 -0
  296. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/base.py +42 -0
  297. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/batch_translation.py +221 -0
  298. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/chunk_retranslation.py +194 -0
  299. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/glossary_export.py +182 -0
  300. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/glossary_extraction.py +255 -0
  301. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/glossary_review.py +196 -0
  302. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/glossary_translation.py +177 -0
  303. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/image_reembedding.py +371 -0
  304. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/ocr.py +333 -0
  305. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/translate_and_export.py +183 -0
  306. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/translation_manga.py +252 -0
  307. contextweave-0.2.0/context_aware_translation/workflow/tasks/handlers/translation_text.py +207 -0
  308. contextweave-0.2.0/context_aware_translation/workflow/tasks/models.py +70 -0
  309. contextweave-0.2.0/context_aware_translation/workflow/tasks/translate_and_export_support.py +410 -0
  310. contextweave-0.2.0/context_aware_translation/workflow/tasks/worker_deps.py +28 -0
  311. contextweave-0.2.0/data/cat-library/registry.db +0 -0
  312. contextweave-0.2.0/data/cat-library/task_store.db +0 -0
  313. contextweave-0.2.0/demo/The Count of Monte Cristo.epub +0 -0
  314. contextweave-0.2.0/demo//345/237/272/347/235/243/345/261/261/344/274/257/347/210/265.epub +0 -0
  315. contextweave-0.2.0/docs/.nojekyll +0 -0
  316. contextweave-0.2.0/docs/examples/contextweave-cli.yaml +162 -0
  317. contextweave-0.2.0/docs/index.html +1170 -0
  318. contextweave-0.2.0/docs/project-terms-manual-entry-ux.md +198 -0
  319. contextweave-0.2.0/docs/screenshots/CN/API/351/205/215/347/275/256.png +0 -0
  320. contextweave-0.2.0/docs/screenshots/CN/latest_new_project_dialog.png +0 -0
  321. contextweave-0.2.0/docs/screenshots/CN/latest_project_work_overview.png +0 -0
  322. contextweave-0.2.0/docs/screenshots/CN/latest_projects_overview.png +0 -0
  323. contextweave-0.2.0/docs/screenshots/CN/latest_setup_wizard_provider_selection.png +0 -0
  324. contextweave-0.2.0/docs/screenshots/CN/latest_setup_wizard_workflow_profile_review.png +0 -0
  325. contextweave-0.2.0/docs/screenshots/CN/latest_terms_overview.png +0 -0
  326. contextweave-0.2.0/docs/screenshots/CN//345/257/274/345/205/245.png +0 -0
  327. contextweave-0.2.0/docs/screenshots/CN//345/257/274/345/207/272.png +0 -0
  328. contextweave-0.2.0/docs/screenshots/CN//346/226/260/351/241/271/347/233/256.png +0 -0
  329. contextweave-0.2.0/docs/screenshots/CN//346/234/257/350/257/255.png +0 -0
  330. contextweave-0.2.0/docs/screenshots/CN//347/277/273/350/257/221.png +0 -0
  331. contextweave-0.2.0/docs/screenshots/CN//350/256/276/347/275/256.png +0 -0
  332. contextweave-0.2.0/docs/screenshots/CN//350/256/276/347/275/256/345/220/221/345/257/274.png +0 -0
  333. contextweave-0.2.0/docs/screenshots/CN//350/256/276/347/275/256/347/273/223/346/235/237.png +0 -0
  334. contextweave-0.2.0/docs/screenshots/EN/APISetup.png +0 -0
  335. contextweave-0.2.0/docs/screenshots/EN/Export.png +0 -0
  336. contextweave-0.2.0/docs/screenshots/EN/Import.png +0 -0
  337. contextweave-0.2.0/docs/screenshots/EN/InitialSetup.png +0 -0
  338. contextweave-0.2.0/docs/screenshots/EN/Language.png +0 -0
  339. contextweave-0.2.0/docs/screenshots/EN/NewProject.png +0 -0
  340. contextweave-0.2.0/docs/screenshots/EN/Terms.png +0 -0
  341. contextweave-0.2.0/docs/screenshots/EN/Translate.png +0 -0
  342. contextweave-0.2.0/docs/screenshots/EN/TranslateAndExport.png +0 -0
  343. contextweave-0.2.0/docs/screenshots/EN/Wizard.png +0 -0
  344. contextweave-0.2.0/docs/screenshots/EN/latest_new_project_dialog.png +0 -0
  345. contextweave-0.2.0/docs/screenshots/EN/latest_project_work_overview.png +0 -0
  346. contextweave-0.2.0/docs/screenshots/EN/latest_projects_overview.png +0 -0
  347. contextweave-0.2.0/docs/screenshots/EN/latest_setup_wizard_provider_selection.png +0 -0
  348. contextweave-0.2.0/docs/screenshots/EN/latest_setup_wizard_workflow_profile_review.png +0 -0
  349. contextweave-0.2.0/docs/screenshots/EN/latest_terms_overview.png +0 -0
  350. contextweave-0.2.0/docs/styles.css +427 -0
  351. contextweave-0.2.0/installer/AGENTS.md +39 -0
  352. contextweave-0.2.0/installer/macos/AGENTS.md +19 -0
  353. contextweave-0.2.0/installer/macos/entitlements.plist +15 -0
  354. contextweave-0.2.0/installer/windows/AGENTS.md +16 -0
  355. contextweave-0.2.0/pyproject.toml +170 -0
  356. contextweave-0.2.0/scripts/AGENTS.md +41 -0
  357. contextweave-0.2.0/scripts/build_ui.py +119 -0
  358. contextweave-0.2.0/scripts/generate_readme_screenshots.py +741 -0
  359. contextweave-0.2.0/scripts/run_ui_tests.py +221 -0
  360. contextweave-0.2.0/tests/AGENTS.md +158 -0
  361. contextweave-0.2.0/tests/adapters/AGENTS.md +19 -0
  362. contextweave-0.2.0/tests/adapters/files/test_glossary_io.py +641 -0
  363. contextweave-0.2.0/tests/application/fakes.py +559 -0
  364. contextweave-0.2.0/tests/application/test_composition.py +827 -0
  365. contextweave-0.2.0/tests/application/test_contracts.py +658 -0
  366. contextweave-0.2.0/tests/application/test_document_service.py +1422 -0
  367. contextweave-0.2.0/tests/application/test_document_translation_service.py +422 -0
  368. contextweave-0.2.0/tests/application/test_events.py +169 -0
  369. contextweave-0.2.0/tests/application/test_export_services.py +513 -0
  370. contextweave-0.2.0/tests/application/test_queue_service.py +237 -0
  371. contextweave-0.2.0/tests/application/test_terms_service.py +149 -0
  372. contextweave-0.2.0/tests/application/test_ui_harness_pattern.py +77 -0
  373. contextweave-0.2.0/tests/architecture/test_migrated_ui_boundaries.py +61 -0
  374. contextweave-0.2.0/tests/architecture/test_packaging_hidden_imports.py +34 -0
  375. contextweave-0.2.0/tests/architecture/test_qml_ui_boundaries.py +83 -0
  376. contextweave-0.2.0/tests/cli/test_cli.py +363 -0
  377. contextweave-0.2.0/tests/config/AGENTS.md +20 -0
  378. contextweave-0.2.0/tests/config/__init__.py +1 -0
  379. contextweave-0.2.0/tests/config/test_endpoint_profiles.py +629 -0
  380. contextweave-0.2.0/tests/conftest.py +42 -0
  381. contextweave-0.2.0/tests/core/AGENTS.md +29 -0
  382. contextweave-0.2.0/tests/core/__init__.py +0 -0
  383. contextweave-0.2.0/tests/core/expected_batching_output.json +11796 -0
  384. contextweave-0.2.0/tests/core/test-terms.json +15160 -0
  385. contextweave-0.2.0/tests/core/test_context_extractor.py +165 -0
  386. contextweave-0.2.0/tests/core/test_context_manager.py +1749 -0
  387. contextweave-0.2.0/tests/core/test_manga_document_handler.py +218 -0
  388. contextweave-0.2.0/tests/core/test_models.py +535 -0
  389. contextweave-0.2.0/tests/core/test_noise_filtering_pipeline.py +99 -0
  390. contextweave-0.2.0/tests/core/test_term_memory_builder.py +35 -0
  391. contextweave-0.2.0/tests/core/test_translation_context_manager_strategy_api.py +1933 -0
  392. contextweave-0.2.0/tests/data/test_chunk.txt +42 -0
  393. contextweave-0.2.0/tests/data/test_chunk2.txt +50 -0
  394. contextweave-0.2.0/tests/documents/AGENTS.md +35 -0
  395. contextweave-0.2.0/tests/documents/__init__.py +0 -0
  396. contextweave-0.2.0/tests/documents/content/AGENTS.md +47 -0
  397. contextweave-0.2.0/tests/documents/content/test_ocr_content.py +1043 -0
  398. contextweave-0.2.0/tests/documents/content/test_ocr_items.py +1003 -0
  399. contextweave-0.2.0/tests/documents/test_base.py +191 -0
  400. contextweave-0.2.0/tests/documents/test_epub.py +3362 -0
  401. contextweave-0.2.0/tests/documents/test_epub_container.py +1377 -0
  402. contextweave-0.2.0/tests/documents/test_epub_inline_markers.py +86 -0
  403. contextweave-0.2.0/tests/documents/test_epub_xhtml_utils.py +777 -0
  404. contextweave-0.2.0/tests/documents/test_manga.py +309 -0
  405. contextweave-0.2.0/tests/documents/test_manga_alignment.py +53 -0
  406. contextweave-0.2.0/tests/documents/test_ocr_image_embedded_text.py +150 -0
  407. contextweave-0.2.0/tests/documents/test_pdf.py +889 -0
  408. contextweave-0.2.0/tests/documents/test_scanned_book.py +837 -0
  409. contextweave-0.2.0/tests/documents/test_subtitle.py +272 -0
  410. contextweave-0.2.0/tests/documents/test_text.py +582 -0
  411. contextweave-0.2.0/tests/integration/AGENTS.md +20 -0
  412. contextweave-0.2.0/tests/integration/__init__.py +1 -0
  413. contextweave-0.2.0/tests/integration/test_business_logic.py +377 -0
  414. contextweave-0.2.0/tests/llm/AGENTS.md +33 -0
  415. contextweave-0.2.0/tests/llm/__init__.py +0 -0
  416. contextweave-0.2.0/tests/llm/test_extractor.py +122 -0
  417. contextweave-0.2.0/tests/llm/test_extractor_unit.py +177 -0
  418. contextweave-0.2.0/tests/llm/test_gemini_backend.py +122 -0
  419. contextweave-0.2.0/tests/llm/test_gemini_batch_gateway.py +198 -0
  420. contextweave-0.2.0/tests/llm/test_glossary_translator.py +585 -0
  421. contextweave-0.2.0/tests/llm/test_image_generator.py +29 -0
  422. contextweave-0.2.0/tests/llm/test_image_token_usage.py +74 -0
  423. contextweave-0.2.0/tests/llm/test_language_detector.py +198 -0
  424. contextweave-0.2.0/tests/llm/test_llm_client.py +678 -0
  425. contextweave-0.2.0/tests/llm/test_manga_translator.py +103 -0
  426. contextweave-0.2.0/tests/llm/test_ocr.py +166 -0
  427. contextweave-0.2.0/tests/llm/test_reviewer.py +172 -0
  428. contextweave-0.2.0/tests/llm/test_session_trace.py +20 -0
  429. contextweave-0.2.0/tests/llm/test_summarizor.py +215 -0
  430. contextweave-0.2.0/tests/llm/test_token_tracker.py +385 -0
  431. contextweave-0.2.0/tests/llm/test_token_usage_extraction.py +125 -0
  432. contextweave-0.2.0/tests/llm/test_translator.py +865 -0
  433. contextweave-0.2.0/tests/storage/AGENTS.md +29 -0
  434. contextweave-0.2.0/tests/storage/__init__.py +0 -0
  435. contextweave-0.2.0/tests/storage/test_book_db.py +2000 -0
  436. contextweave-0.2.0/tests/storage/test_book_manager.py +913 -0
  437. contextweave-0.2.0/tests/storage/test_document_repository.py +434 -0
  438. contextweave-0.2.0/tests/storage/test_document_tables.py +175 -0
  439. contextweave-0.2.0/tests/storage/test_llm_batch_store.py +67 -0
  440. contextweave-0.2.0/tests/storage/test_task_store.py +338 -0
  441. contextweave-0.2.0/tests/storage/test_term_repository.py +1034 -0
  442. contextweave-0.2.0/tests/storage/test_token_tracking.py +299 -0
  443. contextweave-0.2.0/tests/storage/test_translation_batch_task_store.py +71 -0
  444. contextweave-0.2.0/tests/test_logging_handlers.py +50 -0
  445. contextweave-0.2.0/tests/ui/AGENTS.md +49 -0
  446. contextweave-0.2.0/tests/ui/__init__.py +1 -0
  447. contextweave-0.2.0/tests/ui/conftest.py +29 -0
  448. contextweave-0.2.0/tests/ui/tasks/test_task_engine.py +610 -0
  449. contextweave-0.2.0/tests/ui/test_app_settings_dialog_host.py +60 -0
  450. contextweave-0.2.0/tests/ui/test_app_settings_dialog_viewmodel.py +36 -0
  451. contextweave-0.2.0/tests/ui/test_app_settings_pane.py +443 -0
  452. contextweave-0.2.0/tests/ui/test_app_settings_pane_viewmodel.py +42 -0
  453. contextweave-0.2.0/tests/ui/test_app_setup_view.py +748 -0
  454. contextweave-0.2.0/tests/ui/test_app_shell_host.py +80 -0
  455. contextweave-0.2.0/tests/ui/test_app_shell_viewmodel.py +60 -0
  456. contextweave-0.2.0/tests/ui/test_document_export_pane_viewmodel.py +36 -0
  457. contextweave-0.2.0/tests/ui/test_document_images_pane_viewmodel.py +74 -0
  458. contextweave-0.2.0/tests/ui/test_document_images_view.py +564 -0
  459. contextweave-0.2.0/tests/ui/test_document_ocr_tab.py +981 -0
  460. contextweave-0.2.0/tests/ui/test_document_shell_host.py +161 -0
  461. contextweave-0.2.0/tests/ui/test_document_shell_viewmodel.py +61 -0
  462. contextweave-0.2.0/tests/ui/test_document_translation_pane_viewmodel.py +71 -0
  463. contextweave-0.2.0/tests/ui/test_document_translation_view.py +971 -0
  464. contextweave-0.2.0/tests/ui/test_document_workspace_view.py +788 -0
  465. contextweave-0.2.0/tests/ui/test_i18n_progress_messages.py +118 -0
  466. contextweave-0.2.0/tests/ui/test_image_viewer.py +137 -0
  467. contextweave-0.2.0/tests/ui/test_library_view.py +267 -0
  468. contextweave-0.2.0/tests/ui/test_main.py +132 -0
  469. contextweave-0.2.0/tests/ui/test_main_window_shell.py +1019 -0
  470. contextweave-0.2.0/tests/ui/test_progress_widget.py +34 -0
  471. contextweave-0.2.0/tests/ui/test_project_settings_dialog_host.py +60 -0
  472. contextweave-0.2.0/tests/ui/test_project_settings_dialog_viewmodel.py +36 -0
  473. contextweave-0.2.0/tests/ui/test_project_settings_pane.py +537 -0
  474. contextweave-0.2.0/tests/ui/test_project_settings_pane_viewmodel.py +138 -0
  475. contextweave-0.2.0/tests/ui/test_project_shell_host.py +100 -0
  476. contextweave-0.2.0/tests/ui/test_project_shell_viewmodel.py +61 -0
  477. contextweave-0.2.0/tests/ui/test_qml_bootstrap.py +71 -0
  478. contextweave-0.2.0/tests/ui/test_qml_viewmodel_harness.py +78 -0
  479. contextweave-0.2.0/tests/ui/test_queue_drawer_view.py +440 -0
  480. contextweave-0.2.0/tests/ui/test_queue_shell_host.py +54 -0
  481. contextweave-0.2.0/tests/ui/test_queue_shell_viewmodel.py +40 -0
  482. contextweave-0.2.0/tests/ui/test_shell_host_infrastructure.py +80 -0
  483. contextweave-0.2.0/tests/ui/test_sleep_inhibitor.py +432 -0
  484. contextweave-0.2.0/tests/ui/test_terms_pane_viewmodel.py +95 -0
  485. contextweave-0.2.0/tests/ui/test_terms_view.py +789 -0
  486. contextweave-0.2.0/tests/ui/test_ui_clickthrough_smoke.py +786 -0
  487. contextweave-0.2.0/tests/ui/test_viewmodel_base.py +192 -0
  488. contextweave-0.2.0/tests/ui/test_work_view.py +706 -0
  489. contextweave-0.2.0/tests/ui/test_worker_cancellation_reporting.py +355 -0
  490. contextweave-0.2.0/tests/ui/test_workflow_profile_editor.py +802 -0
  491. contextweave-0.2.0/tests/ui/workers/test_batch_task_overlap_guard.py +67 -0
  492. contextweave-0.2.0/tests/ui/workers/test_chunk_retranslation_task_worker.py +150 -0
  493. contextweave-0.2.0/tests/ui/workers/test_config_snapshot_workers.py +338 -0
  494. contextweave-0.2.0/tests/ui/workers/test_glossary_export_task_worker.py +446 -0
  495. contextweave-0.2.0/tests/ui/workers/test_glossary_review_task_worker.py +372 -0
  496. contextweave-0.2.0/tests/ui/workers/test_ocr_task_worker.py +714 -0
  497. contextweave-0.2.0/tests/ui/workers/test_operation_tracker.py +134 -0
  498. contextweave-0.2.0/tests/ui/workers/test_translate_and_export_task_worker.py +165 -0
  499. contextweave-0.2.0/tests/ui/workers/test_translation_manga_task_worker.py +370 -0
  500. contextweave-0.2.0/tests/ui/workers/test_translation_text_task_worker.py +493 -0
  501. contextweave-0.2.0/tests/utils/AGENTS.md +27 -0
  502. contextweave-0.2.0/tests/utils/__init__.py +0 -0
  503. contextweave-0.2.0/tests/utils/test_chunking.py +280 -0
  504. contextweave-0.2.0/tests/utils/test_cjk_normalize.py +9 -0
  505. contextweave-0.2.0/tests/utils/test_file_utils.py +143 -0
  506. contextweave-0.2.0/tests/utils/test_hard_wrap.py +35 -0
  507. contextweave-0.2.0/tests/utils/test_hashing.py +117 -0
  508. contextweave-0.2.0/tests/utils/test_llm_json_cleaner.py +37 -0
  509. contextweave-0.2.0/tests/utils/test_markdown_escape.py +213 -0
  510. contextweave-0.2.0/tests/utils/test_semantic_chunker.py +383 -0
  511. contextweave-0.2.0/tests/utils/test_string_similarity.py +35 -0
  512. contextweave-0.2.0/tests/utils/test_symbol_check.py +89 -0
  513. contextweave-0.2.0/tests/workflow/AGENTS.md +33 -0
  514. contextweave-0.2.0/tests/workflow/__init__.py +1 -0
  515. contextweave-0.2.0/tests/workflow/tasks/AGENTS.md +84 -0
  516. contextweave-0.2.0/tests/workflow/tasks/__init__.py +0 -0
  517. contextweave-0.2.0/tests/workflow/tasks/execution/AGENTS.md +72 -0
  518. contextweave-0.2.0/tests/workflow/tasks/execution/__init__.py +0 -0
  519. contextweave-0.2.0/tests/workflow/tasks/execution/test_batch_translation_executor.py +1450 -0
  520. contextweave-0.2.0/tests/workflow/tasks/handlers/AGENTS.md +116 -0
  521. contextweave-0.2.0/tests/workflow/tasks/handlers/__init__.py +0 -0
  522. contextweave-0.2.0/tests/workflow/tasks/handlers/test_batch_translation_handler.py +413 -0
  523. contextweave-0.2.0/tests/workflow/tasks/handlers/test_chunk_retranslation_handler.py +364 -0
  524. contextweave-0.2.0/tests/workflow/tasks/handlers/test_glossary_export_handler.py +454 -0
  525. contextweave-0.2.0/tests/workflow/tasks/handlers/test_glossary_extraction_handler.py +72 -0
  526. contextweave-0.2.0/tests/workflow/tasks/handlers/test_glossary_review_handler.py +497 -0
  527. contextweave-0.2.0/tests/workflow/tasks/handlers/test_glossary_translation_handler.py +188 -0
  528. contextweave-0.2.0/tests/workflow/tasks/handlers/test_image_reembedding_handler.py +107 -0
  529. contextweave-0.2.0/tests/workflow/tasks/handlers/test_ocr_handler.py +745 -0
  530. contextweave-0.2.0/tests/workflow/tasks/handlers/test_translate_and_export_handler.py +355 -0
  531. contextweave-0.2.0/tests/workflow/tasks/handlers/test_translation_manga_handler.py +449 -0
  532. contextweave-0.2.0/tests/workflow/tasks/handlers/test_translation_text_handler.py +408 -0
  533. contextweave-0.2.0/tests/workflow/tasks/test_claims.py +355 -0
  534. contextweave-0.2.0/tests/workflow/tasks/test_engine_core.py +375 -0
  535. contextweave-0.2.0/tests/workflow/test_glossary_ops_scoping.py +78 -0
  536. contextweave-0.2.0/tests/workflow/test_import_export.py +695 -0
  537. contextweave-0.2.0/tests/workflow/test_multi_document.py +445 -0
  538. contextweave-0.2.0/tests/workflow/test_ocr_required_for_translation.py +119 -0
  539. contextweave-0.2.0/tests/workflow/test_run_ocr.py +51 -0
  540. contextweave-0.2.0/tests/workflow/test_service_bootstrap_lock.py +132 -0
  541. contextweave-0.2.0/tests/workflow/test_service_cancellation_semantics.py +687 -0
  542. contextweave-0.2.0/tests/workflow/test_session.py +64 -0
  543. contextweave-0.2.0/tests/workflow/test_translator_image_fetcher.py +53 -0
  544. contextweave-0.2.0/tests/workflow/test_translator_import_path.py +241 -0
  545. contextweave-0.2.0/uv.lock +2239 -0
@@ -0,0 +1,396 @@
1
+ name: Build & Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: write
11
+
12
+ env:
13
+ PYTHON_VERSION: '3.12'
14
+ APP_NAME: 'ContextWeave'
15
+
16
+ jobs:
17
+ build:
18
+ strategy:
19
+ fail-fast: false
20
+ matrix:
21
+ include:
22
+ - os: macos-14
23
+ platform_name: macos-arm64
24
+ - os: windows-latest
25
+ platform_name: windows-x86_64
26
+
27
+ runs-on: ${{ matrix.os }}
28
+
29
+ steps:
30
+ - name: Checkout
31
+ uses: actions/checkout@v4
32
+
33
+ - name: Set up Python
34
+ uses: actions/setup-python@v5
35
+ with:
36
+ python-version: ${{ env.PYTHON_VERSION }}
37
+
38
+ - name: Install uv
39
+ uses: astral-sh/setup-uv@v4
40
+
41
+ - name: Get version from tag
42
+ id: version
43
+ shell: bash
44
+ run: |
45
+ if [[ "${{ github.ref_type }}" == "tag" ]]; then
46
+ VERSION="${{ github.ref_name }}"
47
+ else
48
+ VERSION="v0.0.0-dev"
49
+ fi
50
+ echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
51
+
52
+ - name: Install dependencies
53
+ run: uv sync --group dev
54
+
55
+ - name: Install CPU-only PyTorch (Windows)
56
+ if: runner.os == 'Windows'
57
+ run: uv pip install torch --index-url https://download.pytorch.org/whl/cpu --reinstall --no-deps
58
+
59
+ # ============================================================
60
+ # macOS: Import signing certificate
61
+ # ============================================================
62
+ - name: Import Apple signing certificate
63
+ if: runner.os == 'macOS'
64
+ env:
65
+ APPLE_CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
66
+ APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
67
+ run: |
68
+ if [ -z "$APPLE_CERTIFICATE_BASE64" ]; then
69
+ echo "::notice::No Apple certificate configured — skipping code signing"
70
+ echo "CODESIGN_IDENTITY=" >> "$GITHUB_ENV"
71
+ exit 0
72
+ fi
73
+
74
+ # Create a temporary keychain
75
+ KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db"
76
+ KEYCHAIN_PASSWORD="$(openssl rand -hex 16)"
77
+ security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
78
+ security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
79
+ security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
80
+
81
+ # Import the certificate
82
+ CERT_PATH="$RUNNER_TEMP/certificate.p12"
83
+ echo "$APPLE_CERTIFICATE_BASE64" | base64 --decode > "$CERT_PATH"
84
+ security import "$CERT_PATH" \
85
+ -P "$APPLE_CERTIFICATE_PASSWORD" \
86
+ -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
87
+ security set-key-partition-list \
88
+ -S apple-tool:,apple: \
89
+ -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
90
+ security list-keychain -d user -s "$KEYCHAIN_PATH"
91
+ rm -f "$CERT_PATH"
92
+
93
+ # Detect signing identity from the imported certificate
94
+ IDENTITY=$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" \
95
+ | grep "Developer ID" | head -1 | sed 's/.*"\(.*\)"/\1/')
96
+ if [ -z "$IDENTITY" ]; then
97
+ echo "::warning::Certificate imported but no Developer ID identity found"
98
+ echo "CODESIGN_IDENTITY=" >> "$GITHUB_ENV"
99
+ else
100
+ echo "Found signing identity: $IDENTITY"
101
+ echo "CODESIGN_IDENTITY=$IDENTITY" >> "$GITHUB_ENV"
102
+ fi
103
+ echo "KEYCHAIN_PATH=$KEYCHAIN_PATH" >> "$GITHUB_ENV"
104
+
105
+ # ============================================================
106
+ # Build
107
+ # ============================================================
108
+ - name: Build with PyInstaller
109
+ run: uv run pyinstaller cat-ui.spec --clean --noconfirm
110
+
111
+ - name: Verify build output
112
+ shell: bash
113
+ run: |
114
+ echo "Working directory: $(pwd)"
115
+ echo "Contents of dist/:"
116
+ ls -la dist/ 2>/dev/null || { echo "::error::dist/ directory does not exist"; exit 1; }
117
+ if [ -d "dist/${{ env.APP_NAME }}" ]; then
118
+ echo "dist/${{ env.APP_NAME }}/ contents (first 20):"
119
+ ls dist/${{ env.APP_NAME }}/ | head -20
120
+ elif [ -d "dist/${{ env.APP_NAME }}.app" ]; then
121
+ echo "dist/${{ env.APP_NAME }}.app/ found (macOS bundle)"
122
+ else
123
+ echo "::error::Expected dist/${{ env.APP_NAME }} or dist/${{ env.APP_NAME }}.app not found"
124
+ exit 1
125
+ fi
126
+
127
+ - name: Verify OpenCC assets (Windows)
128
+ if: runner.os == 'Windows'
129
+ shell: bash
130
+ run: |
131
+ set -euo pipefail
132
+ APP_DIST="dist/${{ env.APP_NAME }}"
133
+
134
+ # PyInstaller layout may vary across versions/platforms:
135
+ # - dist/ContextWeave/_internal/opencc/...
136
+ # - dist/ContextWeave/opencc/...
137
+ OPENCC_BASE=""
138
+ for base in "$APP_DIST/_internal" "$APP_DIST"; do
139
+ if [ -f "$base/opencc/config/jp2s.json" ] && [ -d "$base/opencc/dictionary" ]; then
140
+ OPENCC_BASE="$base/opencc"
141
+ break
142
+ fi
143
+ done
144
+
145
+ if [ -z "$OPENCC_BASE" ]; then
146
+ echo "::group::OpenCC asset debug"
147
+ echo "Expected one of:"
148
+ echo " $APP_DIST/_internal/opencc/config/jp2s.json"
149
+ echo " $APP_DIST/opencc/config/jp2s.json"
150
+ echo "Actual opencc-related paths:"
151
+ find "$APP_DIST" -maxdepth 5 \( -type d -name opencc -o -type f -name 'jp2s.json' \) 2>/dev/null | sort || true
152
+ echo "::endgroup::"
153
+ echo "::error::Missing OpenCC config/dictionary assets under $APP_DIST"
154
+ exit 1
155
+ fi
156
+
157
+ echo "OpenCC assets verified at: $OPENCC_BASE"
158
+
159
+ # ============================================================
160
+ # macOS: Sign, package as DMG, notarize
161
+ # ============================================================
162
+ - name: Sign app bundle (macOS)
163
+ if: runner.os == 'macOS' && env.CODESIGN_IDENTITY != ''
164
+ run: |
165
+ echo "Signing with: $CODESIGN_IDENTITY"
166
+
167
+ # Sign all embedded binaries first (inside-out signing)
168
+ find "dist/${{ env.APP_NAME }}.app" -type f \
169
+ \( -name "*.so" -o -name "*.dylib" \) -print0 | \
170
+ while IFS= read -r -d '' lib; do
171
+ codesign --force --options runtime \
172
+ --entitlements installer/macos/entitlements.plist \
173
+ --sign "$CODESIGN_IDENTITY" "$lib"
174
+ done
175
+
176
+ # Sign executable binaries inside the bundle
177
+ find "dist/${{ env.APP_NAME }}.app/Contents/MacOS" -type f -perm +111 -print0 | \
178
+ while IFS= read -r -d '' bin; do
179
+ codesign --force --options runtime \
180
+ --entitlements installer/macos/entitlements.plist \
181
+ --sign "$CODESIGN_IDENTITY" "$bin"
182
+ done
183
+
184
+ # Sign the app bundle itself
185
+ codesign --force --options runtime \
186
+ --entitlements installer/macos/entitlements.plist \
187
+ --sign "$CODESIGN_IDENTITY" \
188
+ "dist/${{ env.APP_NAME }}.app"
189
+
190
+ # Verify nested signatures strictly and test Gatekeeper assessment
191
+ codesign --verify --deep --strict --verbose=2 "dist/${{ env.APP_NAME }}.app"
192
+ spctl --assess --type execute --verbose=4 "dist/${{ env.APP_NAME }}.app"
193
+ echo "Code signing verified successfully"
194
+
195
+ - name: Create DMG (macOS)
196
+ if: runner.os == 'macOS'
197
+ run: |
198
+ mkdir -p release
199
+ brew install create-dmg || true
200
+ # create-dmg may return non-zero for cosmetic issues; DMG is still created
201
+ create-dmg \
202
+ --volname "ContextWeave" \
203
+ --window-pos 200 120 \
204
+ --window-size 600 400 \
205
+ --icon-size 100 \
206
+ --icon "${{ env.APP_NAME }}.app" 150 190 \
207
+ --app-drop-link 450 190 \
208
+ --no-internet-enable \
209
+ "release/${{ env.APP_NAME }}-${{ steps.version.outputs.version }}-${{ matrix.platform_name }}.dmg" \
210
+ "dist/${{ env.APP_NAME }}.app" \
211
+ || true
212
+ ls -lh release/*.dmg
213
+
214
+ - name: Sign and notarize DMG (macOS)
215
+ if: runner.os == 'macOS' && env.CODESIGN_IDENTITY != ''
216
+ env:
217
+ APPLE_ID: ${{ secrets.APPLE_ID }}
218
+ APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
219
+ APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
220
+ run: |
221
+ DMG_FILE=$(ls release/*.dmg)
222
+
223
+ # Sign the DMG
224
+ codesign --force --sign "$CODESIGN_IDENTITY" "$DMG_FILE"
225
+
226
+ # Notarize (requires Apple ID credentials)
227
+ if [ -n "$APPLE_ID" ] && [ -n "$APPLE_ID_PASSWORD" ] && [ -n "$APPLE_TEAM_ID" ]; then
228
+ echo "Submitting for notarization..."
229
+ xcrun notarytool submit "$DMG_FILE" \
230
+ --apple-id "$APPLE_ID" \
231
+ --password "$APPLE_ID_PASSWORD" \
232
+ --team-id "$APPLE_TEAM_ID" \
233
+ --wait
234
+
235
+ # Staple the notarization ticket to the DMG
236
+ xcrun stapler staple "$DMG_FILE"
237
+ echo "Notarization and stapling complete"
238
+ else
239
+ echo "::notice::Skipping notarization — Apple ID credentials not configured"
240
+ fi
241
+
242
+ - name: Cleanup macOS keychain
243
+ if: runner.os == 'macOS' && env.KEYCHAIN_PATH != ''
244
+ run: security delete-keychain "$KEYCHAIN_PATH"
245
+
246
+ # ============================================================
247
+ # Windows: Sign executable, package portable zip
248
+ # ============================================================
249
+ - name: Sign executable (Windows)
250
+ if: runner.os == 'Windows'
251
+ env:
252
+ WINDOWS_CERTIFICATE_BASE64: ${{ secrets.WINDOWS_CERTIFICATE_BASE64 }}
253
+ WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
254
+ shell: powershell
255
+ run: |
256
+ if (-not $env:WINDOWS_CERTIFICATE_BASE64) {
257
+ Write-Host '::notice::No Windows certificate configured - skipping code signing'
258
+ exit 0
259
+ }
260
+
261
+ $certPath = Join-Path $env:RUNNER_TEMP 'certificate.pfx'
262
+ [IO.File]::WriteAllBytes($certPath,
263
+ [Convert]::FromBase64String($env:WINDOWS_CERTIFICATE_BASE64))
264
+
265
+ $signtool = (Resolve-Path 'C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe' |
266
+ Sort-Object -Descending | Select-Object -First 1).Path
267
+ Write-Host "Using signtool: $signtool"
268
+
269
+ $signArgs = @('sign', '/f', $certPath, '/p', $env:WINDOWS_CERTIFICATE_PASSWORD,
270
+ '/tr', 'http://timestamp.digicert.com', '/td', 'sha256', '/fd', 'sha256')
271
+
272
+ & $signtool @signArgs "dist\${{ env.APP_NAME }}\${{ env.APP_NAME }}.exe"
273
+
274
+ Get-ChildItem "dist\${{ env.APP_NAME }}" -Recurse -Include *.dll,*.pyd | ForEach-Object {
275
+ & $signtool @signArgs $_.FullName 2>$null
276
+ }
277
+
278
+ Remove-Item $certPath -Force
279
+ Write-Host 'Code signing complete'
280
+
281
+ - name: Create portable zip (Windows)
282
+ if: runner.os == 'Windows'
283
+ shell: bash
284
+ run: |
285
+ mkdir -p release
286
+ python - <<'PY'
287
+ from pathlib import Path
288
+ import zipfile
289
+
290
+ source_dir = Path("dist/${{ env.APP_NAME }}")
291
+ archive_path = Path("release/${{ env.APP_NAME }}-${{ steps.version.outputs.version }}-${{ matrix.platform_name }}.zip")
292
+
293
+ if not source_dir.is_dir():
294
+ raise SystemExit(f"Missing source directory: {source_dir}")
295
+
296
+ if archive_path.exists():
297
+ archive_path.unlink()
298
+
299
+ with zipfile.ZipFile(
300
+ archive_path,
301
+ mode="w",
302
+ compression=zipfile.ZIP_DEFLATED,
303
+ compresslevel=6,
304
+ allowZip64=True,
305
+ ) as archive:
306
+ for path in sorted(source_dir.rglob("*")):
307
+ if path.is_file():
308
+ archive.write(path, arcname=path.relative_to(source_dir.parent))
309
+
310
+ print(f"Portable archive created: {archive_path}")
311
+ PY
312
+
313
+ - name: Smoke test portable zip (Windows)
314
+ if: runner.os == 'Windows'
315
+ env:
316
+ CONTEXTWEAVE_SMOKE_TEST_STARTUP: '1'
317
+ shell: powershell
318
+ run: |
319
+ $archivePath = Resolve-Path "release\${{ env.APP_NAME }}-${{ steps.version.outputs.version }}-${{ matrix.platform_name }}.zip"
320
+ $extractRoot = Join-Path $env:RUNNER_TEMP 'portable-smoke'
321
+ $appRoot = Join-Path $extractRoot '${{ env.APP_NAME }}'
322
+ $exePath = Join-Path $appRoot '${{ env.APP_NAME }}.exe'
323
+ $openccCandidates = @(
324
+ (Join-Path $appRoot '_internal\opencc\config\jp2s.json'),
325
+ (Join-Path $appRoot 'opencc\config\jp2s.json')
326
+ )
327
+
328
+ if (Test-Path $extractRoot) {
329
+ Remove-Item $extractRoot -Recurse -Force
330
+ }
331
+
332
+ Expand-Archive -Path $archivePath -DestinationPath $extractRoot -Force
333
+
334
+ $topLevelEntries = @(Get-ChildItem -LiteralPath $extractRoot)
335
+ if ($topLevelEntries.Count -ne 1 -or -not $topLevelEntries[0].PSIsContainer -or $topLevelEntries[0].Name -ne '${{ env.APP_NAME }}') {
336
+ throw "Unexpected archive layout after extraction: $($topLevelEntries.Name -join ', ')"
337
+ }
338
+
339
+ if (-not (Test-Path -LiteralPath $exePath -PathType Leaf)) {
340
+ throw "Extracted executable not found: $exePath"
341
+ }
342
+
343
+ if (-not ($openccCandidates | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf })) {
344
+ throw 'Extracted portable zip is missing expected OpenCC assets'
345
+ }
346
+
347
+ $process = Start-Process -FilePath $exePath -WorkingDirectory $appRoot -PassThru
348
+ try {
349
+ if (-not $process.WaitForExit(30000)) {
350
+ Stop-Process -Id $process.Id -Force
351
+ throw 'Portable app smoke test timed out after 30 seconds'
352
+ }
353
+ if ($process.ExitCode -ne 0) {
354
+ throw "Portable app smoke test exited with code $($process.ExitCode)"
355
+ }
356
+ }
357
+ finally {
358
+ if (-not $process.HasExited) {
359
+ Stop-Process -Id $process.Id -Force
360
+ }
361
+ }
362
+
363
+ Write-Host "Portable zip smoke test passed: $archivePath"
364
+
365
+ # ============================================================
366
+ # Upload
367
+ # ============================================================
368
+ - name: Upload artifact
369
+ uses: actions/upload-artifact@v4
370
+ with:
371
+ name: ${{ env.APP_NAME }}-${{ matrix.platform_name }}
372
+ path: release/*
373
+ if-no-files-found: error
374
+ retention-days: 5
375
+
376
+ release:
377
+ needs: build
378
+ runs-on: ubuntu-latest
379
+ if: startsWith(github.ref, 'refs/tags/v')
380
+
381
+ steps:
382
+ - name: Download all artifacts
383
+ uses: actions/download-artifact@v4
384
+ with:
385
+ path: artifacts
386
+ merge-multiple: true
387
+
388
+ - name: List release files
389
+ run: ls -lhR artifacts/
390
+
391
+ - name: Create GitHub Release
392
+ uses: softprops/action-gh-release@v2
393
+ with:
394
+ files: artifacts/*
395
+ generate_release_notes: true
396
+ draft: true
@@ -0,0 +1,59 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+ *.so
6
+ *.dylib
7
+ *.dll
8
+
9
+ # Virtual environments
10
+ .venv/
11
+ venv/
12
+ .env
13
+ .env.local
14
+ .python-version
15
+
16
+ # Packaging
17
+ build/
18
+ dist/
19
+ release/
20
+ wheels/
21
+ *.egg-info/
22
+ .eggs/
23
+ pip-wheel-metadata/
24
+
25
+ # Caches and tooling
26
+ .mypy_cache/
27
+ .pytest_cache/
28
+ .ruff_cache/
29
+ .nox/
30
+ .cache/
31
+ *.log
32
+ *.pid
33
+
34
+ # Coverage
35
+ .coverage
36
+ .coverage.*
37
+ htmlcov/
38
+
39
+ # Editors/IDE
40
+ .idea/
41
+ .vscode/
42
+
43
+ # macOS / system
44
+ .DS_Store
45
+
46
+ # uv
47
+ .uv/
48
+
49
+ .config.yaml
50
+ output
51
+ output.txt
52
+ output.epub
53
+ delete-me/
54
+ delete-me-output/
55
+ .sisyphus/*
56
+ .omc
57
+ .claude
58
+ evaluation/output/
59
+ MagicMock/
@@ -0,0 +1,58 @@
1
+ <!-- Generated: 2026-02-26 -->
2
+
3
+ # context-aware-translation
4
+
5
+ ## Purpose
6
+ A Python 3.12+ document translation system that uses LLMs with context-aware glossary management. Translates text, PDF, scanned books, and manga with hierarchical context trees that reduce token usage by 99%+.
7
+
8
+ ## Key Files
9
+
10
+ | File | Description |
11
+ |------|-------------|
12
+ | `pyproject.toml` | Project config: dependencies, tooling (ruff, mypy, pytest) |
13
+ | `Makefile` | Build commands: `make check`, `make test`, `make build-ui` |
14
+ | `cat-ui.spec` | PyInstaller spec for standalone UI builds |
15
+ | `uv.lock` | Locked dependency versions (managed by uv) |
16
+
17
+ ## Subdirectories
18
+
19
+ | Directory | Purpose |
20
+ |-----------|---------|
21
+ | `context_aware_translation/` | Main package: core logic, LLM, documents, storage, UI (see `context_aware_translation/AGENTS.md`) |
22
+ | `tests/` | Test suites mirroring main package structure (see `tests/AGENTS.md`) |
23
+ | `scripts/` | Build and evaluation scripts (see `scripts/AGENTS.md`) |
24
+ | `installer/` | Platform-specific packaging configs (see `installer/AGENTS.md`) |
25
+
26
+ ## For AI Agents
27
+
28
+ ### Working In This Directory
29
+ - Use `uv` for dependency management (`uv sync`, `uv run`)
30
+ - Entry points: `cat-ui` (PySide6 GUI via `context_aware_translation.ui.main:main`)
31
+ - Run `make check` before committing (lint, format, typecheck, lupdate)
32
+ - All translation strings must have zh_CN translations; `make lupdate` will fail on unfinished entries
33
+
34
+ ### Testing Requirements
35
+ - Run `make test` or `uv run pytest tests/`
36
+ - Tests run in parallel via pytest-xdist (`-n auto`)
37
+ - Async tests use pytest-asyncio with `auto` mode
38
+
39
+ ### Common Patterns
40
+ - Config models in `config.py` using dataclasses
41
+ - SQLite with WAL mode for all storage (registry.db global, book.db per-book)
42
+ - 5 required config sections: extractor, summarizor, translator, glossary, review
43
+ - Ruff for linting+formatting, mypy for type checking (strict, excludes ui/ and tests/)
44
+ - PySide6 i18n with `.ts`/`.qm` translation files
45
+
46
+ ## Dependencies
47
+
48
+ ### External
49
+ - `pyside6` - Qt-based GUI framework
50
+ - `openai`, `google-genai` - LLM API clients
51
+ - `torch`, `transformers` - ML models for embeddings/tokenization
52
+ - `faiss-cpu` - Vector similarity search
53
+ - `pikepdf`, `pypdfium2` - PDF handling
54
+ - `pypandoc-binary` - Document format conversion
55
+ - `semchunk` - Semantic text chunking
56
+ - `tenacity` - Retry logic for API calls
57
+
58
+ <!-- MANUAL: -->