jarvis-ai-assistant 0.1.176__py3-none-any.whl → 0.1.178__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.

Potentially problematic release.


This version of jarvis-ai-assistant might be problematic. Click here for more details.

Files changed (38) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +33 -62
  3. jarvis/jarvis_agent/jarvis.py +10 -10
  4. jarvis/jarvis_agent/main.py +6 -6
  5. jarvis/jarvis_code_agent/code_agent.py +10 -6
  6. jarvis/jarvis_code_analysis/code_review.py +1 -1
  7. jarvis/jarvis_dev/main.py +1 -1
  8. jarvis/jarvis_event/__init__.py +0 -0
  9. jarvis/jarvis_git_details/main.py +1 -1
  10. jarvis/jarvis_git_squash/main.py +1 -1
  11. jarvis/jarvis_git_utils/git_commiter.py +1 -1
  12. jarvis/jarvis_multi_agent/main.py +1 -1
  13. jarvis/jarvis_platform/base.py +6 -3
  14. jarvis/jarvis_platform/openai.py +66 -10
  15. jarvis/jarvis_platform/yuanbao.py +1 -1
  16. jarvis/jarvis_platform_manager/main.py +1 -1
  17. jarvis/jarvis_smart_shell/main.py +4 -2
  18. jarvis/jarvis_tools/ask_codebase.py +3 -2
  19. jarvis/jarvis_tools/cli/main.py +28 -1
  20. jarvis/jarvis_tools/edit_file.py +186 -118
  21. jarvis/jarvis_tools/read_code.py +0 -2
  22. jarvis/jarvis_tools/registry.py +31 -1
  23. jarvis/jarvis_utils/config.py +13 -4
  24. jarvis/jarvis_utils/output.py +36 -7
  25. jarvis/jarvis_utils/utils.py +19 -1
  26. {jarvis_ai_assistant-0.1.176.dist-info → jarvis_ai_assistant-0.1.178.dist-info}/METADATA +4 -4
  27. {jarvis_ai_assistant-0.1.176.dist-info → jarvis_ai_assistant-0.1.178.dist-info}/RECORD +31 -37
  28. {jarvis_ai_assistant-0.1.176.dist-info → jarvis_ai_assistant-0.1.178.dist-info}/WHEEL +1 -1
  29. jarvis/jarvis_lsp/base.py +0 -66
  30. jarvis/jarvis_lsp/cpp.py +0 -99
  31. jarvis/jarvis_lsp/go.py +0 -104
  32. jarvis/jarvis_lsp/python.py +0 -58
  33. jarvis/jarvis_lsp/registry.py +0 -169
  34. jarvis/jarvis_lsp/rust.py +0 -107
  35. jarvis/jarvis_tools/lsp_get_diagnostics.py +0 -147
  36. {jarvis_ai_assistant-0.1.176.dist-info → jarvis_ai_assistant-0.1.178.dist-info}/entry_points.txt +0 -0
  37. {jarvis_ai_assistant-0.1.176.dist-info → jarvis_ai_assistant-0.1.178.dist-info}/licenses/LICENSE +0 -0
  38. {jarvis_ai_assistant-0.1.176.dist-info → jarvis_ai_assistant-0.1.178.dist-info}/top_level.txt +0 -0
