jarvis-ai-assistant 0.1.44__py3-none-any.whl → 0.1.46__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/agent.py +47 -32
  3. jarvis/main.py +52 -30
  4. jarvis/models/__init__.py +1 -1
  5. jarvis/models/ai8.py +88 -58
  6. jarvis/models/base.py +6 -6
  7. jarvis/models/kimi.py +171 -80
  8. jarvis/models/openai.py +43 -23
  9. jarvis/models/oyi.py +93 -65
  10. jarvis/models/registry.py +63 -44
  11. jarvis/tools/__init__.py +1 -1
  12. jarvis/tools/base.py +2 -2
  13. jarvis/tools/file_ops.py +19 -15
  14. jarvis/tools/generator.py +15 -12
  15. jarvis/tools/methodology.py +20 -20
  16. jarvis/tools/registry.py +44 -30
  17. jarvis/tools/shell.py +12 -11
  18. jarvis/tools/sub_agent.py +1 -2
  19. jarvis/utils.py +47 -27
  20. {jarvis_ai_assistant-0.1.44.dist-info → jarvis_ai_assistant-0.1.46.dist-info}/METADATA +1 -1
  21. jarvis_ai_assistant-0.1.46.dist-info/RECORD +25 -0
  22. jarvis/__pycache__/__init__.cpython-313.pyc +0 -0
  23. jarvis/__pycache__/agent.cpython-313.pyc +0 -0
  24. jarvis/__pycache__/main.cpython-313.pyc +0 -0
  25. jarvis/__pycache__/models.cpython-313.pyc +0 -0
  26. jarvis/__pycache__/tools.cpython-313.pyc +0 -0
  27. jarvis/__pycache__/utils.cpython-313.pyc +0 -0
  28. jarvis/__pycache__/zte_llm.cpython-313.pyc +0 -0
  29. jarvis/models/__pycache__/__init__.cpython-313.pyc +0 -0
  30. jarvis/models/__pycache__/ai8.cpython-313.pyc +0 -0
  31. jarvis/models/__pycache__/base.cpython-313.pyc +0 -0
  32. jarvis/models/__pycache__/kimi.cpython-313.pyc +0 -0
  33. jarvis/models/__pycache__/openai.cpython-313.pyc +0 -0
  34. jarvis/models/__pycache__/oyi.cpython-313.pyc +0 -0
  35. jarvis/models/__pycache__/registry.cpython-313.pyc +0 -0
  36. jarvis/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  37. jarvis/tools/__pycache__/base.cpython-313.pyc +0 -0
  38. jarvis/tools/__pycache__/bing_search.cpython-313.pyc +0 -0
  39. jarvis/tools/__pycache__/calculator.cpython-313.pyc +0 -0
  40. jarvis/tools/__pycache__/calculator_tool.cpython-313.pyc +0 -0
  41. jarvis/tools/__pycache__/file_ops.cpython-313.pyc +0 -0
  42. jarvis/tools/__pycache__/generator.cpython-313.pyc +0 -0
  43. jarvis/tools/__pycache__/methodology.cpython-313.pyc +0 -0
  44. jarvis/tools/__pycache__/python_script.cpython-313.pyc +0 -0
  45. jarvis/tools/__pycache__/rag.cpython-313.pyc +0 -0
  46. jarvis/tools/__pycache__/registry.cpython-313.pyc +0 -0
  47. jarvis/tools/__pycache__/search.cpython-313.pyc +0 -0
  48. jarvis/tools/__pycache__/shell.cpython-313.pyc +0 -0
  49. jarvis/tools/__pycache__/sub_agent.cpython-313.pyc +0 -0
  50. jarvis/tools/__pycache__/user_confirmation.cpython-313.pyc +0 -0
  51. jarvis/tools/__pycache__/user_input.cpython-313.pyc +0 -0
  52. jarvis/tools/__pycache__/user_interaction.cpython-313.pyc +0 -0
  53. jarvis/tools/__pycache__/webpage.cpython-313.pyc +0 -0
  54. jarvis_ai_assistant-0.1.44.dist-info/RECORD +0 -57
  55. {jarvis_ai_assistant-0.1.44.dist-info → jarvis_ai_assistant-0.1.46.dist-info}/LICENSE +0 -0
  56. {jarvis_ai_assistant-0.1.44.dist-info → jarvis_ai_assistant-0.1.46.dist-info}/WHEEL +0 -0
  57. {jarvis_ai_assistant-0.1.44.dist-info → jarvis_ai_assistant-0.1.46.dist-info}/entry_points.txt +0 -0
  58. {jarvis_ai_assistant-0.1.44.dist-info → jarvis_ai_assistant-0.1.46.dist-info}/top_level.txt +0 -0
