jarvis-ai-assistant 0.7.0__py3-none-any.whl → 0.7.6__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 (159) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +243 -139
  3. jarvis/jarvis_agent/agent_manager.py +5 -10
  4. jarvis/jarvis_agent/builtin_input_handler.py +2 -6
  5. jarvis/jarvis_agent/config_editor.py +2 -7
  6. jarvis/jarvis_agent/event_bus.py +82 -12
  7. jarvis/jarvis_agent/file_context_handler.py +265 -15
  8. jarvis/jarvis_agent/file_methodology_manager.py +3 -4
  9. jarvis/jarvis_agent/jarvis.py +113 -98
  10. jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
  11. jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
  12. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
  13. jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
  14. jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
  15. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
  16. jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
  17. jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
  18. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
  19. jarvis/jarvis_agent/language_support_info.py +486 -0
  20. jarvis/jarvis_agent/main.py +6 -12
  21. jarvis/jarvis_agent/memory_manager.py +7 -16
  22. jarvis/jarvis_agent/methodology_share_manager.py +10 -16
  23. jarvis/jarvis_agent/prompt_manager.py +1 -1
  24. jarvis/jarvis_agent/prompts.py +193 -171
  25. jarvis/jarvis_agent/protocols.py +8 -12
  26. jarvis/jarvis_agent/run_loop.py +77 -14
  27. jarvis/jarvis_agent/session_manager.py +2 -3
  28. jarvis/jarvis_agent/share_manager.py +12 -21
  29. jarvis/jarvis_agent/shell_input_handler.py +1 -2
  30. jarvis/jarvis_agent/task_analyzer.py +26 -4
  31. jarvis/jarvis_agent/task_manager.py +11 -27
  32. jarvis/jarvis_agent/tool_executor.py +2 -3
  33. jarvis/jarvis_agent/tool_share_manager.py +12 -24
  34. jarvis/jarvis_agent/web_server.py +55 -20
  35. jarvis/jarvis_c2rust/__init__.py +5 -5
  36. jarvis/jarvis_c2rust/cli.py +461 -499
  37. jarvis/jarvis_c2rust/collector.py +45 -53
  38. jarvis/jarvis_c2rust/constants.py +26 -0
  39. jarvis/jarvis_c2rust/library_replacer.py +264 -132
  40. jarvis/jarvis_c2rust/llm_module_agent.py +162 -190
  41. jarvis/jarvis_c2rust/loaders.py +207 -0
  42. jarvis/jarvis_c2rust/models.py +28 -0
  43. jarvis/jarvis_c2rust/optimizer.py +1592 -395
  44. jarvis/jarvis_c2rust/transpiler.py +1722 -1064
  45. jarvis/jarvis_c2rust/utils.py +385 -0
  46. jarvis/jarvis_code_agent/build_validation_config.py +2 -3
  47. jarvis/jarvis_code_agent/code_agent.py +394 -320
  48. jarvis/jarvis_code_agent/code_analyzer/__init__.py +3 -0
  49. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +4 -0
  50. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +17 -2
  51. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +3 -0
  52. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +36 -4
  53. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +9 -0
  54. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +9 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +12 -1
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +22 -5
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +57 -32
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +62 -6
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +8 -9
  60. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +290 -5
  61. jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -0
  62. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +21 -3
  63. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +72 -4
  64. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +35 -3
  65. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
  66. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
  67. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +52 -2
  68. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +73 -1
  69. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
  70. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +306 -152
  71. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
  72. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +193 -18
  73. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +18 -8
  74. jarvis/jarvis_code_agent/lint.py +258 -27
  75. jarvis/jarvis_code_agent/utils.py +0 -1
  76. jarvis/jarvis_code_analysis/code_review.py +19 -24
  77. jarvis/jarvis_data/config_schema.json +53 -26
  78. jarvis/jarvis_git_squash/main.py +4 -5
  79. jarvis/jarvis_git_utils/git_commiter.py +44 -49
  80. jarvis/jarvis_mcp/sse_mcp_client.py +20 -27
  81. jarvis/jarvis_mcp/stdio_mcp_client.py +11 -12
  82. jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
  83. jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
  84. jarvis/jarvis_methodology/main.py +32 -48
  85. jarvis/jarvis_multi_agent/__init__.py +79 -61
  86. jarvis/jarvis_multi_agent/main.py +3 -7
  87. jarvis/jarvis_platform/base.py +469 -199
  88. jarvis/jarvis_platform/human.py +7 -8
  89. jarvis/jarvis_platform/kimi.py +30 -36
  90. jarvis/jarvis_platform/openai.py +65 -27
  91. jarvis/jarvis_platform/registry.py +26 -10
  92. jarvis/jarvis_platform/tongyi.py +24 -25
  93. jarvis/jarvis_platform/yuanbao.py +31 -42
  94. jarvis/jarvis_platform_manager/main.py +66 -77
  95. jarvis/jarvis_platform_manager/service.py +8 -13
  96. jarvis/jarvis_rag/cli.py +49 -51
  97. jarvis/jarvis_rag/embedding_manager.py +13 -18
  98. jarvis/jarvis_rag/llm_interface.py +8 -9
  99. jarvis/jarvis_rag/query_rewriter.py +10 -21
  100. jarvis/jarvis_rag/rag_pipeline.py +24 -27
  101. jarvis/jarvis_rag/reranker.py +4 -5
  102. jarvis/jarvis_rag/retriever.py +28 -30
  103. jarvis/jarvis_sec/__init__.py +220 -3520
  104. jarvis/jarvis_sec/agents.py +143 -0
  105. jarvis/jarvis_sec/analysis.py +276 -0
  106. jarvis/jarvis_sec/cli.py +29 -6
  107. jarvis/jarvis_sec/clustering.py +1439 -0
  108. jarvis/jarvis_sec/file_manager.py +427 -0
  109. jarvis/jarvis_sec/parsers.py +73 -0
  110. jarvis/jarvis_sec/prompts.py +268 -0
  111. jarvis/jarvis_sec/report.py +83 -4
  112. jarvis/jarvis_sec/review.py +453 -0
  113. jarvis/jarvis_sec/utils.py +499 -0
  114. jarvis/jarvis_sec/verification.py +848 -0
  115. jarvis/jarvis_sec/workflow.py +7 -0
  116. jarvis/jarvis_smart_shell/main.py +38 -87
  117. jarvis/jarvis_stats/cli.py +1 -1
  118. jarvis/jarvis_stats/stats.py +7 -7
  119. jarvis/jarvis_stats/storage.py +15 -21
  120. jarvis/jarvis_tools/clear_memory.py +3 -20
  121. jarvis/jarvis_tools/cli/main.py +20 -23
  122. jarvis/jarvis_tools/edit_file.py +1066 -0
  123. jarvis/jarvis_tools/execute_script.py +42 -21
  124. jarvis/jarvis_tools/file_analyzer.py +6 -9
  125. jarvis/jarvis_tools/generate_new_tool.py +11 -20
  126. jarvis/jarvis_tools/lsp_client.py +1552 -0
  127. jarvis/jarvis_tools/methodology.py +2 -3
  128. jarvis/jarvis_tools/read_code.py +1525 -87
  129. jarvis/jarvis_tools/read_symbols.py +2 -3
  130. jarvis/jarvis_tools/read_webpage.py +7 -10
  131. jarvis/jarvis_tools/registry.py +370 -181
  132. jarvis/jarvis_tools/retrieve_memory.py +20 -19
  133. jarvis/jarvis_tools/rewrite_file.py +105 -0
  134. jarvis/jarvis_tools/save_memory.py +3 -15
  135. jarvis/jarvis_tools/search_web.py +3 -7
  136. jarvis/jarvis_tools/sub_agent.py +17 -6
  137. jarvis/jarvis_tools/sub_code_agent.py +14 -16
  138. jarvis/jarvis_tools/virtual_tty.py +54 -32
  139. jarvis/jarvis_utils/clipboard.py +7 -10
  140. jarvis/jarvis_utils/config.py +98 -63
  141. jarvis/jarvis_utils/embedding.py +5 -5
  142. jarvis/jarvis_utils/fzf.py +8 -8
  143. jarvis/jarvis_utils/git_utils.py +81 -67
  144. jarvis/jarvis_utils/input.py +24 -49
  145. jarvis/jarvis_utils/jsonnet_compat.py +465 -0
  146. jarvis/jarvis_utils/methodology.py +33 -35
  147. jarvis/jarvis_utils/utils.py +245 -202
  148. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/METADATA +205 -70
  149. jarvis_ai_assistant-0.7.6.dist-info/RECORD +218 -0
  150. jarvis/jarvis_agent/edit_file_handler.py +0 -584
  151. jarvis/jarvis_agent/rewrite_file_handler.py +0 -141
  152. jarvis/jarvis_agent/task_planner.py +0 -496
  153. jarvis/jarvis_platform/ai8.py +0 -332
  154. jarvis/jarvis_tools/ask_user.py +0 -54
  155. jarvis_ai_assistant-0.7.0.dist-info/RECORD +0 -192
  156. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/WHEEL +0 -0
  157. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/entry_points.txt +0 -0
  158. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/licenses/LICENSE +0 -0
  159. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/top_level.txt +0 -0
