jarvis-ai-assistant 0.7.8__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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +567 -222
- jarvis/jarvis_agent/agent_manager.py +19 -12
- jarvis/jarvis_agent/builtin_input_handler.py +79 -11
- jarvis/jarvis_agent/config_editor.py +7 -2
- jarvis/jarvis_agent/event_bus.py +24 -13
- jarvis/jarvis_agent/events.py +19 -1
- jarvis/jarvis_agent/file_context_handler.py +67 -64
- jarvis/jarvis_agent/file_methodology_manager.py +38 -24
- jarvis/jarvis_agent/jarvis.py +186 -114
- jarvis/jarvis_agent/language_extractors/__init__.py +8 -1
- jarvis/jarvis_agent/language_extractors/c_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/cpp_extractor.py +9 -4
- jarvis/jarvis_agent/language_extractors/go_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/java_extractor.py +27 -20
- jarvis/jarvis_agent/language_extractors/javascript_extractor.py +22 -17
- jarvis/jarvis_agent/language_extractors/python_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/rust_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/typescript_extractor.py +22 -17
- jarvis/jarvis_agent/language_support_info.py +250 -219
- jarvis/jarvis_agent/main.py +19 -23
- jarvis/jarvis_agent/memory_manager.py +9 -6
- jarvis/jarvis_agent/methodology_share_manager.py +21 -15
- jarvis/jarvis_agent/output_handler.py +4 -2
- jarvis/jarvis_agent/prompt_builder.py +7 -6
- jarvis/jarvis_agent/prompt_manager.py +113 -8
- jarvis/jarvis_agent/prompts.py +317 -85
- jarvis/jarvis_agent/protocols.py +5 -2
- jarvis/jarvis_agent/run_loop.py +192 -32
- jarvis/jarvis_agent/session_manager.py +7 -3
- jarvis/jarvis_agent/share_manager.py +23 -13
- jarvis/jarvis_agent/shell_input_handler.py +12 -8
- jarvis/jarvis_agent/stdio_redirect.py +25 -26
- jarvis/jarvis_agent/task_analyzer.py +29 -23
- jarvis/jarvis_agent/task_list.py +869 -0
- jarvis/jarvis_agent/task_manager.py +26 -23
- jarvis/jarvis_agent/tool_executor.py +6 -5
- jarvis/jarvis_agent/tool_share_manager.py +24 -14
- jarvis/jarvis_agent/user_interaction.py +3 -3
- jarvis/jarvis_agent/utils.py +9 -1
- jarvis/jarvis_agent/web_bridge.py +37 -17
- jarvis/jarvis_agent/web_output_sink.py +5 -2
- jarvis/jarvis_agent/web_server.py +165 -36
- jarvis/jarvis_c2rust/__init__.py +1 -1
- jarvis/jarvis_c2rust/cli.py +260 -141
- jarvis/jarvis_c2rust/collector.py +37 -18
- jarvis/jarvis_c2rust/constants.py +60 -0
- jarvis/jarvis_c2rust/library_replacer.py +242 -1010
- jarvis/jarvis_c2rust/library_replacer_checkpoint.py +133 -0
- jarvis/jarvis_c2rust/library_replacer_llm.py +287 -0
- jarvis/jarvis_c2rust/library_replacer_loader.py +191 -0
- jarvis/jarvis_c2rust/library_replacer_output.py +134 -0
- jarvis/jarvis_c2rust/library_replacer_prompts.py +124 -0
- jarvis/jarvis_c2rust/library_replacer_utils.py +188 -0
- jarvis/jarvis_c2rust/llm_module_agent.py +98 -1044
- jarvis/jarvis_c2rust/llm_module_agent_apply.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_executor.py +288 -0
- jarvis/jarvis_c2rust/llm_module_agent_loader.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_prompts.py +268 -0
- jarvis/jarvis_c2rust/llm_module_agent_types.py +57 -0
- jarvis/jarvis_c2rust/llm_module_agent_utils.py +150 -0
- jarvis/jarvis_c2rust/llm_module_agent_validator.py +119 -0
- jarvis/jarvis_c2rust/loaders.py +28 -10
- jarvis/jarvis_c2rust/models.py +5 -2
- jarvis/jarvis_c2rust/optimizer.py +192 -1974
- jarvis/jarvis_c2rust/optimizer_build_fix.py +286 -0
- jarvis/jarvis_c2rust/optimizer_clippy.py +766 -0
- jarvis/jarvis_c2rust/optimizer_config.py +49 -0
- jarvis/jarvis_c2rust/optimizer_docs.py +183 -0
- jarvis/jarvis_c2rust/optimizer_options.py +48 -0
- jarvis/jarvis_c2rust/optimizer_progress.py +469 -0
- jarvis/jarvis_c2rust/optimizer_report.py +52 -0
- jarvis/jarvis_c2rust/optimizer_unsafe.py +309 -0
- jarvis/jarvis_c2rust/optimizer_utils.py +469 -0
- jarvis/jarvis_c2rust/optimizer_visibility.py +185 -0
- jarvis/jarvis_c2rust/scanner.py +229 -166
- jarvis/jarvis_c2rust/transpiler.py +531 -2732
- jarvis/jarvis_c2rust/transpiler_agents.py +503 -0
- jarvis/jarvis_c2rust/transpiler_build.py +1294 -0
- jarvis/jarvis_c2rust/transpiler_codegen.py +204 -0
- jarvis/jarvis_c2rust/transpiler_compile.py +146 -0
- jarvis/jarvis_c2rust/transpiler_config.py +178 -0
- jarvis/jarvis_c2rust/transpiler_context.py +122 -0
- jarvis/jarvis_c2rust/transpiler_executor.py +516 -0
- jarvis/jarvis_c2rust/transpiler_generation.py +278 -0
- jarvis/jarvis_c2rust/transpiler_git.py +163 -0
- jarvis/jarvis_c2rust/transpiler_mod_utils.py +225 -0
- jarvis/jarvis_c2rust/transpiler_modules.py +336 -0
- jarvis/jarvis_c2rust/transpiler_planning.py +394 -0
- jarvis/jarvis_c2rust/transpiler_review.py +1196 -0
- jarvis/jarvis_c2rust/transpiler_symbols.py +176 -0
- jarvis/jarvis_c2rust/utils.py +269 -79
- jarvis/jarvis_code_agent/after_change.py +233 -0
- jarvis/jarvis_code_agent/build_validation_config.py +37 -30
- jarvis/jarvis_code_agent/builtin_rules.py +68 -0
- jarvis/jarvis_code_agent/code_agent.py +976 -1517
- jarvis/jarvis_code_agent/code_agent_build.py +227 -0
- jarvis/jarvis_code_agent/code_agent_diff.py +246 -0
- jarvis/jarvis_code_agent/code_agent_git.py +525 -0
- jarvis/jarvis_code_agent/code_agent_impact.py +177 -0
- jarvis/jarvis_code_agent/code_agent_lint.py +283 -0
- jarvis/jarvis_code_agent/code_agent_llm.py +159 -0
- jarvis/jarvis_code_agent/code_agent_postprocess.py +105 -0
- jarvis/jarvis_code_agent/code_agent_prompts.py +46 -0
- jarvis/jarvis_code_agent/code_agent_rules.py +305 -0
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +52 -48
- jarvis/jarvis_code_agent/code_analyzer/base_language.py +12 -10
- jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +12 -11
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +16 -12
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +26 -17
- jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +558 -104
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +22 -18
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +21 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +20 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +47 -23
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +71 -37
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +162 -35
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +111 -57
- jarvis/jarvis_code_agent/code_analyzer/build_validator.py +18 -12
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +185 -183
- jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +2 -1
- jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +24 -15
- jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +227 -141
- jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +321 -247
- jarvis/jarvis_code_agent/code_analyzer/language_registry.py +37 -29
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -13
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +15 -9
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +75 -45
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +87 -52
- jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +84 -51
- jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +94 -64
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +109 -71
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +97 -63
- jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +103 -69
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +271 -268
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +76 -64
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +92 -19
- jarvis/jarvis_code_agent/diff_visualizer.py +998 -0
- jarvis/jarvis_code_agent/lint.py +223 -524
- jarvis/jarvis_code_agent/rule_share_manager.py +158 -0
- jarvis/jarvis_code_agent/rules/clean_code.md +144 -0
- jarvis/jarvis_code_agent/rules/code_review.md +115 -0
- jarvis/jarvis_code_agent/rules/documentation.md +165 -0
- jarvis/jarvis_code_agent/rules/generate_rules.md +52 -0
- jarvis/jarvis_code_agent/rules/performance.md +158 -0
- jarvis/jarvis_code_agent/rules/refactoring.md +139 -0
- jarvis/jarvis_code_agent/rules/security.md +160 -0
- jarvis/jarvis_code_agent/rules/tdd.md +78 -0
- jarvis/jarvis_code_agent/test_rules/cpp_test.md +118 -0
- jarvis/jarvis_code_agent/test_rules/go_test.md +98 -0
- jarvis/jarvis_code_agent/test_rules/java_test.md +99 -0
- jarvis/jarvis_code_agent/test_rules/javascript_test.md +113 -0
- jarvis/jarvis_code_agent/test_rules/php_test.md +117 -0
- jarvis/jarvis_code_agent/test_rules/python_test.md +91 -0
- jarvis/jarvis_code_agent/test_rules/ruby_test.md +102 -0
- jarvis/jarvis_code_agent/test_rules/rust_test.md +86 -0
- jarvis/jarvis_code_agent/utils.py +36 -26
- jarvis/jarvis_code_analysis/checklists/loader.py +21 -21
- jarvis/jarvis_code_analysis/code_review.py +64 -33
- jarvis/jarvis_data/config_schema.json +285 -192
- jarvis/jarvis_git_squash/main.py +8 -6
- jarvis/jarvis_git_utils/git_commiter.py +53 -76
- jarvis/jarvis_mcp/__init__.py +5 -2
- jarvis/jarvis_mcp/sse_mcp_client.py +40 -30
- jarvis/jarvis_mcp/stdio_mcp_client.py +27 -19
- jarvis/jarvis_mcp/streamable_mcp_client.py +35 -26
- jarvis/jarvis_memory_organizer/memory_organizer.py +78 -55
- jarvis/jarvis_methodology/main.py +48 -39
- jarvis/jarvis_multi_agent/__init__.py +56 -23
- jarvis/jarvis_multi_agent/main.py +15 -18
- jarvis/jarvis_platform/base.py +179 -111
- jarvis/jarvis_platform/human.py +27 -16
- jarvis/jarvis_platform/kimi.py +52 -45
- jarvis/jarvis_platform/openai.py +101 -40
- jarvis/jarvis_platform/registry.py +51 -33
- jarvis/jarvis_platform/tongyi.py +68 -38
- jarvis/jarvis_platform/yuanbao.py +59 -43
- jarvis/jarvis_platform_manager/main.py +68 -76
- jarvis/jarvis_platform_manager/service.py +24 -14
- jarvis/jarvis_rag/README_CONFIG.md +314 -0
- jarvis/jarvis_rag/README_DYNAMIC_LOADING.md +311 -0
- jarvis/jarvis_rag/README_ONLINE_MODELS.md +230 -0
- jarvis/jarvis_rag/__init__.py +57 -4
- jarvis/jarvis_rag/cache.py +3 -1
- jarvis/jarvis_rag/cli.py +48 -68
- jarvis/jarvis_rag/embedding_interface.py +39 -0
- jarvis/jarvis_rag/embedding_manager.py +7 -230
- jarvis/jarvis_rag/embeddings/__init__.py +41 -0
- jarvis/jarvis_rag/embeddings/base.py +114 -0
- jarvis/jarvis_rag/embeddings/cohere.py +66 -0
- jarvis/jarvis_rag/embeddings/edgefn.py +117 -0
- jarvis/jarvis_rag/embeddings/local.py +260 -0
- jarvis/jarvis_rag/embeddings/openai.py +62 -0
- jarvis/jarvis_rag/embeddings/registry.py +293 -0
- jarvis/jarvis_rag/llm_interface.py +8 -6
- jarvis/jarvis_rag/query_rewriter.py +8 -9
- jarvis/jarvis_rag/rag_pipeline.py +61 -52
- jarvis/jarvis_rag/reranker.py +7 -75
- jarvis/jarvis_rag/reranker_interface.py +32 -0
- jarvis/jarvis_rag/rerankers/__init__.py +41 -0
- jarvis/jarvis_rag/rerankers/base.py +109 -0
- jarvis/jarvis_rag/rerankers/cohere.py +67 -0
- jarvis/jarvis_rag/rerankers/edgefn.py +140 -0
- jarvis/jarvis_rag/rerankers/jina.py +79 -0
- jarvis/jarvis_rag/rerankers/local.py +89 -0
- jarvis/jarvis_rag/rerankers/registry.py +293 -0
- jarvis/jarvis_rag/retriever.py +58 -43
- jarvis/jarvis_sec/__init__.py +66 -141
- jarvis/jarvis_sec/agents.py +21 -17
- jarvis/jarvis_sec/analysis.py +80 -33
- jarvis/jarvis_sec/checkers/__init__.py +7 -13
- jarvis/jarvis_sec/checkers/c_checker.py +356 -164
- jarvis/jarvis_sec/checkers/rust_checker.py +47 -29
- jarvis/jarvis_sec/cli.py +43 -21
- jarvis/jarvis_sec/clustering.py +430 -272
- jarvis/jarvis_sec/file_manager.py +99 -55
- jarvis/jarvis_sec/parsers.py +9 -6
- jarvis/jarvis_sec/prompts.py +4 -3
- jarvis/jarvis_sec/report.py +44 -22
- jarvis/jarvis_sec/review.py +180 -107
- jarvis/jarvis_sec/status.py +50 -41
- jarvis/jarvis_sec/types.py +3 -0
- jarvis/jarvis_sec/utils.py +160 -83
- jarvis/jarvis_sec/verification.py +411 -181
- jarvis/jarvis_sec/workflow.py +132 -21
- jarvis/jarvis_smart_shell/main.py +28 -41
- jarvis/jarvis_stats/cli.py +14 -12
- jarvis/jarvis_stats/stats.py +28 -19
- jarvis/jarvis_stats/storage.py +14 -8
- jarvis/jarvis_stats/visualizer.py +12 -7
- jarvis/jarvis_tools/base.py +5 -2
- jarvis/jarvis_tools/clear_memory.py +13 -9
- jarvis/jarvis_tools/cli/main.py +23 -18
- jarvis/jarvis_tools/edit_file.py +572 -873
- jarvis/jarvis_tools/execute_script.py +10 -7
- jarvis/jarvis_tools/file_analyzer.py +7 -8
- jarvis/jarvis_tools/meta_agent.py +287 -0
- jarvis/jarvis_tools/methodology.py +5 -3
- jarvis/jarvis_tools/read_code.py +305 -1438
- jarvis/jarvis_tools/read_symbols.py +50 -17
- jarvis/jarvis_tools/read_webpage.py +19 -18
- jarvis/jarvis_tools/registry.py +435 -156
- jarvis/jarvis_tools/retrieve_memory.py +16 -11
- jarvis/jarvis_tools/save_memory.py +8 -6
- jarvis/jarvis_tools/search_web.py +31 -31
- jarvis/jarvis_tools/sub_agent.py +32 -28
- jarvis/jarvis_tools/sub_code_agent.py +44 -60
- jarvis/jarvis_tools/task_list_manager.py +1811 -0
- jarvis/jarvis_tools/virtual_tty.py +29 -19
- jarvis/jarvis_utils/__init__.py +4 -0
- jarvis/jarvis_utils/builtin_replace_map.py +2 -1
- jarvis/jarvis_utils/clipboard.py +9 -8
- jarvis/jarvis_utils/collections.py +331 -0
- jarvis/jarvis_utils/config.py +699 -194
- jarvis/jarvis_utils/dialogue_recorder.py +294 -0
- jarvis/jarvis_utils/embedding.py +6 -3
- jarvis/jarvis_utils/file_processors.py +7 -1
- jarvis/jarvis_utils/fzf.py +9 -3
- jarvis/jarvis_utils/git_utils.py +71 -42
- jarvis/jarvis_utils/globals.py +116 -32
- jarvis/jarvis_utils/http.py +6 -2
- jarvis/jarvis_utils/input.py +318 -83
- jarvis/jarvis_utils/jsonnet_compat.py +119 -104
- jarvis/jarvis_utils/methodology.py +37 -28
- jarvis/jarvis_utils/output.py +201 -44
- jarvis/jarvis_utils/utils.py +986 -628
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/METADATA +49 -33
- jarvis_ai_assistant-1.0.2.dist-info/RECORD +304 -0
- jarvis/jarvis_code_agent/code_analyzer/structured_code.py +0 -556
- jarvis/jarvis_tools/generate_new_tool.py +0 -205
- jarvis/jarvis_tools/lsp_client.py +0 -1552
- jarvis/jarvis_tools/rewrite_file.py +0 -105
- jarvis_ai_assistant-0.7.8.dist-info/RECORD +0 -218
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/top_level.txt +0 -0
jarvis/jarvis_agent/__init__.py
CHANGED
|
@@ -5,10 +5,15 @@ import os
|
|
|
5
5
|
import platform
|
|
6
6
|
import re
|
|
7
7
|
import sys
|
|
8
|
-
from pathlib import Path
|
|
9
8
|
from enum import Enum
|
|
10
|
-
from
|
|
11
|
-
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any
|
|
11
|
+
from typing import Callable
|
|
12
|
+
from typing import Dict
|
|
13
|
+
from typing import List
|
|
14
|
+
from typing import Optional
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import Union
|
|
12
17
|
|
|
13
18
|
# 第三方库导入
|
|
14
19
|
from rich.align import Align
|
|
@@ -16,76 +21,73 @@ from rich.console import Console
|
|
|
16
21
|
from rich.panel import Panel
|
|
17
22
|
from rich.text import Text
|
|
18
23
|
|
|
24
|
+
from jarvis.jarvis_agent.builtin_input_handler import builtin_input_handler
|
|
25
|
+
from jarvis.jarvis_agent.event_bus import EventBus
|
|
26
|
+
from jarvis.jarvis_agent.events import AFTER_ADDON_PROMPT
|
|
27
|
+
from jarvis.jarvis_agent.events import AFTER_HISTORY_CLEAR
|
|
28
|
+
from jarvis.jarvis_agent.events import AFTER_MODEL_CALL
|
|
29
|
+
from jarvis.jarvis_agent.events import AFTER_SUMMARY
|
|
30
|
+
from jarvis.jarvis_agent.events import AFTER_TOOL_CALL
|
|
31
|
+
from jarvis.jarvis_agent.events import BEFORE_ADDON_PROMPT
|
|
32
|
+
from jarvis.jarvis_agent.events import BEFORE_HISTORY_CLEAR
|
|
33
|
+
from jarvis.jarvis_agent.events import BEFORE_MODEL_CALL
|
|
34
|
+
from jarvis.jarvis_agent.events import BEFORE_SUMMARY
|
|
35
|
+
from jarvis.jarvis_agent.events import BEFORE_TOOL_FILTER
|
|
36
|
+
from jarvis.jarvis_agent.events import INTERRUPT_TRIGGERED
|
|
37
|
+
from jarvis.jarvis_agent.events import TASK_COMPLETED
|
|
38
|
+
from jarvis.jarvis_agent.events import TASK_STARTED
|
|
39
|
+
from jarvis.jarvis_agent.events import TOOL_FILTERED
|
|
40
|
+
from jarvis.jarvis_agent.file_context_handler import file_context_handler
|
|
41
|
+
from jarvis.jarvis_agent.file_methodology_manager import FileMethodologyManager
|
|
42
|
+
from jarvis.jarvis_agent.memory_manager import MemoryManager
|
|
43
|
+
|
|
19
44
|
# 本地库导入
|
|
20
45
|
# jarvis_agent 相关
|
|
21
46
|
from jarvis.jarvis_agent.prompt_builder import build_action_prompt
|
|
47
|
+
from jarvis.jarvis_agent.prompt_manager import PromptManager
|
|
48
|
+
from jarvis.jarvis_agent.prompts import DEFAULT_SUMMARY_PROMPT
|
|
49
|
+
from jarvis.jarvis_agent.prompts import SUMMARY_REQUEST_PROMPT
|
|
22
50
|
from jarvis.jarvis_agent.protocols import OutputHandlerProtocol
|
|
51
|
+
from jarvis.jarvis_agent.run_loop import AgentRunLoop
|
|
23
52
|
from jarvis.jarvis_agent.session_manager import SessionManager
|
|
24
|
-
from jarvis.jarvis_agent.
|
|
25
|
-
from jarvis.jarvis_agent.memory_manager import MemoryManager
|
|
26
|
-
from jarvis.jarvis_memory_organizer.memory_organizer import MemoryOrganizer
|
|
53
|
+
from jarvis.jarvis_agent.shell_input_handler import shell_input_handler
|
|
27
54
|
from jarvis.jarvis_agent.task_analyzer import TaskAnalyzer
|
|
28
|
-
from jarvis.jarvis_agent.
|
|
29
|
-
from jarvis.jarvis_agent.
|
|
30
|
-
DEFAULT_SUMMARY_PROMPT,
|
|
31
|
-
SUMMARY_REQUEST_PROMPT,
|
|
32
|
-
TASK_ANALYSIS_PROMPT, # noqa: F401
|
|
33
|
-
)
|
|
34
|
-
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
35
|
-
from jarvis.jarvis_agent.prompt_manager import PromptManager
|
|
36
|
-
from jarvis.jarvis_agent.event_bus import EventBus
|
|
37
|
-
from jarvis.jarvis_agent.run_loop import AgentRunLoop
|
|
38
|
-
from jarvis.jarvis_agent.events import (
|
|
39
|
-
BEFORE_SUMMARY,
|
|
40
|
-
AFTER_SUMMARY,
|
|
41
|
-
TASK_COMPLETED,
|
|
42
|
-
TASK_STARTED,
|
|
43
|
-
BEFORE_ADDON_PROMPT,
|
|
44
|
-
AFTER_ADDON_PROMPT,
|
|
45
|
-
BEFORE_HISTORY_CLEAR,
|
|
46
|
-
AFTER_HISTORY_CLEAR,
|
|
47
|
-
BEFORE_MODEL_CALL,
|
|
48
|
-
AFTER_MODEL_CALL,
|
|
49
|
-
INTERRUPT_TRIGGERED,
|
|
50
|
-
BEFORE_TOOL_FILTER,
|
|
51
|
-
TOOL_FILTERED,
|
|
52
|
-
AFTER_TOOL_CALL,
|
|
53
|
-
)
|
|
55
|
+
from jarvis.jarvis_agent.task_list import TaskListManager
|
|
56
|
+
from jarvis.jarvis_agent.tool_executor import execute_tool_call
|
|
54
57
|
from jarvis.jarvis_agent.user_interaction import UserInteractionHandler
|
|
55
58
|
from jarvis.jarvis_agent.utils import join_prompts
|
|
56
|
-
from jarvis.
|
|
57
|
-
from jarvis.jarvis_agent.shell_input_handler import shell_input_handler
|
|
58
|
-
from jarvis.jarvis_agent.file_context_handler import file_context_handler
|
|
59
|
-
from jarvis.jarvis_agent.builtin_input_handler import builtin_input_handler
|
|
59
|
+
from jarvis.jarvis_memory_organizer.memory_organizer import MemoryOrganizer
|
|
60
60
|
|
|
61
61
|
# jarvis_platform 相关
|
|
62
62
|
from jarvis.jarvis_platform.base import BasePlatform
|
|
63
63
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
64
|
+
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
64
65
|
|
|
65
66
|
# jarvis_utils 相关
|
|
66
|
-
from jarvis.jarvis_utils.config import
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
is_enable_memory_organizer,
|
|
78
|
-
)
|
|
67
|
+
from jarvis.jarvis_utils.config import get_addon_prompt_threshold
|
|
68
|
+
from jarvis.jarvis_utils.config import get_after_tool_call_cb_dirs
|
|
69
|
+
from jarvis.jarvis_utils.config import get_data_dir
|
|
70
|
+
from jarvis.jarvis_utils.config import get_normal_model_name
|
|
71
|
+
from jarvis.jarvis_utils.config import get_normal_platform_name
|
|
72
|
+
from jarvis.jarvis_utils.config import get_tool_filter_threshold
|
|
73
|
+
from jarvis.jarvis_utils.config import is_enable_memory_organizer
|
|
74
|
+
from jarvis.jarvis_utils.config import is_execute_tool_confirm
|
|
75
|
+
from jarvis.jarvis_utils.config import is_force_save_memory
|
|
76
|
+
from jarvis.jarvis_utils.config import is_use_analysis
|
|
77
|
+
from jarvis.jarvis_utils.config import is_use_methodology
|
|
79
78
|
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
80
|
-
from jarvis.jarvis_utils.globals import
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
from jarvis.jarvis_utils.input import
|
|
79
|
+
from jarvis.jarvis_utils.globals import clear_current_agent
|
|
80
|
+
from jarvis.jarvis_utils.globals import get_interrupt
|
|
81
|
+
from jarvis.jarvis_utils.globals import get_short_term_memories
|
|
82
|
+
from jarvis.jarvis_utils.globals import make_agent_name
|
|
83
|
+
from jarvis.jarvis_utils.globals import set_global_model_group
|
|
84
|
+
from jarvis.jarvis_utils.globals import set_interrupt
|
|
85
|
+
from jarvis.jarvis_utils.globals import set_current_agent
|
|
86
|
+
from jarvis.jarvis_utils.input import get_multiline_input
|
|
87
|
+
from jarvis.jarvis_utils.input import user_confirm
|
|
88
|
+
from jarvis.jarvis_utils.methodology import _load_all_methodologies
|
|
89
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
90
|
+
from jarvis.jarvis_utils.tag import ct
|
|
89
91
|
from jarvis.jarvis_utils.tag import ot
|
|
90
92
|
|
|
91
93
|
|
|
@@ -143,7 +145,9 @@ def show_agent_startup_stats(
|
|
|
143
145
|
|
|
144
146
|
# 构建欢迎信息
|
|
145
147
|
platform = platform_name or get_normal_platform_name()
|
|
146
|
-
welcome_message =
|
|
148
|
+
welcome_message = (
|
|
149
|
+
f"{agent_name} 初始化完成 - 使用 {platform} 平台 {model_name} 模型"
|
|
150
|
+
)
|
|
147
151
|
|
|
148
152
|
stats_parts = [
|
|
149
153
|
f"📚 本地方法论: [bold cyan]{methodology_count}[/bold cyan]",
|
|
@@ -186,54 +190,47 @@ def show_agent_startup_stats(
|
|
|
186
190
|
console.print(Align.center(panel))
|
|
187
191
|
|
|
188
192
|
except Exception as e:
|
|
189
|
-
|
|
193
|
+
PrettyOutput.auto_print(f"⚠️ 加载统计信息失败: {e}")
|
|
190
194
|
|
|
191
195
|
|
|
192
196
|
origin_agent_system_prompt = f"""
|
|
193
197
|
<role>
|
|
194
|
-
# 🤖
|
|
195
|
-
|
|
198
|
+
# 🤖 Jarvis Agent
|
|
199
|
+
你是一个专业的任务执行助手,根据用户需求制定并执行详细计划。
|
|
196
200
|
</role>
|
|
197
201
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
-
|
|
226
|
-
- 子任务不是以代码改造为主(如调研、方案撰写、评审总结、用例设计、文档生成等)
|
|
227
|
-
- 只是需要短期分流一个轻量的辅助性子任务
|
|
228
|
-
说明:
|
|
229
|
-
- 两者仅需参数 task(可选 background 提供上下文),完成后返回结果给父Agent
|
|
230
|
-
- 子Agent将自动完成并生成总结,请在上层根据返回结果继续编排
|
|
231
|
-
</sub_agents_guide>
|
|
202
|
+
## 核心模式
|
|
203
|
+
每个响应必须以[MODE: MODE_NAME]开头:
|
|
204
|
+
- **INTENT**: 理解用户需求
|
|
205
|
+
- **RESEARCH**: 收集信息
|
|
206
|
+
- **INNOVATE**: 探索方案
|
|
207
|
+
- **PLAN**: 制定计划(复杂任务用task_list_manager)
|
|
208
|
+
- **EXECUTE**: 执行操作
|
|
209
|
+
- **REVIEW**: 验证结果
|
|
210
|
+
|
|
211
|
+
### IIRIPER 工作流强制约束
|
|
212
|
+
- 整体工作流必须严格按照 **INTENT → RESEARCH → INNOVATE → PLAN → EXECUTE → REVIEW** 的顺序推进。
|
|
213
|
+
- **禁止跳步或乱序**:例如,不能在未经过 PLAN 就直接进入 EXECUTE,也不能从 INTENT 直接跳到 REVIEW。
|
|
214
|
+
- 如因用户以非常明确的指令要求跳过某阶段,必须在当前回复中:
|
|
215
|
+
- 明确指出被跳过的阶段;
|
|
216
|
+
- 解释为什么认为可以跳过;
|
|
217
|
+
- 简要提示可能的风险。
|
|
218
|
+
|
|
219
|
+
## 执行规则
|
|
220
|
+
1. **单次操作**: 每个响应只含一个工具调用
|
|
221
|
+
2. **禁止虚构**: 必须基于实际结果,禁止假设
|
|
222
|
+
3. **任务列表**: 复杂任务用task_list_manager,简单任务直接执行
|
|
223
|
+
4. **必须验证**: 代码需编译通过、功能验证
|
|
224
|
+
5. **模式转换**: 需明确信号"ENTER [MODE]"
|
|
225
|
+
|
|
226
|
+
## 工具使用
|
|
227
|
+
- 优先用task_list_manager执行复杂任务
|
|
228
|
+
- execute_task必须提供additional_info参数
|
|
229
|
+
- 禁止同时调用多个工具
|
|
232
230
|
|
|
233
231
|
<system_info>
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
- Time: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
|
232
|
+
OS: {platform.platform()} {platform.version()}
|
|
233
|
+
Time: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
|
237
234
|
</system_info>
|
|
238
235
|
"""
|
|
239
236
|
|
|
@@ -259,12 +256,18 @@ class Agent:
|
|
|
259
256
|
Clears the current conversation history by delegating to the session manager.
|
|
260
257
|
直接调用关键流程函数,事件总线仅用于非关键流程(如日志、监控等)。
|
|
261
258
|
"""
|
|
259
|
+
# 获取当前会话文件路径用于提示
|
|
260
|
+
from jarvis.jarvis_utils.dialogue_recorder import get_global_recorder
|
|
261
|
+
|
|
262
|
+
recorder = get_global_recorder()
|
|
263
|
+
session_file_path = recorder.get_session_file_path()
|
|
264
|
+
|
|
262
265
|
# 关键流程:直接调用 memory_manager 确保记忆提示
|
|
263
266
|
try:
|
|
264
267
|
self.memory_manager._ensure_memory_prompt(agent=self)
|
|
265
268
|
except Exception:
|
|
266
269
|
pass
|
|
267
|
-
|
|
270
|
+
|
|
268
271
|
# 非关键流程:广播清理历史前事件(用于日志、监控等)
|
|
269
272
|
try:
|
|
270
273
|
self.event_bus.emit(BEFORE_HISTORY_CLEAR, agent=self)
|
|
@@ -278,6 +281,11 @@ class Agent:
|
|
|
278
281
|
# 重置没有工具调用的计数器
|
|
279
282
|
self._no_tool_call_count = 0
|
|
280
283
|
|
|
284
|
+
# 提示用户会话文件位置
|
|
285
|
+
if Path(session_file_path).exists():
|
|
286
|
+
PrettyOutput.auto_print(f"💾 当前会话记录已保存到: {session_file_path}")
|
|
287
|
+
PrettyOutput.auto_print("🤖 大模型可以读取此文件了解完整对话历史")
|
|
288
|
+
|
|
281
289
|
# 重置后重新设置系统提示词,确保系统约束仍然生效
|
|
282
290
|
try:
|
|
283
291
|
self._setup_system_prompt()
|
|
@@ -292,16 +300,11 @@ class Agent:
|
|
|
292
300
|
|
|
293
301
|
def __del__(self):
|
|
294
302
|
# 只有在记录启动时才停止记录
|
|
295
|
-
|
|
296
|
-
name = getattr(self, "name", None)
|
|
297
|
-
if name:
|
|
298
|
-
delete_agent(name)
|
|
299
|
-
except Exception:
|
|
300
|
-
pass
|
|
303
|
+
pass
|
|
301
304
|
|
|
302
305
|
def get_tool_usage_prompt(self) -> str:
|
|
303
306
|
"""获取工具使用提示"""
|
|
304
|
-
return build_action_prompt(self.output_handler)
|
|
307
|
+
return build_action_prompt(self.output_handler)
|
|
305
308
|
|
|
306
309
|
def __new__(cls, *args, **kwargs):
|
|
307
310
|
if kwargs.get("agent_type") == "code":
|
|
@@ -325,7 +328,7 @@ class Agent:
|
|
|
325
328
|
description: str = "",
|
|
326
329
|
model_group: Optional[str] = None,
|
|
327
330
|
summary_prompt: Optional[str] = None,
|
|
328
|
-
auto_complete: bool =
|
|
331
|
+
auto_complete: bool = True,
|
|
329
332
|
output_handler: Optional[List[OutputHandlerProtocol]] = None,
|
|
330
333
|
use_tools: Optional[List[str]] = None,
|
|
331
334
|
execute_tool_confirm: Optional[bool] = None,
|
|
@@ -336,7 +339,7 @@ class Agent:
|
|
|
336
339
|
force_save_memory: Optional[bool] = None,
|
|
337
340
|
files: Optional[List[str]] = None,
|
|
338
341
|
confirm_callback: Optional[Callable[[str, bool], bool]] = None,
|
|
339
|
-
non_interactive: Optional[bool] =
|
|
342
|
+
non_interactive: Optional[bool] = True,
|
|
340
343
|
in_multi_agent: Optional[bool] = None,
|
|
341
344
|
agent_type: str = "normal",
|
|
342
345
|
**kwargs,
|
|
@@ -383,17 +386,18 @@ class Agent:
|
|
|
383
386
|
self.first = True
|
|
384
387
|
self.run_input_handlers_next_turn = False
|
|
385
388
|
self.user_data: Dict[str, Any] = {}
|
|
389
|
+
# 记录固定的内容
|
|
390
|
+
self.pin_content: str = ""
|
|
386
391
|
# 记录连续未添加 addon_prompt 的轮数
|
|
387
|
-
self._addon_prompt_skip_rounds
|
|
392
|
+
self._addon_prompt_skip_rounds = 0
|
|
388
393
|
# 记录连续没有工具调用的次数(用于非交互模式下的工具使用提示)
|
|
389
|
-
self._no_tool_call_count
|
|
390
|
-
|
|
391
|
-
self._agent_type = "normal"
|
|
394
|
+
self._no_tool_call_count = 0
|
|
392
395
|
|
|
396
|
+
self._agent_type = "normal"
|
|
393
397
|
|
|
394
398
|
# 用户确认回调:默认使用 CLI 的 user_confirm,可由外部注入以支持 TUI/GUI
|
|
395
399
|
self.confirm_callback: Callable[[str, bool], bool] = (
|
|
396
|
-
confirm_callback or user_confirm
|
|
400
|
+
confirm_callback or user_confirm
|
|
397
401
|
)
|
|
398
402
|
|
|
399
403
|
# 初始化模型和会话
|
|
@@ -407,57 +411,78 @@ class Agent:
|
|
|
407
411
|
use_tools or [],
|
|
408
412
|
)
|
|
409
413
|
# 初始化用户交互封装,保持向后兼容
|
|
410
|
-
self.user_interaction = UserInteractionHandler(
|
|
414
|
+
self.user_interaction = UserInteractionHandler(
|
|
415
|
+
self.multiline_inputer, self.confirm_callback
|
|
416
|
+
)
|
|
411
417
|
# 将确认函数指向封装后的 confirm,保持既有调用不变
|
|
412
|
-
self.confirm_callback = self.user_interaction.confirm
|
|
418
|
+
self.confirm_callback = self.user_interaction.confirm
|
|
413
419
|
# 非交互模式参数支持:允许通过构造参数显式控制,便于其他Agent调用时设置
|
|
420
|
+
# 仅作为 Agent 实例属性,不写入环境变量或全局配置,避免跨 Agent 污染
|
|
414
421
|
try:
|
|
415
|
-
#
|
|
422
|
+
# 优先使用构造参数,若未提供则默认为 False
|
|
416
423
|
self.non_interactive = (
|
|
417
|
-
bool(non_interactive)
|
|
418
|
-
if non_interactive is not None
|
|
419
|
-
else str(os.environ.get("JARVIS_NON_INTERACTIVE", "")).lower() in ("1", "true", "yes")
|
|
424
|
+
bool(non_interactive) if non_interactive is not None else False
|
|
420
425
|
)
|
|
421
|
-
# 如果构造参数显式提供,则同步到环境变量与全局配置,供下游组件读取
|
|
422
|
-
if non_interactive is not None:
|
|
423
|
-
os.environ["JARVIS_NON_INTERACTIVE"] = "true" if self.non_interactive else "false"
|
|
424
|
-
|
|
425
426
|
except Exception:
|
|
426
427
|
# 防御式回退
|
|
427
428
|
self.non_interactive = False
|
|
428
429
|
|
|
429
430
|
# 初始化配置(直接解析,不再依赖 _init_config)
|
|
430
431
|
try:
|
|
431
|
-
resolved_use_methodology = bool(
|
|
432
|
+
resolved_use_methodology = bool(
|
|
433
|
+
use_methodology if use_methodology is not None else is_use_methodology()
|
|
434
|
+
)
|
|
432
435
|
except Exception:
|
|
433
|
-
resolved_use_methodology =
|
|
436
|
+
resolved_use_methodology = (
|
|
437
|
+
bool(use_methodology) if use_methodology is not None else True
|
|
438
|
+
)
|
|
434
439
|
|
|
435
440
|
try:
|
|
436
|
-
resolved_use_analysis = bool(
|
|
441
|
+
resolved_use_analysis = bool(
|
|
442
|
+
use_analysis if use_analysis is not None else is_use_analysis()
|
|
443
|
+
)
|
|
437
444
|
except Exception:
|
|
438
|
-
resolved_use_analysis =
|
|
445
|
+
resolved_use_analysis = (
|
|
446
|
+
bool(use_analysis) if use_analysis is not None else True
|
|
447
|
+
)
|
|
439
448
|
|
|
440
449
|
try:
|
|
441
|
-
resolved_execute_tool_confirm = bool(
|
|
450
|
+
resolved_execute_tool_confirm = bool(
|
|
451
|
+
execute_tool_confirm
|
|
452
|
+
if execute_tool_confirm is not None
|
|
453
|
+
else is_execute_tool_confirm()
|
|
454
|
+
)
|
|
442
455
|
except Exception:
|
|
443
|
-
resolved_execute_tool_confirm =
|
|
456
|
+
resolved_execute_tool_confirm = (
|
|
457
|
+
bool(execute_tool_confirm)
|
|
458
|
+
if execute_tool_confirm is not None
|
|
459
|
+
else False
|
|
460
|
+
)
|
|
444
461
|
|
|
445
462
|
try:
|
|
446
|
-
resolved_force_save_memory = bool(
|
|
463
|
+
resolved_force_save_memory = bool(
|
|
464
|
+
force_save_memory
|
|
465
|
+
if force_save_memory is not None
|
|
466
|
+
else is_force_save_memory()
|
|
467
|
+
)
|
|
447
468
|
except Exception:
|
|
448
|
-
resolved_force_save_memory =
|
|
469
|
+
resolved_force_save_memory = (
|
|
470
|
+
bool(force_save_memory) if force_save_memory is not None else False
|
|
471
|
+
)
|
|
449
472
|
|
|
450
473
|
self.use_methodology = resolved_use_methodology
|
|
451
474
|
self.use_analysis = resolved_use_analysis
|
|
452
475
|
self.execute_tool_confirm = resolved_execute_tool_confirm
|
|
453
|
-
self.summary_prompt =
|
|
476
|
+
self.summary_prompt = summary_prompt or DEFAULT_SUMMARY_PROMPT
|
|
454
477
|
self.force_save_memory = resolved_force_save_memory
|
|
455
478
|
# 多智能体模式下,默认不自动完成(即使是非交互),仅在明确传入 auto_complete=True 时开启
|
|
456
479
|
if self.in_multi_agent:
|
|
457
480
|
self.auto_complete = bool(self.auto_complete)
|
|
458
481
|
else:
|
|
459
482
|
# 非交互模式下默认自动完成;否则保持传入的 auto_complete 值
|
|
460
|
-
self.auto_complete = bool(
|
|
483
|
+
self.auto_complete = bool(
|
|
484
|
+
self.auto_complete or (self.non_interactive or False)
|
|
485
|
+
)
|
|
461
486
|
|
|
462
487
|
# 初始化事件总线需先于管理器,以便管理器在构造中安全订阅事件
|
|
463
488
|
self.event_bus = EventBus()
|
|
@@ -466,6 +491,9 @@ class Agent:
|
|
|
466
491
|
self.task_analyzer = TaskAnalyzer(self)
|
|
467
492
|
self.file_methodology_manager = FileMethodologyManager(self)
|
|
468
493
|
self.prompt_manager = PromptManager(self)
|
|
494
|
+
# 初始化任务列表管理器(使用当前工作目录作为 root_dir,如果子类已设置 root_dir 则使用子类的)
|
|
495
|
+
root_dir = getattr(self, "root_dir", None) or os.getcwd()
|
|
496
|
+
self.task_list_manager = TaskListManager(root_dir)
|
|
469
497
|
|
|
470
498
|
# 如果配置了强制保存记忆,确保 save_memory 工具可用
|
|
471
499
|
if self.force_save_memory:
|
|
@@ -482,10 +510,10 @@ class Agent:
|
|
|
482
510
|
show_agent_startup_stats(
|
|
483
511
|
name,
|
|
484
512
|
self.model.name(),
|
|
485
|
-
self.get_tool_registry(),
|
|
486
|
-
platform_name=self.model.platform_name(),
|
|
513
|
+
self.get_tool_registry(),
|
|
514
|
+
platform_name=self.model.platform_name(),
|
|
487
515
|
)
|
|
488
|
-
|
|
516
|
+
|
|
489
517
|
# 动态加载工具调用后回调
|
|
490
518
|
self._load_after_tool_callbacks()
|
|
491
519
|
|
|
@@ -496,7 +524,7 @@ class Agent:
|
|
|
496
524
|
|
|
497
525
|
maybe_model = PlatformRegistry().create_platform(platform_name)
|
|
498
526
|
if maybe_model is None:
|
|
499
|
-
|
|
527
|
+
PrettyOutput.auto_print(f"⚠️ 平台 {platform_name} 不存在,将使用普通模型")
|
|
500
528
|
maybe_model = PlatformRegistry().get_normal_platform()
|
|
501
529
|
|
|
502
530
|
# 在此处收敛为非可选类型,确保后续赋值满足类型检查
|
|
@@ -508,9 +536,12 @@ class Agent:
|
|
|
508
536
|
self.model.set_model_group(model_group)
|
|
509
537
|
self.model.set_suppress_output(False)
|
|
510
538
|
|
|
539
|
+
# 设置全局模型组,供工具和其他组件使用
|
|
540
|
+
set_global_model_group(model_group)
|
|
541
|
+
|
|
511
542
|
def _init_session(self):
|
|
512
543
|
"""初始化会话管理器"""
|
|
513
|
-
self.session = SessionManager(model=self.model, agent_name=self.name)
|
|
544
|
+
self.session = SessionManager(model=self.model, agent_name=self.name)
|
|
514
545
|
|
|
515
546
|
def _init_handlers(
|
|
516
547
|
self,
|
|
@@ -534,15 +565,20 @@ class Agent:
|
|
|
534
565
|
"""设置系统提示词"""
|
|
535
566
|
try:
|
|
536
567
|
prompt_text = self.prompt_manager.build_system_prompt()
|
|
537
|
-
self.model.set_system_prompt(prompt_text)
|
|
568
|
+
self.model.set_system_prompt(prompt_text)
|
|
538
569
|
except Exception:
|
|
539
570
|
# 回退到原始行为,确保兼容性
|
|
540
571
|
action_prompt = self.get_tool_usage_prompt()
|
|
541
|
-
self.
|
|
572
|
+
rules_prompt = self.rules_manager.load_all_rules(
|
|
573
|
+
",".join(self.loaded_rule_names)
|
|
574
|
+
)
|
|
575
|
+
self.model.set_system_prompt(
|
|
542
576
|
f"""
|
|
543
577
|
{self.system_prompt}
|
|
544
578
|
|
|
545
579
|
{action_prompt}
|
|
580
|
+
|
|
581
|
+
{rules_prompt}
|
|
546
582
|
"""
|
|
547
583
|
)
|
|
548
584
|
|
|
@@ -556,7 +592,7 @@ class Agent:
|
|
|
556
592
|
|
|
557
593
|
def get_remaining_token_count(self) -> int:
|
|
558
594
|
"""获取剩余可用的token数量
|
|
559
|
-
|
|
595
|
+
|
|
560
596
|
返回:
|
|
561
597
|
int: 剩余可用的token数量,如果无法获取则返回0
|
|
562
598
|
"""
|
|
@@ -596,14 +632,16 @@ class Agent:
|
|
|
596
632
|
pass
|
|
597
633
|
try:
|
|
598
634
|
# Try to pass the keyword for enhanced input handler
|
|
599
|
-
return self.multiline_inputer(
|
|
635
|
+
return self.multiline_inputer(
|
|
636
|
+
tip,
|
|
637
|
+
)
|
|
600
638
|
except TypeError:
|
|
601
639
|
# Fallback for custom handlers that only accept one argument
|
|
602
|
-
return self.multiline_inputer(tip)
|
|
640
|
+
return self.multiline_inputer(tip)
|
|
603
641
|
|
|
604
642
|
def _load_after_tool_callbacks(self) -> None:
|
|
605
643
|
"""
|
|
606
|
-
扫描
|
|
644
|
+
扫描 after_tool_call_cb_dirs 中的 Python 文件并动态注册回调。
|
|
607
645
|
约定优先级(任一命中即注册):
|
|
608
646
|
- 模块级可调用对象: after_tool_call_cb
|
|
609
647
|
- 工厂方法返回单个或多个可调用对象: get_after_tool_call_cb(), register_after_tool_call_cb()
|
|
@@ -634,7 +672,7 @@ class Agent:
|
|
|
634
672
|
if hasattr(module, "after_tool_call_cb"):
|
|
635
673
|
obj = getattr(module, "after_tool_call_cb")
|
|
636
674
|
if callable(obj):
|
|
637
|
-
candidates.append(obj)
|
|
675
|
+
candidates.append(obj)
|
|
638
676
|
|
|
639
677
|
# 2) 工厂方法:get_after_tool_call_cb()
|
|
640
678
|
if hasattr(module, "get_after_tool_call_cb"):
|
|
@@ -668,6 +706,7 @@ class Agent:
|
|
|
668
706
|
|
|
669
707
|
for cb in candidates:
|
|
670
708
|
try:
|
|
709
|
+
|
|
671
710
|
def _make_wrapper(callback):
|
|
672
711
|
def _wrapper(**kwargs: Any) -> None:
|
|
673
712
|
try:
|
|
@@ -675,13 +714,17 @@ class Agent:
|
|
|
675
714
|
callback(agent)
|
|
676
715
|
except Exception:
|
|
677
716
|
pass
|
|
717
|
+
|
|
678
718
|
return _wrapper
|
|
679
|
-
|
|
719
|
+
|
|
720
|
+
self.event_bus.subscribe(
|
|
721
|
+
AFTER_TOOL_CALL, _make_wrapper(cb)
|
|
722
|
+
)
|
|
680
723
|
except Exception:
|
|
681
724
|
pass
|
|
682
725
|
|
|
683
726
|
except Exception as e:
|
|
684
|
-
|
|
727
|
+
PrettyOutput.auto_print(f"⚠️ 从 {file_path} 加载回调失败: {e}")
|
|
685
728
|
finally:
|
|
686
729
|
if added_path:
|
|
687
730
|
try:
|
|
@@ -689,7 +732,7 @@ class Agent:
|
|
|
689
732
|
except ValueError:
|
|
690
733
|
pass
|
|
691
734
|
except Exception as e:
|
|
692
|
-
|
|
735
|
+
PrettyOutput.auto_print(f"⚠️ 加载回调目录时发生错误: {e}")
|
|
693
736
|
|
|
694
737
|
def save_session(self) -> bool:
|
|
695
738
|
"""Saves the current session state by delegating to the session manager."""
|
|
@@ -813,7 +856,7 @@ class Agent:
|
|
|
813
856
|
|
|
814
857
|
def _add_addon_prompt(self, message: str, need_complete: bool) -> str:
|
|
815
858
|
"""添加附加提示到消息
|
|
816
|
-
|
|
859
|
+
|
|
817
860
|
规则:
|
|
818
861
|
1. 如果 session.addon_prompt 存在,优先使用它
|
|
819
862
|
2. 如果消息长度超过阈值,添加默认 addon_prompt
|
|
@@ -833,7 +876,7 @@ class Agent:
|
|
|
833
876
|
|
|
834
877
|
addon_text = ""
|
|
835
878
|
should_add = False
|
|
836
|
-
|
|
879
|
+
|
|
837
880
|
if self.session.addon_prompt:
|
|
838
881
|
# 优先使用 session 中设置的 addon_prompt
|
|
839
882
|
addon_text = self.session.addon_prompt
|
|
@@ -852,7 +895,7 @@ class Agent:
|
|
|
852
895
|
addon_text = self.make_default_addon_prompt(need_complete)
|
|
853
896
|
message = join_prompts([message, addon_text])
|
|
854
897
|
should_add = True
|
|
855
|
-
|
|
898
|
+
|
|
856
899
|
# 更新计数器:如果添加了 addon_prompt,重置计数器;否则递增
|
|
857
900
|
if should_add:
|
|
858
901
|
self._addon_prompt_skip_rounds = 0
|
|
@@ -876,7 +919,6 @@ class Agent:
|
|
|
876
919
|
"""管理对话长度计数;摘要触发由剩余token数量在 AgentRunLoop 中统一处理(剩余token低于20%时触发)。"""
|
|
877
920
|
self.session.conversation_length += get_context_token_count(message)
|
|
878
921
|
|
|
879
|
-
|
|
880
922
|
return message
|
|
881
923
|
|
|
882
924
|
def _invoke_model(self, message: str) -> str:
|
|
@@ -894,15 +936,15 @@ class Agent:
|
|
|
894
936
|
except Exception:
|
|
895
937
|
pass
|
|
896
938
|
|
|
897
|
-
response = self.model.chat_until_success(message)
|
|
939
|
+
response = self.model.chat_until_success(message)
|
|
898
940
|
# 防御: 模型可能返回空响应(None或空字符串),统一为空字符串并告警
|
|
899
941
|
if not response:
|
|
900
942
|
try:
|
|
901
|
-
|
|
943
|
+
PrettyOutput.auto_print("⚠️ 模型返回空响应,已使用空字符串回退。")
|
|
902
944
|
except Exception:
|
|
903
945
|
pass
|
|
904
946
|
response = ""
|
|
905
|
-
|
|
947
|
+
|
|
906
948
|
# 事件:模型调用后
|
|
907
949
|
try:
|
|
908
950
|
self.event_bus.emit(
|
|
@@ -935,31 +977,36 @@ class Agent:
|
|
|
935
977
|
try:
|
|
936
978
|
if not self.model:
|
|
937
979
|
raise RuntimeError("Model not initialized")
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
980
|
+
|
|
981
|
+
PrettyOutput.auto_print("🔍 开始生成对话历史摘要...")
|
|
982
|
+
|
|
941
983
|
if for_token_limit:
|
|
942
984
|
# token限制触发的summary:使用SUMMARY_REQUEST_PROMPT进行上下文压缩
|
|
943
985
|
prompt_to_use = self.session.prompt + "\n" + SUMMARY_REQUEST_PROMPT
|
|
944
986
|
else:
|
|
945
987
|
# 任务完成时的summary:使用用户传入的summary_prompt或DEFAULT_SUMMARY_PROMPT
|
|
946
988
|
safe_summary_prompt = self.summary_prompt or ""
|
|
947
|
-
if
|
|
989
|
+
if (
|
|
990
|
+
isinstance(safe_summary_prompt, str)
|
|
991
|
+
and safe_summary_prompt.strip() != ""
|
|
992
|
+
):
|
|
948
993
|
prompt_to_use = safe_summary_prompt
|
|
949
994
|
else:
|
|
950
995
|
prompt_to_use = DEFAULT_SUMMARY_PROMPT
|
|
951
996
|
|
|
952
|
-
summary = self.model.chat_until_success(prompt_to_use)
|
|
997
|
+
summary = self.model.chat_until_success(prompt_to_use)
|
|
953
998
|
# 防御: 可能返回空响应(None或空字符串),统一为空字符串并告警
|
|
954
999
|
if not summary:
|
|
955
1000
|
try:
|
|
956
|
-
|
|
1001
|
+
PrettyOutput.auto_print(
|
|
1002
|
+
"⚠️ 总结模型返回空响应,已使用空字符串回退。"
|
|
1003
|
+
)
|
|
957
1004
|
except Exception:
|
|
958
1005
|
pass
|
|
959
1006
|
summary = ""
|
|
960
1007
|
return summary
|
|
961
1008
|
except Exception:
|
|
962
|
-
|
|
1009
|
+
PrettyOutput.auto_print("❌ 总结对话历史失败")
|
|
963
1010
|
return ""
|
|
964
1011
|
|
|
965
1012
|
def _summarize_and_clear_history(self) -> str:
|
|
@@ -994,18 +1041,62 @@ class Agent:
|
|
|
994
1041
|
# token限制触发的summary,使用SUMMARY_REQUEST_PROMPT
|
|
995
1042
|
summary = self.generate_summary(for_token_limit=True)
|
|
996
1043
|
|
|
1044
|
+
# 获取git diff信息
|
|
1045
|
+
git_diff_info = ""
|
|
1046
|
+
try:
|
|
1047
|
+
# 尝试从 AgentRunLoop 获取已缓存的 git diff
|
|
1048
|
+
from jarvis.jarvis_agent.run_loop import AgentRunLoop
|
|
1049
|
+
|
|
1050
|
+
if hasattr(self, "_agent_run_loop") and isinstance(
|
|
1051
|
+
self._agent_run_loop, AgentRunLoop
|
|
1052
|
+
):
|
|
1053
|
+
agent_run_loop = self._agent_run_loop
|
|
1054
|
+
else:
|
|
1055
|
+
# 创建临时 AgentRunLoop 实例来获取 git diff
|
|
1056
|
+
agent_run_loop = AgentRunLoop(self)
|
|
1057
|
+
|
|
1058
|
+
if agent_run_loop.has_git_diff():
|
|
1059
|
+
cached_diff = agent_run_loop.get_cached_git_diff()
|
|
1060
|
+
git_diff_info = cached_diff or ""
|
|
1061
|
+
else:
|
|
1062
|
+
# 如果还没有缓存,直接获取
|
|
1063
|
+
git_diff_info = agent_run_loop.get_git_diff()
|
|
1064
|
+
except Exception as e:
|
|
1065
|
+
git_diff_info = f"获取git diff失败: {str(e)}"
|
|
1066
|
+
|
|
997
1067
|
# 先获取格式化的摘要消息
|
|
998
1068
|
formatted_summary = ""
|
|
999
1069
|
if summary:
|
|
1000
1070
|
formatted_summary = self._format_summary_message(summary)
|
|
1001
1071
|
|
|
1072
|
+
# 添加git diff信息到摘要中 - 只显示有效的代码变更
|
|
1073
|
+
is_valid_git_diff = (
|
|
1074
|
+
git_diff_info
|
|
1075
|
+
and git_diff_info.strip()
|
|
1076
|
+
and
|
|
1077
|
+
# 过滤错误信息(获取失败等)
|
|
1078
|
+
not git_diff_info.startswith("获取git diff失败")
|
|
1079
|
+
and not git_diff_info.startswith("Failed to get git diff")
|
|
1080
|
+
and
|
|
1081
|
+
# 过滤无变更提示
|
|
1082
|
+
"没有检测到代码变更" not in git_diff_info
|
|
1083
|
+
and "No code changes detected" not in git_diff_info
|
|
1084
|
+
and
|
|
1085
|
+
# 确保包含实际代码变更(diff格式)
|
|
1086
|
+
"diff --git" in git_diff_info
|
|
1087
|
+
)
|
|
1088
|
+
|
|
1089
|
+
if is_valid_git_diff:
|
|
1090
|
+
diff_section = f"\n\n## 代码变更摘要\n```\n{git_diff_info}\n```"
|
|
1091
|
+
formatted_summary += diff_section
|
|
1092
|
+
|
|
1002
1093
|
# 关键流程:直接调用 memory_manager 确保记忆提示
|
|
1003
1094
|
try:
|
|
1004
1095
|
self.memory_manager._ensure_memory_prompt(agent=self)
|
|
1005
1096
|
except Exception:
|
|
1006
1097
|
pass
|
|
1007
|
-
|
|
1008
|
-
|
|
1098
|
+
|
|
1099
|
+
# 非关键流程:广播清理历史前事件(用于日志、监控等)
|
|
1009
1100
|
try:
|
|
1010
1101
|
self.event_bus.emit(BEFORE_HISTORY_CLEAR, agent=self)
|
|
1011
1102
|
except Exception:
|
|
@@ -1022,13 +1113,54 @@ class Agent:
|
|
|
1022
1113
|
self._addon_prompt_skip_rounds = 0
|
|
1023
1114
|
# 重置没有工具调用的计数器
|
|
1024
1115
|
self._no_tool_call_count = 0
|
|
1025
|
-
|
|
1116
|
+
|
|
1117
|
+
# 获取任务列表信息(用于历史记录)
|
|
1118
|
+
task_list_info = ""
|
|
1119
|
+
try:
|
|
1120
|
+
# 获取所有任务列表的摘要信息
|
|
1121
|
+
task_lists_summary: List[Dict[str, Any]] = []
|
|
1122
|
+
for task_list_id, task_list in self.task_list_manager.task_lists.items():
|
|
1123
|
+
summary_dict = self.task_list_manager.get_task_list_summary(
|
|
1124
|
+
task_list_id
|
|
1125
|
+
)
|
|
1126
|
+
if summary_dict and isinstance(summary_dict, dict):
|
|
1127
|
+
task_lists_summary.append(summary_dict)
|
|
1128
|
+
|
|
1129
|
+
if task_lists_summary:
|
|
1130
|
+
task_list_info = "\\n\\n## 任务列表状态\\n"
|
|
1131
|
+
for summary_dict in task_lists_summary:
|
|
1132
|
+
task_list_info += (
|
|
1133
|
+
f"\\n- 目标: {summary_dict.get('main_goal', '未知')}"
|
|
1134
|
+
)
|
|
1135
|
+
task_list_info += (
|
|
1136
|
+
f"\\n- 总任务数: {summary_dict.get('total_tasks', 0)}"
|
|
1137
|
+
)
|
|
1138
|
+
task_list_info += f"\\n- 待执行: {summary_dict.get('pending', 0)}"
|
|
1139
|
+
task_list_info += f"\\n- 执行中: {summary_dict.get('running', 0)}"
|
|
1140
|
+
task_list_info += f"\\n- 已完成: {summary_dict.get('completed', 0)}"
|
|
1141
|
+
task_list_info += f"\\n- 失败: {summary_dict.get('failed', 0)}"
|
|
1142
|
+
task_list_info += (
|
|
1143
|
+
f"\\n- 已放弃: {summary_dict.get('abandoned', 0)}\\n"
|
|
1144
|
+
)
|
|
1145
|
+
except Exception:
|
|
1146
|
+
# 非关键流程,失败时不影响主要功能
|
|
1147
|
+
pass
|
|
1148
|
+
|
|
1026
1149
|
# 非关键流程:广播清理历史后的事件(用于日志、监控等)
|
|
1027
1150
|
try:
|
|
1028
1151
|
self.event_bus.emit(AFTER_HISTORY_CLEAR, agent=self)
|
|
1029
1152
|
except Exception:
|
|
1030
1153
|
pass
|
|
1031
1154
|
|
|
1155
|
+
# 将任务列表信息添加到摘要中
|
|
1156
|
+
if task_list_info:
|
|
1157
|
+
formatted_summary += task_list_info
|
|
1158
|
+
|
|
1159
|
+
# 添加用户固定的重要内容
|
|
1160
|
+
if self.pin_content.strip():
|
|
1161
|
+
pin_section = f"\n\n## 用户的原始需求和要求\n{self.pin_content.strip()}"
|
|
1162
|
+
formatted_summary += pin_section
|
|
1163
|
+
|
|
1032
1164
|
return formatted_summary
|
|
1033
1165
|
|
|
1034
1166
|
def _handle_history_with_file_upload(self) -> str:
|
|
@@ -1038,19 +1170,43 @@ class Agent:
|
|
|
1038
1170
|
self.memory_manager._ensure_memory_prompt(agent=self)
|
|
1039
1171
|
except Exception:
|
|
1040
1172
|
pass
|
|
1041
|
-
|
|
1173
|
+
|
|
1042
1174
|
# 非关键流程:广播清理历史前事件(用于日志、监控等)
|
|
1043
1175
|
try:
|
|
1044
1176
|
self.event_bus.emit(BEFORE_HISTORY_CLEAR, agent=self)
|
|
1045
1177
|
except Exception:
|
|
1046
1178
|
pass
|
|
1047
|
-
|
|
1179
|
+
|
|
1048
1180
|
result = self.file_methodology_manager.handle_history_with_file_upload()
|
|
1049
1181
|
# 重置 addon_prompt 跳过轮数计数器
|
|
1050
1182
|
self._addon_prompt_skip_rounds = 0
|
|
1051
1183
|
# 重置没有工具调用的计数器
|
|
1052
1184
|
self._no_tool_call_count = 0
|
|
1053
|
-
|
|
1185
|
+
|
|
1186
|
+
# 添加系统约束提醒
|
|
1187
|
+
if result:
|
|
1188
|
+
constraint_reminder = """
|
|
1189
|
+
|
|
1190
|
+
**⚠️ 重要系统约束提醒(总结后必须严格遵守):**
|
|
1191
|
+
1. **每次只能执行一个工具调用**:每个响应必须包含且仅包含一个工具调用(任务完成时除外)。同时调用多个工具会导致错误。
|
|
1192
|
+
2. **禁止虚构结果**:所有操作必须基于实际执行结果,禁止推测、假设或虚构任何执行结果。必须等待工具执行完成并获得实际结果后再进行下一步。
|
|
1193
|
+
3. **等待工具结果**:在继续下一步之前,必须等待当前工具的执行结果,不能假设工具执行的结果。
|
|
1194
|
+
4. **基于实际验证**:所有结论必须基于实际执行结果和验证证据,禁止基于推测或假设。
|
|
1195
|
+
5. **代码任务完成标准(严格执行)**:
|
|
1196
|
+
- **编译/构建必须通过**:代码必须能够成功编译/构建,无编译错误、无语法错误、无链接错误
|
|
1197
|
+
- **功能必须验证**:功能必须经过实际运行验证,不能仅凭代码存在就认为完成
|
|
1198
|
+
- **错误必须修复**:如果存在编译错误、运行时错误、测试失败,任务必须标记为"部分完成"或"进行中",不能标记为"已完成"
|
|
1199
|
+
- **不能因为"代码已编写"就认为任务完成**:必须验证编译通过、功能正常运行、测试通过
|
|
1200
|
+
"""
|
|
1201
|
+
result += constraint_reminder
|
|
1202
|
+
|
|
1203
|
+
# 添加用户固定的重要内容
|
|
1204
|
+
if self.pin_content.strip():
|
|
1205
|
+
pin_section = (
|
|
1206
|
+
f"\n\n## 用户强调的任务目标和关键信息\n{self.pin_content.strip()}"
|
|
1207
|
+
)
|
|
1208
|
+
result += pin_section
|
|
1209
|
+
|
|
1054
1210
|
# 非关键流程:广播清理历史后的事件(用于日志、监控等)
|
|
1055
1211
|
try:
|
|
1056
1212
|
self.event_bus.emit(AFTER_HISTORY_CLEAR, agent=self)
|
|
@@ -1060,15 +1216,107 @@ class Agent:
|
|
|
1060
1216
|
|
|
1061
1217
|
def _format_summary_message(self, summary: str) -> str:
|
|
1062
1218
|
"""格式化摘要消息"""
|
|
1063
|
-
|
|
1219
|
+
# 获取任务列表信息
|
|
1220
|
+
task_list_info = self._get_task_list_info()
|
|
1221
|
+
|
|
1222
|
+
# 获取会话文件路径信息
|
|
1223
|
+
session_file_info = ""
|
|
1224
|
+
try:
|
|
1225
|
+
from jarvis.jarvis_utils.dialogue_recorder import get_global_recorder
|
|
1226
|
+
from pathlib import Path
|
|
1227
|
+
|
|
1228
|
+
recorder = get_global_recorder()
|
|
1229
|
+
session_file_path = recorder.get_session_file_path()
|
|
1230
|
+
if Path(session_file_path).exists():
|
|
1231
|
+
session_file_info = f"\n\n**📁 完整对话历史文件**:\n完整的对话历史已自动保存到以下文件,如果需要查看详细的历史信息,可以读取此文件:\n`{session_file_path}`\n\n此文件包含之前所有对话的完整记录(JSONL格式),每行一个消息记录,包括时间戳、角色和内容。"
|
|
1232
|
+
except Exception:
|
|
1233
|
+
# 非关键流程,失败时不影响主要功能
|
|
1234
|
+
pass
|
|
1235
|
+
|
|
1236
|
+
# 获取初始 commit 信息(仅对 CodeAgent)
|
|
1237
|
+
initial_commit_info = ""
|
|
1238
|
+
try:
|
|
1239
|
+
if hasattr(self, "start_commit") and self.start_commit:
|
|
1240
|
+
initial_commit_info = f"\n\n**🔖 初始 Git Commit(安全回退点)**:\n本次任务开始时的初始 commit 是:`{self.start_commit}`\n\n**⚠️ 重要提示**:如果文件被破坏得很严重无法恢复,可以使用以下命令重置到这个初始 commit:\n```bash\ngit reset --hard {self.start_commit}\n```\n这将丢弃所有未提交的更改,将工作区恢复到任务开始时的状态。请谨慎使用此命令,确保这是你真正想要的操作。"
|
|
1241
|
+
except Exception:
|
|
1242
|
+
# 非关键流程,失败时不影响主要功能
|
|
1243
|
+
pass
|
|
1244
|
+
|
|
1245
|
+
formatted_message = f"""
|
|
1064
1246
|
以下是之前对话的关键信息总结:
|
|
1065
1247
|
|
|
1066
1248
|
<content>
|
|
1067
1249
|
{summary}
|
|
1068
1250
|
</content>
|
|
1069
1251
|
|
|
1070
|
-
|
|
1252
|
+
**⚠️ 重要系统约束提醒(总结后必须严格遵守):**
|
|
1253
|
+
1. **每次只能执行一个工具调用**:每个响应必须包含且仅包含一个工具调用(任务完成时除外)。同时调用多个工具会导致错误。
|
|
1254
|
+
2. **禁止虚构结果**:所有操作必须基于实际执行结果,禁止推测、假设或虚构任何执行结果。必须等待工具执行完成并获得实际结果后再进行下一步。
|
|
1255
|
+
3. **等待工具结果**:在继续下一步之前,必须等待当前工具的执行结果,不能假设工具执行的结果。
|
|
1256
|
+
4. **基于实际验证**:所有结论必须基于实际执行结果和验证证据,禁止基于推测或假设。
|
|
1257
|
+
5. **代码任务完成标准(严格执行)**:
|
|
1258
|
+
- **编译/构建必须通过**:代码必须能够成功编译/构建,无编译错误、无语法错误、无链接错误
|
|
1259
|
+
- **功能必须验证**:功能必须经过实际运行验证,不能仅凭代码存在就认为完成
|
|
1260
|
+
- **错误必须修复**:如果存在编译错误、运行时错误、测试失败,任务必须标记为"部分完成"或"进行中",不能标记为"已完成"
|
|
1261
|
+
- **不能因为"代码已编写"就认为任务完成**:必须验证编译通过、功能正常运行、测试通过
|
|
1262
|
+
|
|
1263
|
+
请基于以上信息继续完成任务。请注意,这是之前对话的摘要,上下文长度已超过限制而被重置。请直接继续任务,无需重复已完成的步骤。如有需要,可以询问用户以获取更多信息。{session_file_info}{initial_commit_info}
|
|
1264
|
+
"""
|
|
1265
|
+
|
|
1266
|
+
# 如果有任务列表信息,添加到消息后面
|
|
1267
|
+
if task_list_info:
|
|
1268
|
+
formatted_message += f"\n\n{task_list_info}"
|
|
1269
|
+
|
|
1270
|
+
return formatted_message
|
|
1271
|
+
|
|
1272
|
+
def _get_task_list_info(self) -> str:
|
|
1273
|
+
"""获取并格式化当前任务列表信息
|
|
1274
|
+
|
|
1275
|
+
返回:
|
|
1276
|
+
str: 格式化的任务列表信息,如果没有任务列表则返回空字符串
|
|
1071
1277
|
"""
|
|
1278
|
+
try:
|
|
1279
|
+
# 使用当前Agent的任务列表管理器获取所有任务列表信息
|
|
1280
|
+
if (
|
|
1281
|
+
not hasattr(self, "task_list_manager")
|
|
1282
|
+
or not self.task_list_manager.task_lists
|
|
1283
|
+
):
|
|
1284
|
+
return ""
|
|
1285
|
+
|
|
1286
|
+
all_task_lists_info = []
|
|
1287
|
+
|
|
1288
|
+
# 遍历所有任务列表
|
|
1289
|
+
for task_list_id, task_list in self.task_list_manager.task_lists.items():
|
|
1290
|
+
summary = self.task_list_manager.get_task_list_summary(task_list_id)
|
|
1291
|
+
if not summary:
|
|
1292
|
+
continue
|
|
1293
|
+
|
|
1294
|
+
# 构建任务列表摘要信息
|
|
1295
|
+
info_parts = []
|
|
1296
|
+
info_parts.append(f"📋 任务列表: {summary['main_goal']}")
|
|
1297
|
+
info_parts.append(
|
|
1298
|
+
f" 总任务: {summary['total_tasks']} | 待执行: {summary['pending']} | 执行中: {summary['running']} | 已完成: {summary['completed']}"
|
|
1299
|
+
)
|
|
1300
|
+
|
|
1301
|
+
# 如果有失败或放弃的任务,也显示
|
|
1302
|
+
if summary["failed"] > 0 or summary["abandoned"] > 0:
|
|
1303
|
+
status_parts = []
|
|
1304
|
+
if summary["failed"] > 0:
|
|
1305
|
+
status_parts.append(f"失败: {summary['failed']}")
|
|
1306
|
+
if summary["abandoned"] > 0:
|
|
1307
|
+
status_parts.append(f"放弃: {summary['abandoned']}")
|
|
1308
|
+
info_parts[-1] += f" | {' | '.join(status_parts)}"
|
|
1309
|
+
|
|
1310
|
+
all_task_lists_info.append("\n".join(info_parts))
|
|
1311
|
+
|
|
1312
|
+
if not all_task_lists_info:
|
|
1313
|
+
return ""
|
|
1314
|
+
|
|
1315
|
+
return "\n\n".join(all_task_lists_info)
|
|
1316
|
+
|
|
1317
|
+
except Exception:
|
|
1318
|
+
# 静默失败,不干扰主流程
|
|
1319
|
+
return ""
|
|
1072
1320
|
|
|
1073
1321
|
def _call_tools(self, response: str) -> Tuple[bool, Any]:
|
|
1074
1322
|
"""
|
|
@@ -1098,13 +1346,15 @@ class Agent:
|
|
|
1098
1346
|
result = "任务完成"
|
|
1099
1347
|
|
|
1100
1348
|
if self.need_summary:
|
|
1101
|
-
|
|
1102
1349
|
# 确保总结提示词非空:若为None或仅空白,则回退到默认提示词
|
|
1103
1350
|
safe_summary_prompt = self.summary_prompt or ""
|
|
1104
|
-
if
|
|
1351
|
+
if (
|
|
1352
|
+
isinstance(safe_summary_prompt, str)
|
|
1353
|
+
and safe_summary_prompt.strip() == ""
|
|
1354
|
+
):
|
|
1105
1355
|
safe_summary_prompt = DEFAULT_SUMMARY_PROMPT
|
|
1106
1356
|
# 注意:不要写回 session.prompt,避免回调修改/清空后导致使用空prompt
|
|
1107
|
-
|
|
1357
|
+
|
|
1108
1358
|
# 关键流程:直接调用 task_analyzer 执行任务分析
|
|
1109
1359
|
try:
|
|
1110
1360
|
self.task_analyzer._on_before_summary(
|
|
@@ -1115,7 +1365,7 @@ class Agent:
|
|
|
1115
1365
|
)
|
|
1116
1366
|
except Exception:
|
|
1117
1367
|
pass
|
|
1118
|
-
|
|
1368
|
+
|
|
1119
1369
|
# 非关键流程:广播将要生成总结事件(用于日志、监控等)
|
|
1120
1370
|
try:
|
|
1121
1371
|
self.event_bus.emit(
|
|
@@ -1131,16 +1381,39 @@ class Agent:
|
|
|
1131
1381
|
if not self.model:
|
|
1132
1382
|
raise RuntimeError("Model not initialized")
|
|
1133
1383
|
# 直接使用本地变量,避免受事件回调影响
|
|
1134
|
-
ret = self.model.chat_until_success(safe_summary_prompt)
|
|
1384
|
+
ret = self.model.chat_until_success(safe_summary_prompt)
|
|
1135
1385
|
# 防御: 总结阶段模型可能返回空响应(None或空字符串),统一为空字符串并告警
|
|
1136
1386
|
if not ret:
|
|
1137
1387
|
try:
|
|
1138
|
-
|
|
1388
|
+
PrettyOutput.auto_print(
|
|
1389
|
+
"⚠️ 总结阶段模型返回空响应,已使用空字符串回退。"
|
|
1390
|
+
)
|
|
1139
1391
|
except Exception:
|
|
1140
1392
|
pass
|
|
1141
1393
|
ret = ""
|
|
1142
1394
|
result = ret
|
|
1143
1395
|
|
|
1396
|
+
# 打印任务总结内容给用户查看
|
|
1397
|
+
if ret and ret.strip():
|
|
1398
|
+
try:
|
|
1399
|
+
import jarvis.jarvis_utils.globals as G
|
|
1400
|
+
from jarvis.jarvis_utils.globals import console
|
|
1401
|
+
from rich.panel import Panel
|
|
1402
|
+
from rich import box
|
|
1403
|
+
|
|
1404
|
+
agent_name = self.name if hasattr(self, "name") else None
|
|
1405
|
+
panel = Panel(
|
|
1406
|
+
ret,
|
|
1407
|
+
title=f"[bold cyan]{(G.get_current_agent_name() + ' · ') if G.get_current_agent_name() else ''}{agent_name or 'LLM'} 任务总结[/bold cyan]",
|
|
1408
|
+
border_style="bright_green",
|
|
1409
|
+
box=box.ROUNDED,
|
|
1410
|
+
expand=True,
|
|
1411
|
+
)
|
|
1412
|
+
console.print(panel)
|
|
1413
|
+
except Exception:
|
|
1414
|
+
# 如果格式化输出失败,回退到简单打印
|
|
1415
|
+
PrettyOutput.auto_print(f"📋 任务总结:\n{ret}")
|
|
1416
|
+
|
|
1144
1417
|
# 非关键流程:广播完成总结事件(用于日志、监控等)
|
|
1145
1418
|
try:
|
|
1146
1419
|
self.event_bus.emit(
|
|
@@ -1160,7 +1433,7 @@ class Agent:
|
|
|
1160
1433
|
)
|
|
1161
1434
|
except Exception:
|
|
1162
1435
|
pass
|
|
1163
|
-
|
|
1436
|
+
|
|
1164
1437
|
try:
|
|
1165
1438
|
self.memory_manager._ensure_memory_prompt(
|
|
1166
1439
|
agent=self,
|
|
@@ -1169,7 +1442,7 @@ class Agent:
|
|
|
1169
1442
|
)
|
|
1170
1443
|
except Exception:
|
|
1171
1444
|
pass
|
|
1172
|
-
|
|
1445
|
+
|
|
1173
1446
|
# 非关键流程:广播任务完成事件(用于日志、监控等)
|
|
1174
1447
|
try:
|
|
1175
1448
|
self.event_bus.emit(
|
|
@@ -1201,7 +1474,7 @@ class Agent:
|
|
|
1201
1474
|
|
|
1202
1475
|
# 任务完成提示
|
|
1203
1476
|
complete_prompt = (
|
|
1204
|
-
f"-
|
|
1477
|
+
f"- 如果任务已完成,只输出 {ot('!!!COMPLETE!!!')},不要输出其他任何内容。任务总结将会在后面的交互中被询问。"
|
|
1205
1478
|
if need_complete and self.auto_complete
|
|
1206
1479
|
else ""
|
|
1207
1480
|
)
|
|
@@ -1215,15 +1488,15 @@ class Agent:
|
|
|
1215
1488
|
addon_prompt = f"""
|
|
1216
1489
|
<system_prompt>
|
|
1217
1490
|
请判断是否已经完成任务,如果已经完成:
|
|
1218
|
-
- 直接输出完成原因,不需要再有新的操作,不要输出{ot(
|
|
1219
|
-
{complete_prompt}
|
|
1491
|
+
{complete_prompt if complete_prompt else f"- 直接输出完成原因,不需要再有新的操作,不要输出{ot('TOOL_CALL')}标签"}
|
|
1220
1492
|
如果没有完成,请进行下一步操作:
|
|
1221
1493
|
- 仅包含一个操作
|
|
1222
1494
|
- 如果信息不明确,请请求用户补充
|
|
1223
1495
|
- 如果执行过程中连续失败5次,请请求用户操作
|
|
1496
|
+
- 工具调用必须使用{ot("TOOL_CALL")}和{ct("TOOL_CALL")}标签
|
|
1224
1497
|
- 操作列表:{action_handlers}{memory_prompts}
|
|
1225
1498
|
|
|
1226
|
-
|
|
1499
|
+
注意:如果当前部分任务已完成,之前的上下文价值不大,可以输出{ot("!!!SUMMARY!!!")}标记来触发总结并清空历史,以便开始新的任务阶段。
|
|
1227
1500
|
</system_prompt>
|
|
1228
1501
|
|
|
1229
1502
|
请继续。
|
|
@@ -1246,10 +1519,31 @@ class Agent:
|
|
|
1246
1519
|
3. 包含错误处理和恢复逻辑
|
|
1247
1520
|
4. 自动加载相关方法论(如果是首次运行)
|
|
1248
1521
|
"""
|
|
1249
|
-
|
|
1522
|
+
# 根据当前模式生成额外说明,供 LLM 感知执行策略
|
|
1250
1523
|
try:
|
|
1251
|
-
|
|
1252
|
-
|
|
1524
|
+
# 延迟导入CodeAgent以避免循环依赖
|
|
1525
|
+
from jarvis.jarvis_code_agent.code_agent import CodeAgent
|
|
1526
|
+
|
|
1527
|
+
# 如果是CodeAgent实例,则跳过注册,由CodeAgent.run自行管理
|
|
1528
|
+
if not isinstance(self, CodeAgent):
|
|
1529
|
+
set_current_agent(self.name, self) # 标记agent开始运行
|
|
1530
|
+
non_interactive_note = ""
|
|
1531
|
+
if getattr(self, "non_interactive", False):
|
|
1532
|
+
non_interactive_note = (
|
|
1533
|
+
"\n\n[系统说明]\n"
|
|
1534
|
+
"本次会话处于**非交互模式**:\n"
|
|
1535
|
+
"- 在 PLAN 模式中给出清晰、可执行的详细计划后,应**自动进入 EXECUTE 模式执行计划**,不要等待用户额外确认;\n"
|
|
1536
|
+
"- 在 EXECUTE 模式中,保持一步一步的小步提交和可回退策略,但不需要向用户反复询问“是否继续”;\n"
|
|
1537
|
+
"- 如遇信息严重不足,可以在 RESEARCH 模式中自行补充必要分析,而不是卡在等待用户输入。\n"
|
|
1538
|
+
)
|
|
1539
|
+
|
|
1540
|
+
# 如果是非交互模式,可以假设用户输入的是完整的需求
|
|
1541
|
+
self.pin_content = user_input
|
|
1542
|
+
|
|
1543
|
+
# 将非交互模式说明添加到用户输入中
|
|
1544
|
+
enhanced_input = user_input + non_interactive_note
|
|
1545
|
+
self.session.prompt = enhanced_input
|
|
1546
|
+
|
|
1253
1547
|
# 关键流程:直接调用 memory_manager 重置任务状态
|
|
1254
1548
|
try:
|
|
1255
1549
|
self.memory_manager._on_task_started(
|
|
@@ -1260,7 +1554,7 @@ class Agent:
|
|
|
1260
1554
|
)
|
|
1261
1555
|
except Exception:
|
|
1262
1556
|
pass
|
|
1263
|
-
|
|
1557
|
+
|
|
1264
1558
|
# 非关键流程:广播任务开始事件(用于日志、监控等)
|
|
1265
1559
|
try:
|
|
1266
1560
|
self.event_bus.emit(
|
|
@@ -1272,18 +1566,48 @@ class Agent:
|
|
|
1272
1566
|
)
|
|
1273
1567
|
except Exception:
|
|
1274
1568
|
pass
|
|
1569
|
+
|
|
1275
1570
|
return self._main_loop()
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1571
|
+
|
|
1572
|
+
finally:
|
|
1573
|
+
if not isinstance(self, CodeAgent):
|
|
1574
|
+
clear_current_agent()
|
|
1279
1575
|
|
|
1280
1576
|
def _main_loop(self) -> Any:
|
|
1281
1577
|
"""主运行循环"""
|
|
1282
1578
|
# 委派至独立的运行循环类,保持行为一致
|
|
1283
1579
|
loop = AgentRunLoop(self)
|
|
1580
|
+
self._agent_run_loop = loop # 存储引用以便其他方法访问
|
|
1284
1581
|
return loop.run()
|
|
1285
1582
|
|
|
1286
|
-
def
|
|
1583
|
+
def set_non_interactive(self, value: bool) -> None:
|
|
1584
|
+
"""设置非交互模式并管理自动完成状态。
|
|
1585
|
+
|
|
1586
|
+
当进入非交互模式时,自动启用自动完成;
|
|
1587
|
+
当退出非交互模式时,恢复自动完成的原始值。
|
|
1588
|
+
|
|
1589
|
+
参数:
|
|
1590
|
+
value: 是否启用非交互模式
|
|
1591
|
+
"""
|
|
1592
|
+
# 保存auto_complete的原始值(如果是首次设置)
|
|
1593
|
+
if not hasattr(self, "_auto_complete_backup"):
|
|
1594
|
+
self._auto_complete_backup = self.auto_complete
|
|
1595
|
+
|
|
1596
|
+
# 设置非交互模式(仅作为 Agent 实例属性,不写入环境变量或全局配置)
|
|
1597
|
+
self.non_interactive = value
|
|
1598
|
+
|
|
1599
|
+
# 根据non_interactive的值调整auto_complete
|
|
1600
|
+
if value: # 进入非交互模式
|
|
1601
|
+
self.auto_complete = True
|
|
1602
|
+
else: # 退出非交互模式
|
|
1603
|
+
# 恢复auto_complete的原始值
|
|
1604
|
+
self.auto_complete = self._auto_complete_backup
|
|
1605
|
+
# 清理备份,避免状态污染
|
|
1606
|
+
delattr(self, "_auto_complete_backup")
|
|
1607
|
+
|
|
1608
|
+
def _handle_run_interrupt(
|
|
1609
|
+
self, current_response: str
|
|
1610
|
+
) -> Optional[Union[Any, "LoopAction"]]:
|
|
1287
1611
|
"""处理运行中的中断
|
|
1288
1612
|
|
|
1289
1613
|
返回:
|
|
@@ -1295,6 +1619,11 @@ class Agent:
|
|
|
1295
1619
|
return None
|
|
1296
1620
|
|
|
1297
1621
|
set_interrupt(False)
|
|
1622
|
+
|
|
1623
|
+
# 被中断时,如果当前是非交互模式,立即切换到交互模式(在获取用户输入前)
|
|
1624
|
+
if self.non_interactive:
|
|
1625
|
+
self.set_non_interactive(False)
|
|
1626
|
+
|
|
1298
1627
|
user_input = self._multiline_input(
|
|
1299
1628
|
"模型交互期间被中断,请输入用户干预信息:", False
|
|
1300
1629
|
)
|
|
@@ -1316,17 +1645,21 @@ class Agent:
|
|
|
1316
1645
|
return self._complete_task(auto_completed=False)
|
|
1317
1646
|
|
|
1318
1647
|
if any(handler.can_handle(current_response) for handler in self.output_handler):
|
|
1319
|
-
if self.confirm_callback("检测到有工具调用,是否继续处理工具调用?",
|
|
1320
|
-
self.session.prompt = join_prompts(
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1648
|
+
if self.confirm_callback("检测到有工具调用,是否继续处理工具调用?", False):
|
|
1649
|
+
self.session.prompt = join_prompts(
|
|
1650
|
+
[
|
|
1651
|
+
f"被用户中断,用户补充信息为:{user_input}",
|
|
1652
|
+
"用户同意继续工具调用。",
|
|
1653
|
+
]
|
|
1654
|
+
)
|
|
1324
1655
|
return None # 继续执行工具调用
|
|
1325
1656
|
else:
|
|
1326
|
-
self.session.prompt = join_prompts(
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1657
|
+
self.session.prompt = join_prompts(
|
|
1658
|
+
[
|
|
1659
|
+
f"被用户中断,用户补充信息为:{user_input}",
|
|
1660
|
+
"检测到有工具调用,但被用户拒绝执行。请根据用户的补充信息重新考虑下一步操作。",
|
|
1661
|
+
]
|
|
1662
|
+
)
|
|
1330
1663
|
return LoopAction.SKIP_TURN # 请求主循环 continue
|
|
1331
1664
|
else:
|
|
1332
1665
|
self.session.prompt = f"被用户中断,用户补充信息为:{user_input}"
|
|
@@ -1345,9 +1678,9 @@ class Agent:
|
|
|
1345
1678
|
if user_input:
|
|
1346
1679
|
self.session.prompt = user_input
|
|
1347
1680
|
# 使用显式动作信号,保留返回类型注释以保持兼容
|
|
1348
|
-
return LoopAction.CONTINUE
|
|
1681
|
+
return LoopAction.CONTINUE
|
|
1349
1682
|
else:
|
|
1350
|
-
return LoopAction.COMPLETE
|
|
1683
|
+
return LoopAction.COMPLETE
|
|
1351
1684
|
|
|
1352
1685
|
def _first_run(self):
|
|
1353
1686
|
"""首次运行初始化"""
|
|
@@ -1368,14 +1701,22 @@ class Agent:
|
|
|
1368
1701
|
self.first = False
|
|
1369
1702
|
|
|
1370
1703
|
def _create_temp_model(self, system_prompt: str) -> BasePlatform:
|
|
1371
|
-
"""创建一个用于执行一次性任务的临时模型实例,以避免污染主会话。
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1704
|
+
"""创建一个用于执行一次性任务的临时模型实例,以避免污染主会话。
|
|
1705
|
+
|
|
1706
|
+
筛选操作使用cheap模型以降低成本。
|
|
1707
|
+
"""
|
|
1708
|
+
from jarvis.jarvis_utils.config import get_cheap_model_name
|
|
1709
|
+
from jarvis.jarvis_utils.config import get_cheap_platform_name
|
|
1710
|
+
|
|
1711
|
+
# 筛选操作使用cheap模型
|
|
1712
|
+
platform_name = get_cheap_platform_name(None)
|
|
1713
|
+
model_name = get_cheap_model_name(None)
|
|
1714
|
+
|
|
1715
|
+
temp_model = PlatformRegistry().create_platform(platform_name)
|
|
1375
1716
|
if not temp_model:
|
|
1376
1717
|
raise RuntimeError("创建临时模型失败。")
|
|
1377
1718
|
|
|
1378
|
-
temp_model.set_model_name(
|
|
1719
|
+
temp_model.set_model_name(model_name)
|
|
1379
1720
|
temp_model.set_system_prompt(system_prompt)
|
|
1380
1721
|
return temp_model
|
|
1381
1722
|
|
|
@@ -1412,7 +1753,7 @@ class Agent:
|
|
|
1412
1753
|
|
|
1413
1754
|
def _filter_tools_if_needed(self, task: str):
|
|
1414
1755
|
"""如果工具数量超过阈值,使用大模型筛选相关工具
|
|
1415
|
-
|
|
1756
|
+
|
|
1416
1757
|
注意:仅筛选用户自定义工具,内置工具不参与筛选(始终保留)
|
|
1417
1758
|
"""
|
|
1418
1759
|
tool_registry = self.get_tool_registry()
|
|
@@ -1451,7 +1792,9 @@ class Agent:
|
|
|
1451
1792
|
请根据用户任务,从列表中选择最相关的工具。
|
|
1452
1793
|
请仅返回所选工具的编号,以逗号分隔。例如:1, 5, 12
|
|
1453
1794
|
"""
|
|
1454
|
-
|
|
1795
|
+
PrettyOutput.auto_print(
|
|
1796
|
+
f"ℹ️ 工具数量超过{threshold}个,正在使用AI筛选相关工具..."
|
|
1797
|
+
)
|
|
1455
1798
|
# 广播工具筛选开始事件
|
|
1456
1799
|
try:
|
|
1457
1800
|
self.event_bus.emit(
|
|
@@ -1467,18 +1810,14 @@ class Agent:
|
|
|
1467
1810
|
# 使用临时模型实例调用模型,以避免污染历史记录
|
|
1468
1811
|
try:
|
|
1469
1812
|
temp_model = self._create_temp_model("你是一个帮助筛选工具的助手。")
|
|
1470
|
-
selected_tools_str = temp_model.chat_until_success(
|
|
1471
|
-
selection_prompt
|
|
1472
|
-
) # type: ignore
|
|
1813
|
+
selected_tools_str = temp_model.chat_until_success(selection_prompt)
|
|
1473
1814
|
|
|
1474
1815
|
# 解析响应并筛选工具
|
|
1475
1816
|
selected_indices = [
|
|
1476
1817
|
int(i.strip()) for i in re.findall(r"\d+", selected_tools_str)
|
|
1477
1818
|
]
|
|
1478
1819
|
selected_tool_names = [
|
|
1479
|
-
tool_names[i - 1]
|
|
1480
|
-
for i in selected_indices
|
|
1481
|
-
if 0 < i <= len(tool_names)
|
|
1820
|
+
tool_names[i - 1] for i in selected_indices if 0 < i <= len(tool_names)
|
|
1482
1821
|
]
|
|
1483
1822
|
|
|
1484
1823
|
if selected_tool_names:
|
|
@@ -1486,11 +1825,15 @@ class Agent:
|
|
|
1486
1825
|
selected_tool_names = sorted(list(set(selected_tool_names)))
|
|
1487
1826
|
# 合并内置工具名称和筛选出的用户自定义工具名称
|
|
1488
1827
|
builtin_names = list(tool_registry._builtin_tool_names)
|
|
1489
|
-
final_tool_names = sorted(
|
|
1828
|
+
final_tool_names = sorted(
|
|
1829
|
+
list(set(builtin_names + selected_tool_names))
|
|
1830
|
+
)
|
|
1490
1831
|
tool_registry.use_tools(final_tool_names)
|
|
1491
1832
|
# 使用筛选后的工具列表重新设置系统提示
|
|
1492
1833
|
self._setup_system_prompt()
|
|
1493
|
-
|
|
1834
|
+
PrettyOutput.auto_print(
|
|
1835
|
+
f"✅ 已筛选出 {len(selected_tool_names)} 个相关工具: {', '.join(selected_tool_names)}"
|
|
1836
|
+
)
|
|
1494
1837
|
# 广播工具筛选事件
|
|
1495
1838
|
try:
|
|
1496
1839
|
self.event_bus.emit(
|
|
@@ -1504,7 +1847,7 @@ class Agent:
|
|
|
1504
1847
|
except Exception:
|
|
1505
1848
|
pass
|
|
1506
1849
|
else:
|
|
1507
|
-
|
|
1850
|
+
PrettyOutput.auto_print("⚠️ AI 未能筛选出任何相关工具,将使用所有工具。")
|
|
1508
1851
|
# 广播工具筛选事件(无筛选结果)
|
|
1509
1852
|
try:
|
|
1510
1853
|
self.event_bus.emit(
|
|
@@ -1519,7 +1862,7 @@ class Agent:
|
|
|
1519
1862
|
pass
|
|
1520
1863
|
|
|
1521
1864
|
except Exception as e:
|
|
1522
|
-
|
|
1865
|
+
PrettyOutput.auto_print(f"❌ 工具筛选失败: {e},将使用所有工具。")
|
|
1523
1866
|
|
|
1524
1867
|
def _check_and_organize_memory(self):
|
|
1525
1868
|
"""
|
|
@@ -1536,7 +1879,7 @@ class Agent:
|
|
|
1536
1879
|
"global",
|
|
1537
1880
|
)
|
|
1538
1881
|
except Exception as e:
|
|
1539
|
-
|
|
1882
|
+
PrettyOutput.auto_print(f"⚠️ 检查记忆库时发生意外错误: {e}")
|
|
1540
1883
|
|
|
1541
1884
|
def _perform_memory_check(self, memory_type: str, base_path: Path, scope_name: str):
|
|
1542
1885
|
"""执行特定范围的记忆检查和整理"""
|
|
@@ -1578,7 +1921,9 @@ class Agent:
|
|
|
1578
1921
|
f"是否立即整理记忆库以优化性能和相关性?"
|
|
1579
1922
|
)
|
|
1580
1923
|
if self.confirm_callback(prompt, False):
|
|
1581
|
-
|
|
1924
|
+
PrettyOutput.auto_print(
|
|
1925
|
+
f"ℹ️ 正在开始整理 '{scope_name}' ({memory_type}) 记忆库..."
|
|
1926
|
+
)
|
|
1582
1927
|
organizer.organize_memories(memory_type, min_overlap=3)
|
|
1583
1928
|
else:
|
|
1584
|
-
|
|
1929
|
+
PrettyOutput.auto_print(f"ℹ️ 已取消 '{scope_name}' 记忆库整理。")
|