jarvis/models/oyi.py CHANGED
@@ -6,16 +6,17 @@ from jarvis.utils import PrettyOutput, OutputType
6
6
  import requests
7
7
  import json
8
8
 
9
+
9
10
  class OyiModel(BasePlatform):
10
11
  """Oyi model implementation"""
11
-
12
+
12
13
  platform_name = "oyi"
13
14
  BASE_URL = "https://api-10086.rcouyi.com"
14
-
15
+
15
16
  def __init__(self):
16
17
  """Initialize model"""
17
18
  PrettyOutput.section("支持的模型", OutputType.SUCCESS)
18
-
19
+
19
20
  # 获取可用模型列表
20
21
  available_models = self.get_available_models()
21
22
  if available_models:
@@ -23,30 +24,32 @@ class OyiModel(BasePlatform):
23
24
  PrettyOutput.print(model, OutputType.INFO)
24
25
  else:
25
26
  PrettyOutput.print("获取模型列表失败", OutputType.WARNING)
26
-
27
+
27
28
  PrettyOutput.print("使用OYI_MODEL环境变量配置模型", OutputType.SUCCESS)
28
-
29
+
29
30
  self.messages = []
30
31
  self.system_message = ""
31
32
  self.conversation = None
32
33
  self.upload_files = []
33
34
  self.first_chat = True
34
-
35
+
35
36
  self.token = os.getenv("OYI_API_KEY")
36
37
  if not self.token:
37
38
  raise Exception("OYI_API_KEY is not set")
38
-
39
+
39
40
  self.model_name = os.getenv("OYI_MODEL") or "deepseek-chat"
40
41
  if self.model_name not in [m.split()[0] for m in available_models]:
41
- PrettyOutput.print(f"警告: 当前选择的模型 {self.model_name} 不在可用列表中", OutputType.WARNING)
42
-
42
+ PrettyOutput.print(
43
+ f"警告: 当前选择的模型 {
44
+ self.model_name} 不在可用列表中",
45
+ OutputType.WARNING)
46
+
43
47
  PrettyOutput.print(f"当前使用模型: {self.model_name}", OutputType.SYSTEM)
44
48
 
45
49
  def set_model_name(self, model_name: str):
46
50
  """设置模型名称"""
47
51
  self.model_name = model_name
48
52
 
49
-
50
53
  def create_conversation(self) -> bool:
51
54
  """Create a new conversation"""
52
55
  try:
@@ -56,7 +59,7 @@ class OyiModel(BasePlatform):
56
59
  'Accept': 'application/json',
57
60
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
58
61
  }
59
-
62
+
60
63
  payload = {
61
64
  "id": 0,
62
65
  "roleId": 0,
@@ -75,40 +78,49 @@ class OyiModel(BasePlatform):
75
78
  "chatPluginIds": []
76
79
  })
77
80
  }
78
-
81
+
79
82
  response = requests.post(
80
83
  f"{self.BASE_URL}/chatapi/chat/save",
81
84
  headers=headers,
82
85
  json=payload
83
86
  )
84
-
87
+
85
88
  if response.status_code == 200:
86
89
  data = response.json()
87
90
  if data['code'] == 200 and data['type'] == 'success':
88
91
  self.conversation = data
89
- PrettyOutput.print(f"创建会话成功: {data['result']['id']}", OutputType.SUCCESS)
92
+ PrettyOutput.print(
93
+ f"创建会话成功: {
94
+ data['result']['id']}",
95
+ OutputType.SUCCESS)
90
96
  return True
91
97
  else:
92
- PrettyOutput.print(f"创建会话失败: {data['message']}", OutputType.ERROR)
98
+ PrettyOutput.print(
99
+ f"创建会话失败: {
100
+ data['message']}",
101
+ OutputType.ERROR)
93
102
  return False
94
103
  else:
95
- PrettyOutput.print(f"创建会话失败: {response.status_code}", OutputType.ERROR)
104
+ PrettyOutput.print(
105
+ f"创建会话失败: {
106
+ response.status_code}",
107
+ OutputType.ERROR)
96
108
  return False
97
-
109
+
98
110
  except Exception as e:
99
111
  PrettyOutput.print(f"创建会话异常: {str(e)}", OutputType.ERROR)
100
112
  return False
101
-
113
+
102
114
  def set_system_message(self, message: str):
103
115
  """Set system message"""
104
116
  self.system_message = message
105
-
117
+
106
118
  def chat(self, message: str) -> str:
107
119
  """Execute chat with the model
108
-
120
+
109
121
  Args:
110
122
  message: User input message
111
-
123
+
112
124
  Returns:
113
125
  str: Model response
114
126
  """
@@ -117,7 +129,7 @@ class OyiModel(BasePlatform):
117
129
  if not self.conversation:
118
130
  if not self.create_conversation():
119
131
  raise Exception("Failed to create conversation")
120
-
132
+
121
133
  # 1. 发送消息
122
134
  headers = {
123
135
  'Authorization': f'Bearer {self.token}',
@@ -127,14 +139,14 @@ class OyiModel(BasePlatform):
127
139
  'Origin': 'https://ai.rcouyi.com',
128
140
  'Referer': 'https://ai.rcouyi.com/'
129
141
  }
130
-
142
+
131
143
  payload = {
132
144
  "topicId": self.conversation['result']['id'],
133
145
  "messages": self.messages,
134
146
  "content": message,
135
147
  "contentFiles": []
136
148
  }
137
-
149
+
138
150
  # 如果有上传的文件,添加到请求中
139
151
  if self.first_chat:
140
152
  if self.upload_files:
@@ -153,63 +165,64 @@ class OyiModel(BasePlatform):
153
165
  self.first_chat = False
154
166
 
155
167
  self.messages.append({"role": "user", "content": message})
156
-
168
+
157
169
  # 发送消息
158
170
  response = requests.post(
159
171
  f"{self.BASE_URL}/chatapi/chat/message",
160
172
  headers=headers,
161
173
  json=payload
162
174
  )
163
-
175
+
164
176
  if response.status_code != 200:
165
177
  error_msg = f"聊天请求失败: {response.status_code}"
166
178
  PrettyOutput.print(error_msg, OutputType.ERROR)
167
179
  raise Exception(error_msg)
168
-
180
+
169
181
  data = response.json()
170
182
  if data['code'] != 200 or data['type'] != 'success':
171
183
  error_msg = f"聊天失败: {data.get('message', '未知错误')}"
172
184
  PrettyOutput.print(error_msg, OutputType.ERROR)
173
185
  raise Exception(error_msg)
174
-
186
+
175
187
  message_id = data['result'][-1]
176
-
188
+
177
189
  # 获取响应内容
178
190
  response = requests.post(
179
191
  f"{self.BASE_URL}/chatapi/chat/message/{message_id}",
180
192
  headers=headers
181
193
  )
182
-
194
+
183
195
  if response.status_code == 200:
184
196
  PrettyOutput.print(response.text, OutputType.SYSTEM)
185
- self.messages.append({"role": "assistant", "content": response.text})
197
+ self.messages.append(
198
+ {"role": "assistant", "content": response.text})
186
199
  return response.text
187
200
  else:
188
201
  error_msg = f"获取响应失败: {response.status_code}"
189
202
  PrettyOutput.print(error_msg, OutputType.ERROR)
190
203
  raise Exception(error_msg)
191
-
204
+
192
205
  except Exception as e:
193
206
  PrettyOutput.print(f"聊天异常: {str(e)}", OutputType.ERROR)
194
207
  raise e
195
-
208
+
196
209
  def name(self) -> str:
197
210
  """Return model name"""
198
211
  return self.model_name
199
-
212
+
200
213
  def reset(self):
201
214
  """Reset model state"""
202
215
  self.messages = []
203
216
  self.conversation = None
204
217
  self.upload_files = []
205
218
  self.first_chat = True
206
-
219
+
207
220
  def delete_chat(self) -> bool:
208
221
  """Delete current chat session"""
209
222
  try:
210
223
  if not self.conversation:
211
224
  return True