@@ -25,16 +25,13 @@ from jarvis.jarvis_agent.tool_executor import execute_tool_call
25
25
  from jarvis.jarvis_agent.memory_manager import MemoryManager
26
26
  from jarvis.jarvis_memory_organizer.memory_organizer import MemoryOrganizer
27
27
  from jarvis.jarvis_agent.task_analyzer import TaskAnalyzer
28
- from jarvis.jarvis_agent.task_planner import TaskPlanner
29
28
  from jarvis.jarvis_agent.file_methodology_manager import FileMethodologyManager
30
29
  from jarvis.jarvis_agent.prompts import (
31
30
  DEFAULT_SUMMARY_PROMPT,
32
31
  SUMMARY_REQUEST_PROMPT,
33
- TASK_ANALYSIS_PROMPT as TASK_ANALYSIS_PROMPT,
32
+ TASK_ANALYSIS_PROMPT, # noqa: F401
34
33
  )
35
34
  from jarvis.jarvis_tools.registry import ToolRegistry
36
- from jarvis.jarvis_agent.edit_file_handler import EditFileHandler
37
- from jarvis.jarvis_agent.rewrite_file_handler import RewriteFileHandler
38
35
  from jarvis.jarvis_agent.prompt_manager import PromptManager
39
36
  from jarvis.jarvis_agent.event_bus import EventBus
40
37
  from jarvis.jarvis_agent.run_loop import AgentRunLoop
@@ -76,20 +73,19 @@ from jarvis.jarvis_utils.config import (
76
73
  is_use_methodology,
77
74
  get_tool_filter_threshold,
78
75
  get_after_tool_call_cb_dirs,
79
- get_plan_max_depth,
80
- is_plan_enabled,
81
76
  get_addon_prompt_threshold,
77
+ is_enable_memory_organizer,
82
78
  )
83
79
  from jarvis.jarvis_utils.embedding import get_context_token_count
84
80
  from jarvis.jarvis_utils.globals import (
85
81
  delete_agent,
86
82
  get_interrupt,
83
+ get_short_term_memories,
87
84
  make_agent_name,
88
85
  set_agent,
89
86
  set_interrupt,
90
87
  )
91
88
  from jarvis.jarvis_utils.input import get_multiline_input, user_confirm
92
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
93
89
  from jarvis.jarvis_utils.tag import ot
94
90
 
95
91
 
