MaiBot 1.3.8__py3-none-any.whl

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 (716) hide show
  1. maibot-1.3.8.dist-info/METADATA +245 -0
  2. maibot-1.3.8.dist-info/RECORD +716 -0
  3. maibot-1.3.8.dist-info/WHEEL +5 -0
  4. maibot-1.3.8.dist-info/entry_points.txt +2 -0
  5. maibot-1.3.8.dist-info/licenses/LICENSE +674 -0
  6. maibot-1.3.8.dist-info/top_level.txt +1 -0
  7. src/A_memorix/LICENSE +661 -0
  8. src/A_memorix/LICENSE-MAIBOT-GPL.md +22 -0
  9. src/A_memorix/__init__.py +5 -0
  10. src/A_memorix/config_schema.json +1640 -0
  11. src/A_memorix/core/__init__.py +83 -0
  12. src/A_memorix/core/embedding/__init__.py +17 -0
  13. src/A_memorix/core/embedding/api_adapter.py +650 -0
  14. src/A_memorix/core/embedding/manager.py +506 -0
  15. src/A_memorix/core/embedding/presets.py +68 -0
  16. src/A_memorix/core/image/__init__.py +6 -0
  17. src/A_memorix/core/image/asset_store.py +141 -0
  18. src/A_memorix/core/image/component_paths.py +36 -0
  19. src/A_memorix/core/image/embedder.py +129 -0
  20. src/A_memorix/core/image/fingerprints.py +36 -0
  21. src/A_memorix/core/image/runtime.py +900 -0
  22. src/A_memorix/core/retrieval/__init__.py +66 -0
  23. src/A_memorix/core/retrieval/dual_path.py +3272 -0
  24. src/A_memorix/core/retrieval/graph_relation_recall.py +285 -0
  25. src/A_memorix/core/retrieval/pagerank.py +471 -0
  26. src/A_memorix/core/retrieval/posterior_graph.py +787 -0
  27. src/A_memorix/core/retrieval/score_calibration.py +180 -0
  28. src/A_memorix/core/retrieval/sparse_bm25.py +717 -0
  29. src/A_memorix/core/retrieval/threshold.py +404 -0
  30. src/A_memorix/core/runtime/__init__.py +26 -0
  31. src/A_memorix/core/runtime/admin_contracts.py +293 -0
  32. src/A_memorix/core/runtime/kernel_compat.py +269 -0
  33. src/A_memorix/core/runtime/lifecycle_orchestrator.py +368 -0
  34. src/A_memorix/core/runtime/models.py +27 -0
  35. src/A_memorix/core/runtime/runtime_facade.py +141 -0
  36. src/A_memorix/core/runtime/runtime_writer_lock.py +105 -0
  37. src/A_memorix/core/runtime/sdk_memory_kernel.py +1907 -0
  38. src/A_memorix/core/runtime/search_runtime_initializer.py +290 -0
  39. src/A_memorix/core/runtime/services/__init__.py +63 -0
  40. src/A_memorix/core/runtime/services/background_task_service.py +477 -0
  41. src/A_memorix/core/runtime/services/base.py +28 -0
  42. src/A_memorix/core/runtime/services/bundle_admin_service.py +2200 -0
  43. src/A_memorix/core/runtime/services/chat_filter_service.py +88 -0
  44. src/A_memorix/core/runtime/services/correction_admin_service.py +1274 -0
  45. src/A_memorix/core/runtime/services/delete_admin_service.py +2018 -0
  46. src/A_memorix/core/runtime/services/dual_vector_migration_service.py +109 -0
  47. src/A_memorix/core/runtime/services/dual_vector_state_service.py +503 -0
  48. src/A_memorix/core/runtime/services/embedding_state_service.py +515 -0
  49. src/A_memorix/core/runtime/services/episode_admin_service.py +104 -0
  50. src/A_memorix/core/runtime/services/fact_admin_service.py +199 -0
  51. src/A_memorix/core/runtime/services/feedback_correction_service.py +1523 -0
  52. src/A_memorix/core/runtime/services/graph_admin_service.py +1521 -0
  53. src/A_memorix/core/runtime/services/image_service.py +158 -0
  54. src/A_memorix/core/runtime/services/import_tuning_admin_service.py +158 -0
  55. src/A_memorix/core/runtime/services/ingest_service.py +787 -0
  56. src/A_memorix/core/runtime/services/memory_maintenance_service.py +404 -0
  57. src/A_memorix/core/runtime/services/memory_search_service.py +373 -0
  58. src/A_memorix/core/runtime/services/profile_admin_service.py +646 -0
  59. src/A_memorix/core/runtime/services/request_dedup_service.py +34 -0
  60. src/A_memorix/core/runtime/services/runtime_config_service.py +94 -0
  61. src/A_memorix/core/runtime/services/runtime_dependency_service.py +105 -0
  62. src/A_memorix/core/runtime/services/runtime_lifecycle_service.py +409 -0
  63. src/A_memorix/core/runtime/services/search_hit_processing_service.py +891 -0
  64. src/A_memorix/core/runtime/services/source_admin_service.py +52 -0
  65. src/A_memorix/core/runtime/services/stats_service.py +35 -0
  66. src/A_memorix/core/runtime/services/summary_service.py +50 -0
  67. src/A_memorix/core/runtime/services/v5_admin_service.py +326 -0
  68. src/A_memorix/core/runtime/services/vector_delete_service.py +30 -0
  69. src/A_memorix/core/runtime/services/vector_rebuild_checkpoint.py +65 -0
  70. src/A_memorix/core/runtime/services/vector_recovery_service.py +460 -0
  71. src/A_memorix/core/runtime/services/vector_runtime_service.py +1417 -0
  72. src/A_memorix/core/runtime/services/vector_space_service.py +251 -0
  73. src/A_memorix/core/storage/__init__.py +62 -0
  74. src/A_memorix/core/storage/format_migration.py +676 -0
  75. src/A_memorix/core/storage/graph_store.py +1733 -0
  76. src/A_memorix/core/storage/knowledge_types.py +183 -0
  77. src/A_memorix/core/storage/metadata_cleanup.py +913 -0
  78. src/A_memorix/core/storage/metadata_episode.py +1659 -0
  79. src/A_memorix/core/storage/metadata_fact.py +1410 -0
  80. src/A_memorix/core/storage/metadata_feedback.py +745 -0
  81. src/A_memorix/core/storage/metadata_fts.py +937 -0
  82. src/A_memorix/core/storage/metadata_image.py +1076 -0
  83. src/A_memorix/core/storage/metadata_profile.py +782 -0
  84. src/A_memorix/core/storage/metadata_schema.py +2503 -0
  85. src/A_memorix/core/storage/metadata_store.py +4565 -0
  86. src/A_memorix/core/storage/sqlite_connection.py +176 -0
  87. src/A_memorix/core/storage/tokenizer_runtime.py +9 -0
  88. src/A_memorix/core/storage/transaction.py +42 -0
  89. src/A_memorix/core/storage/type_detection.py +137 -0
  90. src/A_memorix/core/storage/value_coercion.py +10 -0
  91. src/A_memorix/core/storage/vector_store.py +2851 -0
  92. src/A_memorix/core/strategies/__init__.py +0 -0
  93. src/A_memorix/core/strategies/base.py +92 -0
  94. src/A_memorix/core/strategies/chat_log.py +80 -0
  95. src/A_memorix/core/strategies/factual.py +104 -0
  96. src/A_memorix/core/strategies/narrative.py +148 -0
  97. src/A_memorix/core/strategies/quote.py +47 -0
  98. src/A_memorix/core/utils/__init__.py +33 -0
  99. src/A_memorix/core/utils/aggregate_query_service.py +359 -0
  100. src/A_memorix/core/utils/episode_retrieval_service.py +222 -0
  101. src/A_memorix/core/utils/episode_segmentation_service.py +322 -0
  102. src/A_memorix/core/utils/episode_service.py +646 -0
  103. src/A_memorix/core/utils/feedback_policy.py +149 -0
  104. src/A_memorix/core/utils/hash.py +128 -0
  105. src/A_memorix/core/utils/import_payloads.py +222 -0
  106. src/A_memorix/core/utils/io.py +85 -0
  107. src/A_memorix/core/utils/matcher.py +175 -0
  108. src/A_memorix/core/utils/memory_lifecycle_policy.py +336 -0
  109. src/A_memorix/core/utils/metadata.py +11 -0
  110. src/A_memorix/core/utils/model_routing.py +239 -0
  111. src/A_memorix/core/utils/monitor.py +188 -0
  112. src/A_memorix/core/utils/path_fallback_service.py +182 -0
  113. src/A_memorix/core/utils/person_profile_service.py +1277 -0
  114. src/A_memorix/core/utils/plugin_id_policy.py +26 -0
  115. src/A_memorix/core/utils/profile_evidence.py +25 -0
  116. src/A_memorix/core/utils/profile_policy.py +45 -0
  117. src/A_memorix/core/utils/profile_text.py +204 -0
  118. src/A_memorix/core/utils/quantization.py +343 -0
  119. src/A_memorix/core/utils/relation_query.py +121 -0
  120. src/A_memorix/core/utils/relation_write_service.py +504 -0
  121. src/A_memorix/core/utils/retrieval_tuning_manager.py +2369 -0
  122. src/A_memorix/core/utils/runtime_payloads.py +132 -0
  123. src/A_memorix/core/utils/runtime_self_check.py +303 -0
  124. src/A_memorix/core/utils/search_execution_service.py +445 -0
  125. src/A_memorix/core/utils/search_postprocess.py +91 -0
  126. src/A_memorix/core/utils/summary_importer.py +991 -0
  127. src/A_memorix/core/utils/time_parser.py +156 -0
  128. src/A_memorix/core/utils/web_import_manager.py +4511 -0
  129. src/A_memorix/host_service.py +1018 -0
  130. src/A_memorix/paths.py +58 -0
  131. src/A_memorix/plugin.py +321 -0
  132. src/A_memorix/runtime_registry.py +30 -0
  133. src/A_memorix/scripts/_bootstrap.py +22 -0
  134. src/A_memorix/scripts/audit_vector_consistency.py +205 -0
  135. src/A_memorix/scripts/backfill_relation_vectors.py +265 -0
  136. src/A_memorix/scripts/backfill_temporal_metadata.py +67 -0
  137. src/A_memorix/scripts/convert_lpmm.py +537 -0
  138. src/A_memorix/scripts/import_lpmm_json.py +189 -0
  139. src/A_memorix/scripts/migrate_chat_history.py +101 -0
  140. src/A_memorix/scripts/migrate_maibot_memory.py +1955 -0
  141. src/A_memorix/scripts/migrate_person_memory_points.py +113 -0
  142. src/A_memorix/scripts/process_knowledge.py +831 -0
  143. src/A_memorix/scripts/rebuild_episodes.py +207 -0
  144. src/A_memorix/scripts/release_vnext_migrate.py +875 -0
  145. src/A_memorix/scripts/runtime_self_check.py +144 -0
  146. src/__init__.py +14 -0
  147. src/_resources/EULA.md +135 -0
  148. src/_resources/PRIVACY.md +60 -0
  149. src/_resources/changelogs/changelog.md +918 -0
  150. src/_resources/locales/en-US/config.json +39 -0
  151. src/_resources/locales/en-US/core.json +8 -0
  152. src/_resources/locales/en-US/prompts.json +8 -0
  153. src/_resources/locales/en-US/startup.json +98 -0
  154. src/_resources/locales/ja-JP/config.json +39 -0
  155. src/_resources/locales/ja-JP/core.json +8 -0
  156. src/_resources/locales/ja-JP/prompts.json +8 -0
  157. src/_resources/locales/ja-JP/startup.json +98 -0
  158. src/_resources/locales/ko/config.json +39 -0
  159. src/_resources/locales/ko/core.json +8 -0
  160. src/_resources/locales/ko/prompts.json +8 -0
  161. src/_resources/locales/ko/startup.json +98 -0
  162. src/_resources/locales/zh-CN/config.json +39 -0
  163. src/_resources/locales/zh-CN/core.json +8 -0
  164. src/_resources/locales/zh-CN/prompts.json +8 -0
  165. src/_resources/locales/zh-CN/startup.json +98 -0
  166. src/_resources/prompts/en-US/.meta.toml +164 -0
  167. src/_resources/prompts/en-US/a_memorix_chat_summary.prompt +45 -0
  168. src/_resources/prompts/en-US/emoji_content_analysis.prompt +3 -0
  169. src/_resources/prompts/en-US/emoji_content_filtration.prompt +6 -0
  170. src/_resources/prompts/en-US/emoji_replace.prompt +12 -0
  171. src/_resources/prompts/en-US/emoji_selection.prompt +6 -0
  172. src/_resources/prompts/en-US/expression_evaluation.prompt +14 -0
  173. src/_resources/prompts/en-US/heuristic_memory_impression.prompt +15 -0
  174. src/_resources/prompts/en-US/image_description.prompt +1 -0
  175. src/_resources/prompts/en-US/jargon_compare_inference.prompt +14 -0
  176. src/_resources/prompts/en-US/jargon_inference_content_only.prompt +11 -0
  177. src/_resources/prompts/en-US/jargon_inference_with_context.prompt +19 -0
  178. src/_resources/prompts/en-US/learn_jargon.prompt +31 -0
  179. src/_resources/prompts/en-US/learn_style.prompt +28 -0
  180. src/_resources/prompts/en-US/maisaka_chat.prompt +28 -0
  181. src/_resources/prompts/en-US/maisaka_chat_focus.prompt +39 -0
  182. src/_resources/prompts/en-US/maisaka_chat_optimized.prompt +19 -0
  183. src/_resources/prompts/en-US/maisaka_replyer.prompt +10 -0
  184. src/_resources/prompts/en-US/memory_fuzzy_modify_plan.prompt +45 -0
  185. src/_resources/prompts/en-US/mid_term_memory_summary.prompt +10 -0
  186. src/_resources/prompts/en-US/reply_attachments.prompt +3 -0
  187. src/_resources/prompts/en-US/retro_private_replyer.prompt +13 -0
  188. src/_resources/prompts/en-US/retro_private_replyer_self.prompt +13 -0
  189. src/_resources/prompts/en-US/retro_replyer.prompt +17 -0
  190. src/_resources/prompts/en-US/retro_replyer_light.prompt +17 -0
  191. src/_resources/prompts/en-US/webui_ai_search.prompt +24 -0
  192. src/_resources/prompts/en-US/webui_ai_search_correction.prompt +1 -0
  193. src/_resources/prompts/en-US/webui_ai_search_evidence.prompt +3 -0
  194. src/_resources/prompts/en-US/webui_ai_search_final.prompt +1 -0
  195. src/_resources/prompts/ja-JP/.meta.toml +164 -0
  196. src/_resources/prompts/ja-JP/a_memorix_chat_summary.prompt +45 -0
  197. src/_resources/prompts/ja-JP/emoji_content_analysis.prompt +3 -0
  198. src/_resources/prompts/ja-JP/emoji_content_filtration.prompt +6 -0
  199. src/_resources/prompts/ja-JP/emoji_replace.prompt +12 -0
  200. src/_resources/prompts/ja-JP/emoji_selection.prompt +6 -0
  201. src/_resources/prompts/ja-JP/expression_evaluation.prompt +14 -0
  202. src/_resources/prompts/ja-JP/heuristic_memory_impression.prompt +15 -0
  203. src/_resources/prompts/ja-JP/image_description.prompt +1 -0
  204. src/_resources/prompts/ja-JP/jargon_compare_inference.prompt +14 -0
  205. src/_resources/prompts/ja-JP/jargon_inference_content_only.prompt +11 -0
  206. src/_resources/prompts/ja-JP/jargon_inference_with_context.prompt +19 -0
  207. src/_resources/prompts/ja-JP/learn_jargon.prompt +31 -0
  208. src/_resources/prompts/ja-JP/learn_style.prompt +28 -0
  209. src/_resources/prompts/ja-JP/maisaka_chat.prompt +28 -0
  210. src/_resources/prompts/ja-JP/maisaka_chat_focus.prompt +39 -0
  211. src/_resources/prompts/ja-JP/maisaka_chat_optimized.prompt +19 -0
  212. src/_resources/prompts/ja-JP/maisaka_replyer.prompt +10 -0
  213. src/_resources/prompts/ja-JP/memory_fuzzy_modify_plan.prompt +45 -0
  214. src/_resources/prompts/ja-JP/mid_term_memory_summary.prompt +10 -0
  215. src/_resources/prompts/ja-JP/reply_attachments.prompt +3 -0
  216. src/_resources/prompts/ja-JP/retro_private_replyer.prompt +13 -0
  217. src/_resources/prompts/ja-JP/retro_private_replyer_self.prompt +13 -0
  218. src/_resources/prompts/ja-JP/retro_replyer.prompt +17 -0
  219. src/_resources/prompts/ja-JP/retro_replyer_light.prompt +17 -0
  220. src/_resources/prompts/ja-JP/webui_ai_search.prompt +24 -0
  221. src/_resources/prompts/ja-JP/webui_ai_search_correction.prompt +1 -0
  222. src/_resources/prompts/ja-JP/webui_ai_search_evidence.prompt +3 -0
  223. src/_resources/prompts/ja-JP/webui_ai_search_final.prompt +1 -0
  224. src/_resources/prompts/ko/.meta.toml +4 -0
  225. src/_resources/prompts/ko/reply_attachments.prompt +3 -0
  226. src/_resources/prompts/zh-CN/.meta.toml +159 -0
  227. src/_resources/prompts/zh-CN/a_memorix_chat_summary.prompt +59 -0
  228. src/_resources/prompts/zh-CN/emoji_content_analysis.prompt +3 -0
  229. src/_resources/prompts/zh-CN/emoji_content_filtration.prompt +6 -0
  230. src/_resources/prompts/zh-CN/emoji_replace.prompt +12 -0
  231. src/_resources/prompts/zh-CN/emoji_selection.prompt +6 -0
  232. src/_resources/prompts/zh-CN/expression_evaluation.prompt +14 -0
  233. src/_resources/prompts/zh-CN/heuristic_memory_impression.prompt +15 -0
  234. src/_resources/prompts/zh-CN/image_description.prompt +1 -0
  235. src/_resources/prompts/zh-CN/jargon_compare_inference.prompt +14 -0
  236. src/_resources/prompts/zh-CN/jargon_inference_content_only.prompt +11 -0
  237. src/_resources/prompts/zh-CN/jargon_inference_with_context.prompt +19 -0
  238. src/_resources/prompts/zh-CN/learn_jargon.prompt +31 -0
  239. src/_resources/prompts/zh-CN/learn_style.prompt +28 -0
  240. src/_resources/prompts/zh-CN/maisaka_chat.prompt +28 -0
  241. src/_resources/prompts/zh-CN/maisaka_chat_focus.prompt +39 -0
  242. src/_resources/prompts/zh-CN/maisaka_chat_optimized.prompt +19 -0
  243. src/_resources/prompts/zh-CN/maisaka_replyer.prompt +6 -0
  244. src/_resources/prompts/zh-CN/memory_fuzzy_modify_plan.prompt +45 -0
  245. src/_resources/prompts/zh-CN/mid_term_memory_summary.prompt +10 -0
  246. src/_resources/prompts/zh-CN/reply_attachments.prompt +3 -0
  247. src/_resources/prompts/zh-CN/retro_private_replyer.prompt +13 -0
  248. src/_resources/prompts/zh-CN/retro_private_replyer_self.prompt +13 -0
  249. src/_resources/prompts/zh-CN/retro_replyer.prompt +17 -0
  250. src/_resources/prompts/zh-CN/retro_replyer_light.prompt +17 -0
  251. src/_resources/prompts/zh-CN/webui_ai_search.prompt +24 -0
  252. src/_resources/prompts/zh-CN/webui_ai_search_correction.prompt +1 -0
  253. src/_resources/prompts/zh-CN/webui_ai_search_evidence.prompt +3 -0
  254. src/_resources/prompts/zh-CN/webui_ai_search_final.prompt +1 -0
  255. src/_resources/pyproject.toml +156 -0
  256. src/chat/__init__.py +13 -0
  257. src/chat/heart_flow/heartFC_utils.py +29 -0
  258. src/chat/heart_flow/heartflow_manager.py +138 -0
  259. src/chat/heart_flow/heartflow_message_processor.py +104 -0
  260. src/chat/image_system/image_cache_cleanup.py +300 -0
  261. src/chat/image_system/image_manager.py +516 -0
  262. src/chat/message_receive/__init__.py +5 -0
  263. src/chat/message_receive/bot.py +893 -0
  264. src/chat/message_receive/chat_manager.py +540 -0
  265. src/chat/message_receive/image_receive_compressor.py +135 -0
  266. src/chat/message_receive/message.py +546 -0
  267. src/chat/message_receive/uni_message_sender.py +332 -0
  268. src/chat/replyer/expression_vector_index.py +3176 -0
  269. src/chat/replyer/maisaka_expression_selector.py +678 -0
  270. src/chat/replyer/maisaka_generator.py +25 -0
  271. src/chat/replyer/maisaka_generator_base.py +1457 -0
  272. src/chat/replyer/replyer_manager.py +62 -0
  273. src/chat/replyer/retro_prompt.py +512 -0
  274. src/chat/utils/llm_sentence_splitter.py +151 -0
  275. src/chat/utils/statistic.py +3170 -0
  276. src/chat/utils/typo_generator.py +495 -0
  277. src/chat/utils/utils.py +922 -0
  278. src/cli/__init__.py +3 -0
  279. src/cli/bot_console.py +281 -0
  280. src/cli/console.py +17 -0
  281. src/cli/input_reader.py +55 -0
  282. src/cli/maisaka_cli.py +122 -0
  283. src/cli/maisaka_cli_sender.py +28 -0
  284. src/cli/tool.py +62 -0
  285. src/common/__init__.py +1 -0
  286. src/common/data_models/__init__.py +28 -0
  287. src/common/data_models/chat_session_data_model.py +73 -0
  288. src/common/data_models/chat_target_info_data_model.py +73 -0
  289. src/common/data_models/embedding_service_data_models.py +31 -0
  290. src/common/data_models/expression_data_model.py +83 -0
  291. src/common/data_models/image_data_model.py +247 -0
  292. src/common/data_models/jargon_data_model.py +101 -0
  293. src/common/data_models/llm_data_model.py +23 -0
  294. src/common/data_models/llm_service_data_models.py +298 -0
  295. src/common/data_models/mai_message_data_model.py +226 -0
  296. src/common/data_models/message_component_data_model.py +560 -0
  297. src/common/data_models/person_info_data_model.py +177 -0
  298. src/common/data_models/reply_generation_data_models.py +275 -0
  299. src/common/data_models/tool_record_data_model.py +51 -0
  300. src/common/database/__init__.py +0 -0
  301. src/common/database/database.py +240 -0
  302. src/common/database/database_model.py +477 -0
  303. src/common/database/migrations/__init__.py +161 -0
  304. src/common/database/migrations/behavior_generic_tags.py +532 -0
  305. src/common/database/migrations/bootstrap.py +171 -0
  306. src/common/database/migrations/builtin.py +1966 -0
  307. src/common/database/migrations/exceptions.py +33 -0
  308. src/common/database/migrations/frozen_v2_schema.py +282 -0
  309. src/common/database/migrations/legacy_v1_to_v2.py +1300 -0
  310. src/common/database/migrations/manager.py +209 -0
  311. src/common/database/migrations/models.py +305 -0
  312. src/common/database/migrations/planner.py +108 -0
  313. src/common/database/migrations/progress.py +319 -0
  314. src/common/database/migrations/registry.py +98 -0
  315. src/common/database/migrations/resolver.py +135 -0
  316. src/common/database/migrations/schema.py +98 -0
  317. src/common/database/migrations/v10_to_v11.py +60 -0
  318. src/common/database/migrations/v11_to_v12.py +92 -0
  319. src/common/database/migrations/v12_to_v13.py +42 -0
  320. src/common/database/migrations/v13_to_v14.py +55 -0
  321. src/common/database/migrations/v14_to_v15.py +44 -0
  322. src/common/database/migrations/v15_to_v16.py +39 -0
  323. src/common/database/migrations/v16_to_v17.py +66 -0
  324. src/common/database/migrations/v17_to_v18.py +64 -0
  325. src/common/database/migrations/v18_to_v19.py +355 -0
  326. src/common/database/migrations/v19_to_v20.py +169 -0
  327. src/common/database/migrations/v20_to_v21.py +149 -0
  328. src/common/database/migrations/v21_to_v22.py +343 -0
  329. src/common/database/migrations/v22_to_v23.py +114 -0
  330. src/common/database/migrations/v23_to_v24.py +465 -0
  331. src/common/database/migrations/v24_to_v25.py +96 -0
  332. src/common/database/migrations/v25_to_v26.py +32 -0
  333. src/common/database/migrations/v26_to_v27.py +86 -0
  334. src/common/database/migrations/v27_to_v28.py +185 -0
  335. src/common/database/migrations/v28_to_v29.py +80 -0
  336. src/common/database/migrations/v29_to_v30.py +217 -0
  337. src/common/database/migrations/v2_to_v3.py +269 -0
  338. src/common/database/migrations/v30_to_v31.py +323 -0
  339. src/common/database/migrations/v31_to_v32.py +250 -0
  340. src/common/database/migrations/v32_to_v33.py +84 -0
  341. src/common/database/migrations/v33_to_v34.py +119 -0
  342. src/common/database/migrations/v34_to_v35.py +68 -0
  343. src/common/database/migrations/v35_to_v36.py +35 -0
  344. src/common/database/migrations/v36_to_v37.py +54 -0
  345. src/common/database/migrations/v37_to_v38.py +95 -0
  346. src/common/database/migrations/v38_to_v39.py +85 -0
  347. src/common/database/migrations/v39_to_v40.py +53 -0
  348. src/common/database/migrations/v3_to_v4.py +155 -0
  349. src/common/database/migrations/v40_to_v41.py +23 -0
  350. src/common/database/migrations/v41_to_v42.py +44 -0
  351. src/common/database/migrations/v42_to_v43.py +29 -0
  352. src/common/database/migrations/v4_to_v5.py +77 -0
  353. src/common/database/migrations/v5_to_v6.py +51 -0
  354. src/common/database/migrations/v6_to_v7.py +164 -0
  355. src/common/database/migrations/v7_to_v8.py +73 -0
  356. src/common/database/migrations/v8_to_v9.py +313 -0
  357. src/common/database/migrations/v9_to_v10.py +53 -0
  358. src/common/database/migrations/version_store.py +57 -0
  359. src/common/embedding_identity.py +43 -0
  360. src/common/event_loop_watchdog.py +72 -0
  361. src/common/i18n/__init__.py +70 -0
  362. src/common/i18n/exceptions.py +18 -0
  363. src/common/i18n/formatting.py +29 -0
  364. src/common/i18n/loaders.py +162 -0
  365. src/common/i18n/manager.py +201 -0
  366. src/common/logger.py +1009 -0
  367. src/common/logger_color_and_mapping.py +430 -0
  368. src/common/message_repository.py +287 -0
  369. src/common/message_server/__init__.py +19 -0
  370. src/common/message_server/api.py +190 -0
  371. src/common/message_server/server.py +130 -0
  372. src/common/operation_timing.py +52 -0
  373. src/common/paths.py +32 -0
  374. src/common/process_runner.py +142 -0
  375. src/common/prompt_i18n.py +416 -0
  376. src/common/remote.py +288 -0
  377. src/common/reply_effect_fingerprint.py +119 -0
  378. src/common/reply_effect_record_codec.py +40 -0
  379. src/common/runtime_loop.py +31 -0
  380. src/common/self_update.py +580 -0
  381. src/common/shutdown.py +55 -0
  382. src/common/update_notice.py +351 -0
  383. src/common/utils/image_path.py +39 -0
  384. src/common/utils/math_utils.py +122 -0
  385. src/common/utils/port_checker.py +97 -0
  386. src/common/utils/system_utils.py +11 -0
  387. src/common/utils/utils_action.py +32 -0
  388. src/common/utils/utils_config.py +613 -0
  389. src/common/utils/utils_file.py +56 -0
  390. src/common/utils/utils_image.py +257 -0
  391. src/common/utils/utils_message.py +871 -0
  392. src/common/utils/utils_person.py +55 -0
  393. src/common/utils/utils_session.py +42 -0
  394. src/common/utils/utils_voice.py +42 -0
  395. src/common/version.py +33 -0
  396. src/config/__init__.py +0 -0
  397. src/config/config.py +927 -0
  398. src/config/config_base.py +308 -0
  399. src/config/config_upgrade_hooks.py +675 -0
  400. src/config/config_utils.py +166 -0
  401. src/config/default_model_config.py +131 -0
  402. src/config/file_watcher.py +238 -0
  403. src/config/legacy_migration.py +424 -0
  404. src/config/legacy_upgrade_confirmation.py +225 -0
  405. src/config/model_configs.py +548 -0
  406. src/config/official_configs.py +6166 -0
  407. src/config/startup_bindings.py +201 -0
  408. src/core/__init__.py +6 -0
  409. src/core/announcement_manager.py +120 -0
  410. src/core/config_types.py +273 -0
  411. src/core/event_bus.py +225 -0
  412. src/core/local_operator.py +98 -0
  413. src/core/tooling.py +420 -0
  414. src/core/types.py +423 -0
  415. src/emoji_system/emoji_cache_cleanup.py +326 -0
  416. src/emoji_system/emoji_manager.py +1314 -0
  417. src/emoji_system/maisaka_tool.py +286 -0
  418. src/learners/expression_learner.py +927 -0
  419. src/learners/expression_review_store.py +216 -0
  420. src/learners/expression_style_utils.py +32 -0
  421. src/learners/expression_utils.py +299 -0
  422. src/learners/jargon_learner.py +873 -0
  423. src/learners/jargon_miner.py +885 -0
  424. src/learners/weighted_sampling.py +75 -0
  425. src/llm_models/LICENSE +21 -0
  426. src/llm_models/__init__.py +0 -0
  427. src/llm_models/exceptions.py +140 -0
  428. src/llm_models/generation_diagnostics.py +155 -0
  429. src/llm_models/image_normalizer.py +128 -0
  430. src/llm_models/model_client/__init__.py +29 -0
  431. src/llm_models/model_client/adapter_base.py +362 -0
  432. src/llm_models/model_client/base_client.py +678 -0
  433. src/llm_models/model_client/embedding_rate_limit.py +55 -0
  434. src/llm_models/model_client/gemini_client.py +1379 -0
  435. src/llm_models/model_client/image_embedding_protocols.py +397 -0
  436. src/llm_models/model_client/openai_client.py +2200 -0
  437. src/llm_models/model_client/openai_responses_client.py +817 -0
  438. src/llm_models/model_client/plugin_client.py +307 -0
  439. src/llm_models/openai_compat.py +165 -0
  440. src/llm_models/payload_content/__init__.py +51 -0
  441. src/llm_models/payload_content/context_item.py +699 -0
  442. src/llm_models/payload_content/context_protocol.py +243 -0
  443. src/llm_models/payload_content/native_tool.py +18 -0
  444. src/llm_models/payload_content/resp_format.py +239 -0
  445. src/llm_models/payload_content/tool_option.py +547 -0
  446. src/llm_models/request_snapshot.py +1311 -0
  447. src/llm_models/utils.py +276 -0
  448. src/llm_models/utils_model.py +1604 -0
  449. src/main.py +300 -0
  450. src/maisaka/attention_drift.py +116 -0
  451. src/maisaka/builtin_tool/__init__.py +236 -0
  452. src/maisaka/builtin_tool/context.py +530 -0
  453. src/maisaka/builtin_tool/fetch_history.py +62 -0
  454. src/maisaka/builtin_tool/provider.py +74 -0
  455. src/maisaka/builtin_tool/query_image_memory.py +103 -0
  456. src/maisaka/builtin_tool/query_memory.py +335 -0
  457. src/maisaka/builtin_tool/query_person_profile.py +152 -0
  458. src/maisaka/builtin_tool/read_tool_result.py +142 -0
  459. src/maisaka/builtin_tool/reply.py +695 -0
  460. src/maisaka/builtin_tool/send_emoji.py +543 -0
  461. src/maisaka/builtin_tool/show_emoji_list.py +76 -0
  462. src/maisaka/builtin_tool/subagent.py +549 -0
  463. src/maisaka/builtin_tool/switch_chat.py +78 -0
  464. src/maisaka/builtin_tool/tool_search.py +92 -0
  465. src/maisaka/builtin_tool/view_forward_message.py +153 -0
  466. src/maisaka/builtin_tool/wait.py +77 -0
  467. src/maisaka/chat_loop_service.py +1579 -0
  468. src/maisaka/context/__init__.py +1 -0
  469. src/maisaka/context/clear_context.py +42 -0
  470. src/maisaka/context/emoji_candidates.py +36 -0
  471. src/maisaka/context/history.py +384 -0
  472. src/maisaka/context/image_attachment.py +52 -0
  473. src/maisaka/context/message_adapter.py +126 -0
  474. src/maisaka/context/message_id_alias.py +52 -0
  475. src/maisaka/context/messages.py +825 -0
  476. src/maisaka/context/planner_messages.py +199 -0
  477. src/maisaka/context/post_processor.py +204 -0
  478. src/maisaka/context/usage.py +141 -0
  479. src/maisaka/display/__init__.py +25 -0
  480. src/maisaka/display/display_utils.py +144 -0
  481. src/maisaka/display/preview_path_utils.py +64 -0
  482. src/maisaka/display/prompt_cli_renderer.py +1110 -0
  483. src/maisaka/display/prompt_preview_logger.py +603 -0
  484. src/maisaka/display/runtime_mixin.py +709 -0
  485. src/maisaka/display/stage_status_board.py +129 -0
  486. src/maisaka/focus/__init__.py +10 -0
  487. src/maisaka/focus/manager.py +442 -0
  488. src/maisaka/focus/runtime_mixin.py +753 -0
  489. src/maisaka/jargon_context_matcher.py +363 -0
  490. src/maisaka/memory/__init__.py +1 -0
  491. src/maisaka/memory/heuristic_injector.py +393 -0
  492. src/maisaka/memory/image_injector.py +81 -0
  493. src/maisaka/memory/mid_term.py +995 -0
  494. src/maisaka/memory/person_profile.py +280 -0
  495. src/maisaka/mode_policy.py +28 -0
  496. src/maisaka/monitor/__init__.py +1 -0
  497. src/maisaka/monitor/event_store.py +351 -0
  498. src/maisaka/monitor/events.py +795 -0
  499. src/maisaka/monitor/message_payload.py +172 -0
  500. src/maisaka/monitor/planner_delta.py +77 -0
  501. src/maisaka/monitor/tool_media.py +58 -0
  502. src/maisaka/planner_reply_guard.py +69 -0
  503. src/maisaka/reasoning_engine.py +2186 -0
  504. src/maisaka/reply_effect/__init__.py +18 -0
  505. src/maisaka/reply_effect/image_utils.py +100 -0
  506. src/maisaka/reply_effect/judge.py +382 -0
  507. src/maisaka/reply_effect/models.py +185 -0
  508. src/maisaka/reply_effect/path_utils.py +24 -0
  509. src/maisaka/reply_effect/quote_utils.py +32 -0
  510. src/maisaka/reply_effect/scoring.py +205 -0
  511. src/maisaka/reply_effect/storage.py +380 -0
  512. src/maisaka/reply_effect/tracker.py +568 -0
  513. src/maisaka/runtime.py +2218 -0
  514. src/maisaka/subagent_tasks.py +171 -0
  515. src/maisaka/tool_result_condenser.py +143 -0
  516. src/maisaka/tool_result_store.py +57 -0
  517. src/maisaka/turn_trigger/__init__.py +9 -0
  518. src/maisaka/turn_trigger/dynamic_gate.py +211 -0
  519. src/maisaka/turn_trigger/gates.py +252 -0
  520. src/maisaka/turn_trigger/idle_backoff.py +93 -0
  521. src/maisaka/turn_trigger/reply_likelihood.py +88 -0
  522. src/maisaka/turn_trigger/scheduler.py +113 -0
  523. src/maisaka/utils/__init__.py +1 -0
  524. src/maisaka/utils/tool_post_execution.py +76 -0
  525. src/maisaka/utils/tool_record_payload.py +155 -0
  526. src/maisaka/visual/__init__.py +1 -0
  527. src/maisaka/visual/chat_history_refresher.py +303 -0
  528. src/maisaka/visual/message_limiter.py +69 -0
  529. src/maisaka/visual/mode_utils.py +33 -0
  530. src/manager/async_task_manager.py +193 -0
  531. src/manager/local_store_manager.py +126 -0
  532. src/mcp_module/__init__.py +9 -0
  533. src/mcp_module/config.py +174 -0
  534. src/mcp_module/connection.py +726 -0
  535. src/mcp_module/hooks.py +20 -0
  536. src/mcp_module/host_llm_bridge.py +654 -0
  537. src/mcp_module/manager.py +680 -0
  538. src/mcp_module/models.py +437 -0
  539. src/mcp_module/provider.py +62 -0
  540. src/mcp_module/service.py +308 -0
  541. src/mcp_module/stdio_filter.py +177 -0
  542. src/person_info/__init__.py +0 -0
  543. src/person_info/person_info.py +600 -0
  544. src/platform_io/__init__.py +39 -0
  545. src/platform_io/adapter_policy.py +839 -0
  546. src/platform_io/avatar.py +197 -0
  547. src/platform_io/dedupe.py +133 -0
  548. src/platform_io/drivers/__init__.py +11 -0
  549. src/platform_io/drivers/base.py +104 -0
  550. src/platform_io/drivers/legacy_driver.py +92 -0
  551. src/platform_io/drivers/plugin_driver.py +213 -0
  552. src/platform_io/manager.py +716 -0
  553. src/platform_io/outbound_tracker.py +286 -0
  554. src/platform_io/registry.py +70 -0
  555. src/platform_io/route_key_factory.py +174 -0
  556. src/platform_io/routing.py +141 -0
  557. src/platform_io/types.py +265 -0
  558. src/plugin_runtime/__init__.py +60 -0
  559. src/plugin_runtime/avatar_provider.py +64 -0
  560. src/plugin_runtime/capabilities/__init__.py +11 -0
  561. src/plugin_runtime/capabilities/components.py +977 -0
  562. src/plugin_runtime/capabilities/core.py +868 -0
  563. src/plugin_runtime/capabilities/data.py +1415 -0
  564. src/plugin_runtime/capabilities/registry.py +116 -0
  565. src/plugin_runtime/capabilities/render.py +131 -0
  566. src/plugin_runtime/compat_policy.py +47 -0
  567. src/plugin_runtime/component_query.py +1119 -0
  568. src/plugin_runtime/dependency_pipeline.py +547 -0
  569. src/plugin_runtime/docker_layout_migration.py +275 -0
  570. src/plugin_runtime/hook_catalog.py +52 -0
  571. src/plugin_runtime/hook_payloads.py +197 -0
  572. src/plugin_runtime/hook_schema_utils.py +31 -0
  573. src/plugin_runtime/host/__init__.py +1 -0
  574. src/plugin_runtime/host/api_registry.py +353 -0
  575. src/plugin_runtime/host/authorization.py +67 -0
  576. src/plugin_runtime/host/capability_service.py +91 -0
  577. src/plugin_runtime/host/circuit_breaker.py +243 -0
  578. src/plugin_runtime/host/component_registry.py +1336 -0
  579. src/plugin_runtime/host/component_timeout.py +32 -0
  580. src/plugin_runtime/host/event_dispatcher.py +228 -0
  581. src/plugin_runtime/host/hook_dispatcher.py +711 -0
  582. src/plugin_runtime/host/hook_spec_registry.py +190 -0
  583. src/plugin_runtime/host/logger_bridge.py +64 -0
  584. src/plugin_runtime/host/message_gateway.py +116 -0
  585. src/plugin_runtime/host/message_utils.py +572 -0
  586. src/plugin_runtime/host/reply_extension_schema.py +65 -0
  587. src/plugin_runtime/host/reply_extensions.py +204 -0
  588. src/plugin_runtime/host/rpc_server.py +509 -0
  589. src/plugin_runtime/host/supervisor.py +2269 -0
  590. src/plugin_runtime/integration.py +2063 -0
  591. src/plugin_runtime/local_sdk.py +147 -0
  592. src/plugin_runtime/protocol/__init__.py +1 -0
  593. src/plugin_runtime/protocol/codec.py +71 -0
  594. src/plugin_runtime/protocol/envelope.py +600 -0
  595. src/plugin_runtime/protocol/errors.py +77 -0
  596. src/plugin_runtime/runner/__init__.py +1 -0
  597. src/plugin_runtime/runner/log_handler.py +239 -0
  598. src/plugin_runtime/runner/manifest_validator.py +1517 -0
  599. src/plugin_runtime/runner/plugin_loader.py +711 -0
  600. src/plugin_runtime/runner/plugin_paths.py +59 -0
  601. src/plugin_runtime/runner/rpc_client.py +336 -0
  602. src/plugin_runtime/runner/runner_main.py +2670 -0
  603. src/plugin_runtime/tool_provider.py +58 -0
  604. src/plugin_runtime/transport/__init__.py +1 -0
  605. src/plugin_runtime/transport/base.py +116 -0
  606. src/plugin_runtime/transport/factory.py +57 -0
  607. src/plugin_runtime/transport/named_pipe.py +206 -0
  608. src/plugin_runtime/transport/tcp.py +62 -0
  609. src/plugin_runtime/transport/uds.py +133 -0
  610. src/plugin_runtime/update_compatibility_notice.py +303 -0
  611. src/plugin_runtime/upload_store.py +173 -0
  612. src/plugin_runtime/webui_schema.py +571 -0
  613. src/plugins/__init__.py +1 -0
  614. src/plugins/built_in/plugin_management/_manifest.json +48 -0
  615. src/plugins/built_in/plugin_management/plugin.py +665 -0
  616. src/prompt/prompt_manager.py +440 -0
  617. src/runtime.py +688 -0
  618. src/services/__init__.py +7 -0
  619. src/services/bot_account_service.py +327 -0
  620. src/services/database_service.py +203 -0
  621. src/services/embedding_service.py +271 -0
  622. src/services/expression_vector_service.py +106 -0
  623. src/services/html_render_service.py +945 -0
  624. src/services/image_path_maintenance_service.py +454 -0
  625. src/services/image_writeback_journal.py +98 -0
  626. src/services/llm_cache_stats.py +1521 -0
  627. src/services/llm_service.py +799 -0
  628. src/services/memory_flow_service.py +1019 -0
  629. src/services/memory_service.py +528 -0
  630. src/services/message_service.py +295 -0
  631. src/services/message_word_frequency_service.py +595 -0
  632. src/services/news_service.py +123 -0
  633. src/services/person_fact_reverification.py +90 -0
  634. src/services/person_fact_verifier.py +79 -0
  635. src/services/send_service.py +1483 -0
  636. src/services/service_task_resolver.py +59 -0
  637. src/services/statistics_aggregation_service.py +349 -0
  638. src/services/statistics_service.py +850 -0
  639. src/services/telemetry_stats_service.py +294 -0
  640. src/services/tool_record_cleanup_service.py +205 -0
  641. src/webui/app.py +374 -0
  642. src/webui/config_schema.py +481 -0
  643. src/webui/core/__init__.py +32 -0
  644. src/webui/core/auth.py +153 -0
  645. src/webui/core/rate_limiter.py +247 -0
  646. src/webui/core/security.py +361 -0
  647. src/webui/dependencies.py +70 -0
  648. src/webui/logs_ws.py +195 -0
  649. src/webui/middleware/__init__.py +17 -0
  650. src/webui/middleware/anti_crawler.py +824 -0
  651. src/webui/middleware/compression.py +88 -0
  652. src/webui/routers/__init__.py +33 -0
  653. src/webui/routers/avatar.py +250 -0
  654. src/webui/routers/bot_accounts.py +103 -0
  655. src/webui/routers/chat/__init__.py +18 -0
  656. src/webui/routers/chat/routes.py +1715 -0
  657. src/webui/routers/chat/serializers.py +248 -0
  658. src/webui/routers/chat/service.py +1489 -0
  659. src/webui/routers/config.py +1964 -0
  660. src/webui/routers/data_transfer.py +769 -0
  661. src/webui/routers/emoji/__init__.py +3 -0
  662. src/webui/routers/emoji/routes.py +1230 -0
  663. src/webui/routers/emoji/schemas.py +182 -0
  664. src/webui/routers/emoji/support.py +143 -0
  665. src/webui/routers/expression.py +2298 -0
  666. src/webui/routers/jargon.py +1319 -0
  667. src/webui/routers/mcp.py +99 -0
  668. src/webui/routers/memory.py +5589 -0
  669. src/webui/routers/model.py +910 -0
  670. src/webui/routers/news.py +23 -0
  671. src/webui/routers/person.py +427 -0
  672. src/webui/routers/plugin/__init__.py +31 -0
  673. src/webui/routers/plugin/catalog.py +218 -0
  674. src/webui/routers/plugin/config_routes.py +592 -0
  675. src/webui/routers/plugin/icon_routes.py +71 -0
  676. src/webui/routers/plugin/management.py +908 -0
  677. src/webui/routers/plugin/marketplace.py +116 -0
  678. src/webui/routers/plugin/progress.py +172 -0
  679. src/webui/routers/plugin/release_install.py +313 -0
  680. src/webui/routers/plugin/releases.py +181 -0
  681. src/webui/routers/plugin/runtime_routes.py +243 -0
  682. src/webui/routers/plugin/schemas.py +131 -0
  683. src/webui/routers/plugin/stats_proxy.py +127 -0
  684. src/webui/routers/plugin/support.py +366 -0
  685. src/webui/routers/plugin/webui_extensions.py +346 -0
  686. src/webui/routers/plugin/zip_install.py +125 -0
  687. src/webui/routers/reasoning_process.py +2326 -0
  688. src/webui/routers/reply_effects.py +926 -0
  689. src/webui/routers/search.py +249 -0
  690. src/webui/routers/self_update.py +194 -0
  691. src/webui/routers/statistics.py +61 -0
  692. src/webui/routers/system.py +1790 -0
  693. src/webui/routers/user_emoji.py +168 -0
  694. src/webui/routers/websocket/__init__.py +7 -0
  695. src/webui/routers/websocket/auth.py +104 -0
  696. src/webui/routers/websocket/manager.py +373 -0
  697. src/webui/routers/websocket/plugin_runtime.py +54 -0
  698. src/webui/routers/websocket/unified.py +761 -0
  699. src/webui/routes.py +416 -0
  700. src/webui/schemas/__init__.py +18 -0
  701. src/webui/schemas/news.py +24 -0
  702. src/webui/schemas/statistics.py +173 -0
  703. src/webui/services/__init__.py +1 -0
  704. src/webui/services/ai_search_agent.py +509 -0
  705. src/webui/services/ai_search_documents.py +329 -0
  706. src/webui/services/ai_search_grounding.py +103 -0
  707. src/webui/services/ai_search_local_config.py +129 -0
  708. src/webui/services/ai_search_models.py +98 -0
  709. src/webui/services/git_mirror_service.py +1024 -0
  710. src/webui/services/plugin_market_service.py +56 -0
  711. src/webui/utils/__init__.py +1 -0
  712. src/webui/utils/http_client.py +27 -0
  713. src/webui/utils/network_security.py +133 -0
  714. src/webui/utils/toml_utils.py +124 -0
  715. src/webui/version_compatibility.py +180 -0
  716. src/webui/webui_server.py +422 -0
