jarvis-ai-assistant 0.4.1__tar.gz → 0.5.0__tar.gz
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_ai_assistant-0.4.1/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.5.0}/PKG-INFO +1 -1
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/pyproject.toml +1 -1
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/setup.py +1 -1
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/__init__.py +1 -1
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/__init__.py +79 -73
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/run_loop.py +18 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/share_manager.py +8 -1
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_agent/code_agent.py +91 -2
- jarvis_ai_assistant-0.5.0/src/jarvis/jarvis_code_analysis/code_review.py +845 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_data/config_schema.json +7 -2
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_multi_agent/__init__.py +24 -11
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/registry.py +26 -14
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/sub_agent.py +9 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/config.py +16 -11
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/input.py +77 -6
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/methodology.py +25 -19
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/utils.py +58 -2
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +0 -1
- jarvis_ai_assistant-0.4.1/src/jarvis/jarvis_agent/config.py +0 -100
- jarvis_ai_assistant-0.4.1/src/jarvis/jarvis_code_analysis/code_review.py +0 -930
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/LICENSE +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/MANIFEST.in +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/README.md +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/setup.cfg +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/agent_manager.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/builtin_input_handler.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/config_editor.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/edit_file_handler.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/event_bus.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/events.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/file_context_handler.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/file_methodology_manager.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/jarvis.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/main.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/memory_manager.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/methodology_share_manager.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/output_handler.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/prompt_builder.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/prompt_manager.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/prompts.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/protocols.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/rewrite_file_handler.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/session_manager.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/shell_input_handler.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/stdio_redirect.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/task_analyzer.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/task_manager.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/tool_executor.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/tool_share_manager.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/user_interaction.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/utils.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/web_bridge.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/web_output_sink.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/web_server.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_agent/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_agent/lint.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/c_cpp.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/csharp.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/data_format.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/devops.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/docs.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/go.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/infrastructure.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/java.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/javascript.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/kotlin.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/loader.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/php.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/python.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/ruby.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/rust.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/shell.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/sql.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/swift.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_analysis/checklists/web.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_data/tiktoken/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_git_squash/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_git_squash/main.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_git_utils/git_commiter.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_mcp/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_mcp/sse_mcp_client.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_mcp/stdio_mcp_client.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_mcp/streamable_mcp_client.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_memory_organizer/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_memory_organizer/memory_organizer.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_methodology/main.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_multi_agent/main.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform/ai8.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform/base.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform/human.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform/kimi.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform/openai.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform/registry.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform/tongyi.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform/yuanbao.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform_manager/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform_manager/main.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_platform_manager/service.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_rag/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_rag/cache.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_rag/cli.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_rag/embedding_manager.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_rag/llm_interface.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_rag/query_rewriter.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_rag/rag_pipeline.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_rag/reranker.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_rag/retriever.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_smart_shell/main.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_stats/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_stats/cli.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_stats/stats.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_stats/storage.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_stats/visualizer.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/ask_user.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/base.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/clear_memory.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/cli/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/cli/main.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/execute_script.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/file_analyzer.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/generate_new_tool.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/methodology.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/read_code.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/read_webpage.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/retrieve_memory.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/save_memory.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/search_web.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/sub_code_agent.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_tools/virtual_tty.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/__init__.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/builtin_replace_map.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/clipboard.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/embedding.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/file_processors.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/fzf.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/git_utils.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/globals.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/http.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/output.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_utils/tag.py +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis_ai_assistant.egg-info/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
- {jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "jarvis-ai-assistant"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.5.0"
|
|
8
8
|
description = "Jarvis: An AI assistant that uses tools to interact with the system"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "skyfire", email = "skyfireitdiy@hotmail.com" }]
|
|
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages # type: ignore
|
|
|
3
3
|
|
|
4
4
|
setup(
|
|
5
5
|
name="jarvis-ai-assistant",
|
|
6
|
-
version="0.
|
|
6
|
+
version="0.5.0",
|
|
7
7
|
author="skyfire",
|
|
8
8
|
author_email="skyfireitdiy@hotmail.com",
|
|
9
9
|
description="An AI assistant that uses various tools to interact with the system",
|
|
@@ -9,6 +9,7 @@ from pathlib import Path
|
|
|
9
9
|
from enum import Enum
|
|
10
10
|
from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
|
|
11
11
|
|
|
12
|
+
|
|
12
13
|
# 第三方库导入
|
|
13
14
|
from rich.align import Align
|
|
14
15
|
from rich.console import Console
|
|
@@ -35,7 +36,6 @@ from jarvis.jarvis_agent.edit_file_handler import EditFileHandler
|
|
|
35
36
|
from jarvis.jarvis_agent.rewrite_file_handler import RewriteFileHandler
|
|
36
37
|
from jarvis.jarvis_agent.prompt_manager import PromptManager
|
|
37
38
|
from jarvis.jarvis_agent.event_bus import EventBus
|
|
38
|
-
from jarvis.jarvis_agent.config import AgentConfig
|
|
39
39
|
from jarvis.jarvis_agent.run_loop import AgentRunLoop
|
|
40
40
|
from jarvis.jarvis_agent.events import (
|
|
41
41
|
BEFORE_SUMMARY,
|
|
@@ -67,7 +67,6 @@ from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
|
67
67
|
# jarvis_utils 相关
|
|
68
68
|
from jarvis.jarvis_utils.config import (
|
|
69
69
|
get_data_dir,
|
|
70
|
-
get_max_token_count,
|
|
71
70
|
get_normal_model_name,
|
|
72
71
|
get_normal_platform_name,
|
|
73
72
|
is_execute_tool_confirm,
|
|
@@ -76,7 +75,8 @@ from jarvis.jarvis_utils.config import (
|
|
|
76
75
|
is_use_methodology,
|
|
77
76
|
get_tool_filter_threshold,
|
|
78
77
|
get_after_tool_call_cb_dirs,
|
|
79
|
-
|
|
78
|
+
|
|
79
|
+
|
|
80
80
|
)
|
|
81
81
|
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
82
82
|
from jarvis.jarvis_utils.globals import (
|
|
@@ -249,8 +249,23 @@ class Agent:
|
|
|
249
249
|
def clear_history(self):
|
|
250
250
|
"""
|
|
251
251
|
Clears the current conversation history by delegating to the session manager.
|
|
252
|
+
Emits BEFORE_HISTORY_CLEAR/AFTER_HISTORY_CLEAR and reapplies system prompt to preserve constraints.
|
|
252
253
|
"""
|
|
254
|
+
# 广播清理历史前事件(不影响主流程)
|
|
255
|
+
try:
|
|
256
|
+
self.event_bus.emit(BEFORE_HISTORY_CLEAR, agent=self)
|
|
257
|
+
except Exception:
|
|
258
|
+
pass
|
|
259
|
+
|
|
260
|
+
# 清理会话历史并重置模型状态
|
|
253
261
|
self.session.clear_history()
|
|
262
|
+
|
|
263
|
+
# 重置后重新设置系统提示词,确保系统约束仍然生效
|
|
264
|
+
try:
|
|
265
|
+
self._setup_system_prompt()
|
|
266
|
+
except Exception:
|
|
267
|
+
pass
|
|
268
|
+
|
|
254
269
|
# 广播清理历史后的事件
|
|
255
270
|
try:
|
|
256
271
|
self.event_bus.emit(AFTER_HISTORY_CLEAR, agent=self)
|
|
@@ -282,6 +297,7 @@ class Agent:
|
|
|
282
297
|
use_tools: Optional[List[str]] = None,
|
|
283
298
|
execute_tool_confirm: Optional[bool] = None,
|
|
284
299
|
need_summary: bool = True,
|
|
300
|
+
auto_summary_rounds: Optional[int] = None,
|
|
285
301
|
multiline_inputer: Optional[Callable[[str], str]] = None,
|
|
286
302
|
use_methodology: Optional[bool] = None,
|
|
287
303
|
use_analysis: Optional[bool] = None,
|
|
@@ -289,6 +305,7 @@ class Agent:
|
|
|
289
305
|
files: Optional[List[str]] = None,
|
|
290
306
|
confirm_callback: Optional[Callable[[str, bool], bool]] = None,
|
|
291
307
|
non_interactive: Optional[bool] = None,
|
|
308
|
+
in_multi_agent: Optional[bool] = None,
|
|
292
309
|
**kwargs,
|
|
293
310
|
):
|
|
294
311
|
"""初始化Jarvis Agent实例
|
|
@@ -309,20 +326,36 @@ class Agent:
|
|
|
309
326
|
confirm_callback: 用户确认回调函数,签名为 (tip: str, default: bool) -> bool;默认使用CLI的user_confirm
|
|
310
327
|
non_interactive: 是否以非交互模式运行(优先级最高,覆盖环境变量与配置)
|
|
311
328
|
"""
|
|
312
|
-
#
|
|
313
|
-
|
|
329
|
+
# 基础属性初始化(仅根据入参设置原始值;实际生效的默认回退在 _init_config 中统一解析)
|
|
330
|
+
# 标识与描述
|
|
314
331
|
self.name = make_agent_name(name)
|
|
315
332
|
self.description = description
|
|
316
333
|
self.system_prompt = system_prompt
|
|
317
|
-
|
|
318
|
-
self.auto_complete = auto_complete
|
|
334
|
+
# 行为控制开关(原始入参值)
|
|
335
|
+
self.auto_complete = bool(auto_complete)
|
|
336
|
+
self.need_summary = bool(need_summary)
|
|
337
|
+
# 自动摘要轮次:None 表示使用配置文件中的默认值,由 AgentRunLoop 决定最终取值
|
|
338
|
+
self.auto_summary_rounds = auto_summary_rounds
|
|
339
|
+
self.use_methodology = use_methodology
|
|
340
|
+
self.use_analysis = use_analysis
|
|
341
|
+
self.execute_tool_confirm = execute_tool_confirm
|
|
342
|
+
self.summary_prompt = summary_prompt
|
|
343
|
+
self.force_save_memory = force_save_memory
|
|
344
|
+
# 资源与环境
|
|
345
|
+
self.model_group = model_group
|
|
346
|
+
self.files = files or []
|
|
347
|
+
self.use_tools = use_tools
|
|
348
|
+
self.non_interactive = non_interactive
|
|
349
|
+
# 多智能体运行标志:用于控制非交互模式下的自动完成行为
|
|
350
|
+
self.in_multi_agent = bool(in_multi_agent)
|
|
351
|
+
# 运行时状态
|
|
319
352
|
self.first = True
|
|
320
353
|
self.run_input_handlers_next_turn = False
|
|
321
354
|
self.user_data: Dict[str, Any] = {}
|
|
322
355
|
|
|
323
356
|
|
|
324
357
|
# 用户确认回调:默认使用 CLI 的 user_confirm,可由外部注入以支持 TUI/GUI
|
|
325
|
-
self.
|
|
358
|
+
self.confirm_callback: Callable[[str, bool], bool] = (
|
|
326
359
|
confirm_callback or user_confirm # type: ignore[assignment]
|
|
327
360
|
)
|
|
328
361
|
|
|
@@ -337,9 +370,9 @@ class Agent:
|
|
|
337
370
|
use_tools or [],
|
|
338
371
|
)
|
|
339
372
|
# 初始化用户交互封装,保持向后兼容
|
|
340
|
-
self.user_interaction = UserInteractionHandler(self.multiline_inputer, self.
|
|
373
|
+
self.user_interaction = UserInteractionHandler(self.multiline_inputer, self.confirm_callback)
|
|
341
374
|
# 将确认函数指向封装后的 confirm,保持既有调用不变
|
|
342
|
-
self.
|
|
375
|
+
self.confirm_callback = self.user_interaction.confirm # type: ignore[assignment]
|
|
343
376
|
# 非交互模式参数支持:允许通过构造参数显式控制,便于其他Agent调用时设置
|
|
344
377
|
try:
|
|
345
378
|
# 优先使用构造参数,其次回退到环境变量
|
|
@@ -351,24 +384,43 @@ class Agent:
|
|
|
351
384
|
# 如果构造参数显式提供,则同步到环境变量与全局配置,供下游组件读取
|
|
352
385
|
if non_interactive is not None:
|
|
353
386
|
os.environ["JARVIS_NON_INTERACTIVE"] = "true" if self.non_interactive else "false"
|
|
354
|
-
|
|
355
|
-
set_config("JARVIS_NON_INTERACTIVE", self.non_interactive)
|
|
356
|
-
except Exception:
|
|
357
|
-
# 配置同步失败不影响主流程
|
|
358
|
-
pass
|
|
387
|
+
|
|
359
388
|
except Exception:
|
|
360
389
|
# 防御式回退
|
|
361
390
|
self.non_interactive = False
|
|
362
391
|
|
|
363
|
-
#
|
|
364
|
-
|
|
365
|
-
use_methodology
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
392
|
+
# 初始化配置(直接解析,不再依赖 _init_config)
|
|
393
|
+
try:
|
|
394
|
+
resolved_use_methodology = bool(use_methodology if use_methodology is not None else is_use_methodology())
|
|
395
|
+
except Exception:
|
|
396
|
+
resolved_use_methodology = bool(use_methodology) if use_methodology is not None else True
|
|
397
|
+
|
|
398
|
+
try:
|
|
399
|
+
resolved_use_analysis = bool(use_analysis if use_analysis is not None else is_use_analysis())
|
|
400
|
+
except Exception:
|
|
401
|
+
resolved_use_analysis = bool(use_analysis) if use_analysis is not None else True
|
|
402
|
+
|
|
403
|
+
try:
|
|
404
|
+
resolved_execute_tool_confirm = bool(execute_tool_confirm if execute_tool_confirm is not None else is_execute_tool_confirm())
|
|
405
|
+
except Exception:
|
|
406
|
+
resolved_execute_tool_confirm = bool(execute_tool_confirm) if execute_tool_confirm is not None else False
|
|
407
|
+
|
|
408
|
+
try:
|
|
409
|
+
resolved_force_save_memory = bool(force_save_memory if force_save_memory is not None else is_force_save_memory())
|
|
410
|
+
except Exception:
|
|
411
|
+
resolved_force_save_memory = bool(force_save_memory) if force_save_memory is not None else False
|
|
412
|
+
|
|
413
|
+
self.use_methodology = resolved_use_methodology
|
|
414
|
+
self.use_analysis = resolved_use_analysis
|
|
415
|
+
self.execute_tool_confirm = resolved_execute_tool_confirm
|
|
416
|
+
self.summary_prompt = (summary_prompt or DEFAULT_SUMMARY_PROMPT)
|
|
417
|
+
self.force_save_memory = resolved_force_save_memory
|
|
418
|
+
# 多智能体模式下,默认不自动完成(即使是非交互),仅在明确传入 auto_complete=True 时开启
|
|
419
|
+
if self.in_multi_agent:
|
|
420
|
+
self.auto_complete = bool(self.auto_complete)
|
|
421
|
+
else:
|
|
422
|
+
# 非交互模式下默认自动完成;否则保持传入的 auto_complete 值
|
|
423
|
+
self.auto_complete = bool(self.auto_complete or (self.non_interactive or False))
|
|
372
424
|
|
|
373
425
|
# 初始化事件总线需先于管理器,以便管理器在构造中安全订阅事件
|
|
374
426
|
self.event_bus = EventBus()
|
|
@@ -432,46 +484,6 @@ class Agent:
|
|
|
432
484
|
]
|
|
433
485
|
self.multiline_inputer = multiline_inputer or get_multiline_input
|
|
434
486
|
|
|
435
|
-
def _init_config(
|
|
436
|
-
self,
|
|
437
|
-
use_methodology: Optional[bool],
|
|
438
|
-
use_analysis: Optional[bool],
|
|
439
|
-
execute_tool_confirm: Optional[bool],
|
|
440
|
-
summary_prompt: Optional[str],
|
|
441
|
-
model_group: Optional[str],
|
|
442
|
-
force_save_memory: Optional[bool],
|
|
443
|
-
):
|
|
444
|
-
"""初始化配置选项"""
|
|
445
|
-
# 使用集中配置解析,保持与原逻辑一致
|
|
446
|
-
cfg = AgentConfig(
|
|
447
|
-
system_prompt=self.system_prompt,
|
|
448
|
-
name=self.name,
|
|
449
|
-
description=self.description,
|
|
450
|
-
model_group=model_group,
|
|
451
|
-
auto_complete=self.auto_complete,
|
|
452
|
-
need_summary=self.need_summary,
|
|
453
|
-
summary_prompt=summary_prompt,
|
|
454
|
-
execute_tool_confirm=execute_tool_confirm,
|
|
455
|
-
use_methodology=use_methodology,
|
|
456
|
-
use_analysis=use_analysis,
|
|
457
|
-
force_save_memory=force_save_memory,
|
|
458
|
-
files=self.files,
|
|
459
|
-
max_token_count=None,
|
|
460
|
-
).resolve_defaults()
|
|
461
|
-
|
|
462
|
-
# 将解析结果回填到 Agent 实例属性,保持向后兼容
|
|
463
|
-
self.use_methodology = bool(cfg.use_methodology)
|
|
464
|
-
self.use_analysis = bool(cfg.use_analysis)
|
|
465
|
-
self.execute_tool_confirm = bool(cfg.execute_tool_confirm)
|
|
466
|
-
self.summary_prompt = cfg.summary_prompt or DEFAULT_SUMMARY_PROMPT
|
|
467
|
-
self.max_token_count = int(cfg.max_token_count or get_max_token_count(model_group))
|
|
468
|
-
self.force_save_memory = bool(cfg.force_save_memory)
|
|
469
|
-
# 非交互模式下自动完成标志需要同步到 Agent 实例,避免循环
|
|
470
|
-
self.auto_complete = bool(cfg.auto_complete)
|
|
471
|
-
|
|
472
|
-
# 聚合配置到 AgentConfig,作为后续单一事实来源(保持兼容,不改变既有属性使用)
|
|
473
|
-
self.config = cfg
|
|
474
|
-
|
|
475
487
|
def _setup_system_prompt(self):
|
|
476
488
|
"""设置系统提示词"""
|
|
477
489
|
try:
|
|
@@ -731,14 +743,9 @@ class Agent:
|
|
|
731
743
|
return message
|
|
732
744
|
|
|
733
745
|
def _manage_conversation_length(self, message: str) -> str:
|
|
734
|
-
"""
|
|
746
|
+
"""管理对话长度计数;摘要触发由轮次在 AgentRunLoop 中统一处理。"""
|
|
735
747
|
self.session.conversation_length += get_context_token_count(message)
|
|
736
748
|
|
|
737
|
-
if self.session.conversation_length > self.max_token_count:
|
|
738
|
-
summary = self._summarize_and_clear_history()
|
|
739
|
-
if summary:
|
|
740
|
-
message = join_prompts([summary, message])
|
|
741
|
-
self.session.conversation_length = get_context_token_count(message)
|
|
742
749
|
|
|
743
750
|
return message
|
|
744
751
|
|
|
@@ -1011,7 +1018,6 @@ class Agent:
|
|
|
1011
1018
|
{complete_prompt}
|
|
1012
1019
|
如果没有完成,请进行下一步操作:
|
|
1013
1020
|
- 仅包含一个操作
|
|
1014
|
-
- 不要询问用户是否继续,直接继续执行直至完成
|
|
1015
1021
|
- 如果信息不明确,请请求用户补充
|
|
1016
1022
|
- 如果执行过程中连续失败5次,请使用ask_user询问用户操作
|
|
1017
1023
|
- 操作列表:{action_handlers}{memory_prompts}
|
|
@@ -1095,7 +1101,7 @@ class Agent:
|
|
|
1095
1101
|
return self._complete_task(auto_completed=False)
|
|
1096
1102
|
|
|
1097
1103
|
if any(handler.can_handle(current_response) for handler in self.output_handler):
|
|
1098
|
-
if self.
|
|
1104
|
+
if self.confirm_callback("检测到有工具调用,是否继续处理工具调用?", True):
|
|
1099
1105
|
self.session.prompt = join_prompts([
|
|
1100
1106
|
f"被用户中断,用户补充信息为:{user_input}",
|
|
1101
1107
|
"用户同意继续工具调用。"
|
|
@@ -1322,7 +1328,7 @@ class Agent:
|
|
|
1322
1328
|
f"并且存在3个以上标签重叠的记忆。\n"
|
|
1323
1329
|
f"是否立即整理记忆库以优化性能和相关性?"
|
|
1324
1330
|
)
|
|
1325
|
-
if self.
|
|
1331
|
+
if self.confirm_callback(prompt, True):
|
|
1326
1332
|
PrettyOutput.print(
|
|
1327
1333
|
f"正在开始整理 '{scope_name}' ({memory_type}) 记忆库...",
|
|
1328
1334
|
OutputType.INFO,
|
|
@@ -14,6 +14,7 @@ from typing import Any, TYPE_CHECKING
|
|
|
14
14
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
15
15
|
from jarvis.jarvis_agent.events import BEFORE_TOOL_CALL, AFTER_TOOL_CALL
|
|
16
16
|
from jarvis.jarvis_agent.utils import join_prompts, is_auto_complete, normalize_next_action
|
|
17
|
+
from jarvis.jarvis_utils.config import get_auto_summary_rounds
|
|
17
18
|
|
|
18
19
|
if TYPE_CHECKING:
|
|
19
20
|
# 仅用于类型标注,避免运行时循环依赖
|
|
@@ -25,6 +26,12 @@ class AgentRunLoop:
|
|
|
25
26
|
self.agent = agent
|
|
26
27
|
self.conversation_rounds = 0
|
|
27
28
|
self.tool_reminder_rounds = int(os.environ.get("JARVIS_TOOL_REMINDER_ROUNDS", 20))
|
|
29
|
+
# 基于轮次的自动总结阈值:优先使用 Agent 入参,否则回落到全局配置(默认20轮)
|
|
30
|
+
self.auto_summary_rounds = (
|
|
31
|
+
self.agent.auto_summary_rounds
|
|
32
|
+
if getattr(self.agent, "auto_summary_rounds", None) is not None
|
|
33
|
+
else get_auto_summary_rounds()
|
|
34
|
+
)
|
|
28
35
|
|
|
29
36
|
def run(self) -> Any:
|
|
30
37
|
"""主运行循环(委派到传入的 agent 实例的方法与属性)"""
|
|
@@ -37,6 +44,17 @@ class AgentRunLoop:
|
|
|
37
44
|
self.agent.session.addon_prompt = join_prompts(
|
|
38
45
|
[self.agent.session.addon_prompt, self.agent.get_tool_usage_prompt()]
|
|
39
46
|
)
|
|
47
|
+
# 基于轮次的自动总结判断:达到阈值后执行一次总结与历史清理
|
|
48
|
+
if self.conversation_rounds >= self.auto_summary_rounds:
|
|
49
|
+
summary_text = self.agent._summarize_and_clear_history()
|
|
50
|
+
if summary_text:
|
|
51
|
+
# 将摘要作为下一轮的附加提示加入,从而维持上下文连续性
|
|
52
|
+
self.agent.session.addon_prompt = join_prompts(
|
|
53
|
+
[self.agent.session.addon_prompt, summary_text]
|
|
54
|
+
)
|
|
55
|
+
# 重置轮次计数与对话长度计数器,开始新一轮周期
|
|
56
|
+
self.conversation_rounds = 0
|
|
57
|
+
self.agent.session.conversation_length = 0
|
|
40
58
|
|
|
41
59
|
ag = self.agent
|
|
42
60
|
|
{jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_agent/share_manager.py
RENAMED
|
@@ -49,7 +49,14 @@ class ShareManager(ABC):
|
|
|
49
49
|
def __init__(self, central_repo_url: str, repo_name: str):
|
|
50
50
|
self.central_repo_url = central_repo_url
|
|
51
51
|
self.repo_name = repo_name
|
|
52
|
-
|
|
52
|
+
# 支持将中心仓库配置为本地目录(含git子路径)
|
|
53
|
+
expanded = os.path.expanduser(os.path.expandvars(central_repo_url))
|
|
54
|
+
if os.path.isdir(expanded):
|
|
55
|
+
# 直接使用本地目录作为中心仓库路径(支持git仓库子目录)
|
|
56
|
+
self.repo_path = expanded
|
|
57
|
+
else:
|
|
58
|
+
# 仍按原逻辑使用数据目录中的克隆路径
|
|
59
|
+
self.repo_path = os.path.join(get_data_dir(), repo_name)
|
|
53
60
|
|
|
54
61
|
def update_central_repo(self) -> None:
|
|
55
62
|
"""克隆或更新中心仓库"""
|
{jarvis_ai_assistant-0.4.1 → jarvis_ai_assistant-0.5.0}/src/jarvis/jarvis_code_agent/code_agent.py
RENAMED
|
@@ -25,6 +25,7 @@ from jarvis.jarvis_utils.config import (
|
|
|
25
25
|
is_enable_static_analysis,
|
|
26
26
|
get_git_check_mode,
|
|
27
27
|
set_config,
|
|
28
|
+
get_data_dir,
|
|
28
29
|
)
|
|
29
30
|
from jarvis.jarvis_utils.git_utils import (
|
|
30
31
|
confirm_add_new_files,
|
|
@@ -86,6 +87,22 @@ class CodeAgent:
|
|
|
86
87
|
|
|
87
88
|
tool_registry.use_tools(base_tools)
|
|
88
89
|
code_system_prompt = self._get_system_prompt()
|
|
90
|
+
# 先加载全局规则(数据目录 rules),再加载项目规则(.jarvis/rules),并拼接为单一规则块注入
|
|
91
|
+
global_rules = self._read_global_rules()
|
|
92
|
+
project_rules = self._read_project_rules()
|
|
93
|
+
|
|
94
|
+
combined_parts: List[str] = []
|
|
95
|
+
if global_rules:
|
|
96
|
+
combined_parts.append(global_rules)
|
|
97
|
+
if project_rules:
|
|
98
|
+
combined_parts.append(project_rules)
|
|
99
|
+
|
|
100
|
+
if combined_parts:
|
|
101
|
+
merged_rules = "\n\n".join(combined_parts)
|
|
102
|
+
code_system_prompt = (
|
|
103
|
+
f"{code_system_prompt}\n\n"
|
|
104
|
+
f"<rules>\n{merged_rules}\n</rules>"
|
|
105
|
+
)
|
|
89
106
|
self.agent = Agent(
|
|
90
107
|
system_prompt=code_system_prompt,
|
|
91
108
|
name="CodeAgent",
|
|
@@ -164,6 +181,32 @@ class CodeAgent:
|
|
|
164
181
|
</say_to_llm>
|
|
165
182
|
"""
|
|
166
183
|
|
|
184
|
+
def _read_project_rules(self) -> Optional[str]:
|
|
185
|
+
"""读取 .jarvis/rules 内容,如果存在则返回字符串,否则返回 None"""
|
|
186
|
+
try:
|
|
187
|
+
rules_path = os.path.join(self.root_dir, ".jarvis", "rules")
|
|
188
|
+
if os.path.exists(rules_path) and os.path.isfile(rules_path):
|
|
189
|
+
with open(rules_path, "r", encoding="utf-8", errors="replace") as f:
|
|
190
|
+
content = f.read().strip()
|
|
191
|
+
return content if content else None
|
|
192
|
+
except Exception:
|
|
193
|
+
# 读取规则失败时忽略,不影响主流程
|
|
194
|
+
pass
|
|
195
|
+
return None
|
|
196
|
+
|
|
197
|
+
def _read_global_rules(self) -> Optional[str]:
|
|
198
|
+
"""读取数据目录 rules 内容,如果存在则返回字符串,否则返回 None"""
|
|
199
|
+
try:
|
|
200
|
+
rules_path = os.path.join(get_data_dir(), "rules")
|
|
201
|
+
if os.path.exists(rules_path) and os.path.isfile(rules_path):
|
|
202
|
+
with open(rules_path, "r", encoding="utf-8", errors="replace") as f:
|
|
203
|
+
content = f.read().strip()
|
|
204
|
+
return content if content else None
|
|
205
|
+
except Exception:
|
|
206
|
+
# 读取规则失败时忽略,不影响主流程
|
|
207
|
+
pass
|
|
208
|
+
return None
|
|
209
|
+
|
|
167
210
|
def _check_git_config(self) -> None:
|
|
168
211
|
"""检查 git username 和 email 是否已设置,如果没有则提示并退出"""
|
|
169
212
|
try:
|
|
@@ -672,12 +715,58 @@ class CodeAgent:
|
|
|
672
715
|
def _build_per_file_patch_preview(modified_files: List[str]) -> str:
|
|
673
716
|
status_map = _build_name_status_map()
|
|
674
717
|
lines: List[str] = []
|
|
718
|
+
|
|
719
|
+
def _get_file_numstat(file_path: str) -> Tuple[int, int]:
|
|
720
|
+
"""获取单文件的新增/删除行数,失败时返回(0,0)"""
|
|
721
|
+
head_exists = bool(get_latest_commit_hash())
|
|
722
|
+
try:
|
|
723
|
+
# 让未跟踪文件也能统计到新增行数
|
|
724
|
+
subprocess.run(["git", "add", "-N", "--", file_path], check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
725
|
+
cmd = ["git", "diff", "--numstat"] + (["HEAD"] if head_exists else []) + ["--", file_path]
|
|
726
|
+
res = subprocess.run(
|
|
727
|
+
cmd,
|
|
728
|
+
capture_output=True,
|
|
729
|
+
text=True,
|
|
730
|
+
encoding="utf-8",
|
|
731
|
+
errors="replace",
|
|
732
|
+
check=False,
|
|
733
|
+
)
|
|
734
|
+
if res.returncode == 0 and res.stdout:
|
|
735
|
+
for line in res.stdout.splitlines():
|
|
736
|
+
parts = line.strip().split("\t")
|
|
737
|
+
if len(parts) >= 3:
|
|
738
|
+
add_s, del_s = parts[0], parts[1]
|
|
739
|
+
|
|
740
|
+
def to_int(x: str) -> int:
|
|
741
|
+
try:
|
|
742
|
+
return int(x)
|
|
743
|
+
except Exception:
|
|
744
|
+
# 二进制或无法解析时显示为0
|
|
745
|
+
return 0
|
|
746
|
+
|
|
747
|
+
return to_int(add_s), to_int(del_s)
|
|
748
|
+
finally:
|
|
749
|
+
subprocess.run(["git", "reset", "--", file_path], check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
750
|
+
return (0, 0)
|
|
751
|
+
|
|
675
752
|
for f in modified_files:
|
|
676
753
|
status = status_map.get(f, "")
|
|
677
|
-
|
|
754
|
+
adds, dels = _get_file_numstat(f)
|
|
755
|
+
total_changes = adds + dels
|
|
756
|
+
|
|
757
|
+
# 删除文件:不展示diff,仅提示(附带删除行数信息如果可用)
|
|
678
758
|
if (status.startswith("D")) or (not os.path.exists(f)):
|
|
679
|
-
|
|
759
|
+
if dels > 0:
|
|
760
|
+
lines.append(f"- {f} 文件被删除(删除{dels}行)")
|
|
761
|
+
else:
|
|
762
|
+
lines.append(f"- {f} 文件被删除")
|
|
680
763
|
continue
|
|
764
|
+
|
|
765
|
+
# 变更过大:仅提示新增/删除行数,避免输出超长diff
|
|
766
|
+
if total_changes > 300:
|
|
767
|
+
lines.append(f"- {f} 新增{adds}行/删除{dels}行(变更过大,预览已省略)")
|
|
768
|
+
continue
|
|
769
|
+
|
|
681
770
|
# 其它情况:展示该文件的diff
|
|
682
771
|
file_diff = _get_file_diff(f)
|
|
683
772
|
if file_diff.strip():
|