@@ -138,6 +134,10 @@ def show_agent_startup_stats(
138
134
  if project_memory_dir.exists():
139
135
  project_memory_count = len(list(project_memory_dir.glob("*.json")))
140
136
 
137
+ # 检查短期记忆
138
+ short_term_memories = get_short_term_memories()
139
+ short_term_memory_count = len(short_term_memories) if short_term_memories else 0
140
+
141
141
  # 获取当前工作目录
142
142
  current_dir = os.getcwd()
143
143
 
@@ -157,6 +157,12 @@ def show_agent_startup_stats(
157
157
  f"📝 项目记忆: [bold magenta]{project_memory_count}[/bold magenta]"
158
158
  )
159
159
 
160
+ # 如果有短期记忆,添加到统计信息中
161
+ if short_term_memory_count > 0:
162
+ stats_parts.append(
163
+ f"💭 短期记忆: [bold blue]{short_term_memory_count}[/bold blue]"
164
+ )
165
+
160
166
  stats_text = Text.from_markup(" | ".join(stats_parts), justify="center")
161
167
 
162
168
  # 创建包含欢迎信息和统计信息的面板内容
@@ -180,7 +186,7 @@ def show_agent_startup_stats(
180
186
  console.print(Align.center(panel))
181
187
 
182
188
  except Exception as e:
183
- PrettyOutput.print(f"加载统计信息失败: {e}", OutputType.WARNING)
189
+ print(f"⚠️ 加载统计信息失败: {e}")
184
190
 
185
191
 
186
192
  origin_agent_system_prompt = f"""
@@ -251,9 +257,15 @@ class Agent:
251
257
  def clear_history(self):
252
258
  """
253
259
  Clears the current conversation history by delegating to the session manager.
254
- Emits BEFORE_HISTORY_CLEAR/AFTER_HISTORY_CLEAR and reapplies system prompt to preserve constraints.
260
+ 直接调用关键流程函数,事件总线仅用于非关键流程(如日志、监控等)。
255
261
  """
256
- # 广播清理历史前事件(不影响主流程)
262
+ # 关键流程:直接调用 memory_manager 确保记忆提示
263
+ try:
264
+ self.memory_manager._ensure_memory_prompt(agent=self)
265
+ except Exception:
266
+ pass
267
+
268
+ # 非关键流程:广播清理历史前事件(用于日志、监控等)
257
269
  try:
258
270
  self.event_bus.emit(BEFORE_HISTORY_CLEAR, agent=self)
259
271
  except Exception:
@@ -263,6 +275,8 @@ class Agent:
263
275
  self.session.clear_history()
264
276
  # 重置 addon_prompt 跳过轮数计数器
265
277
  self._addon_prompt_skip_rounds = 0
278
+ # 重置没有工具调用的计数器
279
+ self._no_tool_call_count = 0
266
280
 
267
281
  # 重置后重新设置系统提示词,确保系统约束仍然生效
268
282
  try:
@@ -270,7 +284,7 @@ class Agent:
270
284
  except Exception:
271
285
  pass
272
286
 
273
- # 广播清理历史后的事件
287
+ # 非关键流程:广播清理历史后的事件(用于日志、监控等)
274
288
  try:
275
289
  self.event_bus.emit(AFTER_HISTORY_CLEAR, agent=self)
276
290
  except Exception:
@@ -316,19 +330,14 @@ class Agent:
316
330
  use_tools: Optional[List[str]] = None,
317
331
  execute_tool_confirm: Optional[bool] = None,
318
332
  need_summary: bool = True,
319
- auto_summary_rounds: Optional[int] = None,
320
333
  multiline_inputer: Optional[Callable[[str], str]] = None,
321
334
  use_methodology: Optional[bool] = None,
322
335
  use_analysis: Optional[bool] = None,
323
336
  force_save_memory: Optional[bool] = None,
324
- disable_file_edit: bool = False,
325
337
  files: Optional[List[str]] = None,
326
338
  confirm_callback: Optional[Callable[[str, bool], bool]] = None,
327
339
  non_interactive: Optional[bool] = None,
328
340
  in_multi_agent: Optional[bool] = None,
329
- plan: Optional[bool] = None,
330
- plan_max_depth: Optional[int] = None,
331
- plan_depth: int = 0,
332
341
  agent_type: str = "normal",
333
342
  **kwargs,
334
343
  ):
@@ -349,9 +358,6 @@ class Agent:
349
358
  force_save_memory: 是否强制保存记忆
350
359
  confirm_callback: 用户确认回调函数,签名为 (tip: str, default: bool) -> bool;默认使用CLI的user_confirm
351
360
  non_interactive: 是否以非交互模式运行(优先级最高,覆盖环境变量与配置)
352
- plan: 是否启用任务规划与子任务拆分(默认从配置加载;启用后在进入主循环前评估是否需要将任务拆分为 <SUB_TASK> 列表,逐一由子Agent执行并汇总结果)
353
- plan_max_depth: 任务规划的最大层数(默认3,可通过配置 JARVIS_PLAN_MAX_DEPTH 或入参覆盖)
354
- plan_depth: 当前规划层数(内部用于递归控制,子Agent会在父基础上+1)
355
361
  """
356
362
  # 基础属性初始化(仅根据入参设置原始值;实际生效的默认回退在 _init_config 中统一解析)
357
363
  # 标识与描述
@@ -361,14 +367,11 @@ class Agent:
361
367
  # 行为控制开关(原始入参值)
362
368
  self.auto_complete = bool(auto_complete)
363
369
  self.need_summary = bool(need_summary)
364
- # 自动摘要轮次:None 表示使用配置文件中的默认值,由 AgentRunLoop 决定最终取值
365
- self.auto_summary_rounds = auto_summary_rounds
366
370
  self.use_methodology = use_methodology
367
371
  self.use_analysis = use_analysis
368
372
  self.execute_tool_confirm = execute_tool_confirm
369
373
  self.summary_prompt = summary_prompt
370
374
  self.force_save_memory = force_save_memory
371
- self.disable_file_edit = bool(disable_file_edit)
372
375
  # 资源与环境
373
376
  self.model_group = model_group
374
377
  self.files = files or []
@@ -376,25 +379,16 @@ class Agent:
376
379
  self.non_interactive = non_interactive
377
380
  # 多智能体运行标志:用于控制非交互模式下的自动完成行为
378
381
  self.in_multi_agent = bool(in_multi_agent)
379
- # 任务规划:优先使用入参,否则回退到配置
380
- self.plan = bool(plan) if plan is not None else is_plan_enabled()
381
- # 规划深度与上限
382
- try:
383
- self.plan_max_depth = (
384
- int(plan_max_depth) if plan_max_depth is not None else int(get_plan_max_depth())
385
- )
386
- except Exception:
387
- self.plan_max_depth = 2
388
- try:
389
- self.plan_depth = int(plan_depth)
390
- except Exception:
391
- self.plan_depth = 0
392
382
  # 运行时状态
393
383
  self.first = True
394
384
  self.run_input_handlers_next_turn = False
395
385
  self.user_data: Dict[str, Any] = {}
396
386
  # 记录连续未添加 addon_prompt 的轮数
397
387
  self._addon_prompt_skip_rounds: int = 0
388
+ # 记录连续没有工具调用的次数(用于非交互模式下的工具使用提示)
389
+ self._no_tool_call_count: int = 0
390
+
391
+ self._agent_type = "normal"
398
392
 
399
393
 
400
394
  # 用户确认回调:默认使用 CLI 的 user_confirm,可由外部注入以支持 TUI/GUI
@@ -472,8 +466,14 @@ class Agent:
472
466
  self.task_analyzer = TaskAnalyzer(self)
473
467
  self.file_methodology_manager = FileMethodologyManager(self)
474
468
  self.prompt_manager = PromptManager(self)
475
- # 任务规划器:封装规划与子任务调度逻辑
476
- self.task_planner = TaskPlanner(self, plan_depth=self.plan_depth, plan_max_depth=self.plan_max_depth)
469
+
470
+ # 如果配置了强制保存记忆,确保 save_memory 工具可用
471
+ if self.force_save_memory:
472
+ self._ensure_save_memory_tool()
473
+
474
+ # 如果启用了分析,确保 methodology 工具可用
475
+ if self.use_analysis:
476
+ self._ensure_methodology_tool()
477
477
 
478
478
  # 设置系统提示词
479
479
  self._setup_system_prompt()
@@ -485,6 +485,7 @@ class Agent:
485
485
  self.get_tool_registry(), # type: ignore
486
486
  platform_name=self.model.platform_name(), # type: ignore
487
487
  )
488
+
488
489
  # 动态加载工具调用后回调
489
490
  self._load_after_tool_callbacks()
490
491
 
@@ -495,9 +496,7 @@ class Agent:
495
496
 
496
497
  maybe_model = PlatformRegistry().create_platform(platform_name)
497
498
  if maybe_model is None:
498
- PrettyOutput.print(
499
- f"平台 {platform_name} 不存在,将使用普通模型", OutputType.WARNING
500
- )
499
+ print(f"⚠️ 平台 {platform_name} 不存在,将使用普通模型")
501
500
  maybe_model = PlatformRegistry().get_normal_platform()
502
501
 
503
502
  # 在此处收敛为非可选类型,确保后续赋值满足类型检查
@@ -521,11 +520,7 @@ class Agent:
521
520
  ):