212
-
225
+
213
226
  headers = {
214
227
  'Authorization': f'Bearer {self.token}',
215
228
  'Content-Type': 'application/json',
@@ -218,13 +231,15 @@ class OyiModel(BasePlatform):
218
231
  'Origin': 'https://ai.rcouyi.com',
219
232
  'Referer': 'https://ai.rcouyi.com/'
220
233
  }
221
-
234
+
222
235
  response = requests.post(
223
- f"{self.BASE_URL}/chatapi/chat/{self.conversation['result']['id']}",
236
+ f"{
237
+ self.BASE_URL}/chatapi/chat/{
238
+ self.conversation['result']['id']}",
224
239
  headers=headers,
225
240
  json={}
226
241
  )
227
-
242
+
228
243
  if response.status_code == 200:
229
244
  data = response.json()
230
245
  if data['code'] == 200 and data['type'] == 'success':
@@ -239,17 +254,17 @@ class OyiModel(BasePlatform):
239
254
  error_msg = f"删除会话请求失败: {response.status_code}"
240
255
  PrettyOutput.print(error_msg, OutputType.ERROR)
241
256
  return False
242
-
257
+
243
258
  except Exception as e:
244
259
  PrettyOutput.print(f"删除会话异常: {str(e)}", OutputType.ERROR)
245
260
  return False
246
-
261
+
247
262
  def upload_file(self, file_path: str) -> Dict:
248
263
  """Upload a file to OYI API
249
-
264
+
250
265
  Args:
251
266
  file_path: Path to the file to upload
252
-
267
+
253
268
  Returns:
254
269
  Dict: Upload response data
255
270
  """
@@ -257,9 +272,12 @@ class OyiModel(BasePlatform):
257
272
  # 检查当前模型是否支持文件上传
258
273
  model_info = self.models.get(self.model_name)
259
274
  if not model_info or not model_info.get('uploadFile', False):
260
- PrettyOutput.print(f"当前模型 {self.model_name} 不支持文件上传", OutputType.WARNING)
275
+ PrettyOutput.print(
276
+ f"当前模型 {
277
+ self.model_name} 不支持文件上传",
278
+ OutputType.WARNING)
261
279
  return None
262
-
280
+
263
281
  headers = {
264
282
  'Authorization': f'Bearer {self.token}',
265
283
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
@@ -268,18 +286,18 @@ class OyiModel(BasePlatform):
268
286
  'Origin': 'https://ai.rcouyi.com',
269
287
  'Referer': 'https://ai.rcouyi.com/'
270
288
  }
271
-
289
+
272
290
  with open(file_path, 'rb') as f:
273
291
  files = {
274
292
  'file': (os.path.basename(file_path), f, mimetypes.guess_type(file_path)[0])
275
293
  }
276
-
294
+
277
295
  response = requests.post(
278
296
  f"{self.BASE_URL}/chatapi/m_file/uploadfile",
279
297
  headers=headers,
280
298
  files=files
281
299
  )
282
-
300
+
283
301
  if response.status_code == 200:
284
302
  data = response.json()
285
303
  if data.get('code') == 200:
@@ -288,19 +306,25 @@ class OyiModel(BasePlatform):
288
306
  self.upload_files.append(data)
289
307
  return data
290
308
  else:
291
- PrettyOutput.print(f"文件上传失败: {data.get('message')}", OutputType.ERROR)
309
+ PrettyOutput.print(
310
+ f"文件上传失败: {
311
+ data.get('message')}",
312
+ OutputType.ERROR)
292
313
  return None
293
314
  else:
294
- PrettyOutput.print(f"文件上传失败: {response.status_code}", OutputType.ERROR)
315
+ PrettyOutput.print(
316
+ f"文件上传失败: {
317
+ response.status_code}",
318
+ OutputType.ERROR)
295
319
  return None
296
-
320
+
297
321
  except Exception as e:
298
322
  PrettyOutput.print(f"文件上传异常: {str(e)}", OutputType.ERROR)
299
323
  return None
300
324
 
301
325
  def get_available_models(self) -> List[str]:
302
326
  """获取可用的模型列表
303
-
327
+
304
328
  Returns:
305
329
  List[str]: 可用模型名称列表
306
330
  """
@@ -312,55 +336,59 @@ class OyiModel(BasePlatform):
312
336
  'Origin': 'https://ai.rcouyi.com',