@@ -1,169 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import importlib
3
- import inspect
4
- import os
5
- import re
6
- import sys
7
- from typing import Dict, Type, Optional, List
8
- from jarvis.jarvis_lsp.base import BaseLSP
9
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
10
- from jarvis.jarvis_utils.config import get_data_dir
11
-
12
- REQUIRED_METHODS = [
13
- ('initialize', ['workspace_path']),
14
- ('get_diagnostics', ['file_path']),
15
- ('shutdown', [])
16
- ]
17
-
18
- class LSPRegistry:
19
- """LSP server registry"""
20
-
21
- global_lsp_registry = None
22
-
23
- @staticmethod
24
- def get_lsp_dir() -> str:
25
- """Get LSP implementation directory."""
26
- user_lsp_dir = os.path.join(get_data_dir(), "lsp")
27
- if not os.path.exists(user_lsp_dir):
28
- try:
29
- os.makedirs(user_lsp_dir)
30
- with open(os.path.join(user_lsp_dir, "__init__.py"), "w", errors="ignore") as f:
31
- pass
32
- except Exception as e:
33
- PrettyOutput.print(f"创建 LSP 目录失败: {str(e)}", OutputType.ERROR)
34
- return ""
35
- return user_lsp_dir
36
-
37
- @staticmethod
38
- def check_lsp_implementation(lsp_class: Type[BaseLSP]) -> bool:
39
- """Check if the LSP class implements all necessary methods."""
40
- missing_methods = []
41
-
42
- for method_name, params in REQUIRED_METHODS:
43
- if not hasattr(lsp_class, method_name):
44
- missing_methods.append(method_name)
45
- continue
46
-
47
- method = getattr(lsp_class, method_name)
48
- if not callable(method):
49
- missing_methods.append(method_name)
50
- continue
51
-
52
- sig = inspect.signature(method)
53
- method_params = [p for p in sig.parameters if p != 'self']
54
- if len(method_params) != len(params):
55
- missing_methods.append(f"{method_name}(parameter mismatch)")
56
-
57
- if missing_methods:
58
- PrettyOutput.print(
59
- f"LSP {lsp_class.__name__} 缺少必要的方法: {', '.join(missing_methods)}",
60
- OutputType.WARNING
61
- )
62
- return False
63
-
64
- return True
65
-
66
- @staticmethod
67
- def load_lsp_from_dir(directory: str) -> Dict[str, Type[BaseLSP]]:
68
- """Load LSP implementations from specified directory."""
69
- lsp_servers = {}
70
-
71
- if not os.path.exists(directory):
72
- PrettyOutput.print(f"LSP 目录不存在: {directory}", OutputType.WARNING)
73
- return lsp_servers
74
-
75
- package_name = None
76
- if directory == os.path.dirname(__file__):
77
- package_name = "jarvis.jarvis_lsp"
78
-
79
- if directory not in sys.path:
80
- sys.path.append(directory)
81
-
82
- for filename in os.listdir(directory):
83
- if filename.endswith('.py') and not filename.startswith('__'):
84
- module_name = filename[:-3]
85
- try:
86
- if package_name:
87
- module = importlib.import_module(f"{package_name}.{module_name}")
88
- else:
89
- module = importlib.import_module(module_name)
90
-
91
- for _, obj in inspect.getmembers(module):
92
- if (inspect.isclass(obj) and
93
- issubclass(obj, BaseLSP) and
94
- obj != BaseLSP and
95
- hasattr(obj, 'language')):
96
- if not LSPRegistry.check_lsp_implementation(obj):
97
- continue
98
- if hasattr(obj, 'check'):
99
- if not obj.check(): # type: ignore
100
- continue
101
- if isinstance(obj.language, str):
102
- lsp_servers[obj.language] = obj
103
- elif isinstance(obj.language, list):
104
- for lang in obj.language: # type: ignore
105
- lsp_servers[lang] = obj
106
- break
107
- except Exception as e:
108
- PrettyOutput.print(f"加载 LSP {module_name} 失败: {str(e)}", OutputType.ERROR)
109
-
110
- return lsp_servers
111
-
112
- @staticmethod
113
- def get_global_lsp_registry():
114
- """Get global LSP registry instance."""
115
- if LSPRegistry.global_lsp_registry is None:
116
- LSPRegistry.global_lsp_registry = LSPRegistry()
117
- return LSPRegistry.global_lsp_registry
118
-
119
- def __init__(self):
120
- """Initialize LSP registry."""
121
- self.lsp_servers: Dict[str, Type[BaseLSP]] = {}
122
-
123
- # Load from user LSP directory
124
- lsp_dir = LSPRegistry.get_lsp_dir()
125
- if lsp_dir and os.path.exists(lsp_dir):
126
- for language, lsp_class in LSPRegistry.load_lsp_from_dir(lsp_dir).items():
127
- self.register_lsp(language, lsp_class)
128
-
129
- # Load from built-in LSP directory
130
- lsp_dir = os.path.dirname(__file__)
131
- if lsp_dir and os.path.exists(lsp_dir):
132
- for language, lsp_class in LSPRegistry.load_lsp_from_dir(lsp_dir).items():
133
- self.register_lsp(language, lsp_class)
134
-
135
- def register_lsp(self, language: str, lsp_class: Type[BaseLSP]):
136
- """Register LSP implementation for a language."""
137
- self.lsp_servers[language] = lsp_class
138
-
139
- def create_lsp(self, language: str) -> Optional[BaseLSP]:
140
- """Create LSP instance for specified language."""
141
- if language not in self.lsp_servers:
142
- PrettyOutput.print(f"没有找到 LSP 支持的语言: {language}", OutputType.WARNING)
143
- return None
144
-
145
- try:
146
- lsp = self.lsp_servers[language]()
147
- return lsp
148
- except Exception as e:
149
- PrettyOutput.print(f"创建 LSP 失败: {str(e)}", OutputType.ERROR)
150
- return None
151
-
152
- def get_supported_languages(self) -> List[str]:
153
- """Get list of supported languages."""
154
- return list(self.lsp_servers.keys())
155
-
156
- @staticmethod
157
- def get_text_at_position(file_path: str, line: int, start_character: int) -> str:
158
- """Get text at position."""
159
- with open(file_path, 'r', errors="ignore") as file:
160
- lines = file.readlines()
161
- symbol = re.search(r'\b\w+\b', lines[line][start_character:])
162
- return symbol.group() if symbol else ""
163
-
164
- @staticmethod
165
- def get_line_at_position(file_path: str, line: int) -> str:
166
- """Get line at position."""
167
- with open(file_path, 'r', errors="ignore") as file:
168
- lines = file.readlines()
169
- return lines[line]
jarvis/jarvis_lsp/rust.py DELETED
@@ -1,107 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import os
3
- import shutil
4
- import subprocess
5
- from typing import List, Dict, Optional, Any
6
- import json
7
- from jarvis.jarvis_lsp.base import BaseLSP
8
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
-
10
- class RustLSP(BaseLSP):
11
- """Rust LSP implementation using rust-analyzer."""
12
-
13
- language = "rust"
14
-
15
- @staticmethod
16
- def check() -> bool:
17
- """Check if rust-analyzer is installed."""
18
- return shutil.which("rust-analyzer") is not None
19
-
20
- def __init__(self):
21
- self.workspace_path = ""
22
- self.analyzer_process = None
23
- self.request_id = 0
24
-
25
- def initialize(self, workspace_path: str) -> bool:
26
- try:
27
- self.workspace_path = workspace_path
28
- # Start rust-analyzer process
29
- self.analyzer_process = subprocess.Popen(
30
- ["rust-analyzer"],
31
- stdin=subprocess.PIPE,
32
- stdout=subprocess.PIPE,
33
- stderr=subprocess.PIPE
34
- )
35
-
36
- # Send initialize request
37
- self._send_request("initialize", {
38
- "processId": os.getpid(),
39
- "rootUri": f"file://{workspace_path}",
40
- "capabilities": {
41
- "textDocument": {
42
- "semanticTokens": {"full": True},
43
- "hover": {"contentFormat": ["markdown"]},
44
- "inlayHint": {"resolveSupport": {"properties": ["label.tooltip", "label.location", "label.command"]}},
45
- "completion": {"completionItem": {"snippetSupport": True}}
46
- }
47
- },
48
- "workspaceFolders": [{"uri": f"file://{workspace_path}", "name": "workspace"}]
49
- })
50
-
51
- return True
52
- except Exception as e:
53
- PrettyOutput.print(f"Rust LSP 初始化失败: {str(e)}", OutputType.ERROR)
54
- return False
55
-
56
- def _send_request(self, method: str, params: Dict) -> Optional[Dict]:
57
- """Send JSON-RPC request to rust-analyzer."""
58
- if not self.analyzer_process:
59
- return None
60
-
61
- try:
62
- self.request_id += 1
63
- request = {
64
- "jsonrpc": "2.0",
65
- "id": self.request_id,
66
- "method": method,
67
- "params": params
68
- }
69
-
70
- self.analyzer_process.stdin.write(json.dumps(request).encode() + b"\n") # type: ignore
71
- self.analyzer_process.stdin.flush() # type: ignore
72
-
73
- response = json.loads(self.analyzer_process.stdout.readline().decode()) # type: ignore
74
- return response.get("result")
75
- except Exception:
76
- return None
77
-
78
-
79
- def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
80
- # Send didOpen notification to trigger diagnostics
81
- self._send_request("textDocument/didOpen", {
82
- "textDocument": {
83
- "uri": f"file://{file_path}",
84
- "languageId": "rust",
85
- "version": 1,
86
- "text": open(file_path).read()
87
- }
88
- })
89
-
90
- # Wait for diagnostic notification
91
- try:
92
- response = json.loads(self.analyzer_process.stdout.readline().decode()) # type: ignore
93
- if response.get("method") == "textDocument/publishDiagnostics":
94
- return response.get("params", {}).get("diagnostics", [])
95
- except Exception:
96
- pass
97
- return []
98
-
99
-
100
- def shutdown(self):
101
- if self.analyzer_process:
102
- try:
103
- self._send_request("shutdown", {})
104
- self.analyzer_process.terminate()
105
- self.analyzer_process = None
106
- except Exception:
107
- pass
@@ -1,147 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import os
3
- from typing import Dict, Any
4
- from jarvis.jarvis_lsp.registry import LSPRegistry
5
- class LSPGetDiagnosticsTool:
6
- """Tool for getting diagnostics (errors, warnings) from code using LSP."""
7
-
8
- # 工具名称
9
- name = "lsp_get_diagnostics"
10
- # 工具描述
11
- description = "Get diagnostic information (errors, warnings) from code files"
12
- # 工具标签
13
- # 工具参数定义
14
- parameters = {
15
- "file_path": "Path to the file to analyze",
16
- "language": f"Programming language of the file ({', '.join(LSPRegistry.get_global_lsp_registry().get_supported_languages())})",
17
- "root_dir": {
18
- "type": "string",
19
- "description": "Root directory for LSP operations (optional)",
20
- "default": "."
21
- }
22
- }
23
-
24
- @staticmethod
25
- def check() -> bool:
26
- """检查是否有可用的LSP服务器"""
27
- registry = LSPRegistry.get_global_lsp_registry()
28
- return len(registry.get_supported_languages()) > 0
29
-
30
- def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
31
- """执行工具的主要逻辑"""
32
- file_path = args.get("file_path", "")
33
- language = args.get("language", "")
34
- root_dir = args.get("root_dir", ".")
35
-
36
- # 验证输入参数
37
- if not all([file_path, language]):
38
- return {
39
- "success": False,
40
- "stderr": "Both file_path and language must be provided",
41
- "stdout": ""
42
- }
43
-
44
- # 检查文件是否存在
45
- if not os.path.exists(file_path):
46
- return {
47
- "success": False,
48
- "stderr": f"File not found: {file_path}",
49
- "stdout": ""
50
- }
51
-
52
- # 存储当前目录
53
- original_dir = os.getcwd()
54
-
55
- try:
56
- # 切换到root_dir
57
- os.chdir(root_dir)
58
-
59
- # 获取LSP实例
60
- registry = LSPRegistry.get_global_lsp_registry()
61
- lsp = registry.create_lsp(language)
62
-
63
- # 检查语言是否支持
64
- if not lsp:
65
- return {
66
- "success": False,
67
- "stderr": f"No LSP support for language: {language}",
68
- "stdout": ""
69
- }
70
-
71
- try:
72
- # 初始化LSP
73
- if not lsp.initialize(os.path.abspath(os.getcwd())):
74
- return {
75
- "success": False,
76
- "stderr": "LSP initialization failed",
77
- "stdout": ""
78
- }
79
-
80
- # 获取诊断信息
81
- diagnostics = lsp.get_diagnostics(file_path)
82
-
83
- # 如果没有诊断信息
84
- if not diagnostics:
85
- return {
86
- "success": True,
87
- "stdout": "No issues found in the file",
88
- "stderr": ""
89
- }
90
-
91
- # 格式化输出
92
- output = ["Diagnostics:"]
93
- # 严重程度映射
94
- severity_map = {1: "Error", 2: "Warning", 3: "Info", 4: "Hint"}
95
-
96
- # 按严重程度和行号排序诊断信息
97
- sorted_diagnostics = sorted(
98
- diagnostics,
99
- key=lambda x: (x["severity"], x["range"]["start"]["line"])
100
- )
101
-
102
- # 处理每个诊断信息
103
- for diag in sorted_diagnostics:
104
- severity = severity_map.get(diag["severity"], "Unknown")
105
- start = diag["range"]["start"]
106
- line = LSPRegistry.get_line_at_position(file_path, start["line"]).strip()
107
-
108
- output.extend([
109
- f"\n{severity} at line {start['line'] + 1}, column {start['character'] + 1}:",
110
- f"Message: {diag['message']}",
111
- f"Code: {line}",
112
- "-" * 60
113
- ])
114
-
115
- # 处理相关附加信息
116
- if diag.get("relatedInformation"):
117
- output.append("Related information:")
118
- for info in diag["relatedInformation"]:
119
- info_line = LSPRegistry.get_line_at_position(
120
- info["location"]["uri"],
121
- info["location"]["range"]["start"]["line"]
122
- ).strip()
123
- output.extend([
124
- f" - {info['message']}",
125
- f" at {info['location']['uri']}:{info['location']['range']['start']['line'] + 1}",
126
- f" {info_line}"
127
- ])
128
-
129
- return {
130
- "success": True,
131
- "stdout": "\n".join(output),
132
- "stderr": ""
133
- }
134
-
135
- except Exception as e:
136
- return {
137
- "success": False,
138
- "stderr": f"Error getting diagnostics: {str(e)}",
139
- "stdout": ""
140
- }
141
- finally:
142
- # 确保关闭LSP连接
143
- if lsp:
144
- lsp.shutdown()
145
- finally:
146
- # 恢复原始目录
147
- os.chdir(original_dir)