522
521
  """初始化各种处理器"""
523
522
  default_handlers: List[Any] = [ToolRegistry()]
524
- if not getattr(self, "disable_file_edit", False):
525
- default_handlers.extend([EditFileHandler(), RewriteFileHandler()])
526
523
  handlers = output_handler or default_handlers
527
- if getattr(self, "disable_file_edit", False):
528
- handlers = [h for h in handlers if not isinstance(h, (EditFileHandler, RewriteFileHandler))]
529
524
  self.output_handler = handlers
530
525
  self.set_use_tools(use_tools)
531
526
  self.input_handler = [
@@ -538,15 +533,7 @@ class Agent:
538
533
  def _setup_system_prompt(self):
539
534
  """设置系统提示词"""
540
535
  try:
541
- if hasattr(self, "prompt_manager"):
542
- prompt_text = self.prompt_manager.build_system_prompt()
543
- else:
544
- action_prompt = self.get_tool_usage_prompt()
545
- prompt_text = f"""
546
- {self.system_prompt}
547
-
548
- {action_prompt}
549
- """
536
+ prompt_text = self.prompt_manager.build_system_prompt()
550
537
  self.model.set_system_prompt(prompt_text) # type: ignore
551
538
  except Exception:
552
539
  # 回退到原始行为,确保兼容性
@@ -567,6 +554,19 @@ class Agent:
567
554
  """Gets user data from the session."""
568
555
  return self.session.get_user_data(key)
569
556
 
557
+ def get_remaining_token_count(self) -> int:
558
+ """获取剩余可用的token数量
559
+
560
+ 返回:
561
+ int: 剩余可用的token数量,如果无法获取则返回0
562
+ """
563
+ if not self.model:
564
+ return 0
565
+ try:
566
+ return self.model.get_remaining_token_count()
567
+ except Exception:
568
+ return 0
569
+
570
570
  def set_use_tools(self, use_tools):
571
571
  """设置要使用的工具列表"""
572
572
  for handler in self.output_handler:
@@ -590,8 +590,10 @@ class Agent:
590
590
  otherwise, fall back to calling with a single argument for compatibility.
591
591
  """
592
592
  # 优先通过用户交互封装,便于未来替换 UI
593
- if hasattr(self, "user_interaction"):
593
+ try:
594
594
  return self.user_interaction.multiline_input(tip, print_on_empty)
595
+ except Exception:
596
+ pass
595
597
  try:
596
598
  # Try to pass the keyword for enhanced input handler
597
599
  return self.multiline_inputer(tip, print_on_empty=print_on_empty) # type: ignore
@@ -679,7 +681,7 @@ class Agent:
679
681
  pass
680
682
 
681
683
  except Exception as e:
682
- PrettyOutput.print(f"从 {file_path} 加载回调失败: {e}", OutputType.WARNING)
684
+ print(f"⚠️ 从 {file_path} 加载回调失败: {e}")
683
685
  finally:
684
686
  if added_path:
685
687
  try:
@@ -687,7 +689,7 @@ class Agent:
687
689
  except ValueError:
688
690
  pass
689
691
  except Exception as e:
690
- PrettyOutput.print(f"加载回调目录时发生错误: {e}", OutputType.WARNING)
692
+ print(f"⚠️ 加载回调目录时发生错误: {e}")
691
693
 
692
694
  def save_session(self) -> bool:
693
695
  """Saves the current session state by delegating to the session manager."""
@@ -707,6 +709,58 @@ class Agent:
707
709
  return handler
708
710
  return None
709
711
 
712
+ def _ensure_save_memory_tool(self) -> None:
713
+ """如果配置了强制保存记忆,确保 save_memory 工具在 use_tools 列表中"""
714
+ try:
715
+ tool_registry = self.get_tool_registry()
716
+ if not tool_registry:
717
+ return
718
+
719
+ # 检查 save_memory 工具是否已注册(工具默认都会注册)
720
+ if not tool_registry.get_tool("save_memory"):
721
+ # 如果工具本身不存在,则无法使用,直接返回
722
+ return
723
+
724
+ # 检查 save_memory 是否在 use_tools 列表中
725
+ # 如果 use_tools 为 None,表示使用所有工具,无需添加
726
+ if self.use_tools is None:
727
+ return
728
+
729
+ # 如果 save_memory 不在 use_tools 列表中,则添加
730
+ if "save_memory" not in self.use_tools:
731
+ self.use_tools.append("save_memory")
732
+ # 更新工具注册表的工具列表
733
+ self.set_use_tools(self.use_tools)
734
+ except Exception:
735
+ # 忽略所有错误,不影响主流程
736
+ pass
737
+
738
+ def _ensure_methodology_tool(self) -> None:
739
+ """如果启用了分析,确保 methodology 工具在 use_tools 列表中"""
740
+ try:
741
+ tool_registry = self.get_tool_registry()
742
+ if not tool_registry:
743
+ return
744
+
745
+ # 检查 methodology 工具是否已注册(工具默认都会注册)
746
+ if not tool_registry.get_tool("methodology"):
747
+ # 如果工具本身不存在,则无法使用,直接返回
748
+ return
749
+
750
+ # 检查 methodology 是否在 use_tools 列表中
751
+ # 如果 use_tools 为 None,表示使用所有工具,无需添加
752
+ if self.use_tools is None:
753
+ return
754
+
755
+ # 如果 methodology 不在 use_tools 列表中,则添加
756
+ if "methodology" not in self.use_tools:
757
+ self.use_tools.append("methodology")
758
+ # 更新工具注册表的工具列表
759
+ self.set_use_tools(self.use_tools)
760
+ except Exception:
761
+ # 忽略所有错误,不影响主流程
762
+ pass
763
+
710
764
  def get_event_bus(self) -> EventBus:
711
765
  """获取事件总线实例"""
712
766
  return self.event_bus
@@ -819,7 +873,7 @@ class Agent:
819
873
  return message
820
874
 
821
875
  def _manage_conversation_length(self, message: str) -> str:
822
- """管理对话长度计数;摘要触发由轮次在 AgentRunLoop 中统一处理。"""
876
+ """管理对话长度计数;摘要触发由剩余token数量在 AgentRunLoop 中统一处理(剩余token低于20%时触发)。"""
823
877
  self.session.conversation_length += get_context_token_count(message)
824
878
 
825
879
 
@@ -844,7 +898,7 @@ class Agent:
844
898
  # 防御: 模型可能返回空响应(None或空字符串),统一为空字符串并告警
845
899
  if not response:
846
900
  try:
847
- PrettyOutput.print("模型返回空响应,已使用空字符串回退。", OutputType.WARNING)
901
+ print("⚠️ 模型返回空响应,已使用空字符串回退。")
848
902
  except Exception:
849
903
  pass
850
904
  response = ""
@@ -864,9 +918,13 @@ class Agent:
864
918
 
865
919
  return response
866
920
 
867
- def generate_summary(self) -> str:
921
+ def generate_summary(self, for_token_limit: bool = False) -> str:
868
922
  """生成对话历史摘要
869
923
 
924
+ 参数:
925
+ for_token_limit: 如果为True,表示由于token限制触发的summary,使用SUMMARY_REQUEST_PROMPT
926
+ 如果为False,表示任务完成时的summary,使用用户传入的summary_prompt
927
+
870
928
  返回:
871
929
  str: 包含对话摘要的字符串
872
930
 
@@ -877,24 +935,31 @@ class Agent:
877
935
  try:
878
936
  if not self.model:
879
937
  raise RuntimeError("Model not initialized")
880
- # 优先使用外部传入的 summary_prompt;如为空则回退到默认的会话摘要请求
881
- safe_summary_prompt = self.summary_prompt or ""
882
- if isinstance(safe_summary_prompt, str) and safe_summary_prompt.strip() != "":
883
- prompt_to_use = safe_summary_prompt
884
- else:
938
+
939
+ print("🔍 开始生成对话历史摘要...")
940
+
941
+ if for_token_limit:
942
+ # token限制触发的summary:使用SUMMARY_REQUEST_PROMPT进行上下文压缩
885
943
  prompt_to_use = self.session.prompt + "\n" + SUMMARY_REQUEST_PROMPT
944
+ else:
945
+ # 任务完成时的summary:使用用户传入的summary_prompt或DEFAULT_SUMMARY_PROMPT
946
+ safe_summary_prompt = self.summary_prompt or ""
947
+ if isinstance(safe_summary_prompt, str) and safe_summary_prompt.strip() != "":
948
+ prompt_to_use = safe_summary_prompt
949
+ else:
950
+ prompt_to_use = DEFAULT_SUMMARY_PROMPT
886
951
 
887
952
  summary = self.model.chat_until_success(prompt_to_use) # type: ignore
888
953
  # 防御: 可能返回空响应(None或空字符串),统一为空字符串并告警
889
954
  if not summary:
890
955
  try:
891
- PrettyOutput.print("总结模型返回空响应,已使用空字符串回退。", OutputType.WARNING)
956
+ print("⚠️ 总结模型返回空响应,已使用空字符串回退。")
892
957
  except Exception:
893
958
  pass
894
959
  summary = ""
895
960
  return summary
896
961
  except Exception:
897
- PrettyOutput.print("总结对话历史失败", OutputType.ERROR)
962
+ print("总结对话历史失败")
898
963
  return ""
899
964
 
900
965
  def _summarize_and_clear_history(self) -> str:
@@ -914,11 +979,6 @@ class Agent:
914
979
  注意:
915
980
  当上下文长度超过最大值时使用
916
981
  """
917
- # 在清理历史之前,提示用户保存重要记忆(事件驱动触发实际保存)
918
- if self.force_save_memory:
919
- PrettyOutput.print(
920
- "对话历史即将被总结和清理,请先保存重要信息...", OutputType.INFO
921
- )
922
982
 
923
983
  if self._should_use_file_upload():
924
984
  return self._handle_history_with_file_upload()
@@ -931,20 +991,28 @@ class Agent:
931
991
 
932
992
  def _handle_history_with_summary(self) -> str:
933
993
  """使用摘要方式处理历史"""
934
- summary = self.generate_summary()
994
+ # token限制触发的summary,使用SUMMARY_REQUEST_PROMPT
995
+ summary = self.generate_summary(for_token_limit=True)
935
996
 
936
997
  # 先获取格式化的摘要消息
937
998
  formatted_summary = ""
938
999
  if summary:
939
1000
  formatted_summary = self._format_summary_message(summary)
940
1001
 
941
- # 清理历史(但不清理prompt,因为prompt会在builtin_input_handler中设置)
942
- if self.model:
943
- # 广播清理历史前事件
1002
+ # 关键流程:直接调用 memory_manager 确保记忆提示
1003
+ try:
1004
+ self.memory_manager._ensure_memory_prompt(agent=self)
1005
+ except Exception:
1006
+ pass
1007
+
1008
+ # 非关键流程:广播清理历史前事件(用于日志、监控等)
944
1009
  try:
945
1010
  self.event_bus.emit(BEFORE_HISTORY_CLEAR, agent=self)
946
1011
  except Exception:
947
1012
  pass
1013
+
1014
+ # 清理历史(但不清理prompt,因为prompt会在builtin_input_handler中设置)
1015
+ if self.model:
948
1016
  self.model.reset()
949
1017
  # 重置后重新设置系统提示词,确保系统约束仍然生效
950
1018
  self._setup_system_prompt()
@@ -952,7 +1020,10 @@ class Agent:
952
1020
  self.session.clear_history()
953
1021
  # 重置 addon_prompt 跳过轮数计数器
954
1022
  self._addon_prompt_skip_rounds = 0
955
- # 广播清理历史后的事件
1023
+ # 重置没有工具调用的计数器
1024
+ self._no_tool_call_count = 0
1025
+
1026
+ # 非关键流程:广播清理历史后的事件(用于日志、监控等)
956
1027
  try:
957
1028
  self.event_bus.emit(AFTER_HISTORY_CLEAR, agent=self)
958
1029
  except Exception:
@@ -962,15 +1033,25 @@ class Agent:
962
1033
 
963
1034
  def _handle_history_with_file_upload(self) -> str:
964
1035
  """使用文件上传方式处理历史"""
965
- # 广播清理历史前事件
1036
+ # 关键流程:直接调用 memory_manager 确保记忆提示
1037
+ try:
1038
+ self.memory_manager._ensure_memory_prompt(agent=self)
1039
+ except Exception:
1040
+ pass
1041
+
1042
+ # 非关键流程:广播清理历史前事件(用于日志、监控等)
966
1043
  try:
967
1044
  self.event_bus.emit(BEFORE_HISTORY_CLEAR, agent=self)
968
1045
  except Exception:
969
1046
  pass
1047
+
970
1048
  result = self.file_methodology_manager.handle_history_with_file_upload()
971
1049
  # 重置 addon_prompt 跳过轮数计数器
972
1050
  self._addon_prompt_skip_rounds = 0
973
- # 广播清理历史后的事件
1051
+ # 重置没有工具调用的计数器
1052
+ self._no_tool_call_count = 0
1053
+
1054
+ # 非关键流程:广播清理历史后的事件(用于日志、监控等)
974
1055
  try:
975
1056
  self.event_bus.emit(AFTER_HISTORY_CLEAR, agent=self)
976
1057
  except Exception:
@@ -1010,7 +1091,9 @@ class Agent:
1010
1091
  # - TaskAnalyzer 通过订阅 before_summary/task_completed 事件执行分析与满意度收集
1011
1092
  # - MemoryManager 通过订阅 before_history_clear/task_completed 事件执行记忆保存(受 force_save_memory 控制)
1012
1093
  # 为减少耦合,这里不再直接调用上述组件,保持行为由事件触发
1013
- self._check_and_organize_memory()
1094
+ # 仅在启用自动记忆整理时检查并整理记忆
1095
+ if is_enable_memory_organizer():
1096
+ self._check_and_organize_memory()
1014
1097
 
1015
1098
  result = "任务完成"
1016
1099
 
@@ -1020,8 +1103,20 @@ class Agent:
1020
1103
  safe_summary_prompt = self.summary_prompt or ""
1021
1104
  if isinstance(safe_summary_prompt, str) and safe_summary_prompt.strip() == "":
1022
1105
  safe_summary_prompt = DEFAULT_SUMMARY_PROMPT
1023
- # 注意:不要写回 session.prompt,避免 BEFORE_SUMMARY 事件回调修改/清空后导致使用空prompt
1024
- # 广播将要生成总结事件
1106
+ # 注意:不要写回 session.prompt,避免回调修改/清空后导致使用空prompt
1107
+
1108
+ # 关键流程:直接调用 task_analyzer 执行任务分析
1109
+ try:
1110
+ self.task_analyzer._on_before_summary(
1111
+ agent=self,
1112
+ prompt=safe_summary_prompt,
1113
+ auto_completed=auto_completed,
1114
+ need_summary=self.need_summary,
1115
+ )
1116
+ except Exception:
1117
+ pass
1118
+
1119
+ # 非关键流程:广播将要生成总结事件(用于日志、监控等)
1025
1120
  try:
1026
1121
  self.event_bus.emit(
1027
1122
  BEFORE_SUMMARY,
@@ -1040,13 +1135,13 @@ class Agent:
1040
1135
  # 防御: 总结阶段模型可能返回空响应(None或空字符串),统一为空字符串并告警
1041
1136
  if not ret:
1042
1137
  try:
1043
- PrettyOutput.print("总结阶段模型返回空响应,已使用空字符串回退。", OutputType.WARNING)
1138
+ print("⚠️ 总结阶段模型返回空响应,已使用空字符串回退。")
1044
1139
  except Exception:
1045
1140
  pass
1046
1141
  ret = ""
1047
1142
  result = ret
1048
1143
 
1049
- # 广播完成总结事件
1144
+ # 非关键流程:广播完成总结事件(用于日志、监控等)
1050
1145
  try:
1051
1146
  self.event_bus.emit(
1052
1147
  AFTER_SUMMARY,
@@ -1056,7 +1151,26 @@ class Agent:
1056
1151
  except Exception:
1057
1152
  pass
1058
1153
 
1059
- # 广播任务完成事件(不影响主流程)
1154
+ # 关键流程:直接调用 task_analyzer 和 memory_manager
1155
+ try:
1156
+ self.task_analyzer._on_task_completed(
1157
+ agent=self,
1158
+ auto_completed=auto_completed,
1159
+ need_summary=self.need_summary,
1160
+ )
1161
+ except Exception:
1162
+ pass
1163
+
1164
+ try:
1165
+ self.memory_manager._ensure_memory_prompt(
1166
+ agent=self,
1167
+ auto_completed=auto_completed,
1168
+ need_summary=self.need_summary,
1169
+ )
1170
+ except Exception:
1171
+ pass
1172
+
1173
+ # 非关键流程:广播任务完成事件(用于日志、监控等)
1060
1174
  try:
1061
1175
  self.event_bus.emit(
1062
1176
  TASK_COMPLETED,
@@ -1077,10 +1191,12 @@ class Agent:
1077
1191
 
1078
1192
  """
1079
1193
  # 优先使用 PromptManager 以保持逻辑集中
1080
- if hasattr(self, "prompt_manager"):
1194
+ try:
1081
1195
  return self.prompt_manager.build_default_addon_prompt(need_complete)
1196
+ except Exception:
1197
+ pass
1082
1198
 
1083
- # 结构化系统指令
1199
+ # 结构化系统指令(回退方案)
1084
1200
  action_handlers = ", ".join([handler.name() for handler in self.output_handler])
1085
1201
 
1086
1202
  # 任务完成提示
@@ -1104,8 +1220,10 @@ class Agent:
1104
1220
  如果没有完成,请进行下一步操作:
1105
1221
  - 仅包含一个操作
1106
1222
  - 如果信息不明确,请请求用户补充
1107
- - 如果执行过程中连续失败5次,请使用ask_user询问用户操作
1223
+ - 如果执行过程中连续失败5次,请请求用户操作
1108
1224
  - 操作列表:{action_handlers}{memory_prompts}
1225
+
1226
+ 注意:如果当前部分任务已完成,之前的上下文价值不大,可以输出<!!!SUMMARY!!!>标记来触发总结并清空历史,以便开始新的任务阶段。
1109
1227
  </system_prompt>
1110
1228
 
1111
1229
  请继续。
@@ -1131,7 +1249,19 @@ class Agent:
1131
1249
  self.session.prompt = f"{user_input}"
1132
1250
  try:
1133
1251
  set_agent(self.name, self)
1134
- # 广播任务开始事件(不影响主流程)
1252
+
1253
+ # 关键流程:直接调用 memory_manager 重置任务状态
1254
+ try:
1255
+ self.memory_manager._on_task_started(
1256
+ agent=self,
1257
+ name=self.name,
1258
+ description=self.description,
1259
+ user_input=self.session.prompt,
1260
+ )
1261
+ except Exception:
1262
+ pass
1263
+
1264
+ # 非关键流程:广播任务开始事件(用于日志、监控等)
1135
1265
  try:
1136
1266
  self.event_bus.emit(
1137
1267
  TASK_STARTED,
@@ -1142,16 +1272,9 @@ class Agent:
1142
1272
  )
1143
1273
  except Exception:
1144
1274
  pass
1145
- # 如启用规划模式,先判断是否需要拆分并调度子任务
1146
- if self.plan:
1147
- try:
1148
- self._maybe_plan_and_dispatch(self.session.prompt)
1149
- except Exception:
1150
- # 防御式处理,规划失败不影响主流程
1151
- pass
1152
1275
  return self._main_loop()
1153
1276
  except Exception as e:
1154
- PrettyOutput.print(f"任务失败: {str(e)}", OutputType.ERROR)
1277
+ print(f"任务失败: {str(e)}")
1155
1278
  return f"Task failed: {str(e)}"
1156
1279
 
1157
1280
  def _main_loop(self) -> Any:
@@ -1277,37 +1400,21 @@ class Agent:
1277
1400
  "use_tools": use_tools_param,
1278
1401
  "execute_tool_confirm": self.execute_tool_confirm,
1279
1402
  "need_summary": self.need_summary,
1280
- "auto_summary_rounds": self.auto_summary_rounds,
1281
1403
  "multiline_inputer": self.multiline_inputer,
1282
1404
  "use_methodology": self.use_methodology,
1283
1405
  "use_analysis": self.use_analysis,
1284
1406
  "force_save_memory": self.force_save_memory,
1285
- "disable_file_edit": self.disable_file_edit,
1286
1407
  "files": self.files,
1287
1408
  "confirm_callback": self.confirm_callback,
1288
1409
  "non_interactive": True,
1289
1410
  "in_multi_agent": True,
1290
- "plan": self.plan, # 继承父Agent的规划开关
1291
- "plan_depth": self.plan_depth + 1, # 子Agent层数+1
1292
- "plan_max_depth": self.plan_max_depth, # 继承上限
1293
1411
  }