313
337
  'Referer': 'https://ai.rcouyi.com/'
314
338
  }
315
-
339
+
316
340
  response = requests.get(
317
341
  "https://ai.rcouyi.com/config/system.json",
318
342
  headers=headers
319
343
  )
320
-
344
+
321
345
  if response.status_code != 200:
322
- PrettyOutput.print(f"获取模型列表失败: {response.status_code}", OutputType.ERROR)
346
+ PrettyOutput.print(
347
+ f"获取模型列表失败: {
348
+ response.status_code}",
349
+ OutputType.ERROR)
323
350
  return []
324
-
351
+
325
352
  data = response.json()
326
-
353
+
327
354
  # 保存模型信息
328
355
  self.models = {
329
356
  model['value']: model
330
357
  for model in data.get('model', [])
331
358
  if model.get('enable', False) # 只保存启用的模型
332
359
  }
333
-
360
+
334
361
  # 格式化显示
335
362
  models = []
336
363
  for model in self.models.values():
337
364
  # 基本信息
338
365
  model_str = f"{model['value']:<30} {model['label']}"
339
-
366
+
340
367
  # 添加后缀标签
341
368
  suffix = model.get('suffix', [])
342
369
  if suffix:
343
370
  # 处理新格式的suffix (字典列表)
344
371
  if suffix and isinstance(suffix[0], dict):
345
- suffix_str = ', '.join(s.get('tag', '') for s in suffix)
372
+ suffix_str = ', '.join(s.get('tag', '')
373
+ for s in suffix)
346
374
  # 处理旧格式的suffix (字符串列表)
347
375
  else:
348
376
  suffix_str = ', '.join(str(s) for s in suffix)
349
377
  model_str += f" ({suffix_str})"
350
-
378
+
351
379
  # 添加描述或提示
352
380
  info = model.get('tooltip') or model.get('description', '')
353
381
  if info:
354
382
  model_str += f" - {info}"
355
-
383
+
356
384
  # 添加文件上传支持标记
357
385
  if model.get('uploadFile'):
358
386
  model_str += " [支持文件上传]"
359
-
387
+
360
388
  models.append(model_str)
361
-
389
+
362
390
  return sorted(models)
363
-
391
+
364
392
  except Exception as e:
365
393
  PrettyOutput.print(f"获取模型列表异常: {str(e)}", OutputType.ERROR)
366
394
  return []
jarvis/models/registry.py CHANGED
@@ -14,6 +14,7 @@ REQUIRED_METHODS = [
14
14
  ('set_system_message', ['message'])
15
15
  ]
16
16
 
17
+
17
18
  class PlatformRegistry:
18
19
  """平台注册器"""
19
20
 
@@ -29,76 +30,82 @@ class PlatformRegistry:
29
30
  # 创建 __init__.py 使其成为 Python 包
30
31
  with open(os.path.join(user_platform_dir, "__init__.py"), "w") as f:
31
32
  pass
32
- PrettyOutput.print(f"已创建平台目录: {user_platform_dir}", OutputType.INFO)
33
+ PrettyOutput.print(
34
+ f"已创建平台目录: {user_platform_dir}",
35
+ OutputType.INFO)
33
36
  except Exception as e:
34
37
  PrettyOutput.print(f"创建平台目录失败: {str(e)}", OutputType.ERROR)
35
38
  return ""
36
39
  return user_platform_dir
37
40
 
38
41
  @staticmethod
39
- def check_platform_implementation(platform_class: Type[BasePlatform]) -> bool:
42
+ def check_platform_implementation(
43
+ platform_class: Type[BasePlatform]) -> bool:
40
44
  """检查平台类是否实现了所有必要的方法
41
-
45
+
42
46
  Args:
43
47
  platform_class: 要检查的平台类
44
-
48
+
45
49
  Returns:
46
50
  bool: 是否实现了所有必要的方法
47
51
  """
48
52
  missing_methods = []
49
-
53
+
50
54
  for method_name, params in REQUIRED_METHODS:
51
55
  if not hasattr(platform_class, method_name):
52
56
  missing_methods.append(method_name)
53
57
  continue
54
-
58
+
55
59
  method = getattr(platform_class, method_name)
56
60
  if not callable(method):
57
61
  missing_methods.append(method_name)
58
62
  continue
59
-
63
+
60
64
  # 检查方法参数
