jarvis-ai-assistant 0.1.132__py3-none-any.whl → 0.1.138__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 (82) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +330 -347
  3. jarvis/jarvis_agent/builtin_input_handler.py +16 -6
  4. jarvis/jarvis_agent/file_input_handler.py +9 -9
  5. jarvis/jarvis_agent/jarvis.py +143 -0
  6. jarvis/jarvis_agent/main.py +12 -13
  7. jarvis/jarvis_agent/output_handler.py +3 -3
  8. jarvis/jarvis_agent/patch.py +92 -64
  9. jarvis/jarvis_agent/shell_input_handler.py +5 -3
  10. jarvis/jarvis_code_agent/code_agent.py +263 -177
  11. jarvis/jarvis_code_agent/file_select.py +24 -24
  12. jarvis/jarvis_dev/main.py +45 -59
  13. jarvis/jarvis_git_details/__init__.py +0 -0
  14. jarvis/jarvis_git_details/main.py +179 -0
  15. jarvis/jarvis_git_squash/main.py +7 -7
  16. jarvis/jarvis_lsp/base.py +11 -53
  17. jarvis/jarvis_lsp/cpp.py +13 -28
  18. jarvis/jarvis_lsp/go.py +13 -28
  19. jarvis/jarvis_lsp/python.py +8 -27
  20. jarvis/jarvis_lsp/registry.py +21 -83
  21. jarvis/jarvis_lsp/rust.py +15 -30
  22. jarvis/jarvis_methodology/main.py +101 -0
  23. jarvis/jarvis_multi_agent/__init__.py +10 -51
  24. jarvis/jarvis_multi_agent/main.py +43 -0
  25. jarvis/jarvis_platform/__init__.py +1 -1
  26. jarvis/jarvis_platform/ai8.py +67 -89
  27. jarvis/jarvis_platform/base.py +14 -13
  28. jarvis/jarvis_platform/kimi.py +25 -28
  29. jarvis/jarvis_platform/ollama.py +24 -26
  30. jarvis/jarvis_platform/openai.py +15 -19
  31. jarvis/jarvis_platform/oyi.py +48 -50
  32. jarvis/jarvis_platform/registry.py +29 -44
  33. jarvis/jarvis_platform/yuanbao.py +39 -43
  34. jarvis/jarvis_platform_manager/main.py +81 -81
  35. jarvis/jarvis_platform_manager/openai_test.py +21 -21
  36. jarvis/jarvis_rag/file_processors.py +18 -18
  37. jarvis/jarvis_rag/main.py +262 -278
  38. jarvis/jarvis_smart_shell/main.py +12 -12
  39. jarvis/jarvis_tools/ask_codebase.py +85 -78
  40. jarvis/jarvis_tools/ask_user.py +8 -8
  41. jarvis/jarvis_tools/base.py +4 -4
  42. jarvis/jarvis_tools/chdir.py +9 -9
  43. jarvis/jarvis_tools/code_review.py +40 -21
  44. jarvis/jarvis_tools/create_code_agent.py +15 -15
  45. jarvis/jarvis_tools/create_sub_agent.py +0 -1
  46. jarvis/jarvis_tools/execute_python_script.py +3 -3
  47. jarvis/jarvis_tools/execute_shell.py +11 -11
  48. jarvis/jarvis_tools/execute_shell_script.py +3 -3
  49. jarvis/jarvis_tools/file_analyzer.py +116 -105
  50. jarvis/jarvis_tools/file_operation.py +22 -20
  51. jarvis/jarvis_tools/find_caller.py +105 -40
  52. jarvis/jarvis_tools/find_methodolopy.py +65 -0
  53. jarvis/jarvis_tools/find_symbol.py +123 -39
  54. jarvis/jarvis_tools/function_analyzer.py +140 -57
  55. jarvis/jarvis_tools/git_commiter.py +10 -10
  56. jarvis/jarvis_tools/lsp_get_diagnostics.py +19 -19
  57. jarvis/jarvis_tools/methodology.py +22 -67
  58. jarvis/jarvis_tools/project_analyzer.py +137 -53
  59. jarvis/jarvis_tools/rag.py +15 -20
  60. jarvis/jarvis_tools/read_code.py +25 -23
  61. jarvis/jarvis_tools/read_webpage.py +31 -31
  62. jarvis/jarvis_tools/registry.py +72 -52
  63. jarvis/jarvis_tools/search_web.py +23 -353
  64. jarvis/jarvis_tools/tool_generator.py +19 -19
  65. jarvis/jarvis_utils/config.py +36 -96
  66. jarvis/jarvis_utils/embedding.py +83 -83
  67. jarvis/jarvis_utils/git_utils.py +20 -20
  68. jarvis/jarvis_utils/globals.py +18 -6
  69. jarvis/jarvis_utils/input.py +10 -9
  70. jarvis/jarvis_utils/methodology.py +141 -140
  71. jarvis/jarvis_utils/output.py +13 -13
  72. jarvis/jarvis_utils/utils.py +23 -71
  73. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/METADATA +6 -15
  74. jarvis_ai_assistant-0.1.138.dist-info/RECORD +85 -0
  75. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/entry_points.txt +4 -3
  76. jarvis/jarvis_tools/lsp_find_definition.py +0 -150
  77. jarvis/jarvis_tools/lsp_find_references.py +0 -127
  78. jarvis/jarvis_tools/select_code_files.py +0 -62
  79. jarvis_ai_assistant-0.1.132.dist-info/RECORD +0 -82
  80. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/LICENSE +0 -0
  81. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/WHEEL +0 -0
  82. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/top_level.txt +0 -0