1294
1412
 
1295
- def _maybe_plan_and_dispatch(self, task_text: str) -> None:
1296
- """委托给 TaskPlanner 执行任务规划与子任务调度,保持向后兼容。"""
1297
- try:
1298
- if hasattr(self, "task_planner") and self.task_planner:
1299
- # 优先使用初始化时注入的规划器
1300
- self.task_planner.maybe_plan_and_dispatch(task_text) # type: ignore[attr-defined]
1301
- else:
1302
- # 防御式回退:临时创建规划器以避免因未初始化导致的崩溃
1303
- from jarvis.jarvis_agent.task_planner import TaskPlanner
1304
- TaskPlanner(self, plan_depth=self.plan_depth, plan_max_depth=self.plan_max_depth).maybe_plan_and_dispatch(task_text)
1305
- except Exception:
1306
- # 规划失败不影响主流程
1307
- pass
1308
-
1309
1413
  def _filter_tools_if_needed(self, task: str):
1310
- """如果工具数量超过阈值,使用大模型筛选相关工具"""
1414
+ """如果工具数量超过阈值,使用大模型筛选相关工具
1415
+
1416
+ 注意:仅筛选用户自定义工具,内置工具不参与筛选(始终保留)
1417
+ """
1311
1418
  tool_registry = self.get_tool_registry()