61
65
  import inspect
62
66
  sig = inspect.signature(method)
63
67
  method_params = [p for p in sig.parameters if p != 'self']
64
68
  if len(method_params) != len(params):
65
69
  missing_methods.append(f"{method_name}(参数不匹配)")
66
-
70
+
67
71
  if missing_methods:
68
72
  PrettyOutput.print(
69
- f"平台 {platform_class.__name__} 缺少必要的方法: {', '.join(missing_methods)}",
73
+ f"平台 {
74
+ platform_class.__name__} 缺少必要的方法: {
75
+ ', '.join(missing_methods)}",
70
76
  OutputType.ERROR
71
77
  )
72
78
  return False
73
-
79
+
74
80
  return True
75
81
 
76
82
  @staticmethod
77
- def load_platform_from_dir(directory: str) -> Dict[str, Type[BasePlatform]]:
83
+ def load_platform_from_dir(
84
+ directory: str) -> Dict[str, Type[BasePlatform]]:
78
85
  """从指定目录加载平台
79
-
86
+
80
87
  Args:
81
88
  directory: 平台目录路径
82
-
89
+
83
90
  Returns:
84
91
  Dict[str, Type[BaseModel]]: 平台名称到平台类的映射
85
92
  """
86
93
  platforms = {}
87
-
94
+
88
95
  # 确保目录存在
89
96
  if not os.path.exists(directory):
90
97
  PrettyOutput.print(f"平台目录不存在: {directory}", OutputType.ERROR)
91
98
  return platforms
92
-
99
+
93
100
  # 获取目录的包名
94
101
  package_name = None
95
102
  if directory == os.path.dirname(__file__):
96
103
  package_name = "jarvis.models"
97
-
104
+
98
105
  # 添加目录到Python路径
99
106
  if directory not in sys.path:
100
107
  sys.path.append(directory)
101
-
108
+
102
109
  # 遍历目录下的所有.py文件
103
110
  for filename in os.listdir(directory):
104
111
  if filename.endswith('.py') and not filename.startswith('__'):
@@ -106,46 +113,55 @@ class PlatformRegistry:
106
113
  try:
107
114
  # 导入模块
108
115
  if package_name:
109
- module = importlib.import_module(f"{package_name}.{module_name}")
116
+ module = importlib.import_module(
117
+ f"{package_name}.{module_name}")
110
118
  else:
111
119
  module = importlib.import_module(module_name)
112
-
120
+
113
121
  # 遍历模块中的所有类
114
122
  for name, obj in inspect.getmembers(module):
115
123
  # 检查是否是BaseModel的子类,但不是BaseModel本身
116
- if (inspect.isclass(obj) and
117
- issubclass(obj, BasePlatform) and
124
+ if (inspect.isclass(obj) and
125
+ issubclass(obj, BasePlatform) and
118
126
  obj != BasePlatform and
119
- hasattr(obj, 'platform_name')):
127
+ hasattr(obj, 'platform_name')):
120
128
  # 检查平台实现
121
- if not PlatformRegistry.check_platform_implementation(obj):
129
+ if not PlatformRegistry.check_platform_implementation(
130
+ obj):
122
131
  continue
123
132
  platforms[obj.platform_name] = obj
124
- PrettyOutput.print(f"从 {directory} 加载平台: {obj.platform_name}", OutputType.INFO)
133
+ PrettyOutput.print(
134
+ f"从 {directory} 加载平台: {
135
+ obj.platform_name}", OutputType.INFO)
125
136
  break
126
137
  except Exception as e:
127
- PrettyOutput.print(f"加载平台 {module_name} 失败: {str(e)}", OutputType.ERROR)
128
-
129
- return platforms
138
+ PrettyOutput.print(
139
+ f"加载平台 {module_name} 失败: {
140
+ str(e)}", OutputType.ERROR)
130
141
 
142
+ return platforms
131
143
 
132
144
  @staticmethod
133
145
  def get_global_platform_registry():
134
146
  """获取全局平台注册器"""
135
147
  if PlatformRegistry.global_platform_registry is None:
136
148
  PlatformRegistry.global_platform_registry = PlatformRegistry()
137
-
149
+
138
150
  # 从用户平台目录加载额外平台
139
151
  platform_dir = PlatformRegistry.get_platform_dir()