@@ -0,0 +1,1966 @@
1
+ """数据库迁移内置版本与默认注册表。"""
2
+
3
+ from typing import List, Optional
4
+
5
+ from .legacy_v1_to_v2 import migrate_legacy_v1_to_v2
6
+ from .models import DatabaseSchemaSnapshot, MigrationStep
7
+ from .registry import MigrationRegistry
8
+ from .resolver import BaseSchemaVersionDetector, SchemaVersionResolver
9
+ from .schema import SQLiteSchemaInspector
10
+ from .v2_to_v3 import migrate_v2_to_v3
11
+ from .v3_to_v4 import migrate_v3_to_v4
12
+ from .v4_to_v5 import migrate_v4_to_v5
13
+ from .v5_to_v6 import migrate_v5_to_v6
14
+ from .v6_to_v7 import migrate_v6_to_v7
15
+ from .v7_to_v8 import migrate_v7_to_v8
16
+ from .v8_to_v9 import migrate_v8_to_v9
17
+ from .v9_to_v10 import migrate_v9_to_v10
18
+ from .v10_to_v11 import migrate_v10_to_v11
19
+ from .v11_to_v12 import migrate_v11_to_v12
20
+ from .v12_to_v13 import migrate_v12_to_v13
21
+ from .v13_to_v14 import migrate_v13_to_v14
22
+ from .v14_to_v15 import migrate_v14_to_v15
23
+ from .v15_to_v16 import migrate_v15_to_v16
24
+ from .v16_to_v17 import migrate_v16_to_v17
25
+ from .v17_to_v18 import migrate_v17_to_v18
26
+ from .v18_to_v19 import migrate_v18_to_v19
27
+ from .v19_to_v20 import migrate_v19_to_v20
28
+ from .v20_to_v21 import migrate_v20_to_v21
29
+ from .v21_to_v22 import LEGACY_V1_CLEANUP_TABLES, migrate_v21_to_v22
30
+ from .v22_to_v23 import migrate_v22_to_v23
31
+ from .v23_to_v24 import migrate_v23_to_v24
32
+ from .v24_to_v25 import migrate_v24_to_v25
33
+ from .v25_to_v26 import migrate_v25_to_v26
34
+ from .v26_to_v27 import migrate_v26_to_v27
35
+ from .v27_to_v28 import migrate_v27_to_v28
36
+ from .v28_to_v29 import migrate_v28_to_v29
37
+ from .v29_to_v30 import migrate_v29_to_v30
38
+ from .v30_to_v31 import migrate_v30_to_v31
39
+ from .v31_to_v32 import migrate_v31_to_v32
40
+ from .v32_to_v33 import migrate_v32_to_v33
41
+ from .v33_to_v34 import migrate_v33_to_v34
42
+ from .v34_to_v35 import migrate_v34_to_v35
43
+ from .v35_to_v36 import migrate_v35_to_v36
44
+ from .v36_to_v37 import migrate_v36_to_v37
45
+ from .v37_to_v38 import migrate_v37_to_v38
46
+ from .v38_to_v39 import migrate_v38_to_v39
47
+ from .v39_to_v40 import migrate_v39_to_v40
48
+ from .v40_to_v41 import migrate_v40_to_v41
49
+ from .v41_to_v42 import BEHAVIOR_TABLES, migrate_v41_to_v42
50
+ from .v42_to_v43 import migrate_v42_to_v43
51
+ from .version_store import SQLiteUserVersionStore
52
+
53
+ EMPTY_SCHEMA_VERSION = 0
54
+ LEGACY_V1_SCHEMA_VERSION = 1
55
+ V2_SCHEMA_VERSION = 2
56
+ V3_SCHEMA_VERSION = 3
57
+ V4_SCHEMA_VERSION = 4
58
+ V5_SCHEMA_VERSION = 5
59
+ V6_SCHEMA_VERSION = 6
60
+ V7_SCHEMA_VERSION = 7
61
+ V8_SCHEMA_VERSION = 8
62
+ V9_SCHEMA_VERSION = 9
63
+ V10_SCHEMA_VERSION = 10
64
+ V11_SCHEMA_VERSION = 11
65
+ V12_SCHEMA_VERSION = 12
66
+ V13_SCHEMA_VERSION = 13
67
+ V14_SCHEMA_VERSION = 14
68
+ V15_SCHEMA_VERSION = 15
69
+ V16_SCHEMA_VERSION = 16
70
+ V17_SCHEMA_VERSION = 17
71
+ V18_SCHEMA_VERSION = 18
72
+ V19_SCHEMA_VERSION = 19
73
+ V20_SCHEMA_VERSION = 20
74
+ V21_SCHEMA_VERSION = 21
75
+ V22_SCHEMA_VERSION = 22
76
+ V23_SCHEMA_VERSION = 23
77
+ V24_SCHEMA_VERSION = 24
78
+ V25_SCHEMA_VERSION = 25
79
+ V26_SCHEMA_VERSION = 26
80
+ V27_SCHEMA_VERSION = 27
81
+ V28_SCHEMA_VERSION = 28
82
+ V29_SCHEMA_VERSION = 29
83
+ V30_SCHEMA_VERSION = 30
84
+ V31_SCHEMA_VERSION = 31
85
+ V32_SCHEMA_VERSION = 32
86
+ V33_SCHEMA_VERSION = 33
87
+ V34_SCHEMA_VERSION = 34
88
+ V35_SCHEMA_VERSION = 35
89
+ V36_SCHEMA_VERSION = 36
90
+ V37_SCHEMA_VERSION = 37
91
+ V38_SCHEMA_VERSION = 38
92
+ V39_SCHEMA_VERSION = 39
93
+ V40_SCHEMA_VERSION = 40
94
+ V41_SCHEMA_VERSION = 41
95
+ V42_SCHEMA_VERSION = 42
96
+ V43_SCHEMA_VERSION = 43
97
+ LATEST_SCHEMA_VERSION = 43
98
+
99
+ _LEGACY_V1_EXCLUSIVE_TABLES = (
100
+ "chat_streams",
101
+ "emoji",
102
+ "emoji_description_cache",
103
+ "expression",
104
+ "group_info",
105
+ "image_descriptions",
106
+ "jargon",
107
+ "messages",
108
+ "thinking_back",
109
+ )
110
+ _COMMON_MARKER_TABLES = (
111
+ "mai_messages",
112
+ "chat_sessions",
113
+ "expressions",
114
+ "jargons",
115
+ "tool_records",
116
+ )
117
+ def _detect_v13_base_schema(snapshot: DatabaseSchemaSnapshot) -> bool:
118
+ """判断数据库是否满足 v13 共有结构条件。"""
119
+
120
+ if any(snapshot.has_table(table_name) for table_name in _LEGACY_V1_EXCLUSIVE_TABLES):
121
+ return False
122
+ if not all(snapshot.has_table(table_name) for table_name in _COMMON_MARKER_TABLES):
123
+ return False
124
+ if snapshot.has_table("action_records"):
125
+ return False
126
+ if snapshot.has_table("thinking_questions"):
127
+ return False
128
+ if snapshot.has_column("images", "emotion"):
129
+ return False
130
+ if not snapshot.has_column("images", "image_hash"):
131
+ return False
132
+ if not snapshot.has_column("images", "full_path"):
133
+ return False
134
+ if not snapshot.has_column("images", "image_type"):
135
+ return False
136
+ if snapshot.has_table("chat_history") and not snapshot.has_column("chat_history", "session_id"):
137
+ return False
138
+ if not snapshot.has_column("person_info", "user_nickname"):
139
+ return False
140
+ if not snapshot.has_column("chat_sessions", "account_id"):
141
+ return False
142
+ if not snapshot.has_column("chat_sessions", "scope"):
143
+ return False
144
+ if not snapshot.has_column("chat_sessions", "user_nickname"):
145
+ return False
146
+ if not snapshot.has_column("chat_sessions", "user_cardname"):
147
+ return False
148
+ if not snapshot.has_column("chat_sessions", "group_name"):
149
+ return False
150
+ if snapshot.has_column("expressions", "rejected"):
151
+ return False
152
+ if snapshot.has_column("mai_messages", "display_message"):
153
+ return False
154
+ if not snapshot.has_table("statistics_message_hourly"):
155
+ return False
156
+ if not snapshot.has_table("statistics_tool_hourly"):
157
+ return False
158
+ if not snapshot.has_table("statistics_model_hourly"):
159
+ return False
160
+ if not snapshot.has_table("statistics_aggregation_cursors"):
161
+ return False
162
+ if not snapshot.has_column("jargons", "created_timestamp"):
163
+ return False
164
+ if not snapshot.has_column("jargons", "updated_timestamp"):
165
+ return False
166
+ if snapshot.has_column("jargons", "inference_with_context"):
167
+ return False
168
+ if snapshot.has_column("jargons", "inference_with_content_only"):
169
+ return False
170
+ if not snapshot.has_column("jargons", "created_by"):
171
+ return False
172
+ return True
173
+
174
+
175
+ def _detect_v18_base_schema(snapshot: DatabaseSchemaSnapshot) -> bool:
176
+ """判断数据库是否满足 v18 共有结构条件。"""
177
+
178
+ if not _detect_v18_common_schema(snapshot):
179
+ return False
180
+ if not snapshot.has_table("behavior_patterns"):
181
+ return False
182
+ if not snapshot.has_column("behavior_patterns", "trigger"):
183
+ return False
184
+ if not snapshot.has_column("behavior_patterns", "action"):
185
+ return False
186
+ if not snapshot.has_column("behavior_patterns", "outcome"):
187
+ return False
188
+ if not snapshot.has_column("behavior_patterns", "score"):
189
+ return False
190
+ if not snapshot.has_column("behavior_patterns", "enabled"):
191
+ return False
192
+ return True
193
+
194
+
195
+ def _detect_v18_common_schema(snapshot: DatabaseSchemaSnapshot, *, use_latest_high_frequency_terms: bool = False) -> bool:
196
+ """判断数据库是否满足 v18 之后行为学习以外的共有结构条件。"""
197
+
198
+ if not _detect_v13_base_schema(snapshot):
199
+ return False
200
+ if not snapshot.has_column("mai_messages", "reply_frequency"):
201
+ return False
202
+ if not snapshot.has_column("llm_usage", "task_name"):
203
+ return False
204
+ if not snapshot.has_column("llm_usage", "prompt_cache_hit_tokens"):
205
+ return False
206
+ if not snapshot.has_column("llm_usage", "prompt_cache_miss_tokens"):
207
+ return False
208
+ if not snapshot.has_column("llm_usage", "prompt_cache_enabled"):
209
+ return False
210
+ if use_latest_high_frequency_terms:
211
+ if not _detect_latest_high_frequency_terms_schema(snapshot):
212
+ return False
213
+ elif not _detect_legacy_high_frequency_terms_schema(snapshot):
214
+ return False
215
+ return True
216
+
217
+
218
+ def _detect_legacy_high_frequency_terms_schema(snapshot: DatabaseSchemaSnapshot) -> bool:
219
+ """判断高频词表是否为 v18-v28 的全局词频结构。"""
220
+
221
+ if not snapshot.has_table("high_frequency_terms"):
222
+ return False
223
+ if not snapshot.has_column("high_frequency_terms", "term"):
224
+ return False
225
+ if not snapshot.has_column("high_frequency_terms", "normalized_term"):
226
+ return False
227
+ if not snapshot.has_column("high_frequency_terms", "updated_at"):
228
+ return False
229
+ return True
230
+
231
+
232
+ def _detect_latest_high_frequency_terms_schema(snapshot: DatabaseSchemaSnapshot) -> bool:
233
+ """判断高频词表是否为按聊天流分类的当前结构。"""
234
+
235
+ if not snapshot.has_table("high_frequency_terms"):
236
+ return False
237
+ if not snapshot.has_column("high_frequency_terms", "chat_id"):
238
+ return False
239
+ if not snapshot.has_column("high_frequency_terms", "term"):
240
+ return False
241
+ if snapshot.has_column("high_frequency_terms", "normalized_term"):
242
+ return False
243
+ if snapshot.has_column("high_frequency_terms", "term_type"):
244
+ return False
245
+ if not snapshot.has_column("high_frequency_terms", "updated_at"):
246
+ return False
247
+ return True
248
+
249
+
250
+ def _detect_v19_base_schema(snapshot: DatabaseSchemaSnapshot) -> bool:
251
+ """判断数据库是否满足 v19 节点化行为经验路径结构。"""
252
+
253
+ if not _detect_v18_common_schema(snapshot):
254
+ return False
255
+ if snapshot.has_table("command_records"):
256
+ return False
257
+ if snapshot.has_table("behavior_patterns"):
258
+ return False
259
+ if snapshot.has_table("behavior_pattern_scene_links"):
260
+ return False
261
+ if not snapshot.has_table("behavior_experience_paths"):
262
+ return False
263
+ if not snapshot.has_column("behavior_experience_paths", "start_scene_node_id"):
264
+ return False
265
+ if not snapshot.has_column("behavior_experience_paths", "action_node_id"):
266
+ return False
267
+ if not snapshot.has_column("behavior_experience_paths", "outcome_node_id"):
268
+ return False
269
+ if not snapshot.has_table("behavior_experience_scene_links"):
270
+ return False
271
+ if not snapshot.has_column("behavior_experience_scene_links", "behavior_experience_path_id"):
272
+ return False
273
+ if not snapshot.has_table("behavior_scene_nodes"):
274
+ return False
275
+ if not snapshot.has_table("behavior_scene_edges"):
276
+ return False
277
+ if not snapshot.has_table("behavior_action_nodes"):
278
+ return False
279
+ if snapshot.has_column("behavior_action_nodes", "normalized_action"):
280
+ return False
281
+ if not snapshot.has_table("behavior_outcome_nodes"):
282
+ return False
283
+ if snapshot.has_column("behavior_outcome_nodes", "normalized_outcome"):
284
+ return False
285
+ if not snapshot.has_table("behavior_scene_action_edges"):
286
+ return False
287
+ if not snapshot.has_column("behavior_scene_action_edges", "behavior_experience_path_id"):
288
+ return False
289
+ if snapshot.has_column("behavior_scene_action_edges", "behavior_pattern_id"):
290
+ return False
291
+ if not snapshot.has_table("behavior_action_outcome_edges"):
292
+ return False
293
+ if not snapshot.has_column("behavior_action_outcome_edges", "behavior_experience_path_id"):
294
+ return False
295
+ if snapshot.has_column("behavior_action_outcome_edges", "behavior_pattern_id"):
296
+ return False
297
+ return True
298
+
299
+
300
+ def _detect_v20_base_schema(snapshot: DatabaseSchemaSnapshot) -> bool:
301
+ """判断数据库是否满足独立场景簇行为经验路径结构。"""
302
+
303
+ if not _detect_v18_common_schema(snapshot):
304
+ return False
305
+ if not snapshot.has_table("behavior_scene_clusters"):
306
+ return False
307
+ if not snapshot.has_column("behavior_scene_clusters", "tag_distribution"):
308
+ return False
309
+ if not snapshot.has_column("behavior_scene_clusters", "normalized_tags"):
310
+ return False
311
+ if not snapshot.has_table("behavior_experience_paths"):
312
+ return False
313
+ if not snapshot.has_column("behavior_experience_paths", "scene_cluster_id"):
314
+ return False
315
+ if snapshot.has_column("behavior_experience_paths", "actor_type"):
316
+ return False
317
+ if snapshot.has_column("behavior_experience_paths", "learning_type"):
318
+ return False
319
+ if snapshot.has_column("behavior_experience_paths", "start_scene_node_id"):
320
+ return False
321
+ if not snapshot.has_table("behavior_experience_scene_links"):
322
+ return False
323
+ if not snapshot.has_table("behavior_scene_nodes"):
324
+ return False
325
+ if not snapshot.has_table("behavior_scene_edges"):
326
+ return False
327
+ if not snapshot.has_table("behavior_action_nodes"):
328
+ return False
329
+ if not snapshot.has_table("behavior_outcome_nodes"):
330
+ return False
331
+ if not snapshot.has_table("behavior_scene_action_edges"):
332
+ return False
333
+ if not snapshot.has_table("behavior_action_outcome_edges"):
334
+ return False
335
+ return True
336
+
337
+
338
+ def _detect_v21_base_schema(snapshot: DatabaseSchemaSnapshot) -> bool:
339
+ """判断数据库是否满足区分观察学习与自身反馈的行为路径结构。"""
340
+
341
+ if not _detect_v18_common_schema(snapshot):
342
+ return False
343
+ if not snapshot.has_table("behavior_scene_clusters"):
344
+ return False
345
+ if not snapshot.has_column("behavior_scene_clusters", "tag_distribution"):
346
+ return False
347
+ if not snapshot.has_column("behavior_scene_clusters", "normalized_tags"):
348
+ return False
349
+ if not snapshot.has_table("behavior_experience_paths"):
350
+ return False
351
+ if not snapshot.has_column("behavior_experience_paths", "scene_cluster_id"):
352
+ return False
353
+ if not snapshot.has_column("behavior_experience_paths", "actor_type"):
354
+ return False
355
+ if not snapshot.has_column("behavior_experience_paths", "learning_type"):
356
+ return False
357
+ if snapshot.has_column("behavior_experience_paths", "start_scene_node_id"):
358
+ return False
359
+ if not snapshot.has_table("behavior_experience_scene_links"):
360
+ return False
361
+ if not snapshot.has_table("behavior_scene_nodes"):
362
+ return False
363
+ if not snapshot.has_table("behavior_scene_edges"):
364
+ return False
365
+ if not snapshot.has_table("behavior_action_nodes"):
366
+ return False
367
+ if not snapshot.has_table("behavior_outcome_nodes"):
368
+ return False
369
+ if not snapshot.has_table("behavior_scene_action_edges"):
370
+ return False
371
+ if not snapshot.has_table("behavior_action_outcome_edges"):
372
+ return False
373
+ return True
374
+
375
+
376
+ def _detect_v22_base_schema(snapshot: DatabaseSchemaSnapshot) -> bool:
377
+ """判断数据库是否满足合并后的行为场景 tag 簇索引结构。"""
378
+
379
+ if not _detect_v21_base_schema(snapshot):
380
+ return False
381
+ if not snapshot.has_table("behavior_scene_tag_clusters"):
382
+ return False
383
+ if not snapshot.has_column("behavior_scene_tag_clusters", "tag_kind"):
384
+ return False
385
+ if not snapshot.has_column("behavior_scene_tag_clusters", "tag"):
386
+ return False
387
+ if not snapshot.has_column("behavior_scene_tag_clusters", "cluster_key"):
388
+ return False
389
+ if snapshot.has_column("behavior_scene_tag_clusters", "normalized_tag"):
390
+ return False
391
+ if snapshot.has_column("behavior_scene_tag_clusters", "display_tag"):
392
+ return False
393
+ if snapshot.has_column("behavior_scene_tag_clusters", "cluster_name"):
394
+ return False
395
+ if snapshot.has_column("behavior_scene_tag_clusters", "tag_members"):
396
+ return False
397
+ if snapshot.has_column("behavior_scene_nodes", "normalized_name"):
398
+ return False
399
+ if not snapshot.has_table("behavior_scene_node_tags"):
400
+ return False
401
+ if not snapshot.has_column("behavior_scene_node_tags", "scene_node_id"):
402
+ return False
403
+ if not snapshot.has_column("behavior_scene_node_tags", "tag_kind"):
404
+ return False
405
+ if not snapshot.has_column("behavior_scene_node_tags", "cluster_key"):
406
+ return False
407
+ return True
408
+
409
+
410
+ def _detect_v23_base_schema(snapshot: DatabaseSchemaSnapshot) -> bool:
411
+ """判断数据库是否满足移除场景簇冗余字段后的行为场景结构。"""
412
+
413
+ if not _detect_v18_common_schema(snapshot):
414
+ return False
415
+ if not snapshot.has_table("behavior_scene_clusters"):
416
+ return False
417
+ if snapshot.has_column("behavior_scene_clusters", "name"):
418
+ return False
419
+ if snapshot.has_column("behavior_scene_clusters", "normalized_tags"):
420
+ return False
421
+ if not snapshot.has_column("behavior_scene_clusters", "tag_distribution"):
422
+ return False
423
+ if not snapshot.has_table("behavior_experience_paths"):
424
+ return False
425
+ if not snapshot.has_column("behavior_experience_paths", "scene_cluster_id"):
426
+ return False
427
+ if not snapshot.has_column("behavior_experience_paths", "actor_type"):
428
+ return False
429
+ if not snapshot.has_column("behavior_experience_paths", "learning_type"):
430
+ return False
431
+ if snapshot.has_column("behavior_experience_paths", "start_scene_node_id"):
432
+ return False
433
+ if not snapshot.has_table("behavior_experience_scene_links"):
434
+ return False
435
+ if not snapshot.has_table("behavior_scene_nodes"):
436
+ return False
437
+ if snapshot.has_column("behavior_scene_nodes", "normalized_name"):
438
+ return False
439
+ if not snapshot.has_table("behavior_scene_edges"):
440
+ return False
441
+ if not snapshot.has_table("behavior_action_nodes"):
442
+ return False
443
+ if not snapshot.has_table("behavior_outcome_nodes"):
444
+ return False
445
+ if not snapshot.has_table("behavior_scene_action_edges"):
446
+ return False
447
+ if not snapshot.has_table("behavior_action_outcome_edges"):
448
+ return False
449
+ if not snapshot.has_table("behavior_scene_tag_clusters"):
450
+ return False
451
+ if not snapshot.has_column("behavior_scene_tag_clusters", "tag_kind"):
452
+ return False
453
+ if not snapshot.has_column("behavior_scene_tag_clusters", "tag"):
454
+ return False
455
+ if not snapshot.has_column("behavior_scene_tag_clusters", "cluster_key"):
456
+ return False
457
+ if snapshot.has_column("behavior_scene_tag_clusters", "normalized_tag"):
458
+ return False
459
+ if snapshot.has_column("behavior_scene_tag_clusters", "display_tag"):
460
+ return False
461
+ if snapshot.has_column("behavior_scene_tag_clusters", "cluster_name"):
462
+ return False
463
+ if snapshot.has_column("behavior_scene_tag_clusters", "tag_members"):
464
+ return False
465
+ if not snapshot.has_table("behavior_scene_node_tags"):
466
+ return False
467
+ if not snapshot.has_column("behavior_scene_node_tags", "scene_node_id"):
468
+ return False
469
+ if not snapshot.has_column("behavior_scene_node_tags", "tag_kind"):
470
+ return False
471
+ if not snapshot.has_column("behavior_scene_node_tags", "cluster_key"):
472
+ return False
473
+ return True
474
+
475
+
476
+ def _detect_v24_base_schema(snapshot: DatabaseSchemaSnapshot) -> bool:
477
+ """判断数据库是否满足收敛后的行为动作/结果实体结构。"""
478
+
479
+ if not _detect_v18_common_schema(snapshot):
480
+ return False
481
+ if not snapshot.has_table("behavior_scene_clusters"):
482
+ return False
483
+ if snapshot.has_column("behavior_scene_clusters", "name"):
484
+ return False
485
+ if snapshot.has_column("behavior_scene_clusters", "normalized_tags"):
486
+ return False
487
+ if not snapshot.has_column("behavior_scene_clusters", "tag_distribution"):
488
+ return False
489
+ if not snapshot.has_table("behavior_experience_paths"):
490
+ return False
491
+ if not snapshot.has_column("behavior_experience_paths", "scene_cluster_id"):
492
+ return False
493
+ if not snapshot.has_column("behavior_experience_paths", "action_id"):
494
+ return False
495
+ if not snapshot.has_column("behavior_experience_paths", "outcome_id"):
496
+ return False
497
+ if snapshot.has_column("behavior_experience_paths", "action_node_id"):
498
+ return False
499
+ if snapshot.has_column("behavior_experience_paths", "outcome_node_id"):
500
+ return False
501
+ if not snapshot.has_column("behavior_experience_paths", "actor_type"):
502
+ return False
503
+ if not snapshot.has_column("behavior_experience_paths", "learning_type"):
504
+ return False
505
+ if snapshot.has_column("behavior_experience_paths", "start_scene_node_id"):
506
+ return False
507
+ if not snapshot.has_table("behavior_experience_scene_links"):
508
+ return False
509
+ if not snapshot.has_table("behavior_scene_nodes"):
510
+ return False
511
+ if snapshot.has_column("behavior_scene_nodes", "normalized_name"):
512
+ return False
513
+ if not snapshot.has_table("behavior_scene_edges"):
514
+ return False
515
+ if not snapshot.has_table("behavior_actions"):
516
+ return False
517
+ if not snapshot.has_column("behavior_actions", "action_hash"):
518
+ return False
519
+ if snapshot.has_column("behavior_actions", "normalized_action"):
520
+ return False
521
+ if snapshot.has_table("behavior_action_nodes"):
522
+ return False
523
+ if not snapshot.has_table("behavior_outcomes"):
524
+ return False
525
+ if not snapshot.has_column("behavior_outcomes", "outcome_hash"):
526
+ return False
527
+ if snapshot.has_column("behavior_outcomes", "normalized_outcome"):
528
+ return False
529
+ if snapshot.has_table("behavior_outcome_nodes"):
530
+ return False
531
+ if snapshot.has_table("behavior_scene_action_edges"):
532
+ return False
533
+ if snapshot.has_table("behavior_action_outcome_edges"):
534
+ return False
535
+ if not snapshot.has_table("behavior_scene_tag_clusters"):
536
+ return False
537
+ if not snapshot.has_column("behavior_scene_tag_clusters", "tag_kind"):
538
+ return False
539
+ if not snapshot.has_column("behavior_scene_tag_clusters", "tag"):
540
+ return False
541
+ if not snapshot.has_column("behavior_scene_tag_clusters", "cluster_key"):
542
+ return False
543
+ if snapshot.has_column("behavior_scene_tag_clusters", "normalized_tag"):
544
+ return False
545
+ if snapshot.has_column("behavior_scene_tag_clusters", "display_tag"):
546
+ return False
547
+ if snapshot.has_column("behavior_scene_tag_clusters", "cluster_name"):
548
+ return False
549
+ if snapshot.has_column("behavior_scene_tag_clusters", "tag_members"):
550
+ return False
551
+ if not snapshot.has_table("behavior_scene_node_tags"):
552
+ return False
553
+ if not snapshot.has_column("behavior_scene_node_tags", "scene_node_id"):
554
+ return False
555
+ if not snapshot.has_column("behavior_scene_node_tags", "tag_kind"):
556
+ return False
557
+ if not snapshot.has_column("behavior_scene_node_tags", "cluster_key"):
558
+ return False
559
+ return True
560
+
561
+
562
+ def _detect_v26_base_schema(snapshot: DatabaseSchemaSnapshot, *, use_latest_high_frequency_terms: bool = False) -> bool:
563
+ """判断数据库是否满足移除 scene node 图层后的行为学习结构。"""
564
+
565
+ if not _detect_v18_common_schema(
566
+ snapshot,
567
+ use_latest_high_frequency_terms=use_latest_high_frequency_terms,
568
+ ):
569
+ return False
570
+ if not snapshot.has_table("behavior_scene_clusters"):
571
+ return False
572
+ if snapshot.has_column("behavior_scene_clusters", "name"):
573
+ return False
574
+ if snapshot.has_column("behavior_scene_clusters", "normalized_tags"):
575
+ return False
576
+ if not snapshot.has_column("behavior_scene_clusters", "tag_distribution"):
577
+ return False
578
+ if not snapshot.has_table("behavior_experience_paths"):
579
+ return False
580
+ if not snapshot.has_column("behavior_experience_paths", "scene_cluster_id"):
581
+ return False
582
+ if not snapshot.has_column("behavior_experience_paths", "action_id"):
583
+ return False
584
+ if not snapshot.has_column("behavior_experience_paths", "outcome_id"):
585
+ return False
586
+ if snapshot.has_column("behavior_experience_paths", "action_node_id"):
587
+ return False
588
+ if snapshot.has_column("behavior_experience_paths", "outcome_node_id"):
589
+ return False
590
+ if snapshot.has_column("behavior_experience_paths", "start_scene_node_id"):
591
+ return False
592
+ if snapshot.has_table("behavior_experience_scene_links"):
593
+ return False
594
+ if snapshot.has_table("behavior_scene_node_tags"):
595
+ return False
596
+ if snapshot.has_table("behavior_scene_edges"):
597
+ return False
598
+ if snapshot.has_table("behavior_scene_nodes"):
599
+ return False
600
+ if not snapshot.has_table("behavior_actions"):
601
+ return False
602
+ if not snapshot.has_column("behavior_actions", "action_hash"):
603
+ return False
604
+ if snapshot.has_column("behavior_actions", "normalized_action"):
605
+ return False
606
+ if snapshot.has_table("behavior_action_nodes"):
607
+ return False
608
+ if not snapshot.has_table("behavior_outcomes"):
609
+ return False
610
+ if not snapshot.has_column("behavior_outcomes", "outcome_hash"):
611
+ return False
612
+ if snapshot.has_column("behavior_outcomes", "normalized_outcome"):
613
+ return False
614
+ if snapshot.has_table("behavior_outcome_nodes"):
615
+ return False
616
+ if snapshot.has_table("behavior_scene_action_edges"):
617
+ return False
618
+ if snapshot.has_table("behavior_action_outcome_edges"):
619
+ return False
620
+ if not snapshot.has_table("behavior_scene_tag_clusters"):
621
+ return False
622
+ if not snapshot.has_column("behavior_scene_tag_clusters", "tag_kind"):
623
+ return False
624
+ if not snapshot.has_column("behavior_scene_tag_clusters", "tag"):
625
+ return False
626
+ if not snapshot.has_column("behavior_scene_tag_clusters", "cluster_key"):
627
+ return False
628
+ if snapshot.has_column("behavior_scene_tag_clusters", "normalized_tag"):
629
+ return False
630
+ if snapshot.has_column("behavior_scene_tag_clusters", "display_tag"):
631
+ return False
632
+ if snapshot.has_column("behavior_scene_tag_clusters", "cluster_name"):
633
+ return False
634
+ if snapshot.has_column("behavior_scene_tag_clusters", "tag_members"):
635
+ return False
636
+ return True
637
+
638
+
639
+ def _detect_v37_base_schema(snapshot: DatabaseSchemaSnapshot, *, behavior_removed: bool = False) -> bool:
640
+ """判断数据库是否具备 v37 的主体结构。"""
641
+
642
+ if not snapshot.has_table("maisaka_reply_effects"):
643
+ return False
644
+ if behavior_removed:
645
+ has_base_schema = _detect_v18_common_schema(snapshot, use_latest_high_frequency_terms=True)
646
+ else:
647
+ has_base_schema = _detect_v26_base_schema(snapshot, use_latest_high_frequency_terms=True)
648
+ if not has_base_schema:
649
+ return False
650
+ if snapshot.has_column("behavior_scene_clusters", "score"):
651
+ return False
652
+ if not snapshot.has_table("one_time_maintenance_tasks"):
653
+ return False
654
+ if snapshot.has_column("tool_records", "tool_builtin_prompt"):
655
+ return False
656
+ if snapshot.has_column("tool_records", "tool_display_prompt"):
657
+ return False
658
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
659
+ return False
660
+ if not snapshot.has_column("llm_usage", "session_id"):
661
+ return False
662
+ if snapshot.has_column("llm_usage", "endpoint"):
663
+ return False
664
+ if snapshot.has_column("llm_usage", "user_type"):
665
+ return False
666
+ if not snapshot.has_column("jargons", "evidence_messages"):
667
+ return False
668
+ if snapshot.has_column("jargons", "raw_content"):
669
+ return False
670
+ if not snapshot.has_table("maisaka_monitor_events"):
671
+ return False
672
+ if not snapshot.has_column("maisaka_monitor_events", "event_id"):
673
+ return False
674
+ if not snapshot.has_column("maisaka_monitor_events", "payload_json"):
675
+ return False
676
+ return True
677
+
678
+
679
+ class LatestSchemaVersionDetector(BaseSchemaVersionDetector):
680
+ """当前最新 schema 结构探测器。"""
681
+
682
+ @property
683
+ def name(self) -> str:
684
+ return "latest_schema_detector"
685
+
686
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
687
+ """检测数据库是否已经是当前最新结构。"""
688
+
689
+ behavior_removed = not any(snapshot.has_table(table_name) for table_name in BEHAVIOR_TABLES)
690
+ if not _detect_v37_base_schema(snapshot, behavior_removed=behavior_removed):
691
+ return None
692
+ if not snapshot.has_column("maisaka_reply_effects", "request_fingerprint"):
693
+ return None
694
+ if not snapshot.has_column("maisaka_reply_effects", "record_blob"):
695
+ return None
696
+ if not snapshot.has_table("bot_platform_accounts"):
697
+ return V39_SCHEMA_VERSION
698
+ if not all(snapshot.has_column("mai_messages", name) for name in ("account_id", "scope")):
699
+ return V40_SCHEMA_VERSION
700
+ # v43 只压缩文件,结构与 v42 相同;未标记版本的库仍需执行瘦身迁移。
701
+ return V42_SCHEMA_VERSION if behavior_removed else V41_SCHEMA_VERSION
702
+
703
+
704
+ class V38SchemaVersionDetector(BaseSchemaVersionDetector):
705
+ """v38 schema 结构探测器。"""
706
+
707
+ @property
708
+ def name(self) -> str:
709
+ return "v38_schema_detector"
710
+
711
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
712
+ if not _detect_v37_base_schema(snapshot):
713
+ return None
714
+ if not snapshot.has_column("maisaka_reply_effects", "request_fingerprint"):
715
+ return None
716
+ if snapshot.has_column("maisaka_reply_effects", "record_blob"):
717
+ return None
718
+ return V38_SCHEMA_VERSION
719
+
720
+
721
+ class V37SchemaVersionDetector(BaseSchemaVersionDetector):
722
+ """v37 schema 结构探测器。"""
723
+
724
+ @property
725
+ def name(self) -> str:
726
+ return "v37_schema_detector"
727
+
728
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
729
+ if not _detect_v37_base_schema(snapshot):
730
+ return None
731
+ if snapshot.has_column("maisaka_reply_effects", "request_fingerprint"):
732
+ return None
733
+ return V37_SCHEMA_VERSION
734
+
735
+
736
+ class V34SchemaVersionDetector(BaseSchemaVersionDetector):
737
+ """v34 schema 结构探测器。"""
738
+
739
+ @property
740
+ def name(self) -> str:
741
+ return "v34_schema_detector"
742
+
743
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
744
+ """检测数据库是否为 v34 结构。"""
745
+
746
+ if not _detect_v26_base_schema(snapshot, use_latest_high_frequency_terms=True):
747
+ return None
748
+ if snapshot.has_column("behavior_scene_clusters", "score"):
749
+ return None
750
+ if not snapshot.has_table("one_time_maintenance_tasks"):
751
+ return None
752
+ if snapshot.has_column("tool_records", "tool_builtin_prompt"):
753
+ return None
754
+ if snapshot.has_column("tool_records", "tool_display_prompt"):
755
+ return None
756
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
757
+ return None
758
+ if not snapshot.has_column("llm_usage", "session_id"):
759
+ return None
760
+ if snapshot.has_column("llm_usage", "endpoint"):
761
+ return None
762
+ if snapshot.has_column("llm_usage", "user_type"):
763
+ return None
764
+ if not snapshot.has_column("jargons", "evidence_messages"):
765
+ return None
766
+ if snapshot.has_column("jargons", "raw_content"):
767
+ return None
768
+ if snapshot.has_table("maisaka_monitor_events"):
769
+ return None
770
+ return V34_SCHEMA_VERSION
771
+
772
+
773
+ class V30SchemaVersionDetector(BaseSchemaVersionDetector):
774
+ """v30 schema 结构探测器。"""
775
+
776
+ @property
777
+ def name(self) -> str:
778
+ return "v30_schema_detector"
779
+
780
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
781
+ """检测数据库是否为 v30 结构。"""
782
+
783
+ if not _detect_v26_base_schema(snapshot, use_latest_high_frequency_terms=True):
784
+ return None
785
+ if snapshot.has_column("behavior_scene_clusters", "score"):
786
+ return None
787
+ if not snapshot.has_table("one_time_maintenance_tasks"):
788
+ return None
789
+ if snapshot.has_column("tool_records", "tool_builtin_prompt"):
790
+ return None
791
+ if snapshot.has_column("tool_records", "tool_display_prompt"):
792
+ return None
793
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
794
+ return None
795
+ if not snapshot.has_column("llm_usage", "session_id"):
796
+ return None
797
+ if snapshot.has_column("llm_usage", "endpoint"):
798
+ return None
799
+ if snapshot.has_column("llm_usage", "user_type"):
800
+ return None
801
+ return V30_SCHEMA_VERSION
802
+
803
+
804
+ class V29SchemaVersionDetector(BaseSchemaVersionDetector):
805
+ """v29 schema 结构探测器。"""
806
+
807
+ @property
808
+ def name(self) -> str:
809
+ return "v29_schema_detector"
810
+
811
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
812
+ """检测数据库是否为 v29 结构。"""
813
+
814
+ if not _detect_v26_base_schema(snapshot, use_latest_high_frequency_terms=True):
815
+ return None
816
+ if snapshot.has_column("behavior_scene_clusters", "score"):
817
+ return None
818
+ if not snapshot.has_table("one_time_maintenance_tasks"):
819
+ return None
820
+ if snapshot.has_column("tool_records", "tool_builtin_prompt"):
821
+ return None
822
+ if snapshot.has_column("tool_records", "tool_display_prompt"):
823
+ return None
824
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
825
+ return None
826
+ if snapshot.has_column("llm_usage", "session_id"):
827
+ return None
828
+ return V29_SCHEMA_VERSION
829
+
830
+
831
+ class V28SchemaVersionDetector(BaseSchemaVersionDetector):
832
+ """v28 schema 结构探测器。"""
833
+
834
+ @property
835
+ def name(self) -> str:
836
+ return "v28_schema_detector"
837
+
838
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
839
+ """检测数据库是否为 v28 结构。"""
840
+
841
+ if not _detect_v26_base_schema(snapshot):
842
+ return None
843
+ if snapshot.has_column("behavior_scene_clusters", "score"):
844
+ return None
845
+ if not snapshot.has_table("one_time_maintenance_tasks"):
846
+ return None
847
+ if snapshot.has_column("tool_records", "tool_builtin_prompt"):
848
+ return None
849
+ if snapshot.has_column("tool_records", "tool_display_prompt"):
850
+ return None
851
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
852
+ return None
853
+ return V28_SCHEMA_VERSION
854
+
855
+
856
+ class V27SchemaVersionDetector(BaseSchemaVersionDetector):
857
+ """v27 schema 结构探测器。"""
858
+
859
+ @property
860
+ def name(self) -> str:
861
+ return "v27_schema_detector"
862
+
863
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
864
+ """检测数据库是否为 v27 结构。"""
865
+
866
+ if not _detect_v26_base_schema(snapshot):
867
+ return None
868
+ if snapshot.has_column("behavior_scene_clusters", "score"):
869
+ return None
870
+ if snapshot.has_table("one_time_maintenance_tasks"):
871
+ return None
872
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
873
+ return None
874
+ return V27_SCHEMA_VERSION
875
+
876
+
877
+ class V24SchemaVersionDetector(BaseSchemaVersionDetector):
878
+ """v24 schema 结构探测器。"""
879
+
880
+ @property
881
+ def name(self) -> str:
882
+ return "v24_schema_detector"
883
+
884
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
885
+ """检测数据库是否为 v24 结构。"""
886
+
887
+ if not _detect_v24_base_schema(snapshot):
888
+ return None
889
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
890
+ return None
891
+ return V24_SCHEMA_VERSION
892
+
893
+
894
+ class V26SchemaVersionDetector(BaseSchemaVersionDetector):
895
+ """v26 schema 结构探测器。"""
896
+
897
+ @property
898
+ def name(self) -> str:
899
+ return "v26_schema_detector"
900
+
901
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
902
+ """检测数据库是否为 v26 结构。"""
903
+
904
+ if not _detect_v26_base_schema(snapshot):
905
+ return None
906
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
907
+ return None
908
+ return V26_SCHEMA_VERSION
909
+
910
+
911
+ class V25SchemaVersionDetector(BaseSchemaVersionDetector):
912
+ """v25 schema 结构探测器。"""
913
+
914
+ @property
915
+ def name(self) -> str:
916
+ return "v25_schema_detector"
917
+
918
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
919
+ """检测数据库是否为 v25 结构。"""
920
+
921
+ if not _detect_v24_base_schema(snapshot):
922
+ return None
923
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
924
+ return None
925
+ return V25_SCHEMA_VERSION
926
+
927
+
928
+ class V23SchemaVersionDetector(BaseSchemaVersionDetector):
929
+ """v23 schema 结构探测器。"""
930
+
931
+ @property
932
+ def name(self) -> str:
933
+ return "v23_schema_detector"
934
+
935
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
936
+ """检测数据库是否为 v23 结构。"""
937
+
938
+ if not _detect_v23_base_schema(snapshot):
939
+ return None
940
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
941
+ return None
942
+ return V23_SCHEMA_VERSION
943
+
944
+
945
+ class V22SchemaVersionDetector(BaseSchemaVersionDetector):
946
+ """v22 schema 结构探测器。"""
947
+
948
+ @property
949
+ def name(self) -> str:
950
+ return "v22_schema_detector"
951
+
952
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
953
+ """检测数据库是否为 v22 结构。"""
954
+
955
+ if not _detect_v22_base_schema(snapshot):
956
+ return None
957
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
958
+ return None
959
+ return V22_SCHEMA_VERSION
960
+
961
+
962
+ class V21SchemaVersionDetector(BaseSchemaVersionDetector):
963
+ """v21 schema 结构探测器。"""
964
+
965
+ @property
966
+ def name(self) -> str:
967
+ return "v21_schema_detector"
968
+
969
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
970
+ """检测数据库是否为 v21 结构。"""
971
+
972
+ if _detect_v22_base_schema(snapshot):
973
+ if any(snapshot.has_table(table_name) for table_name in LEGACY_V1_CLEANUP_TABLES):
974
+ return V21_SCHEMA_VERSION
975
+ return None
976
+ if not _detect_v21_base_schema(snapshot):
977
+ return None
978
+ if snapshot.has_table("behavior_scene_tag_clusters"):
979
+ return None
980
+ return V21_SCHEMA_VERSION
981
+
982
+
983
+ class V20SchemaVersionDetector(BaseSchemaVersionDetector):
984
+ """v20 schema 结构探测器。"""
985
+
986
+ @property
987
+ def name(self) -> str:
988
+ return "v20_schema_detector"
989
+
990
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
991
+ """检测数据库是否为 v20 结构。"""
992
+
993
+ if not _detect_v20_base_schema(snapshot):
994
+ return None
995
+ return V20_SCHEMA_VERSION
996
+
997
+
998
+ class V19SchemaVersionDetector(BaseSchemaVersionDetector):
999
+ """v19 schema 结构探测器。"""
1000
+
1001
+ @property
1002
+ def name(self) -> str:
1003
+ return "v19_schema_detector"
1004
+
1005
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1006
+ """检测数据库是否为 v19 结构。"""
1007
+
1008
+ if not _detect_v19_base_schema(snapshot):
1009
+ return None
1010
+ return V19_SCHEMA_VERSION
1011
+
1012
+
1013
+ class V18SchemaVersionDetector(BaseSchemaVersionDetector):
1014
+ """v18 schema 结构探测器。"""
1015
+
1016
+ @property
1017
+ def name(self) -> str:
1018
+ return "v18_schema_detector"
1019
+
1020
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1021
+ """检测数据库是否为 v18 结构。"""
1022
+
1023
+ if not _detect_v18_base_schema(snapshot):
1024
+ return None
1025
+ if not snapshot.has_table("command_records"):
1026
+ return None
1027
+ return V18_SCHEMA_VERSION
1028
+
1029
+
1030
+ class V17SchemaVersionDetector(BaseSchemaVersionDetector):
1031
+ """v17 schema 结构探测器。"""
1032
+
1033
+ @property
1034
+ def name(self) -> str:
1035
+ return "v17_schema_detector"
1036
+
1037
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1038
+ """检测数据库是否为 v17 结构。"""
1039
+
1040
+ if not _detect_v13_base_schema(snapshot):
1041
+ return None
1042
+ if not snapshot.has_column("mai_messages", "reply_frequency"):
1043
+ return None
1044
+ if not snapshot.has_column("llm_usage", "task_name"):
1045
+ return None
1046
+ if not snapshot.has_column("llm_usage", "prompt_cache_hit_tokens"):
1047
+ return None
1048
+ if not snapshot.has_column("llm_usage", "prompt_cache_miss_tokens"):
1049
+ return None
1050
+ if not snapshot.has_column("llm_usage", "prompt_cache_enabled"):
1051
+ return None
1052
+ if not snapshot.has_table("behavior_patterns"):
1053
+ return None
1054
+ if not snapshot.has_column("behavior_patterns", "trigger"):
1055
+ return None
1056
+ if not snapshot.has_column("behavior_patterns", "action"):
1057
+ return None
1058
+ if not snapshot.has_column("behavior_patterns", "outcome"):
1059
+ return None
1060
+ if not snapshot.has_column("behavior_patterns", "score"):
1061
+ return None
1062
+ if not snapshot.has_column("behavior_patterns", "enabled"):
1063
+ return None
1064
+ if snapshot.has_table("high_frequency_terms"):
1065
+ return None
1066
+ return V17_SCHEMA_VERSION
1067
+
1068
+
1069
+ class V16SchemaVersionDetector(BaseSchemaVersionDetector):
1070
+ """v16 schema 结构探测器。"""
1071
+
1072
+ @property
1073
+ def name(self) -> str:
1074
+ return "v16_schema_detector"
1075
+
1076
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1077
+ """检测数据库是否为 v16 结构。"""
1078
+
1079
+ if not _detect_v13_base_schema(snapshot):
1080
+ return None
1081
+ if not snapshot.has_column("mai_messages", "reply_frequency"):
1082
+ return None
1083
+ if not snapshot.has_column("llm_usage", "task_name"):
1084
+ return None
1085
+ if not snapshot.has_column("llm_usage", "prompt_cache_hit_tokens"):
1086
+ return None
1087
+ if not snapshot.has_column("llm_usage", "prompt_cache_miss_tokens"):
1088
+ return None
1089
+ if not snapshot.has_column("llm_usage", "prompt_cache_enabled"):
1090
+ return None
1091
+ if snapshot.has_table("behavior_patterns"):
1092
+ return None
1093
+ return V16_SCHEMA_VERSION
1094
+
1095
+
1096
+ class V15SchemaVersionDetector(BaseSchemaVersionDetector):
1097
+ """v15 schema 结构探测器。"""
1098
+
1099
+ @property
1100
+ def name(self) -> str:
1101
+ return "v15_schema_detector"
1102
+
1103
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1104
+ """检测数据库是否为 v15 结构。"""
1105
+
1106
+ if not _detect_v13_base_schema(snapshot):
1107
+ return None
1108
+ if not snapshot.has_column("mai_messages", "reply_frequency"):
1109
+ return None
1110
+ if not snapshot.has_column("llm_usage", "task_name"):
1111
+ return None
1112
+ if not snapshot.has_column("llm_usage", "prompt_cache_hit_tokens"):
1113
+ return None
1114
+ if not snapshot.has_column("llm_usage", "prompt_cache_miss_tokens"):
1115
+ return None
1116
+ if snapshot.has_column("llm_usage", "prompt_cache_enabled"):
1117
+ return None
1118
+ return V15_SCHEMA_VERSION
1119
+
1120
+
1121
+ class V14SchemaVersionDetector(BaseSchemaVersionDetector):
1122
+ """v14 schema 结构探测器。"""
1123
+
1124
+ @property
1125
+ def name(self) -> str:
1126
+ return "v14_schema_detector"
1127
+
1128
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1129
+ """检测数据库是否为 v14 结构。"""
1130
+
1131
+ if not _detect_v13_base_schema(snapshot):
1132
+ return None
1133
+ if not snapshot.has_column("mai_messages", "reply_frequency"):
1134
+ return None
1135
+ if not snapshot.has_column("llm_usage", "task_name"):
1136
+ return None
1137
+ if snapshot.has_column("llm_usage", "prompt_cache_hit_tokens"):
1138
+ return None
1139
+ if snapshot.has_column("llm_usage", "prompt_cache_miss_tokens"):
1140
+ return None
1141
+ return V14_SCHEMA_VERSION
1142
+
1143
+
1144
+ class V13SchemaVersionDetector(BaseSchemaVersionDetector):
1145
+ """v13 schema 结构探测器。"""
1146
+
1147
+ @property
1148
+ def name(self) -> str:
1149
+ return "v13_schema_detector"
1150
+
1151
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1152
+ """检测数据库是否为 v13 结构。"""
1153
+
1154
+ if not _detect_v13_base_schema(snapshot):
1155
+ return None
1156
+ if snapshot.has_column("mai_messages", "reply_frequency"):
1157
+ return None
1158
+ if snapshot.has_column("llm_usage", "task_name"):
1159
+ return None
1160
+ return V13_SCHEMA_VERSION
1161
+
1162
+
1163
+ class V12SchemaVersionDetector(BaseSchemaVersionDetector):
1164
+ """v12 schema 结构探测器。"""
1165
+
1166
+ @property
1167
+ def name(self) -> str:
1168
+ return "v12_schema_detector"
1169
+
1170
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1171
+ """检测数据库是否为 v12 结构。"""
1172
+
1173
+ if any(snapshot.has_table(table_name) for table_name in _LEGACY_V1_EXCLUSIVE_TABLES):
1174
+ return None
1175
+ if not all(snapshot.has_table(table_name) for table_name in _COMMON_MARKER_TABLES):
1176
+ return None
1177
+ if snapshot.has_table("action_records"):
1178
+ return None
1179
+ if snapshot.has_table("thinking_questions"):
1180
+ return None
1181
+ if snapshot.has_column("images", "emotion"):
1182
+ return None
1183
+ if not snapshot.has_column("images", "image_hash"):
1184
+ return None
1185
+ if not snapshot.has_column("images", "full_path"):
1186
+ return None
1187
+ if not snapshot.has_column("images", "image_type"):
1188
+ return None
1189
+ if not snapshot.has_column("chat_history", "session_id"):
1190
+ return None
1191
+ if not snapshot.has_column("person_info", "user_nickname"):
1192
+ return None
1193
+ if not snapshot.has_column("chat_sessions", "account_id"):
1194
+ return None
1195
+ if not snapshot.has_column("chat_sessions", "scope"):
1196
+ return None
1197
+ if not snapshot.has_column("chat_sessions", "user_nickname"):
1198
+ return None
1199
+ if not snapshot.has_column("chat_sessions", "user_cardname"):
1200
+ return None
1201
+ if not snapshot.has_column("chat_sessions", "group_name"):
1202
+ return None
1203
+ if snapshot.has_column("expressions", "rejected"):
1204
+ return None
1205
+ if snapshot.has_column("mai_messages", "display_message"):
1206
+ return None
1207
+ if not snapshot.has_table("statistics_message_hourly"):
1208
+ return None
1209
+ if not snapshot.has_table("statistics_tool_hourly"):
1210
+ return None
1211
+ if not snapshot.has_table("statistics_model_hourly"):
1212
+ return None
1213
+ if not snapshot.has_table("statistics_aggregation_cursors"):
1214
+ return None
1215
+ if not snapshot.has_column("jargons", "created_timestamp"):
1216
+ return None
1217
+ if not snapshot.has_column("jargons", "updated_timestamp"):
1218
+ return None
1219
+ if snapshot.has_column("jargons", "inference_with_context"):
1220
+ return None
1221
+ if snapshot.has_column("jargons", "inference_with_content_only"):
1222
+ return None
1223
+ if snapshot.has_column("jargons", "created_by"):
1224
+ return None
1225
+ return V12_SCHEMA_VERSION
1226
+
1227
+
1228
+ class V11SchemaVersionDetector(BaseSchemaVersionDetector):
1229
+ """v11 schema 结构探测器。"""
1230
+
1231
+ @property
1232
+ def name(self) -> str:
1233
+ return "v11_schema_detector"
1234
+
1235
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1236
+ """检测数据库是否为 v11 结构。"""
1237
+
1238
+ if any(snapshot.has_table(table_name) for table_name in _LEGACY_V1_EXCLUSIVE_TABLES):
1239
+ return None
1240
+ if not all(snapshot.has_table(table_name) for table_name in _COMMON_MARKER_TABLES):
1241
+ return None
1242
+ if snapshot.has_table("action_records"):
1243
+ return None
1244
+ if snapshot.has_table("thinking_questions"):
1245
+ return None
1246
+ if snapshot.has_column("images", "emotion"):
1247
+ return None
1248
+ if not snapshot.has_column("images", "image_hash"):
1249
+ return None
1250
+ if not snapshot.has_column("images", "full_path"):
1251
+ return None
1252
+ if not snapshot.has_column("images", "image_type"):
1253
+ return None
1254
+ if not snapshot.has_column("chat_history", "session_id"):
1255
+ return None
1256
+ if not snapshot.has_column("person_info", "user_nickname"):
1257
+ return None
1258
+ if not snapshot.has_column("chat_sessions", "account_id"):
1259
+ return None
1260
+ if not snapshot.has_column("chat_sessions", "scope"):
1261
+ return None
1262
+ if not snapshot.has_column("chat_sessions", "user_nickname"):
1263
+ return None
1264
+ if not snapshot.has_column("chat_sessions", "user_cardname"):
1265
+ return None
1266
+ if not snapshot.has_column("chat_sessions", "group_name"):
1267
+ return None
1268
+ if snapshot.has_column("expressions", "rejected"):
1269
+ return None
1270
+ if snapshot.has_column("mai_messages", "display_message"):
1271
+ return None
1272
+ if not snapshot.has_table("statistics_message_hourly"):
1273
+ return None
1274
+ if not snapshot.has_table("statistics_tool_hourly"):
1275
+ return None
1276
+ if not snapshot.has_table("statistics_model_hourly"):
1277
+ return None
1278
+ if not snapshot.has_table("statistics_aggregation_cursors"):
1279
+ return None
1280
+ if not snapshot.has_column("jargons", "created_timestamp"):
1281
+ return None
1282
+ if not snapshot.has_column("jargons", "updated_timestamp"):
1283
+ return None
1284
+ has_jargon_inference_cache = snapshot.has_column(
1285
+ "jargons", "inference_with_context"
1286
+ ) or snapshot.has_column("jargons", "inference_with_content_only")
1287
+ if not has_jargon_inference_cache:
1288
+ return None
1289
+ return V11_SCHEMA_VERSION
1290
+
1291
+
1292
+ class V10SchemaVersionDetector(BaseSchemaVersionDetector):
1293
+ """v10 schema 结构探测器。"""
1294
+
1295
+ @property
1296
+ def name(self) -> str:
1297
+ return "v10_schema_detector"
1298
+
1299
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1300
+ """检测数据库是否为 v10 结构。"""
1301
+
1302
+ if any(snapshot.has_table(table_name) for table_name in _LEGACY_V1_EXCLUSIVE_TABLES):
1303
+ return None
1304
+ if not all(snapshot.has_table(table_name) for table_name in _COMMON_MARKER_TABLES):
1305
+ return None
1306
+ if snapshot.has_table("action_records"):
1307
+ return None
1308
+ if snapshot.has_table("thinking_questions"):
1309
+ return None
1310
+ if snapshot.has_column("images", "emotion"):
1311
+ return None
1312
+ if not snapshot.has_column("images", "image_hash"):
1313
+ return None
1314
+ if not snapshot.has_column("images", "full_path"):
1315
+ return None
1316
+ if not snapshot.has_column("images", "image_type"):
1317
+ return None
1318
+ if not snapshot.has_column("chat_history", "session_id"):
1319
+ return None
1320
+ if not snapshot.has_column("person_info", "user_nickname"):
1321
+ return None
1322
+ if not snapshot.has_column("chat_sessions", "account_id"):
1323
+ return None
1324
+ if not snapshot.has_column("chat_sessions", "scope"):
1325
+ return None
1326
+ if not snapshot.has_column("chat_sessions", "user_nickname"):
1327
+ return None
1328
+ if not snapshot.has_column("chat_sessions", "user_cardname"):
1329
+ return None
1330
+ if not snapshot.has_column("chat_sessions", "group_name"):
1331
+ return None
1332
+ if snapshot.has_column("expressions", "rejected"):
1333
+ return None
1334
+ if snapshot.has_column("mai_messages", "display_message"):
1335
+ return None
1336
+ if not snapshot.has_table("statistics_message_hourly"):
1337
+ return None
1338
+ if not snapshot.has_table("statistics_tool_hourly"):
1339
+ return None
1340
+ if not snapshot.has_table("statistics_model_hourly"):
1341
+ return None
1342
+ if not snapshot.has_table("statistics_aggregation_cursors"):
1343
+ return None
1344
+ has_jargon_created_timestamp = snapshot.has_column("jargons", "created_timestamp")
1345
+ has_jargon_updated_timestamp = snapshot.has_column("jargons", "updated_timestamp")
1346
+ if has_jargon_created_timestamp and has_jargon_updated_timestamp:
1347
+ return None
1348
+ return V10_SCHEMA_VERSION
1349
+
1350
+
1351
+ class V9SchemaVersionDetector(BaseSchemaVersionDetector):
1352
+ """v9 schema 结构探测器。"""
1353
+
1354
+ @property
1355
+ def name(self) -> str:
1356
+ return "v9_schema_detector"
1357
+
1358
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1359
+ """检测数据库是否为 v9 结构。"""
1360
+
1361
+ if any(snapshot.has_table(table_name) for table_name in _LEGACY_V1_EXCLUSIVE_TABLES):
1362
+ return None
1363
+ if not all(snapshot.has_table(table_name) for table_name in _COMMON_MARKER_TABLES):
1364
+ return None
1365
+ if snapshot.has_table("action_records"):
1366
+ return None
1367
+ if snapshot.has_table("thinking_questions"):
1368
+ return None
1369
+ if snapshot.has_column("images", "emotion"):
1370
+ return None
1371
+ if not snapshot.has_column("images", "image_hash"):
1372
+ return None
1373
+ if not snapshot.has_column("images", "full_path"):
1374
+ return None
1375
+ if not snapshot.has_column("images", "image_type"):
1376
+ return None
1377
+ if not snapshot.has_column("chat_history", "session_id"):
1378
+ return None
1379
+ if not snapshot.has_column("person_info", "user_nickname"):
1380
+ return None
1381
+ if not snapshot.has_column("chat_sessions", "account_id"):
1382
+ return None
1383
+ if not snapshot.has_column("chat_sessions", "scope"):
1384
+ return None
1385
+ if snapshot.has_column("chat_sessions", "user_nickname"):
1386
+ return None
1387
+ if snapshot.has_column("chat_sessions", "user_cardname"):
1388
+ return None
1389
+ if snapshot.has_column("chat_sessions", "group_name"):
1390
+ return None
1391
+ if snapshot.has_column("expressions", "rejected"):
1392
+ return None
1393
+ if snapshot.has_column("mai_messages", "display_message"):
1394
+ return None
1395
+ if not snapshot.has_table("statistics_message_hourly"):
1396
+ return None
1397
+ if not snapshot.has_table("statistics_tool_hourly"):
1398
+ return None
1399
+ if not snapshot.has_table("statistics_model_hourly"):
1400
+ return None
1401
+ if not snapshot.has_table("statistics_aggregation_cursors"):
1402
+ return None
1403
+ return V9_SCHEMA_VERSION
1404
+
1405
+
1406
+ class V6SchemaVersionDetector(BaseSchemaVersionDetector):
1407
+ """v6 schema 缁撴瀯鎺㈡祴鍣ㄣ€?"""
1408
+
1409
+ @property
1410
+ def name(self) -> str:
1411
+ return "v6_schema_detector"
1412
+
1413
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1414
+ """妫€娴嬫暟鎹簱鏄惁涓?v6 缁撴瀯銆?"""
1415
+
1416
+ if any(snapshot.has_table(table_name) for table_name in _LEGACY_V1_EXCLUSIVE_TABLES):
1417
+ return None
1418
+ if not all(snapshot.has_table(table_name) for table_name in _COMMON_MARKER_TABLES):
1419
+ return None
1420
+ if snapshot.has_table("action_records"):
1421
+ return None
1422
+ if snapshot.has_table("thinking_questions"):
1423
+ return None
1424
+ if snapshot.has_column("images", "emotion"):
1425
+ return None
1426
+ if not snapshot.has_column("images", "image_hash"):
1427
+ return None
1428
+ if not snapshot.has_column("images", "full_path"):
1429
+ return None
1430
+ if not snapshot.has_column("images", "image_type"):
1431
+ return None
1432
+ if not snapshot.has_column("chat_history", "session_id"):
1433
+ return None
1434
+ if not snapshot.has_column("person_info", "user_nickname"):
1435
+ return None
1436
+ if not snapshot.has_column("chat_sessions", "account_id"):
1437
+ return None
1438
+ if not snapshot.has_column("chat_sessions", "scope"):
1439
+ return None
1440
+ if not snapshot.has_column("expressions", "rejected"):
1441
+ return None
1442
+ if snapshot.has_column("mai_messages", "display_message"):
1443
+ return None
1444
+ return V6_SCHEMA_VERSION
1445
+
1446
+
1447
+ class V5SchemaVersionDetector(BaseSchemaVersionDetector):
1448
+ """v5 schema 结构探测器。"""
1449
+
1450
+ @property
1451
+ def name(self) -> str:
1452
+ return "v5_schema_detector"
1453
+
1454
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1455
+ """检测数据库是否为 v5 结构。"""
1456
+
1457
+ if any(snapshot.has_table(table_name) for table_name in _LEGACY_V1_EXCLUSIVE_TABLES):
1458
+ return None
1459
+ if not all(snapshot.has_table(table_name) for table_name in _COMMON_MARKER_TABLES):
1460
+ return None
1461
+ if snapshot.has_table("action_records"):
1462
+ return None
1463
+ if snapshot.has_table("thinking_questions"):
1464
+ return None
1465
+ if snapshot.has_column("images", "emotion"):
1466
+ return None
1467
+ if not snapshot.has_column("images", "image_hash"):
1468
+ return None
1469
+ if not snapshot.has_column("images", "full_path"):
1470
+ return None
1471
+ if not snapshot.has_column("images", "image_type"):
1472
+ return None
1473
+ if not snapshot.has_column("chat_history", "session_id"):
1474
+ return None
1475
+ if not snapshot.has_column("person_info", "user_nickname"):
1476
+ return None
1477
+ if snapshot.has_column("mai_messages", "display_message"):
1478
+ return None
1479
+ if snapshot.has_column("chat_sessions", "account_id") or snapshot.has_column("chat_sessions", "scope"):
1480
+ return None
1481
+ return V5_SCHEMA_VERSION
1482
+
1483
+
1484
+ class V3SchemaVersionDetector(BaseSchemaVersionDetector):
1485
+ """v3 schema 结构探测器。"""
1486
+
1487
+ @property
1488
+ def name(self) -> str:
1489
+ return "v3_schema_detector"
1490
+
1491
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1492
+ """检测数据库是否为 v3 结构。"""
1493
+
1494
+ if any(snapshot.has_table(table_name) for table_name in _LEGACY_V1_EXCLUSIVE_TABLES):
1495
+ return None
1496
+ if not all(snapshot.has_table(table_name) for table_name in _COMMON_MARKER_TABLES):
1497
+ return None
1498
+ if snapshot.has_table("action_records"):
1499
+ return None
1500
+ if snapshot.has_table("thinking_questions"):
1501
+ return None
1502
+ if snapshot.has_column("images", "emotion"):
1503
+ return None
1504
+ if not snapshot.has_column("images", "image_hash"):
1505
+ return None
1506
+ if not snapshot.has_column("images", "full_path"):
1507
+ return None
1508
+ if not snapshot.has_column("images", "image_type"):
1509
+ return None
1510
+ if not snapshot.has_column("chat_history", "session_id"):
1511
+ return None
1512
+ if not snapshot.has_column("person_info", "user_nickname"):
1513
+ return None
1514
+ if not snapshot.has_column("mai_messages", "display_message"):
1515
+ return None
1516
+ return V3_SCHEMA_VERSION
1517
+
1518
+
1519
+ class V2SchemaVersionDetector(BaseSchemaVersionDetector):
1520
+ """v2 schema 结构探测器。"""
1521
+
1522
+ @property
1523
+ def name(self) -> str:
1524
+ """返回探测器名称。
1525
+
1526
+ Returns:
1527
+ str: 当前探测器名称。
1528
+ """
1529
+
1530
+ return "v2_schema_detector"
1531
+
1532
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1533
+ """检测数据库是否为 v2 结构。
1534
+
1535
+ Args:
1536
+ snapshot: 当前数据库结构快照。
1537
+
1538
+ Returns:
1539
+ Optional[int]: 若识别为 v2 结构则返回 ``2``,否则返回 ``None``。
1540
+ """
1541
+
1542
+ if any(snapshot.has_table(table_name) for table_name in _LEGACY_V1_EXCLUSIVE_TABLES):
1543
+ return None
1544
+ if not all(snapshot.has_table(table_name) for table_name in _COMMON_MARKER_TABLES):
1545
+ return None
1546
+ if not snapshot.has_table("action_records"):
1547
+ return None
1548
+ if not snapshot.has_table("thinking_questions"):
1549
+ return None
1550
+ if not snapshot.has_column("images", "emotion"):
1551
+ return None
1552
+ if not snapshot.has_column("action_records", "session_id"):
1553
+ return None
1554
+ if not snapshot.has_column("chat_history", "session_id"):
1555
+ return None
1556
+ if not snapshot.has_column("person_info", "user_nickname"):
1557
+ return None
1558
+ return V2_SCHEMA_VERSION
1559
+
1560
+
1561
+ class LegacyV1SchemaDetector(BaseSchemaVersionDetector):
1562
+ """旧版 ``0.x`` schema 结构探测器。"""
1563
+
1564
+ @property
1565
+ def name(self) -> str:
1566
+ """返回探测器名称。
1567
+
1568
+ Returns:
1569
+ str: 当前探测器名称。
1570
+ """
1571
+
1572
+ return "legacy_v1_schema_detector"
1573
+
1574
+ def detect_version(self, snapshot: DatabaseSchemaSnapshot) -> Optional[int]:
1575
+ """检测数据库是否为旧版 ``0.x`` 结构。
1576
+
1577
+ Args:
1578
+ snapshot: 当前数据库结构快照。
1579
+
1580
+ Returns:
1581
+ Optional[int]: 若识别为旧版结构则返回 ``1``,否则返回 ``None``。
1582
+ """
1583
+
1584
+ if any(snapshot.has_table(table_name) for table_name in _LEGACY_V1_EXCLUSIVE_TABLES):
1585
+ return LEGACY_V1_SCHEMA_VERSION
1586
+
1587
+ legacy_shared_markers = (
1588
+ ("action_records", ("chat_id", "time")),
1589
+ ("chat_history", ("chat_id", "original_text")),
1590
+ ("images", ("emoji_hash", "path", "type")),
1591
+ ("llm_usage", ("model_api_provider", "status")),
1592
+ ("online_time", ("duration",)),
1593
+ ("person_info", ("nickname", "group_nick_name")),
1594
+ )
1595
+ for table_name, required_columns in legacy_shared_markers:
1596
+ if snapshot.has_table(table_name) and all(
1597
+ snapshot.has_column(table_name, column_name) for column_name in required_columns
1598
+ ):
1599
+ return LEGACY_V1_SCHEMA_VERSION
1600
+ return None
1601
+
1602
+
1603
+ def build_default_schema_version_detectors() -> List[BaseSchemaVersionDetector]:
1604
+ """构建默认 schema 版本探测器链。
1605
+
1606
+ Returns:
1607
+ List[BaseSchemaVersionDetector]: 按优先级排序的探测器列表。
1608
+ """
1609
+
1610
+ return [
1611
+ LatestSchemaVersionDetector(),
1612
+ V38SchemaVersionDetector(),
1613
+ V37SchemaVersionDetector(),
1614
+ V34SchemaVersionDetector(),
1615
+ V30SchemaVersionDetector(),
1616
+ V29SchemaVersionDetector(),
1617
+ V28SchemaVersionDetector(),
1618
+ V27SchemaVersionDetector(),
1619
+ V26SchemaVersionDetector(),
1620
+ V25SchemaVersionDetector(),
1621
+ V24SchemaVersionDetector(),
1622
+ V23SchemaVersionDetector(),
1623
+ V22SchemaVersionDetector(),
1624
+ V21SchemaVersionDetector(),
1625
+ V20SchemaVersionDetector(),
1626
+ V19SchemaVersionDetector(),
1627
+ V18SchemaVersionDetector(),
1628
+ V17SchemaVersionDetector(),
1629
+ V16SchemaVersionDetector(),
1630
+ V15SchemaVersionDetector(),
1631
+ V14SchemaVersionDetector(),
1632
+ V13SchemaVersionDetector(),
1633
+ V12SchemaVersionDetector(),
1634
+ V11SchemaVersionDetector(),
1635
+ V10SchemaVersionDetector(),
1636
+ V9SchemaVersionDetector(),
1637
+ V6SchemaVersionDetector(),
1638
+ V5SchemaVersionDetector(),
1639
+ V3SchemaVersionDetector(),
1640
+ V2SchemaVersionDetector(),
1641
+ LegacyV1SchemaDetector(),
1642
+ ]
1643
+
1644
+
1645
+ def build_default_schema_version_resolver() -> SchemaVersionResolver:
1646
+ """构建默认 schema 版本解析器。
1647
+
1648
+ Returns:
1649
+ SchemaVersionResolver: 配置完成的 schema 版本解析器。
1650
+ """
1651
+
1652
+ return SchemaVersionResolver(
1653
+ version_store=SQLiteUserVersionStore(),
1654
+ schema_inspector=SQLiteSchemaInspector(),
1655
+ detectors=build_default_schema_version_detectors(),
1656
+ )
1657
+
1658
+
1659
+ def build_default_migration_registry() -> MigrationRegistry:
1660
+ """构建默认迁移步骤注册表。
1661
+
1662
+ Returns:
1663
+ MigrationRegistry: 含默认迁移步骤的注册表实例。
1664
+ """
1665
+
1666
+ return MigrationRegistry(
1667
+ steps=[
1668
+ MigrationStep(
1669
+ version_from=LEGACY_V1_SCHEMA_VERSION,
1670
+ version_to=V2_SCHEMA_VERSION,
1671
+ name="legacy_v1_to_v2",
1672
+ description="将旧版 0.x 数据库迁移到 v2 schema。",
1673
+ handler=migrate_legacy_v1_to_v2,
1674
+ ),
1675
+ MigrationStep(
1676
+ version_from=V2_SCHEMA_VERSION,
1677
+ version_to=V3_SCHEMA_VERSION,
1678
+ name="v2_to_v3",
1679
+ description="移除废弃表,并将 emoji 标签统一收敛到 description 字段。",
1680
+ handler=migrate_v2_to_v3,
1681
+ ),
1682
+ MigrationStep(
1683
+ version_from=V3_SCHEMA_VERSION,
1684
+ version_to=V4_SCHEMA_VERSION,
1685
+ name="v3_to_v4",
1686
+ description="移除 mai_messages.display_message 弃用列。",
1687
+ handler=migrate_v3_to_v4,
1688
+ ),
1689
+ MigrationStep(
1690
+ version_from=V4_SCHEMA_VERSION,
1691
+ version_to=V5_SCHEMA_VERSION,
1692
+ name="v4_to_v5",
1693
+ description="清空群聊 chat_sessions.user_id,避免把首个发言人误认为聊天流归属。",
1694
+ handler=migrate_v4_to_v5,
1695
+ ),
1696
+ MigrationStep(
1697
+ version_from=V5_SCHEMA_VERSION,
1698
+ version_to=V6_SCHEMA_VERSION,
1699
+ name="v5_to_v6",
1700
+ description="为 chat_sessions 增加 account_id/scope 路由归属字段。",
1701
+ handler=migrate_v5_to_v6,
1702
+ ),
1703
+ MigrationStep(
1704
+ version_from=V6_SCHEMA_VERSION,
1705
+ version_to=V7_SCHEMA_VERSION,
1706
+ name="v6_to_v7",
1707
+ description="移除 expressions.rejected 列,并删除已审核拒绝的表达方式。",
1708
+ handler=migrate_v6_to_v7,
1709
+ ),
1710
+ MigrationStep(
1711
+ version_from=V7_SCHEMA_VERSION,
1712
+ version_to=V8_SCHEMA_VERSION,
1713
+ name="v7_to_v8",
1714
+ description="将 AI 标记的已审核表达方式改回待人工审核。",
1715
+ handler=migrate_v7_to_v8,
1716
+ ),
1717
+ MigrationStep(
1718
+ version_from=V8_SCHEMA_VERSION,
1719
+ version_to=V9_SCHEMA_VERSION,
1720
+ name="v8_to_v9",
1721
+ description="新增统计汇总表、索引与历史统计回填。",
1722
+ handler=migrate_v8_to_v9,
1723
+ ),
1724
+ MigrationStep(
1725
+ version_from=V9_SCHEMA_VERSION,
1726
+ version_to=V10_SCHEMA_VERSION,
1727
+ name="v9_to_v10",
1728
+ description="为 chat_sessions 增加群名与私聊用户展示名字段。",
1729
+ handler=migrate_v9_to_v10,
1730
+ ),
1731
+ MigrationStep(
1732
+ version_from=V10_SCHEMA_VERSION,
1733
+ version_to=V11_SCHEMA_VERSION,
1734
+ name="v10_to_v11",
1735
+ description="为 jargons 增加创建时间和更新时间字段。",
1736
+ handler=migrate_v10_to_v11,
1737
+ ),
1738
+ MigrationStep(
1739
+ version_from=V11_SCHEMA_VERSION,
1740
+ version_to=V12_SCHEMA_VERSION,
1741
+ name="v11_to_v12",
1742
+ description="移除 jargons 中不再持久化的推理过程缓存字段。",
1743
+ handler=migrate_v11_to_v12,
1744
+ ),
1745
+ MigrationStep(
1746
+ version_from=V12_SCHEMA_VERSION,
1747
+ version_to=V13_SCHEMA_VERSION,
1748
+ name="v12_to_v13",
1749
+ description="为 jargons 增加创建来源字段。",
1750
+ handler=migrate_v12_to_v13,
1751
+ ),
1752
+ MigrationStep(
1753
+ version_from=V13_SCHEMA_VERSION,
1754
+ version_to=V14_SCHEMA_VERSION,
1755
+ name="v13_to_v14",
1756
+ description="为遥测聚合增加消息回复频率与模型任务名称字段。",
1757
+ handler=migrate_v13_to_v14,
1758
+ ),
1759
+ MigrationStep(
1760
+ version_from=V14_SCHEMA_VERSION,
1761
+ version_to=V15_SCHEMA_VERSION,
1762
+ name="v14_to_v15",
1763
+ description="为 LLM 使用记录增加 prompt cache token 统计字段。",
1764
+ handler=migrate_v14_to_v15,
1765
+ ),
1766
+ MigrationStep(
1767
+ version_from=V15_SCHEMA_VERSION,
1768
+ version_to=V16_SCHEMA_VERSION,
1769
+ name="v15_to_v16",
1770
+ description="为 LLM 使用记录增加当次请求是否启用 prompt cache 计费字段。",
1771
+ handler=migrate_v15_to_v16,
1772
+ ),
1773
+ MigrationStep(
1774
+ version_from=V16_SCHEMA_VERSION,
1775
+ version_to=V17_SCHEMA_VERSION,
1776
+ name="v16_to_v17",
1777
+ description="新增行为表现模式表。",
1778
+ handler=migrate_v16_to_v17,
1779
+ ),
1780
+ MigrationStep(
1781
+ version_from=V17_SCHEMA_VERSION,
1782
+ version_to=V18_SCHEMA_VERSION,
1783
+ name="v17_to_v18",
1784
+ description="新增高频词/词组词库表。",
1785
+ handler=migrate_v17_to_v18,
1786
+ ),
1787
+ MigrationStep(
1788
+ version_from=V18_SCHEMA_VERSION,
1789
+ version_to=V19_SCHEMA_VERSION,
1790
+ name="v18_to_v19",
1791
+ description="移除旧行为表现主表,创建节点化行为经验路径图谱。",
1792
+ handler=migrate_v18_to_v19,
1793
+ ),
1794
+ MigrationStep(
1795
+ version_from=V19_SCHEMA_VERSION,
1796
+ version_to=V20_SCHEMA_VERSION,
1797
+ name="v19_to_v20",
1798
+ description="删除测试期行为数据,创建独立场景簇概率分布结构。",
1799
+ handler=migrate_v19_to_v20,
1800
+ ),
1801
+ MigrationStep(
1802
+ version_from=V20_SCHEMA_VERSION,
1803
+ version_to=V21_SCHEMA_VERSION,
1804
+ name="v20_to_v21",
1805
+ description="为行为经验路径增加行为主体与学习类型字段。",
1806
+ handler=migrate_v20_to_v21,
1807
+ ),
1808
+ MigrationStep(
1809
+ version_from=V21_SCHEMA_VERSION,
1810
+ version_to=V22_SCHEMA_VERSION,
1811
+ name="v21_to_v22",
1812
+ description="合并行为场景索引重建、旧行为学习数据清理和 legacy v1 遗留表清理。",
1813
+ handler=migrate_v21_to_v22,
1814
+ transactional=False,
1815
+ ),
1816
+ MigrationStep(
1817
+ version_from=V22_SCHEMA_VERSION,
1818
+ version_to=V23_SCHEMA_VERSION,
1819
+ name="v22_to_v23",
1820
+ description="移除行为场景簇冗余身份字段。",
1821
+ handler=migrate_v22_to_v23,
1822
+ ),
1823
+ MigrationStep(
1824
+ version_from=V23_SCHEMA_VERSION,
1825
+ version_to=V24_SCHEMA_VERSION,
1826
+ name="v23_to_v24",
1827
+ description="将行为动作/结果收敛为文本实体,并移除冗余 action/outcome 图边。",
1828
+ handler=migrate_v23_to_v24,
1829
+ ),
1830
+ MigrationStep(
1831
+ version_from=V24_SCHEMA_VERSION,
1832
+ version_to=V25_SCHEMA_VERSION,
1833
+ name="v24_to_v25",
1834
+ description="将行为场景簇规整为仅由 domain tag 定义。",
1835
+ handler=migrate_v24_to_v25,
1836
+ ),
1837
+ MigrationStep(
1838
+ version_from=V25_SCHEMA_VERSION,
1839
+ version_to=V26_SCHEMA_VERSION,
1840
+ name="v25_to_v26",
1841
+ description="移除行为学习中不再显式存储的 scene node 图层。",
1842
+ handler=migrate_v25_to_v26,
1843
+ ),
1844
+ MigrationStep(
1845
+ version_from=V26_SCHEMA_VERSION,
1846
+ version_to=V27_SCHEMA_VERSION,
1847
+ name="v26_to_v27",
1848
+ description="移除行为场景簇不再使用的 score 字段。",
1849
+ handler=migrate_v26_to_v27,
1850
+ ),
1851
+ MigrationStep(
1852
+ version_from=V27_SCHEMA_VERSION,
1853
+ version_to=V28_SCHEMA_VERSION,
1854
+ name="v27_to_v28",
1855
+ description="新增一次性维护任务状态表,并移除工具 prompt 冗余列。",
1856
+ handler=migrate_v27_to_v28,
1857
+ ),
1858
+ MigrationStep(
1859
+ version_from=V28_SCHEMA_VERSION,
1860
+ version_to=V29_SCHEMA_VERSION,
1861
+ name="v28_to_v29",
1862
+ description="将高频词词库改为按 chat_id 分类,并移除归一化词与类型列。",
1863
+ handler=migrate_v28_to_v29,
1864
+ ),
1865
+ MigrationStep(
1866
+ version_from=V29_SCHEMA_VERSION,
1867
+ version_to=V30_SCHEMA_VERSION,
1868
+ name="v29_to_v30",
1869
+ description="调整 LLM 使用记录字段:移除 endpoint/user_type,新增 session_id。",
1870
+ handler=migrate_v29_to_v30,
1871
+ ),
1872
+ MigrationStep(
1873
+ version_from=V30_SCHEMA_VERSION,
1874
+ version_to=V31_SCHEMA_VERSION,
1875
+ name="v30_to_v31",
1876
+ description="清理泛 tag 和低信息行为场景簇。",
1877
+ handler=migrate_v30_to_v31,
1878
+ ),
1879
+ MigrationStep(
1880
+ version_from=V31_SCHEMA_VERSION,
1881
+ version_to=V32_SCHEMA_VERSION,
1882
+ name="v31_to_v32",
1883
+ description="清理表达方式中由 prompt 示例带出的前缀和示例内容。",
1884
+ handler=migrate_v31_to_v32,
1885
+ ),
1886
+ MigrationStep(
1887
+ version_from=V32_SCHEMA_VERSION,
1888
+ version_to=V33_SCHEMA_VERSION,
1889
+ name="v32_to_v33",
1890
+ description="修复黑话记录中无法被 DateTime 解析的空时间字段。",
1891
+ handler=migrate_v32_to_v33,
1892
+ ),
1893
+ MigrationStep(
1894
+ version_from=V33_SCHEMA_VERSION,
1895
+ version_to=V34_SCHEMA_VERSION,
1896
+ name="v33_to_v34",
1897
+ description="为黑话记录增加证据消息引用列。",
1898
+ handler=migrate_v33_to_v34,
1899
+ ),
1900
+ MigrationStep(
1901
+ version_from=V34_SCHEMA_VERSION,
1902
+ version_to=V35_SCHEMA_VERSION,
1903
+ name="v34_to_v35",
1904
+ description="新增麦麦观察事件账本表。",
1905
+ handler=migrate_v34_to_v35,
1906
+ ),
1907
+ MigrationStep(
1908
+ version_from=V35_SCHEMA_VERSION,
1909
+ version_to=V36_SCHEMA_VERSION,
1910
+ name="v35_to_v36",
1911
+ description="为消息表新增平台与消息 ID 复合索引。",
1912
+ handler=migrate_v35_to_v36,
1913
+ ),
1914
+ MigrationStep(
1915
+ version_from=V36_SCHEMA_VERSION,
1916
+ version_to=V37_SCHEMA_VERSION,
1917
+ name="v36_to_v37",
1918
+ description="新增 MaiSaka 回复效果汇总表。",
1919
+ handler=migrate_v36_to_v37,
1920
+ ),
1921
+ MigrationStep(
1922
+ version_from=V37_SCHEMA_VERSION,
1923
+ version_to=V38_SCHEMA_VERSION,
1924
+ name="v37_to_v38",
1925
+ description="拆分回复请求指纹与稳定 Prompt 版本指纹。",
1926
+ handler=migrate_v37_to_v38,
1927
+ ),
1928
+ MigrationStep(
1929
+ version_from=V38_SCHEMA_VERSION,
1930
+ version_to=V39_SCHEMA_VERSION,
1931
+ name="v38_to_v39",
1932
+ description="无损压缩回复效果完整记录与诊断镜像。",
1933
+ handler=migrate_v38_to_v39,
1934
+ transactional=False,
1935
+ ),
1936
+ MigrationStep(
1937
+ version_from=V39_SCHEMA_VERSION,
1938
+ version_to=V40_SCHEMA_VERSION,
1939
+ name="v39_to_v40",
1940
+ description="新增适配器上报的 Bot 平台账号表。",
1941
+ handler=migrate_v39_to_v40,
1942
+ ),
1943
+ MigrationStep(
1944
+ version_from=V40_SCHEMA_VERSION,
1945
+ version_to=V41_SCHEMA_VERSION,
1946
+ name="v40_to_v41",
1947
+ description="为消息增加正式 account_id/scope 归属字段。",
1948
+ handler=migrate_v40_to_v41,
1949
+ ),
1950
+ MigrationStep(
1951
+ version_from=V41_SCHEMA_VERSION,
1952
+ version_to=V42_SCHEMA_VERSION,
1953
+ name="v41_to_v42",
1954
+ description="彻底移除行为学习数据表。",
1955
+ handler=migrate_v41_to_v42,
1956
+ ),
1957
+ MigrationStep(
1958
+ version_from=V42_SCHEMA_VERSION,
1959
+ version_to=V43_SCHEMA_VERSION,
1960
+ name="v42_to_v43",
1961
+ description="压缩移除行为学习表后的数据库,回收磁盘空间。",
1962
+ handler=migrate_v42_to_v43,
1963
+ transactional=False,
1964
+ ),
1965
+ ]
1966
+ )