1312
1419
  if not isinstance(tool_registry, ToolRegistry):
1313
1420
  return
@@ -1317,10 +1424,16 @@ class Agent:
1317
1424
  if len(all_tools) <= threshold:
1318
1425
  return
1319
1426
 
1320
- # 为工具选择构建提示
1427
+ # 获取用户自定义工具(非内置工具),仅对这些工具进行筛选
1428
+ custom_tools = tool_registry.get_custom_tools()
1429
+ if not custom_tools:
1430
+ # 没有用户自定义工具,无需筛选
1431
+ return
1432
+
1433
+ # 为工具选择构建提示(仅包含用户自定义工具)
1321
1434
  tools_prompt_part = ""
1322
1435
  tool_names = []
1323
- for i, tool in enumerate(all_tools, 1):
1436
+ for i, tool in enumerate(custom_tools, 1):
1324
1437
  tool_names.append(tool["name"])
1325
1438
  tools_prompt_part += f"{i}. {tool['name']}: {tool['description']}\n"
1326
1439
 
@@ -1338,9 +1451,7 @@ class Agent:
1338
1451
  请根据用户任务,从列表中选择最相关的工具。
1339
1452
  请仅返回所选工具的编号,以逗号分隔。例如:1, 5, 12
1340
1453
  """
1341
- PrettyOutput.print(
1342
- f"工具数量超过{threshold}个,正在使用AI筛选相关工具...", OutputType.INFO
1343
- )
1454
+ print(f"ℹ️ 工具数量超过{threshold}个,正在使用AI筛选相关工具...")
1344
1455
  # 广播工具筛选开始事件
1345
1456
  try:
1346
1457
  self.event_bus.emit(
@@ -1373,13 +1484,13 @@ class Agent:
1373
1484
  if selected_tool_names:
1374
1485
  # 移除重复项
1375
1486
  selected_tool_names = sorted(list(set(selected_tool_names)))
1376
- tool_registry.use_tools(selected_tool_names)
1487
+ # 合并内置工具名称和筛选出的用户自定义工具名称
1488
+ builtin_names = list(tool_registry._builtin_tool_names)
1489
+ final_tool_names = sorted(list(set(builtin_names + selected_tool_names)))
1490
+ tool_registry.use_tools(final_tool_names)
1377
1491
  # 使用筛选后的工具列表重新设置系统提示
1378
1492
  self._setup_system_prompt()
1379
- PrettyOutput.print(
1380
- f"已筛选出 {len(selected_tool_names)} 个相关工具: {', '.join(selected_tool_names)}",
1381
- OutputType.SUCCESS,
1382
- )
1493
+ print(f"✅ 已筛选出 {len(selected_tool_names)} 个相关工具: {', '.join(selected_tool_names)}")
1383
1494
  # 广播工具筛选事件
1384
1495
  try:
1385
1496
  self.event_bus.emit(
@@ -1393,9 +1504,7 @@ class Agent:
1393
1504
  except Exception:
1394
1505
  pass
1395
1506
  else:
1396
- PrettyOutput.print(
1397
- "AI 未能筛选出任何相关工具,将使用所有工具。", OutputType.WARNING
1398
- )
1507
+ print("⚠️ AI 未能筛选出任何相关工具,将使用所有工具。")
1399
1508
  # 广播工具筛选事件(无筛选结果)
1400
1509
  try:
1401
1510
  self.event_bus.emit(
@@ -1410,9 +1519,7 @@ class Agent:
1410
1519
  pass
1411
1520
 
1412
1521
  except Exception as e:
1413
- PrettyOutput.print(
1414
- f"工具筛选失败: {e},将使用所有工具。", OutputType.ERROR
1415
- )
1522
+ print(f"❌ 工具筛选失败: {e},将使用所有工具。")
1416
1523
 
1417
1524
  def _check_and_organize_memory(self):
1418
1525
  """