140
152
  if platform_dir and os.path.exists(platform_dir):
141
- for platform_name, platform_class in PlatformRegistry.load_platform_from_dir(platform_dir).items():
142
- PlatformRegistry.global_platform_registry.register_platform(platform_name, platform_class)
153
+ for platform_name, platform_class in PlatformRegistry.load_platform_from_dir(
154
+ platform_dir).items():
155
+ PlatformRegistry.global_platform_registry.register_platform(
156
+ platform_name, platform_class)
143
157
  platform_dir = os.path.dirname(__file__)
144
158
  if platform_dir and os.path.exists(platform_dir):
145
- for platform_name, platform_class in PlatformRegistry.load_platform_from_dir(platform_dir).items():
146
- PlatformRegistry.global_platform_registry.register_platform(platform_name, platform_class)
159
+ for platform_name, platform_class in PlatformRegistry.load_platform_from_dir(
160
+ platform_dir).items():
161
+ PlatformRegistry.global_platform_registry.register_platform(
162
+ platform_name, platform_class)
147
163
  return PlatformRegistry.global_platform_registry
148
-
164
+
149
165
  def __init__(self):
150
166
  """初始化平台注册器
151
167
  """
@@ -154,34 +170,37 @@ class PlatformRegistry:
154
170
  @staticmethod
155
171
  def get_global_platform() -> BasePlatform:
156
172
  """获取全局平台实例"""
157
- platform = PlatformRegistry.get_global_platform_registry().create_platform(PlatformRegistry.global_platform_name)
173
+ platform = PlatformRegistry.get_global_platform_registry(
174
+ ).create_platform(PlatformRegistry.global_platform_name)
158
175
  if not platform:
159
- raise Exception(f"Failed to create platform: {PlatformRegistry.global_platform_name}")
176
+ raise Exception(
177
+ f"Failed to create platform: {
178
+ PlatformRegistry.global_platform_name}")
160
179
  return platform
161
-
180
+
162
181
  def register_platform(self, name: str, platform_class: Type[BasePlatform]):
163
182
  """注册平台类
164
-
183
+
165
184
  Args:
166
185
  name: 平台名称
167
186
  model_class: 平台类
168
187
  """
169
188
  self.platforms[name] = platform_class
170
189
  PrettyOutput.print(f"已注册平台: {name}", OutputType.INFO)
171
-
190
+
172
191
  def create_platform(self, name: str) -> Optional[BasePlatform]:
173
192
  """创建平台实例
174
-
193
+
175
194
  Args:
176
195
  name: 平台名称
177
-
196
+
178
197
  Returns:
179
198
  BaseModel: 平台实例
180
199
  """
181
200
  if name not in self.platforms:
182
201
  PrettyOutput.print(f"未找到平台: {name}", OutputType.ERROR)
183
202
  return None
184
-
203
+
185
204
  try:
186
205
  platform = self.platforms[name]()
187
206
  PrettyOutput.print(f"已创建平台实例: {name}", OutputType.INFO)
@@ -189,11 +208,11 @@ class PlatformRegistry:
189
208
  except Exception as e:
190
209
  PrettyOutput.print(f"创建平台失败: {str(e)}", OutputType.ERROR)
191
210
  return None
192
-
211
+
193
212
  def get_available_platforms(self) -> List[str]:
194
213
  """获取可用平台列表"""
195
- return list(self.platforms.keys())
196
-
214
+ return list(self.platforms.keys())
215
+
197
216
  def set_global_platform_name(self, platform_name: str):
198
217
  """设置全局平台"""
199
218
  PlatformRegistry.global_platform_name = platform_name
jarvis/tools/__init__.py CHANGED
@@ -2,4 +2,4 @@ from .registry import ToolRegistry
2
2
 
3
3
  __all__ = [
4
4
  'ToolRegistry',
5
- ]
5
+ ]
jarvis/tools/base.py CHANGED
@@ -2,9 +2,9 @@ from typing import Dict, Any, Callable
2
2
  import json
3
3
 
4
4
 
5
-
6
5
  class Tool:
7
- def __init__(self, name: str, description: str, parameters: Dict, func: Callable):
6
+ def __init__(self, name: str, description: str,
7
+ parameters: Dict, func: Callable):
8
8
  self.name = name
9
9
  self.description = description
10
10
  self.parameters = parameters