@@ -4,14 +4,13 @@ import os
4
4
  import sys
5
5
  from typing import Dict, Type, Optional, List
6
6
  from jarvis.jarvis_platform.base import BasePlatform
7
- from jarvis.jarvis_utils.config import get_cheap_model_name, get_cheap_platform_name, get_codegen_model_name, get_codegen_platform_name, get_normal_model_name, get_normal_platform_name, get_thinking_model_name, get_thinking_platform_name
7
+ from jarvis.jarvis_utils.config import get_normal_model_name, get_normal_platform_name, get_thinking_model_name, get_thinking_platform_name
8
8
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
9
 
10
10
  REQUIRED_METHODS = [
11
11
  ('chat', ['message']), # 方法名和参数列表
12
12
  ('name', []),
13
13
  ('delete_chat', []),
14
- ('reset', []),
15
14
  ('set_system_message', ['message']),
16
15
  ('set_model_name', ['model_name']),
17
16
  ('get_model_list', []),
@@ -21,7 +20,7 @@ REQUIRED_METHODS = [
21
20
  class PlatformRegistry:
22
21
  """Platform registry"""
23
22
 
24
- global_platform_name = "kimi"
23
+ global_platform_name = "yuanbao"
25
24
  global_platform_registry = None
26
25
 
27
26
  @staticmethod
@@ -43,67 +42,67 @@ class PlatformRegistry:
43
42
  @staticmethod
44
43
  def check_platform_implementation(platform_class: Type[BasePlatform]) -> bool:
45
44
  """Check if the platform class implements all necessary methods
46
-
45
+
47
46
  Args:
48
47
  platform_class: The platform class to check
49
-
48
+
50
49
  Returns:
51
50
  bool: Whether all necessary methods are implemented
52
51
  """
53
52
  missing_methods = []
54
-
53
+
55
54
  for method_name, params in REQUIRED_METHODS:
56
55
  if not hasattr(platform_class, method_name):
57
56
  missing_methods.append(method_name)
58
57
  continue
59
-
58
+
60
59
  method = getattr(platform_class, method_name)
61
60
  if not callable(method):
62
61
  missing_methods.append(method_name)
63
62
  continue
64
-
63
+
65
64
  # 检查方法参数
66
65
  import inspect
67
66
  sig = inspect.signature(method)
68
67
  method_params = [p for p in sig.parameters if p != 'self']
69
68
  if len(method_params) != len(params):
70
69
  missing_methods.append(f"{method_name}(parameter mismatch)")
71
-
70
+
72
71
  if missing_methods:
73
72
  PrettyOutput.print(
74
- f"平台 {platform_class.__name__} 缺少必要的方法: {', '.join(missing_methods)}",
73
+ f"平台 {platform_class.__name__} 缺少必要的方法: {', '.join(missing_methods)}",
75
74
  OutputType.WARNING
76
75
  )
77
76
  return False
78
-
77
+
79
78
  return True
80
79
 
81
80
  @staticmethod
82
81
  def load_platform_from_dir(directory: str) -> Dict[str, Type[BasePlatform]]:
83
82
  """Load platforms from specified directory
84
-
83
+
85
84
  Args:
86
85
  directory: Platform directory path
87
-
86
+
88
87
  Returns:
89
88
  Dict[str, Type[BasePlatform]]: Platform name to platform class mapping
90
89
  """
91
90
  platforms = {}
92
-
91
+
93
92
  # 确保目录存在
94
93
  if not os.path.exists(directory):
95
94
  PrettyOutput.print(f"平台目录不存在: {directory}", OutputType.WARNING)
96
95
  return platforms
97
-
96
+
98
97
  # 获取目录的包名
99
98
  package_name = None
100
99
  if directory == os.path.dirname(__file__):
101
100
  package_name = "jarvis.jarvis_platform"
102
-
101
+
103
102
  # 添加目录到Python路径
104
103
  if directory not in sys.path:
105
104
  sys.path.append(directory)
106
-
105
+
107
106
  # 遍历目录下的所有.py文件
108
107
  for filename in os.listdir(directory):
109
108
  if filename.endswith('.py') and not filename.startswith('__'):
@@ -114,12 +113,12 @@ class PlatformRegistry:
114
113
  module = importlib.import_module(f"{package_name}.{module_name}")
115
114
  else:
116
115
  module = importlib.import_module(module_name)
117
-
116
+
118
117
  # 遍历模块中的所有类
119
118
  for _, obj in inspect.getmembers(module):
120
119
  # 检查是否是BasePlatform的子类,但不是BasePlatform本身
121
- if (inspect.isclass(obj) and
122
- issubclass(obj, BasePlatform) and
120
+ if (inspect.isclass(obj) and
121
+ issubclass(obj, BasePlatform) and
123
122
  obj != BasePlatform and
124
123
  hasattr(obj, 'platform_name')):
125
124
  # 检查平台实现
@@ -129,7 +128,7 @@ class PlatformRegistry:
129
128
  break
130
129
  except Exception as e:
131
130
  PrettyOutput.print(f"加载平台 {module_name} 失败: {str(e)}", OutputType.ERROR)
132
-
131
+
133
132
  return platforms
134
133
 
135
134
 
@@ -137,9 +136,9 @@ class PlatformRegistry:
137
136
  def get_global_platform_registry():
138
137
  """Get global platform registry"""
139
138
  if PlatformRegistry.global_platform_registry is None:
140
- PlatformRegistry.global_platform_registry = PlatformRegistry()
139
+ PlatformRegistry.global_platform_registry = PlatformRegistry()
141
140
  return PlatformRegistry.global_platform_registry
142
-
141
+
143
142
  def __init__(self):
144
143
  """Initialize platform registry"""
145
144
  self.platforms: Dict[str, Type[BasePlatform]] = {}
@@ -152,7 +151,7 @@ class PlatformRegistry:
152
151
  if platform_dir and os.path.exists(platform_dir):
153
152
  for platform_name, platform_class in PlatformRegistry.load_platform_from_dir(platform_dir).items():
154
153
  self.register_platform(platform_name, platform_class)
155
-
154
+
156
155
 
157
156
  def get_normal_platform(self) -> BasePlatform:
158
157
  platform_name = get_normal_platform_name()
@@ -160,21 +159,7 @@ class PlatformRegistry:
160
159
  platform = self.create_platform(platform_name)
161
160
  platform.set_model_name(model_name) # type: ignore
162
161
  return platform # type: ignore
163
-
164
- def get_codegen_platform(self) -> BasePlatform:
165
- platform_name = get_codegen_platform_name()
166
- model_name = get_codegen_model_name()
167
- platform = self.create_platform(platform_name)
168
- platform.set_model_name(model_name) # type: ignore
169
- return platform # type: ignore
170
-
171
- def get_cheap_platform(self) -> BasePlatform:
172
- platform_name = get_cheap_platform_name()
173
- model_name = get_cheap_model_name()
174
- platform = self.create_platform(platform_name)
175
- platform.set_model_name(model_name) # type: ignore
176
- return platform # type: ignore
177
-
162
+
178
163
  def get_thinking_platform(self) -> BasePlatform:
179
164
  platform_name = get_thinking_platform_name()
180
165
  model_name = get_thinking_model_name()
@@ -184,26 +169,26 @@ class PlatformRegistry:
184
169
 
185
170
  def register_platform(self, name: str, platform_class: Type[BasePlatform]):
186
171
  """Register platform class
187
-
172
+
188
173
  Args:
189
174
  name: Platform name
190
175
  model_class: Platform class
191
176
  """
192
177
  self.platforms[name] = platform_class
193
-
178
+
194
179
  def create_platform(self, name: str) -> Optional[BasePlatform]:
195
180
  """Create platform instance
196
-
181
+
197
182
  Args:
198
183
  name: Platform name
199
-
184
+
200
185
  Returns:
201
186
  BasePlatform: Platform instance
202
187
  """
203
188
  if name not in self.platforms:
204
189
  PrettyOutput.print(f"未找到平台: {name}", OutputType.WARNING)
205
190
  return None
206
-
191
+
207
192
  try:
208
193
 
209
194
  platform = self.platforms[name]()
@@ -6,7 +6,7 @@ from jarvis.jarvis_platform.base import BasePlatform
6
6
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
7
7
  from jarvis.jarvis_utils.utils import while_success
8
8
 
9
- class HunyuanModel(BasePlatform):
9
+ class YuanbaoPlatform(BasePlatform):
10
10
  """Hunyuan model implementation"""
11
11
 
12
12
  platform_name = "yuanbao"
@@ -14,7 +14,7 @@ class HunyuanModel(BasePlatform):
14
14
  def get_model_list(self) -> List[Tuple[str, str]]:
15
15
  """获取支持的模型列表"""
16
16
  return [("deep_seek", "DeepSeek-R1"), ("deep_seek_v3", "DeepSeek-v3"), ("hunyuan_gpt_175B_0404", "Tencent Hunyuan"), ("hunyuan_t1", "Tencent Hunyuan-T1")]
17
-
17
+
18
18
  def __init__(self):
19
19
  """
20
20
  初始化Hunyuan模型
@@ -25,13 +25,13 @@ class HunyuanModel(BasePlatform):
25
25
  self.cookies = os.getenv("YUANBAO_COOKIES") # 认证cookies
26
26
  self.agent_id = os.getenv("YUANBAO_AGENT_ID") # 代理ID
27
27
  self.web = os.getenv("YUANBAO_WEB", "false") == "true" # 是否启用网页功能
28
-
28
+
29
29
  if not self.cookies:
30
30
  message = (
31
31
  "需要设置 YUANBAO_COOKIES 和 YUANBAO_AGENT_ID 才能使用 Jarvis 的元宝功能。请按照以下步骤操作:\n"
32
32
  "1. 获取元宝 API 参数:\n"
33
33
  " • 访问元宝平台: https://yuanbao.tencent.com\n"
34
- " • 登录您的账户\n"
34
+ " • 登录您的账户\n"
35
35
  " • 打开浏览器开发者工具 (F12 或右键 -> 检查)\n"
36
36
  " • 切换到网络标签\n"
37
37
  " • 发送任意消息\n"
@@ -47,7 +47,7 @@ class HunyuanModel(BasePlatform):
47
47
  )
48
48
  PrettyOutput.print(message, OutputType.INFO)
49
49
  PrettyOutput.print("YUANBAO_COOKIES 未设置", OutputType.WARNING)
50
-
50
+
51
51
  self.system_message = "" # 系统消息,用于初始化对话
52
52
  self.first_chat = True # 标识是否为第一次对话
53
53
  self.model_name = "deep_seek_v3" # 默认模型名称,使用下划线保持一致
@@ -59,18 +59,17 @@ class HunyuanModel(BasePlatform):
59
59
  def set_model_name(self, model_name: str):
60
60
  # 模型映射表,可以根据需要扩展
61
61
  model_mapping = [m[0] for m in self.get_model_list()]
62
-
62
+
63
63
  if model_name in model_mapping:
64
64
  self.model_name = model_name
65
65
  else:
66
66
  PrettyOutput.print(f"错误:不支持的模型: {model_name}", OutputType.ERROR)
67
- self.reset()
68
67
 
69
68
  def _get_base_headers(self):
70
69
  """Get base headers for API requests"""
71
70
  return {
72
71
  'Host': 'yuanbao.tencent.com',
73
- 'X-Language': 'zh-CN',
72
+ 'X-Language': 'zh-CN',
74
73
  'X-Requested-With': 'XMLHttpRequest',
75
74
  'chat_version': 'v1',
76
75
  'X-Instance-ID': '5',
@@ -94,17 +93,17 @@ class HunyuanModel(BasePlatform):
94
93
  def _create_conversation(self) -> bool:
95
94
  """Create a new conversation session"""
96
95
  url = "https://yuanbao.tencent.com/api/user/agent/conversation/create"
97
-
96
+
98
97
  headers = self._get_base_headers()
99
-
98
+
100
99
  payload = json.dumps({
101
100
  "agentId": self.agent_id
102
101
  })
103
-
102
+
104
103
  try:
105
104
  response = while_success(lambda: requests.post(url, headers=headers, data=payload), sleep_time=5)
106
105
  response_json = response.json()
107
-
106
+
108
107
  if "id" in response_json:
109
108
  self.conversation_id = response_json["id"]
110
109
  return True
@@ -120,11 +119,11 @@ class HunyuanModel(BasePlatform):
120
119
  if not self.conversation_id:
121
120
  if not self._create_conversation():
122
121
  raise Exception("Failed to create conversation session")
123
-
122
+
124
123
  url = f"https://yuanbao.tencent.com/api/chat/{self.conversation_id}"
125
-
124
+
126
125
  headers = self._get_base_headers()
127
-
126
+
128
127
  # 准备消息内容
129
128
  payload = {
130
129
  "model": "gpt_175B_0404",
@@ -149,44 +148,44 @@ class HunyuanModel(BasePlatform):
149
148
 
150
149
  if self.web:
151
150
  payload["supportFunctions"] = ["supportInternetSearch"]
152
-
153
-
151
+
152
+
154
153
  # 添加系统消息(如果是第一次对话)
155
154
  if self.first_chat and self.system_message:
156
155
  payload["prompt"] = f"{self.system_message}\n\n{message}"
157
156
  payload["displayPrompt"] = payload["prompt"]
158
157
  self.first_chat = False
159
-
160
- try:
158
+
159
+ try:
161
160
  # 发送消息请求,获取流式响应
162
161
  response = while_success(
163
162
  lambda: requests.post(url, headers=headers, json=payload, stream=True),
164
163
  sleep_time=5
165
164
  )
166
-
165
+
167
166
  # 检查响应状态
168
167
  if response.status_code != 200:
169
168
  error_msg = f"发送消息失败,状态码: {response.status_code}"
170
169
  if hasattr(response, 'text'):
171
170
  error_msg += f", 响应: {response.text}"
172
171
  raise Exception(error_msg)
173
-
172
+
174
173
  full_response = ""
175
174
  is_text_block = False
176
-
175
+
177
176
  # 处理SSE流响应
178
177
  for line in response.iter_lines():
179
178
  if not line:
180
179
  continue
181
-
180
+
182
181
  line_str = line.decode('utf-8')
183
-
182
+
184
183
  # SSE格式的行通常以"data: "开头
185
184
  if line_str.startswith("data: "):
186
185
  try:
187
186
  data_str = line_str[6:] # 移除"data: "前缀
188
187
  data = json.loads(data_str)
189
-
188
+
190
189
  # 处理文本类型的消息
191
190
  if data.get("type") == "text":
192
191
  is_text_block = True
@@ -195,60 +194,57 @@ class HunyuanModel(BasePlatform):
195
194
  if not self.suppress_output:
196
195
  PrettyOutput.print_stream(msg)
197
196
  full_response += msg
198
-
197
+
199
198
  # 处理思考中的消息(可选展示)
200
199
  elif data.get("type") == "think" and not self.suppress_output:
201
200
  think_content = data.get("content", "")
202
201
  # 可以选择性地显示思考过程,但不加入最终响应
203
202
  PrettyOutput.print_stream(f"{think_content}", is_thinking=True)
204
203
  pass
205
-
204
+
206
205
  except json.JSONDecodeError:
207
206
  pass
208
-
207
+
209
208
  # 检测结束标志
210
209
  elif line_str == "data: [DONE]":
211
210
  break
212
-
211
+
213
212
  if not self.suppress_output:
214
213
  PrettyOutput.print_stream_end()
215
-
214
+
216
215
  return full_response
217
-
216
+
218
217
  except Exception as e:
219
218
  raise Exception(f"对话失败: {str(e)}")
220
219
 
221
- def reset(self):
222
- """Reset chat"""
223
- self.conversation_id = ""
224
- self.first_chat = True
225
220
 
226
221
  def delete_chat(self) -> bool:
227
222
  """Delete current session"""
228
223
  if not self.conversation_id:
229
224
  return True # 如果没有会话ID,视为删除成功
230
-
225
+
231
226
  # Hunyuan使用专门的clear API来清除会话
232
227
  url = "https://yuanbao.tencent.com/api/user/agent/conversation/v1/clear"
233
-
228
+
234
229
  # 为这个请求获取基础头部
235
230
  headers = self._get_base_headers()
236
-
231
+
237
232
  # 更新X-AgentID头部,需要包含会话ID
238
233
  headers.update({
239
234
  'X-AgentID': f"{self.agent_id}/{self.conversation_id}"
240
235
  })
241
-
236
+
242
237
  # 创建请求体,包含要删除的会话ID
243
238
  payload = {
244
239
  "conversationIds": [self.conversation_id]
245
240
  }
246
-
241
+
247
242
  try:
248
243
  response = while_success(lambda: requests.post(url, headers=headers, json=payload), sleep_time=5)
249
-
244
+
250
245
  if response.status_code == 200:
251
- self.reset()
246
+ self.conversation_id = ""
247
+ self.first_chat = True
252
248
  return True
253
249
  else:
254
250
  PrettyOutput.print(f"删除会话失败: HTTP {response.status_code}", OutputType.WARNING)
@@ -261,4 +257,4 @@ class HunyuanModel(BasePlatform):
261
257
 
262
258
  def name(self) -> str:
263
259
  """Model name"""
264
- return "yuanbao"
260
+ return self.model_name