@@ -1429,7 +1536,7 @@ class Agent:
1429
1536
  "global",
1430
1537
  )
1431
1538
  except Exception as e:
1432
- PrettyOutput.print(f"检查记忆库时发生意外错误: {e}", OutputType.WARNING)
1539
+ print(f"⚠️ 检查记忆库时发生意外错误: {e}")
1433
1540
 
1434
1541
  def _perform_memory_check(self, memory_type: str, base_path: Path, scope_name: str):
1435
1542
  """执行特定范围的记忆检查和整理"""
@@ -1470,11 +1577,8 @@ class Agent:
1470
1577
  f"并且存在3个以上标签重叠的记忆。\n"
1471
1578
  f"是否立即整理记忆库以优化性能和相关性?"
1472
1579
  )
1473
- if self.confirm_callback(prompt, True):
1474
- PrettyOutput.print(
1475
- f"正在开始整理 '{scope_name}' ({memory_type}) 记忆库...",
1476
- OutputType.INFO,
1477
- )
1580
+ if self.confirm_callback(prompt, False):
1581
+ print(f"ℹ️ 正在开始整理 '{scope_name}' ({memory_type}) 记忆库...")
1478
1582
  organizer.organize_memories(memory_type, min_overlap=3)
1479
1583
  else:
1480
- PrettyOutput.print(f"已取消 '{scope_name}' 记忆库整理。", OutputType.INFO)
1584
+ print(f"ℹ️ 已取消 '{scope_name}' 记忆库整理。")