jarvis-ai-assistant 0.7.16__py3-none-any.whl → 1.0.2__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 (279) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +567 -222
  3. jarvis/jarvis_agent/agent_manager.py +19 -12
  4. jarvis/jarvis_agent/builtin_input_handler.py +79 -11
  5. jarvis/jarvis_agent/config_editor.py +7 -2
  6. jarvis/jarvis_agent/event_bus.py +24 -13
  7. jarvis/jarvis_agent/events.py +19 -1
  8. jarvis/jarvis_agent/file_context_handler.py +67 -64
  9. jarvis/jarvis_agent/file_methodology_manager.py +38 -24
  10. jarvis/jarvis_agent/jarvis.py +186 -114
  11. jarvis/jarvis_agent/language_extractors/__init__.py +8 -1
  12. jarvis/jarvis_agent/language_extractors/c_extractor.py +7 -4
  13. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +9 -4
  14. jarvis/jarvis_agent/language_extractors/go_extractor.py +7 -4
  15. jarvis/jarvis_agent/language_extractors/java_extractor.py +27 -20
  16. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +22 -17
  17. jarvis/jarvis_agent/language_extractors/python_extractor.py +7 -4
  18. jarvis/jarvis_agent/language_extractors/rust_extractor.py +7 -4
  19. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +22 -17
  20. jarvis/jarvis_agent/language_support_info.py +250 -219
  21. jarvis/jarvis_agent/main.py +19 -23
  22. jarvis/jarvis_agent/memory_manager.py +9 -6
  23. jarvis/jarvis_agent/methodology_share_manager.py +21 -15
  24. jarvis/jarvis_agent/output_handler.py +4 -2
  25. jarvis/jarvis_agent/prompt_builder.py +7 -6
  26. jarvis/jarvis_agent/prompt_manager.py +113 -8
  27. jarvis/jarvis_agent/prompts.py +317 -85
  28. jarvis/jarvis_agent/protocols.py +5 -2
  29. jarvis/jarvis_agent/run_loop.py +192 -32
  30. jarvis/jarvis_agent/session_manager.py +7 -3
  31. jarvis/jarvis_agent/share_manager.py +23 -13
  32. jarvis/jarvis_agent/shell_input_handler.py +12 -8
  33. jarvis/jarvis_agent/stdio_redirect.py +25 -26
  34. jarvis/jarvis_agent/task_analyzer.py +29 -23
  35. jarvis/jarvis_agent/task_list.py +869 -0
  36. jarvis/jarvis_agent/task_manager.py +26 -23
  37. jarvis/jarvis_agent/tool_executor.py +6 -5
  38. jarvis/jarvis_agent/tool_share_manager.py +24 -14
  39. jarvis/jarvis_agent/user_interaction.py +3 -3
  40. jarvis/jarvis_agent/utils.py +9 -1
  41. jarvis/jarvis_agent/web_bridge.py +37 -17
  42. jarvis/jarvis_agent/web_output_sink.py +5 -2
  43. jarvis/jarvis_agent/web_server.py +165 -36
  44. jarvis/jarvis_c2rust/__init__.py +1 -1
  45. jarvis/jarvis_c2rust/cli.py +260 -141
  46. jarvis/jarvis_c2rust/collector.py +37 -18
  47. jarvis/jarvis_c2rust/constants.py +60 -0
  48. jarvis/jarvis_c2rust/library_replacer.py +242 -1010
  49. jarvis/jarvis_c2rust/library_replacer_checkpoint.py +133 -0
  50. jarvis/jarvis_c2rust/library_replacer_llm.py +287 -0
  51. jarvis/jarvis_c2rust/library_replacer_loader.py +191 -0
  52. jarvis/jarvis_c2rust/library_replacer_output.py +134 -0
  53. jarvis/jarvis_c2rust/library_replacer_prompts.py +124 -0
  54. jarvis/jarvis_c2rust/library_replacer_utils.py +188 -0
  55. jarvis/jarvis_c2rust/llm_module_agent.py +98 -1044
  56. jarvis/jarvis_c2rust/llm_module_agent_apply.py +170 -0
  57. jarvis/jarvis_c2rust/llm_module_agent_executor.py +288 -0
  58. jarvis/jarvis_c2rust/llm_module_agent_loader.py +170 -0
  59. jarvis/jarvis_c2rust/llm_module_agent_prompts.py +268 -0
  60. jarvis/jarvis_c2rust/llm_module_agent_types.py +57 -0
  61. jarvis/jarvis_c2rust/llm_module_agent_utils.py +150 -0
  62. jarvis/jarvis_c2rust/llm_module_agent_validator.py +119 -0
  63. jarvis/jarvis_c2rust/loaders.py +28 -10
  64. jarvis/jarvis_c2rust/models.py +5 -2
  65. jarvis/jarvis_c2rust/optimizer.py +192 -1974
  66. jarvis/jarvis_c2rust/optimizer_build_fix.py +286 -0
  67. jarvis/jarvis_c2rust/optimizer_clippy.py +766 -0
  68. jarvis/jarvis_c2rust/optimizer_config.py +49 -0
  69. jarvis/jarvis_c2rust/optimizer_docs.py +183 -0
  70. jarvis/jarvis_c2rust/optimizer_options.py +48 -0
  71. jarvis/jarvis_c2rust/optimizer_progress.py +469 -0
  72. jarvis/jarvis_c2rust/optimizer_report.py +52 -0
  73. jarvis/jarvis_c2rust/optimizer_unsafe.py +309 -0
  74. jarvis/jarvis_c2rust/optimizer_utils.py +469 -0
  75. jarvis/jarvis_c2rust/optimizer_visibility.py +185 -0
  76. jarvis/jarvis_c2rust/scanner.py +229 -166
  77. jarvis/jarvis_c2rust/transpiler.py +531 -2732
  78. jarvis/jarvis_c2rust/transpiler_agents.py +503 -0
  79. jarvis/jarvis_c2rust/transpiler_build.py +1294 -0
  80. jarvis/jarvis_c2rust/transpiler_codegen.py +204 -0
  81. jarvis/jarvis_c2rust/transpiler_compile.py +146 -0
  82. jarvis/jarvis_c2rust/transpiler_config.py +178 -0
  83. jarvis/jarvis_c2rust/transpiler_context.py +122 -0
  84. jarvis/jarvis_c2rust/transpiler_executor.py +516 -0
  85. jarvis/jarvis_c2rust/transpiler_generation.py +278 -0
  86. jarvis/jarvis_c2rust/transpiler_git.py +163 -0
  87. jarvis/jarvis_c2rust/transpiler_mod_utils.py +225 -0
  88. jarvis/jarvis_c2rust/transpiler_modules.py +336 -0
  89. jarvis/jarvis_c2rust/transpiler_planning.py +394 -0
  90. jarvis/jarvis_c2rust/transpiler_review.py +1196 -0
  91. jarvis/jarvis_c2rust/transpiler_symbols.py +176 -0
  92. jarvis/jarvis_c2rust/utils.py +269 -79
  93. jarvis/jarvis_code_agent/after_change.py +233 -0
  94. jarvis/jarvis_code_agent/build_validation_config.py +37 -30
  95. jarvis/jarvis_code_agent/builtin_rules.py +68 -0
  96. jarvis/jarvis_code_agent/code_agent.py +976 -1517
  97. jarvis/jarvis_code_agent/code_agent_build.py +227 -0
  98. jarvis/jarvis_code_agent/code_agent_diff.py +246 -0
  99. jarvis/jarvis_code_agent/code_agent_git.py +525 -0
  100. jarvis/jarvis_code_agent/code_agent_impact.py +177 -0
  101. jarvis/jarvis_code_agent/code_agent_lint.py +283 -0
  102. jarvis/jarvis_code_agent/code_agent_llm.py +159 -0
  103. jarvis/jarvis_code_agent/code_agent_postprocess.py +105 -0
  104. jarvis/jarvis_code_agent/code_agent_prompts.py +46 -0
  105. jarvis/jarvis_code_agent/code_agent_rules.py +305 -0
  106. jarvis/jarvis_code_agent/code_analyzer/__init__.py +52 -48
  107. jarvis/jarvis_code_agent/code_analyzer/base_language.py +12 -10
  108. jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +12 -11
  109. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +16 -12
  110. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +26 -17
  111. jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +558 -104
  112. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +27 -16
  113. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +22 -18
  114. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +21 -16
  115. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +20 -16
  116. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +27 -16
  117. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +47 -23
  118. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +71 -37
  119. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +162 -35
  120. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +111 -57
  121. jarvis/jarvis_code_agent/code_analyzer/build_validator.py +18 -12
  122. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +185 -183
  123. jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +2 -1
  124. jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +24 -15
  125. jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +227 -141
  126. jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +321 -247
  127. jarvis/jarvis_code_agent/code_analyzer/language_registry.py +37 -29
  128. jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -13
  129. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +15 -9
  130. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +75 -45
  131. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +87 -52
  132. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +84 -51
  133. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +94 -64
  134. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +109 -71
  135. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +97 -63
  136. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +103 -69
  137. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +271 -268
  138. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +76 -64
  139. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +92 -19
  140. jarvis/jarvis_code_agent/diff_visualizer.py +998 -0
  141. jarvis/jarvis_code_agent/lint.py +223 -524
  142. jarvis/jarvis_code_agent/rule_share_manager.py +158 -0
  143. jarvis/jarvis_code_agent/rules/clean_code.md +144 -0
  144. jarvis/jarvis_code_agent/rules/code_review.md +115 -0
  145. jarvis/jarvis_code_agent/rules/documentation.md +165 -0
  146. jarvis/jarvis_code_agent/rules/generate_rules.md +52 -0
  147. jarvis/jarvis_code_agent/rules/performance.md +158 -0
  148. jarvis/jarvis_code_agent/rules/refactoring.md +139 -0
  149. jarvis/jarvis_code_agent/rules/security.md +160 -0
  150. jarvis/jarvis_code_agent/rules/tdd.md +78 -0
  151. jarvis/jarvis_code_agent/test_rules/cpp_test.md +118 -0
  152. jarvis/jarvis_code_agent/test_rules/go_test.md +98 -0
  153. jarvis/jarvis_code_agent/test_rules/java_test.md +99 -0
  154. jarvis/jarvis_code_agent/test_rules/javascript_test.md +113 -0
  155. jarvis/jarvis_code_agent/test_rules/php_test.md +117 -0
  156. jarvis/jarvis_code_agent/test_rules/python_test.md +91 -0
  157. jarvis/jarvis_code_agent/test_rules/ruby_test.md +102 -0
  158. jarvis/jarvis_code_agent/test_rules/rust_test.md +86 -0
  159. jarvis/jarvis_code_agent/utils.py +36 -26
  160. jarvis/jarvis_code_analysis/checklists/loader.py +21 -21
  161. jarvis/jarvis_code_analysis/code_review.py +64 -33
  162. jarvis/jarvis_data/config_schema.json +285 -192
  163. jarvis/jarvis_git_squash/main.py +8 -6
  164. jarvis/jarvis_git_utils/git_commiter.py +53 -76
  165. jarvis/jarvis_mcp/__init__.py +5 -2
  166. jarvis/jarvis_mcp/sse_mcp_client.py +40 -30
  167. jarvis/jarvis_mcp/stdio_mcp_client.py +27 -19
  168. jarvis/jarvis_mcp/streamable_mcp_client.py +35 -26
  169. jarvis/jarvis_memory_organizer/memory_organizer.py +78 -55
  170. jarvis/jarvis_methodology/main.py +48 -39
  171. jarvis/jarvis_multi_agent/__init__.py +56 -23
  172. jarvis/jarvis_multi_agent/main.py +15 -18
  173. jarvis/jarvis_platform/base.py +179 -111
  174. jarvis/jarvis_platform/human.py +27 -16
  175. jarvis/jarvis_platform/kimi.py +52 -45
  176. jarvis/jarvis_platform/openai.py +101 -40
  177. jarvis/jarvis_platform/registry.py +51 -33
  178. jarvis/jarvis_platform/tongyi.py +68 -38
  179. jarvis/jarvis_platform/yuanbao.py +59 -43
  180. jarvis/jarvis_platform_manager/main.py +68 -76
  181. jarvis/jarvis_platform_manager/service.py +24 -14
  182. jarvis/jarvis_rag/README_CONFIG.md +314 -0
  183. jarvis/jarvis_rag/README_DYNAMIC_LOADING.md +311 -0
  184. jarvis/jarvis_rag/README_ONLINE_MODELS.md +230 -0
  185. jarvis/jarvis_rag/__init__.py +57 -4
  186. jarvis/jarvis_rag/cache.py +3 -1
  187. jarvis/jarvis_rag/cli.py +48 -68
  188. jarvis/jarvis_rag/embedding_interface.py +39 -0
  189. jarvis/jarvis_rag/embedding_manager.py +7 -230
  190. jarvis/jarvis_rag/embeddings/__init__.py +41 -0
  191. jarvis/jarvis_rag/embeddings/base.py +114 -0
  192. jarvis/jarvis_rag/embeddings/cohere.py +66 -0
  193. jarvis/jarvis_rag/embeddings/edgefn.py +117 -0
  194. jarvis/jarvis_rag/embeddings/local.py +260 -0
  195. jarvis/jarvis_rag/embeddings/openai.py +62 -0
  196. jarvis/jarvis_rag/embeddings/registry.py +293 -0
  197. jarvis/jarvis_rag/llm_interface.py +8 -6
  198. jarvis/jarvis_rag/query_rewriter.py +8 -9
  199. jarvis/jarvis_rag/rag_pipeline.py +61 -52
  200. jarvis/jarvis_rag/reranker.py +7 -75
  201. jarvis/jarvis_rag/reranker_interface.py +32 -0
  202. jarvis/jarvis_rag/rerankers/__init__.py +41 -0
  203. jarvis/jarvis_rag/rerankers/base.py +109 -0
  204. jarvis/jarvis_rag/rerankers/cohere.py +67 -0
  205. jarvis/jarvis_rag/rerankers/edgefn.py +140 -0
  206. jarvis/jarvis_rag/rerankers/jina.py +79 -0
  207. jarvis/jarvis_rag/rerankers/local.py +89 -0
  208. jarvis/jarvis_rag/rerankers/registry.py +293 -0
  209. jarvis/jarvis_rag/retriever.py +58 -43
  210. jarvis/jarvis_sec/__init__.py +66 -141
  211. jarvis/jarvis_sec/agents.py +21 -17
  212. jarvis/jarvis_sec/analysis.py +80 -33
  213. jarvis/jarvis_sec/checkers/__init__.py +7 -13
  214. jarvis/jarvis_sec/checkers/c_checker.py +356 -164
  215. jarvis/jarvis_sec/checkers/rust_checker.py +47 -29
  216. jarvis/jarvis_sec/cli.py +43 -21
  217. jarvis/jarvis_sec/clustering.py +430 -272
  218. jarvis/jarvis_sec/file_manager.py +99 -55
  219. jarvis/jarvis_sec/parsers.py +9 -6
  220. jarvis/jarvis_sec/prompts.py +4 -3
  221. jarvis/jarvis_sec/report.py +44 -22
  222. jarvis/jarvis_sec/review.py +180 -107
  223. jarvis/jarvis_sec/status.py +50 -41
  224. jarvis/jarvis_sec/types.py +3 -0
  225. jarvis/jarvis_sec/utils.py +160 -83
  226. jarvis/jarvis_sec/verification.py +411 -181
  227. jarvis/jarvis_sec/workflow.py +132 -21
  228. jarvis/jarvis_smart_shell/main.py +28 -41
  229. jarvis/jarvis_stats/cli.py +14 -12
  230. jarvis/jarvis_stats/stats.py +28 -19
  231. jarvis/jarvis_stats/storage.py +14 -8
  232. jarvis/jarvis_stats/visualizer.py +12 -7
  233. jarvis/jarvis_tools/base.py +5 -2
  234. jarvis/jarvis_tools/clear_memory.py +13 -9
  235. jarvis/jarvis_tools/cli/main.py +23 -18
  236. jarvis/jarvis_tools/edit_file.py +572 -873
  237. jarvis/jarvis_tools/execute_script.py +10 -7
  238. jarvis/jarvis_tools/file_analyzer.py +7 -8
  239. jarvis/jarvis_tools/meta_agent.py +287 -0
  240. jarvis/jarvis_tools/methodology.py +5 -3
  241. jarvis/jarvis_tools/read_code.py +305 -1438
  242. jarvis/jarvis_tools/read_symbols.py +50 -17
  243. jarvis/jarvis_tools/read_webpage.py +19 -18
  244. jarvis/jarvis_tools/registry.py +435 -156
  245. jarvis/jarvis_tools/retrieve_memory.py +16 -11
  246. jarvis/jarvis_tools/save_memory.py +8 -6
  247. jarvis/jarvis_tools/search_web.py +31 -31
  248. jarvis/jarvis_tools/sub_agent.py +32 -28
  249. jarvis/jarvis_tools/sub_code_agent.py +44 -60
  250. jarvis/jarvis_tools/task_list_manager.py +1811 -0
  251. jarvis/jarvis_tools/virtual_tty.py +29 -19
  252. jarvis/jarvis_utils/__init__.py +4 -0
  253. jarvis/jarvis_utils/builtin_replace_map.py +2 -1
  254. jarvis/jarvis_utils/clipboard.py +9 -8
  255. jarvis/jarvis_utils/collections.py +331 -0
  256. jarvis/jarvis_utils/config.py +699 -194
  257. jarvis/jarvis_utils/dialogue_recorder.py +294 -0
  258. jarvis/jarvis_utils/embedding.py +6 -3
  259. jarvis/jarvis_utils/file_processors.py +7 -1
  260. jarvis/jarvis_utils/fzf.py +9 -3
  261. jarvis/jarvis_utils/git_utils.py +71 -42
  262. jarvis/jarvis_utils/globals.py +116 -32
  263. jarvis/jarvis_utils/http.py +6 -2
  264. jarvis/jarvis_utils/input.py +318 -83
  265. jarvis/jarvis_utils/jsonnet_compat.py +119 -104
  266. jarvis/jarvis_utils/methodology.py +37 -28
  267. jarvis/jarvis_utils/output.py +201 -44
  268. jarvis/jarvis_utils/utils.py +986 -628
  269. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/METADATA +49 -33
  270. jarvis_ai_assistant-1.0.2.dist-info/RECORD +304 -0
  271. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +0 -556
  272. jarvis/jarvis_tools/generate_new_tool.py +0 -205
  273. jarvis/jarvis_tools/lsp_client.py +0 -1552
  274. jarvis/jarvis_tools/rewrite_file.py +0 -105
  275. jarvis_ai_assistant-0.7.16.dist-info/RECORD +0 -218
  276. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
  277. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
  278. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
  279. {jarvis_ai_assistant-0.7.16.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/top_level.txt +0 -0
@@ -1,40 +1,52 @@
1
+ import os
2
+
1
3
  # -*- coding: utf-8 -*-
2
4
  import re
3
- import os
5
+ from abc import ABC
6
+ from abc import abstractmethod
4
7
  from datetime import datetime
5
- from abc import ABC, abstractmethod
6
8
  from types import TracebackType
7
- from typing import Dict, Generator, List, Optional, Tuple, Type
8
-
9
+ from typing import Any
10
+ from typing import Dict
11
+ from typing import Generator
12
+ from typing import List
13
+ from typing import Optional
14
+ from typing import Tuple
15
+ from typing import Type
16
+
17
+ from rich import box
18
+ from rich.live import Live
19
+ from rich.panel import Panel
20
+ from rich.status import Status
21
+ from rich.text import Text
9
22
  from typing_extensions import Self
10
23
 
11
- from rich import box # type: ignore
12
- from rich.live import Live # type: ignore
13
- from rich.panel import Panel # type: ignore
14
- from rich.status import Status # type: ignore
15
- from rich.text import Text # type: ignore
16
-
17
- from jarvis.jarvis_utils.config import (
18
- get_pretty_output,
19
- is_print_prompt,
20
- is_immediate_abort,
21
- is_save_session_history,
22
- get_data_dir,
23
- get_max_input_token_count,
24
- get_conversation_turn_threshold,
25
- )
26
- from jarvis.jarvis_utils.globals import set_in_chat, get_interrupt, console
27
24
  import jarvis.jarvis_utils.globals as G
28
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput # 保留用于语法高亮
29
- from jarvis.jarvis_utils.tag import ct, ot
30
- from jarvis.jarvis_utils.utils import while_success, while_true
25
+ from jarvis.jarvis_utils.config import get_cheap_max_input_token_count
26
+ from jarvis.jarvis_utils.config import get_conversation_turn_threshold
27
+ from jarvis.jarvis_utils.config import get_data_dir
28
+ from jarvis.jarvis_utils.config import get_max_input_token_count
29
+ from jarvis.jarvis_utils.config import get_pretty_output
30
+ from jarvis.jarvis_utils.config import get_smart_max_input_token_count
31
+ from jarvis.jarvis_utils.config import is_immediate_abort
32
+ from jarvis.jarvis_utils.config import is_print_prompt
33
+ from jarvis.jarvis_utils.config import is_save_session_history
31
34
  from jarvis.jarvis_utils.embedding import get_context_token_count
35
+ from jarvis.jarvis_utils.globals import console
36
+ from jarvis.jarvis_utils.globals import get_interrupt
37
+ from jarvis.jarvis_utils.globals import set_in_chat
38
+ from jarvis.jarvis_utils.output import OutputType # 保留用于语法高亮
39
+ from jarvis.jarvis_utils.output import PrettyOutput
40
+ from jarvis.jarvis_utils.tag import ct
41
+ from jarvis.jarvis_utils.tag import ot
42
+ from jarvis.jarvis_utils.utils import while_success
43
+ from jarvis.jarvis_utils.utils import while_true
32
44
 
33
45
 
34
46
  class BasePlatform(ABC):
35
47
  """大语言模型基类"""
36
48
 
37
- def __init__(self):
49
+ def __init__(self, llm_config: Optional[Dict[str, Any]] = None):
38
50
  """初始化模型"""
39
51
  self.suppress_output = True # 添加输出控制标志
40
52
  self.web = False # 添加web属性,默认false
@@ -42,6 +54,7 @@ class BasePlatform(ABC):
42
54
  self.model_group: Optional[str] = None
43
55
  self._session_history_file: Optional[str] = None
44
56
  self._conversation_turn = 0 # 对话轮次计数器
57
+ self.platform_type: str = "normal" # 平台类型:normal/cheap/smart
45
58
 
46
59
  def __enter__(self) -> Self:
47
60
  """进入上下文管理器"""
@@ -84,21 +97,21 @@ class BasePlatform(ABC):
84
97
 
85
98
  def _format_progress_bar(self, percent: float, width: int = 20) -> str:
86
99
  """格式化进度条字符串
87
-
100
+
88
101
  参数:
89
102
  percent: 百分比 (0-100)
90
103
  width: 进度条宽度(字符数)
91
-
104
+
92
105
  返回:
93
106
  str: 格式化的进度条字符串
94
107
  """
95
108
  # 限制百分比范围
96
109
  percent = max(0, min(100, percent))
97
-
110
+
98
111
  # 计算填充的字符数
99
112
  filled = int(width * percent / 100)
100
113
  empty = width - filled
101
-
114
+
102
115
  # 根据百分比选择颜色
103
116
  if percent >= 90:
104
117
  color = "red"
@@ -106,18 +119,20 @@ class BasePlatform(ABC):
106
119
  color = "yellow"
107
120
  else:
108
121
  color = "green"
109
-
122
+
110
123
  # 构建进度条:使用 █ 表示已填充,░ 表示未填充
111
124
  bar = "█" * filled + "░" * empty
112
-
125
+
113
126
  return f"[{color}]{bar}[/{color}]"
114
127
 
115
- def _get_token_usage_info(self, current_response: str = "") -> Tuple[float, str, str]:
128
+ def _get_token_usage_info(
129
+ self, current_response: str = ""
130
+ ) -> Tuple[float, str, str]:
116
131
  """获取 token 使用信息
117
-
132
+
118
133
  参数:
119
134
  current_response: 当前响应内容(用于计算流式输出时的 token)
120
-
135
+
121
136
  返回:
122
137
  Tuple[float, str, str]: (usage_percent, percent_color, progress_bar)
123
138
  """
@@ -125,8 +140,8 @@ class BasePlatform(ABC):
125
140
  history_tokens = self.get_used_token_count()
126
141
  current_response_tokens = get_context_token_count(current_response)
127
142
  total_tokens = history_tokens + current_response_tokens
128
- max_tokens = get_max_input_token_count(self.model_group)
129
-
143
+ max_tokens = self._get_platform_max_input_token_count()
144
+
130
145
  if max_tokens > 0:
131
146
  usage_percent = (total_tokens / max_tokens) * 100
132
147
  if usage_percent >= 90:
@@ -142,10 +157,14 @@ class BasePlatform(ABC):
142
157
  return 0.0, "green", ""
143
158
 
144
159
  def _update_panel_subtitle_with_token(
145
- self, panel: Panel, response: str, is_completed: bool = False, duration: float = 0.0
160
+ self,
161
+ panel: Panel,
162
+ response: str,
163
+ is_completed: bool = False,
164
+ duration: float = 0.0,
146
165
  ) -> None:
147
166
  """更新面板的 subtitle,包含 token 使用信息
148
-
167
+
149
168
  参数:
150
169
  panel: 要更新的面板
151
170
  response: 当前响应内容
@@ -153,13 +172,17 @@ class BasePlatform(ABC):
153
172
  duration: 耗时(秒)
154
173
  """
155
174
  from datetime import datetime
156
-
175
+
157
176
  current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
158
177
  try:
159
- usage_percent, percent_color, progress_bar = self._get_token_usage_info(response)
160
- max_tokens = get_max_input_token_count(self.model_group)
161
- total_tokens = self.get_used_token_count() + get_context_token_count(response)
162
-
178
+ usage_percent, percent_color, progress_bar = self._get_token_usage_info(
179
+ response
180
+ )
181
+ max_tokens = self._get_platform_max_input_token_count()
182
+ total_tokens = self.get_used_token_count() + get_context_token_count(
183
+ response
184
+ )
185
+
163
186
  threshold = get_conversation_turn_threshold()
164
187
  if is_completed:
165
188
  if max_tokens > 0 and progress_bar:
@@ -188,21 +211,21 @@ class BasePlatform(ABC):
188
211
 
189
212
  def _chat_with_pretty_output(self, message: str, start_time: float) -> str:
190
213
  """使用 pretty output 模式进行聊天
191
-
214
+
192
215
  参数:
193
216
  message: 用户消息
194
217
  start_time: 开始时间
195
-
218
+
196
219
  返回:
197
220
  str: 模型响应
198
221
  """
199
222
  import time
200
-
223
+
201
224
  chat_iterator = self.chat(message)
202
225
  first_chunk = None
203
226
 
204
227
  with Status(
205
- f"🤔 {(G.current_agent_name + ' · ') if G.current_agent_name else ''}{self.name()} 正在思考中...",
228
+ f"🤔 {(G.get_current_agent_name() + ' · ') if G.get_current_agent_name() else ''}{self.name()} 正在思考中...",
206
229
  spinner="dots",
207
230
  console=console,
208
231
  ):
@@ -218,7 +241,7 @@ class BasePlatform(ABC):
218
241
  text_content = Text(overflow="fold")
219
242
  panel = Panel(
220
243
  text_content,
221
- title=f"[bold cyan]{(G.current_agent_name + ' · ') if G.current_agent_name else ''}{self.name()}[/bold cyan]",
244
+ title=f"[bold cyan]{(G.get_current_agent_name() + ' · ') if G.get_current_agent_name() else ''}{self.name()}[/bold cyan]",
222
245
  subtitle="[yellow]正在回答... (按 Ctrl+C 中断)[/yellow]",
223
246
  border_style="bright_blue",
224
247
  box=box.ROUNDED,
@@ -227,14 +250,17 @@ class BasePlatform(ABC):
227
250
 
228
251
  response = ""
229
252
  last_subtitle_update_time = time.time()
230
- subtitle_update_interval = 3 # subtitle 更新间隔(秒),减少更新频率避免重复渲染标题
253
+ subtitle_update_interval = (
254
+ 3 # subtitle 更新间隔(秒),减少更新频率避免重复渲染标题
255
+ )
231
256
  update_count = 0 # 更新计数器,用于控制 subtitle 更新频率
232
- with Live(panel, refresh_per_second=4, transient=False) as live:
257
+ with Live(panel, refresh_per_second=4, transient=True) as live:
258
+
233
259
  def _update_panel_content(content: str, update_subtitle: bool = False):
234
260
  nonlocal response, last_subtitle_update_time, update_count
235
261
  text_content.append(content, style="bright_white")
236
262
  update_count += 1
237
-
263
+
238
264
  # Scrolling Logic - 只在内容超过一定行数时才应用滚动
239
265
  max_text_height = console.height - 5
240
266
  if max_text_height <= 0:
@@ -250,27 +276,32 @@ class BasePlatform(ABC):
250
276
  text_content.plain = "\n".join(
251
277
  [line.plain for line in lines[-max_text_height:]]
252
278
  )
253
-
279
+
254
280
  # 只在需要时更新 subtitle(减少更新频率,避免重复渲染标题)
255
281
  # 策略:每 10 次内容更新或每 3 秒更新一次 subtitle
256
282
  current_time = time.time()
257
283
  should_update_subtitle = (
258
- update_subtitle
284
+ update_subtitle
259
285
  or update_count % 10 == 0 # 每 10 次更新一次
260
- or (current_time - last_subtitle_update_time) >= subtitle_update_interval
286
+ or (current_time - last_subtitle_update_time)
287
+ >= subtitle_update_interval
261
288
  )
262
-
289
+
263
290
  if should_update_subtitle:
264
- self._update_panel_subtitle_with_token(panel, response, is_completed=False)
291
+ self._update_panel_subtitle_with_token(
292
+ panel, response, is_completed=False
293
+ )
265
294
  last_subtitle_update_time = current_time
266
-
295
+
267
296
  # 更新 panel(只更新内容,subtitle 更新频率已降低)
268
297
  live.update(panel)
269
298
 
270
299
  # Process first chunk
271
300
  response += first_chunk
272
301
  if first_chunk:
273
- _update_panel_content(first_chunk, update_subtitle=True) # 第一次更新时更新 subtitle
302
+ _update_panel_content(
303
+ first_chunk, update_subtitle=True
304
+ ) # 第一次更新时更新 subtitle
274
305
 
275
306
  # 缓存机制:降低更新频率,减少界面闪烁
276
307
  buffer = ""
@@ -308,33 +339,22 @@ class BasePlatform(ABC):
308
339
 
309
340
  _flush_buffer()
310
341
  # 在结束前,将面板内容替换为完整响应,确保最后一次渲染的 panel 显示全部内容
311
- if response:
312
- text_content.plain = response
313
- # 最后更新 subtitle 和 panel
314
- end_time = time.time()
315
- duration = end_time - start_time
316
- self._update_panel_subtitle_with_token(panel, response, is_completed=True, duration=duration)
317
- # 最后更新 panel,Live 上下文退出时会自动打印(transient=False)
318
- live.update(panel)
319
- # 注意:不要在这里调用 console.print(),因为 Live 退出时会自动打印 panel
320
- # Live 退出后仅添加空行分隔,不再重复打印 panel,避免内容重复
321
- console.print()
322
342
  return response
323
343
 
324
344
  def _chat_with_simple_output(self, message: str, start_time: float) -> str:
325
345
  """使用简单输出模式进行聊天
326
-
346
+
327
347
  参数:
328
348
  message: 用户消息
329
349
  start_time: 开始时间
330
-
350
+
331
351
  返回:
332
352
  str: 模型响应
333
353
  """
334
354
  import time
335
-
355
+
336
356
  console.print(
337
- f"🤖 模型输出 - {(G.current_agent_name + ' · ') if G.current_agent_name else ''}{self.name()} (按 Ctrl+C 中断)",
357
+ f"🤖 模型输出 - {(G.get_current_agent_name() + ' · ') if G.get_current_agent_name() else ''}{self.name()} (按 Ctrl+C 中断)",
338
358
  soft_wrap=False,
339
359
  )
340
360
  response = ""
@@ -352,10 +372,10 @@ class BasePlatform(ABC):
352
372
 
353
373
  def _chat_with_suppressed_output(self, message: str) -> str:
354
374
  """使用静默模式进行聊天
355
-
375
+
356
376
  参数:
357
377
  message: 用户消息
358
-
378
+
359
379
  返回:
360
380
  str: 模型响应
361
381
  """
@@ -369,10 +389,10 @@ class BasePlatform(ABC):
369
389
 
370
390
  def _process_response(self, response: str) -> str:
371
391
  """处理响应,移除 think 标签
372
-
392
+
373
393
  参数:
374
394
  response: 原始响应
375
-
395
+
376
396
  返回:
377
397
  str: 处理后的响应
378
398
  """
@@ -391,7 +411,7 @@ class BasePlatform(ABC):
391
411
 
392
412
  # 当输入为空白字符串时,打印警告并直接返回空字符串
393
413
  if message.strip() == "":
394
- print("⚠️ 输入为空白字符串,已忽略本次请求")
414
+ PrettyOutput.auto_print("⚠️ 输入为空白字符串,已忽略本次请求")
395
415
  return ""
396
416
 
397
417
  # 检查并截断消息以避免超出剩余token限制
@@ -403,12 +423,18 @@ class BasePlatform(ABC):
403
423
  response = self._chat_with_pretty_output(message, start_time)
404
424
  else:
405
425
  response = self._chat_with_simple_output(message, start_time)
426
+
427
+ # 计算响应时间并打印总结
428
+ end_time = time.time()
429
+ duration = end_time - start_time
430
+ PrettyOutput.auto_print(f"✅ {self.name()}模型响应完成: {duration:.2f}秒")
406
431
  else:
407
432
  response = self._chat_with_suppressed_output(message)
408
433
 
409
434
  # 处理响应并保存会话历史
410
435
  response = self._process_response(response)
411
436
  self._append_session_history(message, response)
437
+
412
438
  # 增加对话轮次计数
413
439
  self._conversation_turn += 1
414
440
  return response
@@ -419,17 +445,25 @@ class BasePlatform(ABC):
419
445
  set_in_chat(True)
420
446
  if not self.suppress_output and is_print_prompt():
421
447
  PrettyOutput.print(f"{message}", OutputType.USER) # 保留用于语法高亮
422
-
448
+
449
+ # 记录用户输入(模型输入)
450
+ from jarvis.jarvis_utils.dialogue_recorder import record_user_message
451
+
452
+ record_user_message(message)
453
+
423
454
  result: str = ""
424
- result = while_true(
425
- lambda: while_success(lambda: self._chat(message))
426
- )
427
-
455
+ result = while_true(lambda: while_success(lambda: self._chat(message)))
456
+
428
457
  # Check if result is empty or False (retry exhausted)
429
458
  # Convert False to empty string for type safety
430
459
  if result is False or result == "":
431
460
  raise ValueError("返回结果为空")
432
-
461
+
462
+ # 记录模型输出
463
+ from jarvis.jarvis_utils.dialogue_recorder import record_assistant_message
464
+
465
+ record_assistant_message(result)
466
+
433
467
  from jarvis.jarvis_utils.globals import set_last_message
434
468
 
435
469
  set_last_message(result)
@@ -437,6 +471,14 @@ class BasePlatform(ABC):
437
471
  finally:
438
472
  set_in_chat(False)
439
473
 
474
+ def get_conversation_turn(self) -> int:
475
+ """获取当前对话轮次数
476
+
477
+ 返回:
478
+ int: 当前对话轮次数
479
+ """
480
+ return self._conversation_turn
481
+
440
482
  @abstractmethod
441
483
  def name(self) -> str:
442
484
  """模型名称"""
@@ -523,6 +565,27 @@ class BasePlatform(ABC):
523
565
  """设置网页标志"""
524
566
  self.web = web
525
567
 
568
+ def set_platform_type(self, platform_type: str):
569
+ """设置平台类型
570
+
571
+ 参数:
572
+ platform_type: 平台类型,可选值为 'normal'、'cheap' 或 'smart'
573
+ """
574
+ self.platform_type = platform_type
575
+
576
+ def _get_platform_max_input_token_count(self) -> int:
577
+ """根据平台类型获取对应的最大输入token数量
578
+
579
+ 返回:
580
+ int: 模型能处理的最大输入token数量
581
+ """
582
+ if self.platform_type == "cheap":
583
+ return get_cheap_max_input_token_count(self.model_group)
584
+ elif self.platform_type == "smart":
585
+ return get_smart_max_input_token_count(self.model_group)
586
+ else:
587
+ return get_max_input_token_count(self.model_group)
588
+
526
589
  def _append_session_history(self, user_input: str, model_output: str) -> None:
527
590
  """
528
591
  Append the user input and model output to a session history file if enabled.
@@ -554,11 +617,14 @@ class BasePlatform(ABC):
554
617
  ts = datetime.now().strftime("%Y%m%d_%H%M%S")
555
618
 
556
619
  self._session_history_file = os.path.join(
557
- session_dir, f"session_history_{safe_platform}_{safe_model}_{ts}.log"
620
+ session_dir,
621
+ f"session_history_{safe_platform}_{safe_model}_{ts}.log",
558
622
  )
559
623
 
560
624
  # Append record
561
- with open(self._session_history_file, "a", encoding="utf-8", errors="ignore") as f:
625
+ with open(
626
+ self._session_history_file, "a", encoding="utf-8", errors="ignore"
627
+ ) as f:
562
628
  ts_line = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
563
629
  f.write(f"===== {ts_line} =====\n")
564
630
  f.write("USER:\n")
@@ -571,10 +637,10 @@ class BasePlatform(ABC):
571
637
 
572
638
  def get_conversation_history(self) -> List[Dict[str, str]]:
573
639
  """获取当前对话历史
574
-
640
+
575
641
  返回:
576
642
  List[Dict[str, str]]: 对话历史列表,每个元素包含 role 和 content
577
-
643
+
578
644
  注意:
579
645
  默认实现检查是否有 messages 属性,子类可以重写此方法以提供自定义实现
580
646
  """
@@ -584,88 +650,90 @@ class BasePlatform(ABC):
584
650
 
585
651
  def get_used_token_count(self) -> int:
586
652
  """计算当前对话历史使用的token数量
587
-
653
+
588
654
  返回:
589
655
  int: 当前对话历史使用的token数量
590
656
  """
591
657
  history = self.get_conversation_history()
592
658
  if not history:
593
659
  return 0
594
-
660
+
595
661
  total_tokens = 0
596
662
  for message in history:
597
663
  content = message.get("content", "")
598
664
  if content:
599
665
  total_tokens += get_context_token_count(content)
600
-
666
+
601
667
  return total_tokens
602
668
 
603
669
  def get_remaining_token_count(self) -> int:
604
670
  """获取剩余可用的token数量
605
-
671
+
606
672
  返回:
607
673
  int: 剩余可用的token数量(输入窗口限制 - 当前使用的token数量)
608
674
  """
609
- max_tokens = get_max_input_token_count(self.model_group)
675
+ max_tokens = self._get_platform_max_input_token_count()
610
676
  used_tokens = self.get_used_token_count()
611
677
  remaining = max_tokens - used_tokens
612
678
  return max(0, remaining) # 确保返回值不为负数
613
679
 
614
680
  def _truncate_message_if_needed(self, message: str) -> str:
615
681
  """如果消息超出剩余token限制,则截断消息
616
-
682
+
617
683
  参数:
618
684
  message: 原始消息
619
-
685
+
620
686
  返回:
621
687
  str: 截断后的消息(如果不需要截断则返回原消息)
622
688
  """
623
689
  try:
624
690
  # 获取剩余token数量
625
691
  remaining_tokens = self.get_remaining_token_count()
626
-
692
+
627
693
  # 如果剩余token为0或负数,返回空消息
628
694
  if remaining_tokens <= 0:
629
- print("⚠️ 警告:剩余token为0,无法发送消息")
695
+ PrettyOutput.auto_print("⚠️ 警告:剩余token为0,无法发送消息")
630
696
  return ""
631
-
697
+
632
698
  # 计算消息的token数量
633
699
  message_tokens = get_context_token_count(message)
634
-
700
+
635
701
  # 如果消息token数小于等于剩余token数,不需要截断
636
702
  if message_tokens <= remaining_tokens:
637
703
  return message
638
-
704
+
639
705
  # 需要截断:保留剩余token的80%用于消息,20%作为安全余量
640
706
  target_tokens = int(remaining_tokens * 0.8)
641
707
  if target_tokens <= 0:
642
- print("⚠️ 警告:剩余token不足,无法发送消息")
708
+ PrettyOutput.auto_print("⚠️ 警告:剩余token不足,无法发送消息")
643
709
  return ""
644
-
710
+
645
711
  # 估算字符数(1 token ≈ 4字符)
646
712
  target_chars = target_tokens * 4
647
-
713
+
648
714
  # 如果消息长度小于目标字符数,不需要截断(token估算可能有误差)
649
715
  if len(message) <= target_chars:
650
716
  return message
651
-
717
+
652
718
  # 截断消息:保留前面的内容,添加截断提示
653
719
  truncated_message = message[:target_chars]
654
720
  # 尝试在最后一个完整句子处截断
655
- last_period = truncated_message.rfind('.')
656
- last_newline = truncated_message.rfind('\n')
721
+ last_period = truncated_message.rfind(".")
722
+ last_newline = truncated_message.rfind("\n")
657
723
  last_break = max(last_period, last_newline)
658
-
724
+
659
725
  if last_break > target_chars * 0.5: # 如果找到的断点不太靠前
660
- truncated_message = truncated_message[:last_break + 1]
661
-
726
+ truncated_message = truncated_message[: last_break + 1]
727
+
662
728
  truncated_message += "\n\n... (消息过长,已截断以避免超出上下文限制)"
663
- print(f"⚠️ 警告:消息过长({message_tokens} tokens),已截断至约 {target_tokens} tokens")
664
-
729
+ PrettyOutput.auto_print(
730
+ f"⚠️ 警告:消息过长({message_tokens} tokens),已截断至约 {target_tokens} tokens"
731
+ )
732
+
665
733
  return truncated_message
666
734
  except Exception as e:
667
735
  # 如果截断过程中出错,返回原消息(避免阻塞对话)
668
- print(f"⚠️ 警告:检查消息长度时出错: {e},使用原消息")
736
+ PrettyOutput.auto_print(f"⚠️ 警告:检查消息长度时出错: {e},使用原消息")
669
737
  return message
670
738
 
671
739
  @abstractmethod
@@ -1,17 +1,23 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # 人类交互平台实现模块
4
-
5
- # 提供与真实人类交互的模拟接口
6
-
7
1
  import json
8
2
  import random
9
3
  import string
10
- from typing import Generator, List, Tuple
4
+ from typing import Any
5
+ from typing import Dict
6
+ from typing import Generator
7
+ from typing import List
8
+ from typing import Optional
9
+ from typing import Tuple
11
10
 
12
11
  from jarvis.jarvis_platform.base import BasePlatform
13
12
  from jarvis.jarvis_utils.clipboard import copy_to_clipboard
14
13
  from jarvis.jarvis_utils.input import get_multiline_input
14
+ from jarvis.jarvis_utils.output import PrettyOutput
15
+
16
+ # -*- coding: utf-8 -*-
17
+
18
+ # 人类交互平台实现模块
19
+
20
+ # 提供与真实人类交互的模拟接口
15
21
 
16
22
 
17
23
  class HumanPlatform(BasePlatform):
@@ -21,8 +27,13 @@ class HumanPlatform(BasePlatform):
21
27
  """获取支持的模型列表"""
22
28
  return [("human", "Human Interaction")]
23
29
 
24
- def __init__(self):
25
- """初始化人类交互平台"""
30
+ def __init__(self, llm_config: Optional[Dict[str, Any]] = None):
31
+ """
32
+ 初始化人类交互平台
33
+
34
+ 参数:
35
+ llm_config: LLM配置字典(人类平台不使用此配置,但为保持接口一致而接受)
36
+ """
26
37
  super().__init__()
27
38
  self.conversation_id = "" # 会话ID,用于标识当前对话
28
39
  self.model_name = "human" # 默认模型名称
@@ -38,7 +49,7 @@ class HumanPlatform(BasePlatform):
38
49
  if model_name == "human":
39
50
  self.model_name = model_name
40
51
  else:
41
- print(f"❌ 错误:不支持的模型: {model_name}")
52
+ PrettyOutput.auto_print(f"❌ 错误:不支持的模型: {model_name}")
42
53
 
43
54
  def chat(self, message: str) -> Generator[str, None, None]:
44
55
  """发送消息并获取人类响应"""
@@ -65,7 +76,7 @@ class HumanPlatform(BasePlatform):
65
76
 
66
77
  def upload_files(self, file_list: List[str]) -> bool:
67
78
  """文件上传功能,人类平台不需要实际处理"""
68
- print("⚠️ 人类交互平台不支持文件上传")
79
+ PrettyOutput.auto_print("⚠️ 人类交互平台不支持文件上传")
69
80
  return False
70
81
 
71
82
  def delete_chat(self) -> bool:
@@ -87,10 +98,10 @@ class HumanPlatform(BasePlatform):
87
98
  with open(file_path, "w", encoding="utf-8") as f:
88
99
  json.dump(state, f, ensure_ascii=False, indent=4)
89
100
  self._saved = True
90
- print(f"✅ 会话已成功保存到 {file_path}")
101
+ PrettyOutput.auto_print(f"✅ 会话已成功保存到 {file_path}")
91
102
  return True
92
103
  except Exception as e:
93
- print(f"❌ 保存会话失败: {str(e)}")
104
+ PrettyOutput.auto_print(f"❌ 保存会话失败: {str(e)}")
94
105
  return False
95
106
 
96
107
  def restore(self, file_path: str) -> bool:
@@ -105,13 +116,13 @@ class HumanPlatform(BasePlatform):
105
116
  self.first_message = state.get("first_message", True)
106
117
  self._saved = True
107
118
 
108
- print(f"✅ 从 {file_path} 成功恢复会话")
119
+ PrettyOutput.auto_print(f"✅ 从 {file_path} 成功恢复会话")
109
120
  return True
110
121
  except FileNotFoundError:
111
- print(f"❌ 会话文件未找到: {file_path}")
122
+ PrettyOutput.auto_print(f"❌ 会话文件未找到: {file_path}")
112
123
  return False
113
124
  except Exception as e:
114
- print(f"❌ 恢复会话失败: {str(e)}")
125
+ PrettyOutput.auto_print(f"❌ 恢复会话失败: {str(e)}")
115
126
  return False
116
127
 
117
128
  def name(self) -> str: