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
src/main.py ADDED
@@ -0,0 +1,300 @@
1
+ from typing import TYPE_CHECKING, Any, Optional
2
+
3
+ from rich.traceback import install
4
+
5
+ import asyncio
6
+ import sys
7
+ import time
8
+
9
+ from src.common.i18n import t
10
+ from src.common.logger import get_logger
11
+ from src.common.runtime_loop import set_main_loop
12
+ from src.config.config import config_manager, global_config
13
+ from src.manager.async_task_manager import async_task_manager
14
+ from src.prompt.prompt_manager import prompt_manager
15
+
16
+ # from src.api.main import start_api_server
17
+
18
+ # 导入插件运行时
19
+ # 导入消息API和traceback模块
20
+ # from src.chat.utils.token_statistics import TokenStatisticsTask
21
+
22
+ install(extra_lines=3)
23
+
24
+ logger = get_logger("main")
25
+
26
+
27
+ if TYPE_CHECKING:
28
+ from maim_message import MessageServer
29
+ from src.common.message_server.server import Server
30
+ from src.webui.webui_server import ThreadedWebUIServer
31
+
32
+
33
+ async def _wait_for_plugin_runners_spawned(
34
+ plugin_runtime_manager: Any,
35
+ plugin_runtime_task: asyncio.Task[None],
36
+ timeout: float = 1.0,
37
+ ) -> None:
38
+ """让插件 Runner 子进程先拉起,以便和后续重初始化并行。"""
39
+
40
+ deadline = asyncio.get_running_loop().time() + timeout
41
+ while not plugin_runtime_task.done():
42
+ supervisors = list(getattr(plugin_runtime_manager, "supervisors", []))
43
+ if supervisors and all(getattr(supervisor, "_runner_process", None) is not None for supervisor in supervisors):
44
+ return
45
+ if asyncio.get_running_loop().time() >= deadline:
46
+ return
47
+ await asyncio.sleep(0.02)
48
+
49
+
50
+ class MainSystem:
51
+ def __init__(self) -> None:
52
+ # 使用消息API替代直接的FastAPI实例
53
+ self.app: MessageServer | None = None
54
+ self.server: Server | None = None
55
+ self.webui_server: ThreadedWebUIServer | None = None # 独立线程中的 WebUI 服务器
56
+ self._message_handlers_registered = False
57
+ self.watchdog_task: Optional[asyncio.Task[None]] = None
58
+
59
+ def _ensure_message_server(self) -> None:
60
+ """按需初始化消息 API,避免阻塞主启动链路的早期阶段。"""
61
+
62
+ if self.app is not None and self.server is not None:
63
+ return
64
+
65
+ from src.common.message_server import get_global_api
66
+ from src.common.message_server.server import get_global_server
67
+
68
+ self.app = get_global_api()
69
+ self.server = get_global_server()
70
+
71
+ def _register_message_handlers(self) -> None:
72
+ """注册主消息处理器;消息服务实际调度前完成即可。"""
73
+
74
+ if self._message_handlers_registered:
75
+ return
76
+
77
+ self._ensure_message_server()
78
+ if self.app is None:
79
+ raise RuntimeError("消息 API 初始化失败")
80
+
81
+ from src.chat.message_receive.bot import chat_bot
82
+
83
+ self.app.register_message_handler(chat_bot.message_process)
84
+ self.app.register_custom_message_handler("message_id_echo", chat_bot.echo_message_process)
85
+ self._message_handlers_registered = True
86
+
87
+ def _start_webui_server(self) -> None:
88
+ """启动独立线程中的 WebUI 服务器。"""
89
+ from src.config.config import global_config
90
+
91
+ if not global_config.webui.enabled:
92
+ logger.info(t("startup.webui_disabled"))
93
+ return
94
+
95
+ try:
96
+ from src.webui.webui_server import get_threaded_webui_server
97
+
98
+ self.webui_server = get_threaded_webui_server()
99
+ self.webui_server.start()
100
+
101
+ except Exception as e:
102
+ logger.error(t("startup.webui_server_init_failed", error=e))
103
+
104
+ async def initialize(self) -> None:
105
+ """初始化系统组件"""
106
+ logger.info(t("startup.waking_up", nickname=global_config.bot.nickname))
107
+
108
+ try:
109
+ from src.services.tool_record_cleanup_service import run_startup_tool_record_vacuum_if_needed
110
+
111
+ await asyncio.to_thread(run_startup_tool_record_vacuum_if_needed)
112
+ await self._init_components()
113
+ except Exception:
114
+ if self.webui_server:
115
+ await self.webui_server.shutdown()
116
+ raise
117
+
118
+ logger.info(t("startup.initialization_completed_banner", nickname=global_config.bot.nickname))
119
+
120
+ async def _init_components(self) -> None:
121
+ """初始化其他组件"""
122
+ init_start_time = time.time()
123
+
124
+ await config_manager.start_file_watcher()
125
+
126
+ # 插件 Runner 启动最重,尽早发起以便和后续初始化并行。
127
+ from src.plugin_runtime.integration import get_plugin_runtime_manager
128
+
129
+ plugin_runtime_manager = get_plugin_runtime_manager()
130
+ plugin_runtime_task = asyncio.create_task(plugin_runtime_manager.start(), name="plugin_runtime_start")
131
+ await _wait_for_plugin_runners_spawned(plugin_runtime_manager, plugin_runtime_task)
132
+
133
+ # 数据库启动维护已完成;让 WebUI 在线程中加载,与后续组件初始化并行,
134
+ # 无需等待全部插件就绪后才开放管理页面。
135
+ self._start_webui_server()
136
+
137
+ from src.A_memorix.host_service import a_memorix_host_service
138
+ from src.mcp_module.service import get_mcp_service
139
+ from src.services.expression_vector_service import expression_vector_service
140
+
141
+ a_memorix_host_service.register_config_reload_callback()
142
+ get_mcp_service().register_config_reload_callback()
143
+ expression_vector_service.start()
144
+ a_memorix_task = asyncio.create_task(a_memorix_host_service.start(), name="a_memorix_start")
145
+
146
+ await asyncio.sleep(0)
147
+ prompt_manager.load_prompts()
148
+
149
+ from src.emoji_system.emoji_manager import emoji_manager
150
+
151
+ emoji_load_task = asyncio.create_task(asyncio.to_thread(emoji_manager.load_emojis_from_db), name="emoji_load_from_db")
152
+
153
+ # 启动API服务器
154
+ # start_api_server()
155
+ # logger.info("API服务器启动成功")
156
+
157
+ try:
158
+ await asyncio.gather(plugin_runtime_task, a_memorix_task)
159
+ await emoji_load_task
160
+ except Exception:
161
+ for task in (plugin_runtime_task, a_memorix_task, emoji_load_task):
162
+ if not task.done():
163
+ task.cancel()
164
+ await asyncio.gather(
165
+ plugin_runtime_task,
166
+ a_memorix_task,
167
+ emoji_load_task,
168
+ return_exceptions=True,
169
+ )
170
+ raise
171
+
172
+ # 初始化表情管理器
173
+ logger.info(t("startup.emoji_manager_initialized"))
174
+
175
+ # 初始化聊天管理器
176
+ from src.chat.message_receive.chat_manager import chat_manager
177
+ from src.services.memory_flow_service import memory_automation_service
178
+
179
+ await chat_manager.initialize()
180
+ asyncio.create_task(chat_manager.regularly_save_sessions())
181
+
182
+ logger.info(t("startup.chat_manager_initialized"))
183
+ await memory_automation_service.start()
184
+
185
+ # await asyncio.sleep(0.5) #防止logger输出飞了
186
+
187
+ # 触发 ON_START 事件,事件总线会统一桥接到 IPC 插件运行时。
188
+ from src.core.event_bus import event_bus
189
+ from src.core.types import EventType
190
+
191
+ await event_bus.emit(event_type=EventType.ON_START)
192
+ # logger.info("已触发 ON_START 事件")
193
+
194
+ from src.chat.utils.statistic import OnlineTimeRecordTask, StatisticOutputTask
195
+
196
+ # 添加在线时间统计任务
197
+ await async_task_manager.add_task(OnlineTimeRecordTask())
198
+
199
+ # 添加统计信息输出任务
200
+ await async_task_manager.add_task(StatisticOutputTask())
201
+
202
+ # 添加遥测心跳与统计上传任务
203
+ from src.common.remote import TelemetryHeartBeatTask, TelemetryStatsUploadTask
204
+
205
+ await async_task_manager.add_task(TelemetryHeartBeatTask())
206
+ await async_task_manager.add_task(TelemetryStatsUploadTask())
207
+
208
+ # 主循环卡顿看门狗;WebUI 循环另有一份,挂在 WebUI 服务器启动处。
209
+ from src.common.event_loop_watchdog import start_watchdog
210
+
211
+ self.watchdog_task = start_watchdog("main")
212
+
213
+ try:
214
+ init_time = int(1000 * (time.time() - init_start_time))
215
+ logger.info(t("startup.initialization_completed_cycles", init_time=init_time))
216
+ except Exception as e:
217
+ logger.error(t("startup.brain_external_world_failed", error=e))
218
+ raise
219
+
220
+ async def schedule_tasks(self) -> None:
221
+ """调度定时任务"""
222
+ try:
223
+ from src.chat.image_system.image_cache_cleanup import periodic_image_cache_cleanup
224
+ from src.emoji_system.emoji_cache_cleanup import periodic_emoji_cache_cleanup
225
+ from src.emoji_system.emoji_manager import emoji_manager
226
+ from src.maisaka.display.prompt_preview_logger import PromptPreviewLogger
227
+ from src.services.image_path_maintenance_service import (
228
+ run_image_path_maintenance_background,
229
+ should_schedule_image_path_maintenance_background,
230
+ )
231
+ from src.webui.routers.data_transfer import periodic_transfer_temp_cleanup
232
+
233
+ # 在独立线程中巡检推理图片,空闲时也能清理旧版本遗留的孤立缓存。
234
+ PromptPreviewLogger.start()
235
+ self._register_message_handlers()
236
+ if self.app is None or self.server is None:
237
+ raise RuntimeError("消息服务未初始化")
238
+
239
+ tasks = [
240
+ emoji_manager.periodic_emoji_maintenance(),
241
+ periodic_emoji_cache_cleanup(),
242
+ periodic_image_cache_cleanup(),
243
+ periodic_transfer_temp_cleanup(),
244
+ self.app.run(),
245
+ self.server.run(),
246
+ ]
247
+ if global_config.debug.enable_console_input:
248
+ if sys.stdin.isatty():
249
+ from src.cli.bot_console import BotConsole
250
+
251
+ logger.info("已启用终端输入,可输入普通消息或 /clear、/pm 等指令;输入 exit() 关闭终端输入")
252
+ tasks.append(BotConsole().run())
253
+ else:
254
+ logger.warning("终端输入已配置为启用,但当前 stdin 不是交互式终端,已跳过")
255
+ image_path_maintenance_needed = await asyncio.to_thread(should_schedule_image_path_maintenance_background)
256
+ if image_path_maintenance_needed:
257
+ tasks.append(run_image_path_maintenance_background())
258
+
259
+ await asyncio.gather(*tasks)
260
+ except asyncio.CancelledError:
261
+ logger.info(t("startup.schedule_cancelled"))
262
+ raise
263
+
264
+
265
+ async def main() -> None:
266
+ """主函数"""
267
+ set_main_loop(asyncio.get_running_loop())
268
+ system = MainSystem()
269
+ try:
270
+ await system.initialize()
271
+ await system.schedule_tasks()
272
+ finally:
273
+ if system.webui_server:
274
+ await system.webui_server.shutdown()
275
+ if system.watchdog_task is not None:
276
+ system.watchdog_task.cancel()
277
+ system.watchdog_task = None
278
+ from src.A_memorix.host_service import a_memorix_host_service
279
+ from src.chat.image_system.image_manager import image_manager
280
+ from src.emoji_system.emoji_manager import emoji_manager
281
+ from src.mcp_module.service import get_mcp_service
282
+ from src.plugin_runtime.integration import get_plugin_runtime_manager
283
+ from src.services.expression_vector_service import expression_vector_service
284
+ from src.services.memory_flow_service import memory_automation_service
285
+
286
+ emoji_manager.shutdown()
287
+ await image_manager.shutdown()
288
+ await expression_vector_service.stop()
289
+ await memory_automation_service.shutdown()
290
+ await a_memorix_host_service.stop()
291
+ await get_plugin_runtime_manager().bridge_event("on_stop")
292
+ await get_plugin_runtime_manager().stop()
293
+ await async_task_manager.stop_and_wait_all_tasks()
294
+ await get_mcp_service().close()
295
+ await config_manager.stop_file_watcher()
296
+ set_main_loop(None)
297
+
298
+
299
+ if __name__ == "__main__":
300
+ asyncio.run(main())
@@ -0,0 +1,116 @@
1
+ from typing import Mapping
2
+
3
+ from src.common.i18n import get_locale
4
+ from src.config.config import global_config
5
+
6
+
7
+ DRIFT_LEVEL_RULES = {
8
+ "subtle": {
9
+ "zh-CN": "漂移档位:轻微漂移。只在最近消息里出现非常自然的触发点时,轻轻联想一句;大多数时候继续当前话题。",
10
+ "en-US": "Drift level: subtle. Add a small aside only when recent messages provide a very natural hook; usually stay on the current topic.",
11
+ "ja-JP": "ドリフト段階:軽め。直近メッセージにとても自然なきっかけがある時だけ軽く一言連想し、基本は現在の話題に沿ってください。",
12
+ },
13
+ "active": {
14
+ "zh-CN": "漂移档位:活跃联想。可以主动抓住新鲜、好笑、反差强或熟悉的细节接话,但回复仍要清楚、短促、能被最近消息解释。",
15
+ "en-US": "Drift level: active. You may actively pick up fresh, funny, contrasting, or familiar details, but the reply must stay clear, short, and explainable from recent messages.",
16
+ "ja-JP": "ドリフト段階:活発な連想。新鮮、面白い、ギャップの強い、見知った細部を拾ってもよいですが、返信は明確で短く、直近文脈から説明できるものにしてください。",
17
+ },
18
+ "scattered": {
19
+ "zh-CN": "漂移档位:明显发散。你可以明显地被支线、关键词、熟人语气或反差点勾走,先接住那个点再回到正题;回复里允许出现一次可理解的突然拐弯。",
20
+ "en-US": "Drift level: scattered. You may noticeably get pulled by side topics, keywords, familiar voices, or contrasts; catch that detail first, then return to the point. One understandable sudden turn is allowed in a reply.",
21
+ "ja-JP": "ドリフト段階:はっきり発散。支線、キーワード、見知った口調、ギャップに明確に引かれてよく、その点を先に拾ってから本題へ戻ってください。返信内で一度なら理解できる急な曲がり方をしてかまいません。",
22
+ },
23
+ "wild": {
24
+ "zh-CN": "漂移档位:强烈跳跃。你可以先被最有趣的细节劫走一下,出现短促插话、突然联想或半路拐弯;但每轮最多一次明显跳跃,不能无视明确提问,最后要让人看得出你在接哪条消息。",
25
+ "en-US": "Drift level: wild. You may first get hijacked by the most interesting detail, with a short interjection, sudden association, or mid-reply turn. Allow at most one obvious jump per turn, do not ignore direct questions, and leave the reply traceable to a recent message.",
26
+ "ja-JP": "ドリフト段階:強めのジャンプ。いちばん面白い細部に一瞬さらわれ、短い差し込み、突然の連想、途中の方向転換をしてもかまいません。ただし一回の返信で明確なジャンプは最大一度、明確な質問は無視せず、どの直近メッセージを受けたのか分かるようにしてください。",
27
+ },
28
+ }
29
+
30
+ ANCHOR_POLICY_RULES = {
31
+ "strict": {
32
+ "zh-CN": "回钩策略:严格回钩。联想或短反应之后,要立刻回到当前正在聊的主题或被回复对象。",
33
+ "en-US": "Anchor policy: strict. After an aside or short reaction, immediately return to the current topic or reply target.",
34
+ "ja-JP": "アンカー方針:厳格。連想や短い反応の後は、すぐ現在の話題または返信対象へ戻ってください。",
35
+ },
36
+ "balanced": {
37
+ "zh-CN": "回钩策略:自然回钩。可以短暂沿着支线说一句,但通常要让结尾或主要意思回到当前聊天。",
38
+ "en-US": "Anchor policy: balanced. You may briefly follow a side association, but usually bring the ending or main point back to the current chat.",
39
+ "ja-JP": "アンカー方針:自然。短く寄り道してもよいですが、基本的には結末や主旨を現在の会話へ戻してください。",
40
+ },
41
+ "loose": {
42
+ "zh-CN": "回钩策略:宽松关联。可以保留更自由的相关联想,但不能凭空换话题,也不能无视明确提问。",
43
+ "en-US": "Anchor policy: loose. You may keep a freer related association, but do not switch topics out of nowhere or ignore direct questions.",
44
+ "ja-JP": "アンカー方針:ゆるめ。より自由な関連連想を残してもよいですが、唐突に話題を変えたり、明確な質問を無視したりしないでください。",
45
+ },
46
+ }
47
+
48
+ REACTION_STYLE_RULES = {
49
+ "reserved": {
50
+ "zh-CN": "短反应风格:少量短反应。只有特别适合接话时,才用一句很短的反应开头。",
51
+ "en-US": "Short reaction style: reserved. Start with a very short reaction only when it fits especially well.",
52
+ "ja-JP": "短い反応スタイル:控えめ。特に合う時だけ、とても短い反応から始めてください。",
53
+ },
54
+ "natural": {
55
+ "zh-CN": "短反应风格:自然短反应。可以偶尔先用短句、吐槽或语气词接住话题,再继续正常回复。",
56
+ "en-US": "Short reaction style: natural. You may occasionally start with a short phrase, quip, or interjection before continuing normally.",
57
+ "ja-JP": "短い反応スタイル:自然。たまに短い一言、ツッコミ、間投詞で受けてから普通に返信してもかまいません。",
58
+ },
59
+ "lively": {
60
+ "zh-CN": "短反应风格:活泼短反应。更容易先用短促反应开头,但不要把回复拆得太碎,也不要每次都这样。",
61
+ "en-US": "Short reaction style: lively. You are more likely to open with a short reaction, but do not fragment the reply too much or do it every time.",
62
+ "ja-JP": "短い反応スタイル:活発。短い反応から入りやすくしてよいですが、返信を細かく分けすぎず、毎回そうしないでください。",
63
+ },
64
+ }
65
+
66
+
67
+ def _localized_text(texts: Mapping[str, str]) -> str:
68
+ locale = get_locale()
69
+ return texts.get(locale, texts["zh-CN"])
70
+
71
+
72
+ def build_attention_drift_prompt_block() -> str:
73
+ """构建注意力漂移模式的 prompt 注入块。"""
74
+
75
+ config = global_config.experimental.attention_drift
76
+ if not config.enabled:
77
+ return ""
78
+
79
+ drift_rule = _localized_text(DRIFT_LEVEL_RULES[config.drift_level])
80
+ anchor_rule = _localized_text(ANCHOR_POLICY_RULES[config.anchor_policy])
81
+ reaction_rule = _localized_text(REACTION_STYLE_RULES[config.reaction_style])
82
+
83
+ return _localized_text(
84
+ {
85
+ "en-US": (
86
+ "Attention drift style:\n"
87
+ "- You may be briefly attracted by fresh, funny, contrasting, or personally familiar details in the chat, but every drift must have a clear hook in recent messages.\n"
88
+ "- Drift is not just changing the topic: grab a standout hook first, then make a brief turn that feels like a sudden spark of thought.\n"
89
+ "- Prefer lively association over real inefficiency: do not deliberately delay, ignore tasks, or scatter tool use just to act distracted.\n"
90
+ "- Do not medicalize this style, do not call yourself ADHD, and do not announce that you are distracted.\n"
91
+ f"- {drift_rule}\n"
92
+ f"- {anchor_rule}\n"
93
+ f"- {reaction_rule}\n"
94
+ ),
95
+ "ja-JP": (
96
+ "注意ドリフトスタイル:\n"
97
+ "- チャット内の新鮮、面白い、ギャップの強い、または見知った要素に一時的に引かれてもよいですが、ドリフトには必ず直近メッセージ内の明確なきっかけが必要です。\n"
98
+ "- ドリフトは単なる話題変更ではありません。目立つきっかけを先に拾い、思考が急に光ったような短い曲がり方にしてください。\n"
99
+ "- 本当に非効率にするのではなく、活発な連想として表現してください。気が散ったふりのために遅延、タスク無視、ツール使用の散乱をしないでください。\n"
100
+ "- このスタイルを医学化せず、自分を ADHD と呼ばず、気が散っていると宣言しないでください。\n"
101
+ f"- {drift_rule}\n"
102
+ f"- {anchor_rule}\n"
103
+ f"- {reaction_rule}\n"
104
+ ),
105
+ "zh-CN": (
106
+ "注意力漂移风格:\n"
107
+ "- 你可以短暂被聊天里新鲜、好笑、反差强或熟悉的人和梗吸引,但每次漂移都必须能从最近消息里找到明确触发点。\n"
108
+ "- 漂移不是单纯换话题,而是先抓一个突出的触发点,再用很短的拐弯制造“脑子突然亮了一下”的感觉。\n"
109
+ "- 表现活跃联想,不要真的降效;不要为了显得分心而故意拖延、忽略任务或打散工具调用。\n"
110
+ "- 不要医学化描述这种风格,不要自称 ADHD,也不要主动声明自己分心。\n"
111
+ f"- {drift_rule}\n"
112
+ f"- {anchor_rule}\n"
113
+ f"- {reaction_rule}\n"
114
+ ),
115
+ }
116
+ )
@@ -0,0 +1,236 @@
1
+ """Maisaka 内置工具聚合入口。"""
2
+
3
+ from collections.abc import Awaitable, Callable
4
+ from copy import deepcopy
5
+ from dataclasses import dataclass
6
+ from typing import Dict, List, Literal, Optional
7
+
8
+ from src.config.config import global_config
9
+ from src.core.tooling import ToolAvailabilityContext, ToolExecutionContext, ToolExecutionResult, ToolInvocation, ToolSpec
10
+ from src.llm_models.payload_content.tool_option import ToolDefinitionInput
11
+ from src.maisaka.focus import focus_mode_manager
12
+
13
+ from .context import BuiltinToolRuntimeContext
14
+ from .fetch_history import get_tool_spec as get_fetch_history_tool_spec
15
+ from .fetch_history import handle_tool as handle_fetch_history_tool
16
+ from .query_memory import get_tool_spec as get_query_memory_tool_spec
17
+ from .query_memory import handle_tool as handle_query_memory_tool
18
+ from .query_image_memory import get_tool_spec as get_query_image_memory_tool_spec
19
+ from .query_image_memory import handle_tool as handle_query_image_memory_tool
20
+ from .query_person_profile import get_tool_spec as get_query_person_profile_tool_spec
21
+ from .query_person_profile import handle_tool as handle_query_person_profile_tool
22
+ from .read_tool_result import get_tool_spec as get_read_tool_result_tool_spec
23
+ from .read_tool_result import handle_tool as handle_read_tool_result_tool
24
+ from .reply import get_tool_spec as get_reply_tool_spec
25
+ from .reply import handle_tool as handle_reply_tool
26
+ from .send_emoji import get_tool_spec as get_send_emoji_tool_spec
27
+ from .send_emoji import handle_tool as handle_send_emoji_tool
28
+ from .show_emoji_list import get_tool_spec as get_show_emoji_list_tool_spec
29
+ from .show_emoji_list import handle_tool as handle_show_emoji_list_tool
30
+ from .subagent import get_status_tool_spec as get_subagent_status_tool_spec
31
+ from .subagent import get_stop_tool_spec as get_subagent_stop_tool_spec
32
+ from .subagent import get_tool_spec as get_subagent_tool_spec
33
+ from .subagent import handle_status_tool as handle_subagent_status_tool
34
+ from .subagent import handle_stop_tool as handle_subagent_stop_tool
35
+ from .subagent import handle_tool as handle_subagent_tool
36
+ from .switch_chat import get_tool_spec as get_switch_chat_tool_spec
37
+ from .switch_chat import handle_tool as handle_switch_chat_tool
38
+ from .tool_search import get_tool_spec as get_tool_search_tool_spec
39
+ from .tool_search import handle_tool as handle_tool_search_tool
40
+ from .view_forward_message import get_tool_spec as get_view_forward_message_tool_spec
41
+ from .view_forward_message import handle_tool as handle_view_forward_message_tool
42
+ from .wait import get_tool_spec as get_wait_tool_spec
43
+ from .wait import handle_tool as handle_wait_tool
44
+
45
+ BuiltinToolHandler = Callable[[ToolInvocation, Optional[ToolExecutionContext]], Awaitable[ToolExecutionResult]]
46
+ BuiltinToolRawHandler = Callable[
47
+ [BuiltinToolRuntimeContext, ToolInvocation, Optional[ToolExecutionContext]],
48
+ Awaitable[ToolExecutionResult],
49
+ ]
50
+ BuiltinToolStage = Literal["action", "both"]
51
+ BuiltinToolVisibility = Literal["visible", "deferred", "hidden"]
52
+ BuiltinToolChatScope = Literal["all", "group", "private"]
53
+
54
+
55
+ @dataclass(frozen=True)
56
+ class BuiltinToolEntry:
57
+ """内置工具目录项,集中声明工具所属阶段与默认可见性。"""
58
+
59
+ name: str
60
+ get_spec: Callable[[], ToolSpec]
61
+ handle_tool: BuiltinToolRawHandler
62
+ stage: BuiltinToolStage
63
+ visibility: BuiltinToolVisibility = "visible"
64
+ chat_scope: BuiltinToolChatScope = "all"
65
+
66
+ def build_spec(self, context: Optional[ToolAvailabilityContext] = None) -> ToolSpec:
67
+ """生成带统一可见性元数据的工具声明。"""
68
+
69
+ tool_spec = deepcopy(get_reply_tool_spec(context) if self.name == "reply" else self.get_spec())
70
+ tool_spec.metadata["builtin_stage"] = self.stage
71
+ tool_spec.metadata["visibility"] = self.visibility
72
+ return tool_spec
73
+
74
+
75
+ def _get_query_memory_tool_spec() -> ToolSpec:
76
+ """根据配置生成 query_memory 工具声明。"""
77
+
78
+ return get_query_memory_tool_spec(enabled=bool(global_config.a_memorix.integration.enable_memory_query_tool))
79
+
80
+
81
+ def _get_query_person_profile_tool_spec() -> ToolSpec:
82
+ """根据配置生成 query_person_profile 工具声明。"""
83
+
84
+ return get_query_person_profile_tool_spec(
85
+ enabled=bool(global_config.a_memorix.integration.enable_person_profile_query_tool)
86
+ )
87
+
88
+
89
+ def _get_query_image_memory_tool_spec() -> ToolSpec:
90
+ return get_query_image_memory_tool_spec(enabled=bool(global_config.a_memorix.image_memory.enabled))
91
+
92
+
93
+ BUILTIN_TOOL_ENTRIES: List[BuiltinToolEntry] = [
94
+ BuiltinToolEntry("wait", get_wait_tool_spec, handle_wait_tool, stage="both"),
95
+ BuiltinToolEntry("reply", get_reply_tool_spec, handle_reply_tool, stage="action"),
96
+ BuiltinToolEntry(
97
+ "view_forward_message",
98
+ get_view_forward_message_tool_spec,
99
+ handle_view_forward_message_tool,
100
+ stage="action",
101
+ visibility="deferred",
102
+ ),
103
+ BuiltinToolEntry("query_memory", _get_query_memory_tool_spec, handle_query_memory_tool, stage="action"),
104
+ BuiltinToolEntry(
105
+ "query_image_memory",
106
+ _get_query_image_memory_tool_spec,
107
+ handle_query_image_memory_tool,
108
+ stage="action",
109
+ ),
110
+ BuiltinToolEntry(
111
+ "query_person_profile",
112
+ _get_query_person_profile_tool_spec,
113
+ handle_query_person_profile_tool,
114
+ stage="action",
115
+ ),
116
+ BuiltinToolEntry("send_emoji", get_send_emoji_tool_spec, handle_send_emoji_tool, stage="action"),
117
+ BuiltinToolEntry("show_emoji_list", get_show_emoji_list_tool_spec, handle_show_emoji_list_tool, stage="action"),
118
+ BuiltinToolEntry("tool_search", get_tool_search_tool_spec, handle_tool_search_tool, stage="action"),
119
+ BuiltinToolEntry("subagent", get_subagent_tool_spec, handle_subagent_tool, stage="action"),
120
+ BuiltinToolEntry("subagent_status", get_subagent_status_tool_spec, handle_subagent_status_tool, stage="action"),
121
+ BuiltinToolEntry("subagent_stop", get_subagent_stop_tool_spec, handle_subagent_stop_tool, stage="action"),
122
+ BuiltinToolEntry(
123
+ "read_tool_result",
124
+ get_read_tool_result_tool_spec,
125
+ handle_read_tool_result_tool,
126
+ stage="action",
127
+ ),
128
+ BuiltinToolEntry(
129
+ "fetch_history",
130
+ get_fetch_history_tool_spec,
131
+ handle_fetch_history_tool,
132
+ stage="action",
133
+ ),
134
+ BuiltinToolEntry("switch_chat", get_switch_chat_tool_spec, handle_switch_chat_tool, stage="action"),
135
+ ]
136
+
137
+
138
+ def _get_builtin_tool_entries(
139
+ *,
140
+ stage: Optional[BuiltinToolStage] = None,
141
+ visibility: Optional[BuiltinToolVisibility] = None,
142
+ context: Optional[ToolAvailabilityContext] = None,
143
+ ) -> List[BuiltinToolEntry]:
144
+ """按阶段与可见性筛选内置工具目录项。"""
145
+
146
+ entries = BUILTIN_TOOL_ENTRIES
147
+ entries = [entry for entry in entries if _is_builtin_tool_enabled_by_config(entry)]
148
+ if stage is not None:
149
+ entries = [entry for entry in entries if entry.stage in {stage, "both"}]
150
+ if visibility is not None:
151
+ entries = [entry for entry in entries if entry.visibility == visibility]
152
+ if context is not None:
153
+ entries = [entry for entry in entries if _is_builtin_tool_available(entry, context)]
154
+ return entries
155
+
156
+
157
+ def _is_builtin_tool_enabled_by_config(entry: BuiltinToolEntry) -> bool:
158
+ """根据全局配置判断内置工具是否应暴露。"""
159
+
160
+ if entry.name == "show_emoji_list":
161
+ return global_config.emoji.use_new_send_logic
162
+ if entry.name == "send_emoji":
163
+ return not global_config.emoji.use_new_send_logic
164
+ if entry.name in {"fetch_history", "switch_chat"}:
165
+ return bool(global_config.experimental.focus_mode)
166
+ if entry.name == "subagent":
167
+ return global_config.experimental.planner_subagent
168
+ if entry.name in {"subagent_status", "subagent_stop"}:
169
+ # 只有后台子代理才有需要查看和终止的任务
170
+ return global_config.experimental.planner_subagent and global_config.experimental.advanced_sub_agent
171
+ if entry.name == "read_tool_result":
172
+ # 只有开启超长结果整理时才会有被暂存的原文可读
173
+ return global_config.experimental.tool_result_condense
174
+ return True
175
+
176
+
177
+ def _is_builtin_tool_available(entry: BuiltinToolEntry, context: ToolAvailabilityContext) -> bool:
178
+ """判断内置工具是否适用于当前聊天。"""
179
+
180
+ if entry.name in {"fetch_history", "switch_chat"}:
181
+ if context.session_id:
182
+ return focus_mode_manager.is_enabled_for_session(
183
+ context.session_id,
184
+ is_group_chat=context.is_group_chat,
185
+ )
186
+ if not focus_mode_manager.is_enabled_for_chat(is_group_chat=context.is_group_chat):
187
+ return False
188
+ if entry.chat_scope == "all":
189
+ return True
190
+ if entry.chat_scope == "group":
191
+ return context.is_group_chat is True
192
+ if entry.chat_scope == "private":
193
+ return context.is_group_chat is False
194
+ return True
195
+
196
+
197
+ def get_builtin_tool_visibility(tool_spec: ToolSpec) -> BuiltinToolVisibility:
198
+ """读取工具声明里的可见性。"""
199
+
200
+ raw_visibility = str(tool_spec.metadata.get("visibility") or "").strip()
201
+ if raw_visibility == "deferred":
202
+ return "deferred"
203
+ if raw_visibility == "hidden":
204
+ return "hidden"
205
+ return "visible"
206
+
207
+
208
+ def is_builtin_tool_in_action_stage(tool_spec: ToolSpec) -> bool:
209
+ """判断内置工具是否属于 Action Loop 阶段。"""
210
+
211
+ return str(tool_spec.metadata.get("builtin_stage") or "").strip() in {"action", "both"}
212
+
213
+
214
+ def get_all_builtin_tool_specs(context: Optional[ToolAvailabilityContext] = None) -> List[ToolSpec]:
215
+ """获取全部内置工具声明。"""
216
+
217
+ return [entry.build_spec(context) for entry in _get_builtin_tool_entries(context=context)]
218
+
219
+
220
+ def get_builtin_tools(context: Optional[ToolAvailabilityContext] = None) -> List[ToolDefinitionInput]:
221
+ """获取默认暴露给模型层的内置工具定义。"""
222
+
223
+ tool_specs = [
224
+ entry.build_spec(context)
225
+ for entry in _get_builtin_tool_entries(stage="action", visibility="visible", context=context)
226
+ ]
227
+ return [tool_spec.to_llm_definition() for tool_spec in tool_specs if tool_spec.enabled]
228
+
229
+
230
+ def build_builtin_tool_handlers(tool_ctx: BuiltinToolRuntimeContext) -> Dict[str, BuiltinToolHandler]:
231
+ """构建内置工具处理器映射。"""
232
+
233
+ return {
234
+ entry.name: lambda invocation, context=None, entry=entry: entry.handle_tool(tool_ctx, invocation, context)
235
+ for entry in BUILTIN_TOOL_ENTRIES
236
+ }