jarvis-ai-assistant 0.1.177__py3-none-any.whl → 0.1.179__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 (73) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +145 -125
  3. jarvis/jarvis_agent/builtin_input_handler.py +1 -1
  4. jarvis/jarvis_agent/jarvis.py +9 -13
  5. jarvis/jarvis_agent/main.py +4 -2
  6. jarvis/jarvis_code_agent/code_agent.py +34 -23
  7. jarvis/jarvis_code_agent/lint.py +164 -0
  8. jarvis/jarvis_code_analysis/checklists/loader.py +6 -20
  9. jarvis/jarvis_code_analysis/code_review.py +8 -6
  10. jarvis/jarvis_dev/main.py +1 -8
  11. jarvis/jarvis_event/__init__.py +0 -0
  12. jarvis/jarvis_git_details/main.py +1 -1
  13. jarvis/jarvis_git_squash/main.py +5 -3
  14. jarvis/jarvis_git_utils/git_commiter.py +24 -23
  15. jarvis/jarvis_mcp/sse_mcp_client.py +6 -4
  16. jarvis/jarvis_mcp/stdio_mcp_client.py +5 -4
  17. jarvis/jarvis_mcp/streamable_mcp_client.py +404 -0
  18. jarvis/jarvis_methodology/main.py +10 -9
  19. jarvis/jarvis_multi_agent/main.py +3 -1
  20. jarvis/jarvis_platform/base.py +14 -8
  21. jarvis/jarvis_platform/human.py +3 -1
  22. jarvis/jarvis_platform/kimi.py +10 -7
  23. jarvis/jarvis_platform/openai.py +70 -11
  24. jarvis/jarvis_platform/registry.py +6 -2
  25. jarvis/jarvis_platform/yuanbao.py +13 -10
  26. jarvis/jarvis_platform_manager/main.py +11 -9
  27. jarvis/jarvis_smart_shell/main.py +1 -0
  28. jarvis/jarvis_tools/ask_codebase.py +6 -4
  29. jarvis/jarvis_tools/ask_user.py +2 -1
  30. jarvis/jarvis_tools/base.py +3 -1
  31. jarvis/jarvis_tools/chdir.py +2 -1
  32. jarvis/jarvis_tools/cli/main.py +1 -0
  33. jarvis/jarvis_tools/code_plan.py +5 -3
  34. jarvis/jarvis_tools/create_code_agent.py +5 -2
  35. jarvis/jarvis_tools/create_sub_agent.py +1 -3
  36. jarvis/jarvis_tools/edit_file.py +37 -29
  37. jarvis/jarvis_tools/execute_script.py +1 -1
  38. jarvis/jarvis_tools/file_analyzer.py +5 -3
  39. jarvis/jarvis_tools/file_operation.py +4 -7
  40. jarvis/jarvis_tools/find_methodology.py +4 -2
  41. jarvis/jarvis_tools/generate_new_tool.py +2 -1
  42. jarvis/jarvis_tools/methodology.py +3 -4
  43. jarvis/jarvis_tools/read_code.py +2 -1
  44. jarvis/jarvis_tools/read_webpage.py +3 -1
  45. jarvis/jarvis_tools/registry.py +23 -14
  46. jarvis/jarvis_tools/rewrite_file.py +2 -1
  47. jarvis/jarvis_tools/search_web.py +1 -0
  48. jarvis/jarvis_tools/virtual_tty.py +5 -4
  49. jarvis/jarvis_utils/__init__.py +2 -0
  50. jarvis/jarvis_utils/builtin_replace_map.py +1 -1
  51. jarvis/jarvis_utils/config.py +40 -1
  52. jarvis/jarvis_utils/embedding.py +4 -3
  53. jarvis/jarvis_utils/file_processors.py +1 -0
  54. jarvis/jarvis_utils/git_utils.py +55 -25
  55. jarvis/jarvis_utils/globals.py +4 -2
  56. jarvis/jarvis_utils/input.py +14 -7
  57. jarvis/jarvis_utils/methodology.py +6 -4
  58. jarvis/jarvis_utils/output.py +10 -6
  59. jarvis/jarvis_utils/utils.py +89 -13
  60. {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/METADATA +45 -33
  61. jarvis_ai_assistant-0.1.179.dist-info/RECORD +98 -0
  62. jarvis/jarvis_lsp/base.py +0 -66
  63. jarvis/jarvis_lsp/cpp.py +0 -99
  64. jarvis/jarvis_lsp/go.py +0 -104
  65. jarvis/jarvis_lsp/python.py +0 -58
  66. jarvis/jarvis_lsp/registry.py +0 -169
  67. jarvis/jarvis_lsp/rust.py +0 -107
  68. jarvis/jarvis_tools/lsp_get_diagnostics.py +0 -147
  69. jarvis_ai_assistant-0.1.177.dist-info/RECORD +0 -102
  70. {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/WHEEL +0 -0
  71. {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/entry_points.txt +0 -0
  72. {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/licenses/LICENSE +0 -0
  73. {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,404 @@
1
+ # -*- coding: utf-8 -*-
2
+ import json
3
+ import threading
4
+ from typing import Any, Callable, Dict, List
5
+ from urllib.parse import urljoin
6
+
7
+ import requests
8
+
9
+ from jarvis.jarvis_mcp import McpClient
10
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
11
+
12
+
13
+ class StreamableMcpClient(McpClient):
14
+ """Streamable HTTP MCP客户端实现
15
+
16
+ 参数:
17
+ config: 配置字典,包含以下字段:
18
+ - base_url: str - MCP服务器的基础URL
19
+ - auth_token: str - 认证令牌(可选)
20
+ - headers: Dict[str, str] - 额外的HTTP头(可选)
21
+ """
22
+ def __init__(self, config: Dict[str, Any]):
23
+ self.config = config
24
+ self.base_url = config.get('base_url', '')
25
+ if not self.base_url:
26
+ raise ValueError('No base_url specified in config')
27
+
28
+ # 设置HTTP客户端
29
+ self.session = requests.Session()
30
+ self.session.headers.update({
31
+ 'Content-Type': 'application/json',
32
+ 'Accept': 'application/json',
33
+ })
34
+
35
+ # 添加认证令牌(如果提供)
36
+ auth_token = config.get('auth_token')
37
+ if auth_token:
38
+ self.session.headers['Authorization'] = f'Bearer {auth_token}'
39
+
40
+ # 添加额外的HTTP头
41
+ extra_headers = config.get('headers', {})
42
+ self.session.headers.update(extra_headers)
43
+
44
+ # 请求相关属性
45
+ self.pending_requests = {} # 存储等待响应的请求 {id: Event}
46
+ self.request_results = {} # 存储请求结果 {id: result}
47
+ self.notification_handlers = {}
48
+ self.event_lock = threading.Lock()
49
+ self.request_id_counter = 0
50
+
51
+ # 初始化连接
52
+ self._initialize()
53
+
54
+ def _initialize(self) -> None:
55
+ """初始化MCP连接"""
56
+ try:
57
+ # 发送初始化请求
58
+ response = self._send_request('initialize', {
59
+ 'processId': None, # 远程客户端不需要进程ID
60
+ 'clientInfo': {
61
+ 'name': 'jarvis',
62
+ 'version': '1.0.0'
63
+ },
64
+ 'capabilities': {},
65
+ 'protocolVersion': "2025-03-26"
66
+ })
67
+
68
+ # 验证服务器响应
69
+ if 'result' not in response:
70
+ raise RuntimeError(f"初始化失败: {response.get('error', 'Unknown error')}")
71
+
72
+ # 发送initialized通知
73
+ self._send_notification('notifications/initialized', {})
74
+
75
+ except Exception as e:
76
+ PrettyOutput.print(f"MCP初始化失败: {str(e)}", OutputType.ERROR)
77
+ raise
78
+
79
+ def register_notification_handler(self, method: str, handler: Callable) -> None:
80
+ """注册通知处理器
81
+
82
+ 参数:
83
+ method: 通知方法名
84
+ handler: 处理通知的回调函数,接收params参数
85
+ """
86
+ with self.event_lock:
87
+ if method not in self.notification_handlers:
88
+ self.notification_handlers[method] = []
89
+ self.notification_handlers[method].append(handler)
90
+
91
+ def unregister_notification_handler(self, method: str, handler: Callable) -> None:
92
+ """注销通知处理器
93
+
94
+ 参数:
95
+ method: 通知方法名
96
+ handler: 要注销的处理器函数
97
+ """
98
+ with self.event_lock:
99
+ if method in self.notification_handlers:
100
+ if handler in self.notification_handlers[method]:
101
+ self.notification_handlers[method].remove(handler)
102
+ if not self.notification_handlers[method]:
103
+ del self.notification_handlers[method]
104
+
105
+ def _get_next_request_id(self) -> str:
106
+ """获取下一个请求ID"""
107
+ with self.event_lock:
108
+ self.request_id_counter += 1
109
+ return str(self.request_id_counter)
110
+
111
+ def _send_request(self, method: str, params: Dict[str, Any]) -> Dict[str, Any]:
112
+ """发送请求到MCP服务器
113
+
114
+ 参数:
115
+ method: 请求方法
116
+ params: 请求参数
117
+
118
+ 返回:
119
+ Dict[str, Any]: 响应结果
120
+ """
121
+ # 生成唯一请求ID
122
+ req_id = self._get_next_request_id()
123
+
124
+ # 创建事件标志,用于等待响应
125
+ event = threading.Event()
126
+
127
+ with self.event_lock:
128
+ self.pending_requests[req_id] = event
129
+
130
+ try:
131
+ # 构建请求
132
+ request = {
133
+ 'jsonrpc': '2.0',
134
+ 'method': method,
135
+ 'params': params,
136
+ 'id': req_id
137
+ }
138
+
139
+ # 发送请求到Streamable HTTP端点
140
+ mcp_url = urljoin(self.base_url, 'mcp')
141
+ response = self.session.post(
142
+ mcp_url,
143
+ json=request,
144
+ stream=True # 启用流式传输
145
+ )
146
+ response.raise_for_status()
147
+
148
+ # 处理流式响应
149
+ result = None
150
+ for line in response.iter_lines(decode_unicode=True):
151
+ if line:
152
+ try:
153
+ data = json.loads(line)
154
+ if 'id' in data and data['id'] == req_id:
155
+ # 这是我们的请求响应
156
+ result = data
157
+ break
158
+ elif 'method' in data:
159
+ # 这是一个通知
160
+ method = data.get('method', '')
161
+ params = data.get('params', {})
162
+ if method in self.notification_handlers:
163
+ for handler in self.notification_handlers[method]:
164
+ try:
165
+ handler(params)
166
+ except Exception as e:
167
+ PrettyOutput.print(
168
+ f"处理通知时出错 ({method}): {e}",
169
+ OutputType.ERROR
170
+ )
171
+ except json.JSONDecodeError:
172
+ PrettyOutput.print(f"无法解析响应: {line}", OutputType.WARNING)
173
+ continue
174
+
175
+ if result is None:
176
+ raise RuntimeError(f"未收到响应: {method}")
177
+
178
+ return result
179
+
180
+ except Exception as e:
181
+ PrettyOutput.print(f"发送请求失败: {str(e)}", OutputType.ERROR)
182
+ raise
183
+ finally:
184
+ # 清理请求状态
185
+ with self.event_lock:
186
+ self.pending_requests.pop(req_id, None)
187
+ self.request_results.pop(req_id, None)
188
+
189
+ def _send_notification(self, method: str, params: Dict[str, Any]) -> None:
190
+ """发送通知到MCP服务器(不需要响应)
191
+
192
+ 参数:
193
+ method: 通知方法
194
+ params: 通知参数
195
+ """
196
+ try:
197
+ # 构建通知
198
+ notification = {
199
+ 'jsonrpc': '2.0',
200
+ 'method': method,
201
+ 'params': params
202
+ }
203
+
204
+ # 发送通知到Streamable HTTP端点
205
+ mcp_url = urljoin(self.base_url, 'mcp')
206
+ response = self.session.post(
207
+ mcp_url,
208
+ json=notification
209
+ )
210
+ response.raise_for_status()
211
+
212
+ except Exception as e:
213
+ PrettyOutput.print(f"发送通知失败: {str(e)}", OutputType.ERROR)
214
+ raise
215
+
216
+ def get_tool_list(self) -> List[Dict[str, Any]]:
217
+ """获取工具列表
218
+
219
+ 返回:
220
+ List[Dict[str, Any]]: 工具列表,每个工具包含以下字段:
221
+ - name: str - 工具名称
222
+ - description: str - 工具描述
223
+ - parameters: Dict - 工具参数
224
+ """
225
+ try:
226
+ response = self._send_request('tools/list', {})
227
+ if 'result' in response and 'tools' in response['result']:
228
+ # 注意这里: 响应结构是 response['result']['tools']
229
+ tools = response['result']['tools']
230
+ # 将MCP协议字段转换为内部格式
231
+ formatted_tools = []
232
+ for tool in tools:
233
+ # 从inputSchema中提取参数定义
234
+ input_schema = tool.get('inputSchema', {})
235
+ parameters = {}
236
+ if 'properties' in input_schema:
237
+ parameters = input_schema['properties']
238
+
239
+ formatted_tools.append({
240
+ 'name': tool.get('name', ''),
241
+ 'description': tool.get('description', ''),
242
+ 'parameters': parameters
243
+ })
244
+ return formatted_tools
245
+ else:
246
+ error_msg = "获取工具列表失败"
247
+ if 'error' in response:
248
+ error_msg += f": {response['error']}"
249
+ elif 'result' in response:
250
+ error_msg += f": 响应格式不正确 - {response['result']}"
251
+ else:
252
+ error_msg += ": 未知错误"
253
+
254
+ PrettyOutput.print(error_msg, OutputType.ERROR)
255
+ return []
256
+ except Exception as e:
257
+ PrettyOutput.print(f"获取工具列表失败: {str(e)}", OutputType.ERROR)
258
+ return []
259
+
260
+ def execute(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
261
+ """执行工具
262
+
263
+ 参数:
264
+ tool_name: 工具名称
265
+ arguments: 参数字典,包含工具执行所需的参数
266
+
267
+ 返回:
268
+ Dict[str, Any]: 执行结果,包含以下字段:
269
+ - success: bool - 是否执行成功
270
+ - stdout: str - 标准输出
271
+ - stderr: str - 标准错误
272
+ """
273
+ try:
274
+ response = self._send_request('tools/call', {
275
+ 'name': tool_name,
276
+ 'arguments': arguments
277
+ })
278
+ if 'result' in response:
279
+ result = response['result']
280
+ # 从content中提取输出信息
281
+ stdout = ''
282
+ stderr = ''
283
+ for content in result.get('content', []):
284
+ if content.get('type') == 'text':
285
+ stdout += content.get('text', '')
286
+ elif content.get('type') == 'error':
287
+ stderr += content.get('text', '')
288
+
289
+ return {
290
+ 'success': True,
291
+ 'stdout': stdout,
292
+ 'stderr': stderr
293
+ }
294
+ else:
295
+ return {
296
+ 'success': False,
297
+ 'stdout': '',
298
+ 'stderr': response.get('error', 'Unknown error')
299
+ }
300
+ except Exception as e:
301
+ PrettyOutput.print(f"执行工具失败: {str(e)}", OutputType.ERROR)
302
+ return {
303
+ 'success': False,
304
+ 'stdout': '',
305
+ 'stderr': str(e)
306
+ }
307
+
308
+ def get_resource_list(self) -> List[Dict[str, Any]]:
309
+ """获取资源列表
310
+
311
+ 返回:
312
+ List[Dict[str, Any]]: 资源列表,每个资源包含以下字段:
313
+ - uri: str - 资源的唯一标识符
314
+ - name: str - 资源的名称
315
+ - description: str - 资源的描述(可选)
316
+ - mimeType: str - 资源的MIME类型(可选)
317
+ """
318
+ try:
319
+ response = self._send_request('resources/list', {})
320
+ if 'result' in response and 'resources' in response['result']:
321
+ return response['result']['resources']
322
+ else:
323
+ error_msg = "获取资源列表失败"
324
+ if 'error' in response:
325
+ error_msg += f": {response['error']}"
326
+ else:
327
+ error_msg += ": 未知错误"
328
+ PrettyOutput.print(error_msg, OutputType.ERROR)
329
+ return []
330
+ except Exception as e:
331
+ PrettyOutput.print(f"获取资源列表失败: {str(e)}", OutputType.ERROR)
332
+ return []
333
+
334
+ def get_resource(self, uri: str) -> Dict[str, Any]:
335
+ """获取指定资源的内容
336
+
337
+ 参数:
338
+ uri: str - 资源的URI标识符
339
+
340
+ 返回:
341
+ Dict[str, Any]: 执行结果,包含以下字段:
342
+ - success: bool - 是否执行成功
343
+ - stdout: str - 资源内容(文本或base64编码的二进制内容)
344
+ - stderr: str - 错误信息
345
+ """
346
+ try:
347
+ response = self._send_request('resources/read', {
348
+ 'uri': uri
349
+ })
350
+ if 'result' in response and 'contents' in response['result']:
351
+ contents = response['result']['contents']
352
+ if contents:
353
+ content = contents[0] # 获取第一个资源内容
354
+ # 根据资源类型返回内容
355
+ if 'text' in content:
356
+ return {
357
+ 'success': True,
358
+ 'stdout': content['text'],
359
+ 'stderr': ''
360
+ }
361
+ elif 'blob' in content:
362
+ return {
363
+ 'success': True,
364
+ 'stdout': content['blob'],
365
+ 'stderr': ''
366
+ }
367
+ return {
368
+ 'success': False,
369
+ 'stdout': '',
370
+ 'stderr': '资源内容为空'
371
+ }
372
+ else:
373
+ error_msg = "获取资源内容失败"
374
+ if 'error' in response:
375
+ error_msg += f": {response['error']}"
376
+ else:
377
+ error_msg += ": 未知错误"
378
+ PrettyOutput.print(error_msg, OutputType.ERROR)
379
+ return {
380
+ 'success': False,
381
+ 'stdout': '',
382
+ 'stderr': error_msg
383
+ }
384
+ except Exception as e:
385
+ error_msg = f"获取资源内容失败: {str(e)}"
386
+ PrettyOutput.print(error_msg, OutputType.ERROR)
387
+ return {
388
+ 'success': False,
389
+ 'stdout': '',
390
+ 'stderr': error_msg
391
+ }
392
+
393
+ def __del__(self):
394
+ """清理资源"""
395
+ # 清理请求状态
396
+ with self.event_lock:
397
+ for event in self.pending_requests.values():
398
+ event.set() # 释放所有等待的请求
399
+ self.pending_requests.clear()
400
+ self.request_results.clear()
401
+
402
+ # 关闭HTTP会话
403
+ if self.session:
404
+ self.session.close()
@@ -8,18 +8,19 @@
8
8
  - 列出所有方法论
9
9
  """
10
10
 
11
+ import argparse
11
12
  import hashlib
12
- import os
13
13
  import json
14
- import argparse
15
- import yaml # type: ignore
16
- from jarvis.jarvis_utils.methodology import (
17
- _get_methodology_directory,
18
- _load_all_methodologies
19
- )
14
+ import os
15
+
16
+ import yaml # type: ignore
17
+ from yaspin import yaspin # type: ignore
18
+
20
19
  from jarvis.jarvis_platform.registry import PlatformRegistry
21
- from jarvis.jarvis_utils.output import PrettyOutput, OutputType
22
- from yaspin import yaspin # type: ignore
20
+ from jarvis.jarvis_utils.methodology import (_get_methodology_directory,
21
+ _load_all_methodologies)
22
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
23
+
23
24
 
24
25
  def import_methodology(input_file):
25
26
  """导入方法论文件(合并策略)"""
@@ -1,8 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import yaml
3
+
3
4
  from jarvis.jarvis_multi_agent import MultiAgent
4
- from jarvis.jarvis_utils.utils import init_env
5
5
  from jarvis.jarvis_utils.input import get_multiline_input
6
+ from jarvis.jarvis_utils.utils import init_env
7
+
6
8
 
7
9
  def main():
8
10
  """从YAML配置文件初始化并运行多智能体系统
@@ -1,19 +1,23 @@
1
1
  # -*- coding: utf-8 -*-
2
- from abc import ABC, abstractmethod
3
2
  import re
3
+ from abc import ABC, abstractmethod
4
4
  from typing import Generator, List, Tuple
5
5
 
6
+ from rich import box
7
+ from rich.live import Live
8
+ from rich.panel import Panel
9
+ from rich.text import Text
6
10
  from yaspin import yaspin
7
11
 
8
- from jarvis.jarvis_utils.config import get_max_input_token_count, get_pretty_output
12
+ from jarvis.jarvis_utils.config import (get_max_input_token_count,
13
+ get_pretty_output, is_print_prompt)
9
14
  from jarvis.jarvis_utils.embedding import split_text_into_chunks
10
15
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
11
- from jarvis.jarvis_utils.utils import get_context_token_count, is_context_overflow, while_success, while_true
12
- from jarvis.jarvis_utils.tag import ot, ct
13
- from rich.live import Live
14
- from rich.text import Text
15
- from rich.panel import Panel
16
- from rich import box
16
+ from jarvis.jarvis_utils.tag import ct, ot
17
+ from jarvis.jarvis_utils.utils import (get_context_token_count,
18
+ is_context_overflow, while_success,
19
+ while_true)
20
+
17
21
 
18
22
  class BasePlatform(ABC):
19
23
  """Base class for large language models"""
@@ -122,6 +126,8 @@ class BasePlatform(ABC):
122
126
  return response
123
127
 
124
128
  def chat_until_success(self, message: str) -> str:
129
+ if is_print_prompt():
130
+ PrettyOutput.print(f"{message}", OutputType.USER)
125
131
  return while_true(lambda: while_success(lambda: self._chat(message), 5), 5)
126
132
 
127
133
  @abstractmethod
@@ -1,11 +1,13 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Generator, List, Tuple
3
2
  import random
4
3
  import string
4
+ from typing import Generator, List, Tuple
5
+
5
6
  from jarvis.jarvis_platform.base import BasePlatform
6
7
  from jarvis.jarvis_utils.input import get_multiline_input
7
8
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
9
 
10
+
9
11
  class HumanPlatform(BasePlatform):
10
12
  """人类交互平台实现,模拟大模型但实际上与人交互"""
11
13
 
@@ -1,18 +1,21 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Generator, List, Tuple
3
- import requests # type: ignore
4
2
  import json
5
- import os
6
3
  import mimetypes
4
+ import os
7
5
  import time
6
+ from typing import Dict, Generator, List, Tuple
7
+
8
+ import requests # type: ignore
9
+ from rich import box
8
10
  from rich.live import Live
9
- from rich.text import Text
10
11
  from rich.panel import Panel
11
- from rich import box
12
+ from rich.text import Text
13
+
12
14
  from jarvis.jarvis_platform.base import BasePlatform
15
+ from jarvis.jarvis_utils.config import get_data_dir
13
16
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
14
17
  from jarvis.jarvis_utils.utils import while_success
15
- from jarvis.jarvis_utils.config import get_data_dir
18
+
16
19
 
17
20
  class KimiModel(BasePlatform):
18
21
  """Kimi model implementation"""
@@ -183,7 +186,7 @@ class KimiModel(BasePlatform):
183
186
  if not file_list:
184
187
  return True
185
188
 
186
- from yaspin import yaspin # type: ignore
189
+ from yaspin import yaspin # type: ignore
187
190
 
188
191
  if not self.chat_id:
189
192
  with yaspin(text="创建聊天会话...", color="yellow") as spinner:
@@ -1,14 +1,13 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Generator, List, Tuple
3
2
  import os
3
+ from typing import Dict, Generator, List, Tuple
4
+
4
5
  from openai import OpenAI
5
- from rich.live import Live
6
- from rich.text import Text
7
- from rich.panel import Panel
8
- from rich import box
6
+
9
7
  from jarvis.jarvis_platform.base import BasePlatform
10
8
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
11
9
 
10
+
12
11
  class OpenAIModel(BasePlatform):
13
12
  platform_name = "openai"
14
13
 
@@ -49,10 +48,27 @@ class OpenAIModel(BasePlatform):
49
48
  self.system_message = ""
50
49
 
51
50
  def upload_files(self, file_list: List[str]) -> bool:
51
+ """
52
+ 上传文件到OpenAI平台
53
+
54
+ 参数:
55
+ file_list: 需要上传的文件路径列表
56
+
57
+ 返回:
58
+ bool: 上传是否成功 (当前实现始终返回False)
59
+ """
52
60
  return False
53
61
 
54
62
  def get_model_list(self) -> List[Tuple[str, str]]:
55
- """Get model list"""
63
+ """
64
+ 获取可用的OpenAI模型列表
65
+
66
+ 返回:
67
+ List[Tuple[str, str]]: 模型ID和名称的元组列表
68
+
69
+ 异常:
70
+ 当API调用失败时会打印错误信息并返回空列表
71
+ """
56
72
  try:
57
73
  models = self.client.models.list()
58
74
  model_list = []
@@ -64,17 +80,41 @@ class OpenAIModel(BasePlatform):
64
80
  return []
65
81
 
66
82
  def set_model_name(self, model_name: str):
67
- """Set model name"""
83
+ """
84
+ 设置当前使用的模型名称
85
+
86
+ 参数:
87
+ model_name: 要设置的模型名称
88
+ """
68
89
 
69
90
  self.model_name = model_name
70
91
 
71
92
  def set_system_message(self, message: str):
72
- """Set system message"""
93
+ """
94
+ 设置系统消息(角色设定)
95
+
96
+ 参数:
97
+ message: 系统消息内容
98
+
99
+ 说明:
100
+ 设置后会立即添加到消息历史中
101
+ """
73
102
  self.system_message = message
74
103
  self.messages.append({"role": "system", "content": self.system_message})
75
104
 
76
105
  def chat(self, message: str) -> Generator[str, None, None]:
77
- """Execute conversation"""
106
+ """
107
+ 执行对话并返回生成器
108
+
109
+ 参数:
110
+ message: 用户输入的消息内容
111
+
112
+ 返回:
113
+ Generator[str, None, None]: 生成器,逐块返回AI响应内容
114
+
115
+ 异常:
116
+ 当API调用失败时会抛出异常并打印错误信息
117
+ """
78
118
  try:
79
119
 
80
120
  # Add user message to history
@@ -103,12 +143,25 @@ class OpenAIModel(BasePlatform):
103
143
  raise Exception(f"Chat failed: {str(e)}")
104
144
 
105
145
  def name(self) -> str:
106
- """Return model name"""
146
+ """
147
+ 获取当前使用的模型名称
148
+
149
+ 返回:
150
+ str: 当前配置的模型名称
151
+ """
107
152
  return self.model_name
108
153
 
109
154
 
110
155
  def delete_chat(self)->bool:
111
- """Delete conversation"""
156
+ """
157
+ 删除当前对话历史
158
+
159
+ 返回:
160
+ bool: 操作是否成功
161
+
162
+ 说明:
163
+ 如果设置了系统消息,会保留系统消息
164
+ """
112
165
  if self.system_message:
113
166
  self.messages = [{"role": "system", "content": self.system_message}]
114
167
  else:
@@ -116,4 +169,10 @@ class OpenAIModel(BasePlatform):
116
169
  return True
117
170
 
118
171
  def support_web(self) -> bool:
172
+ """
173
+ 检查是否支持网页访问功能
174
+
175
+ 返回:
176
+ bool: 当前是否支持网页访问 (OpenAI平台始终返回False)
177
+ """
119
178
  return False
@@ -3,9 +3,13 @@ import importlib
3
3
  import inspect
4
4
  import os
5
5
  import sys
6
- from typing import Dict, Type, Optional, List
6
+ from typing import Dict, List, Optional, Type
7
+
7
8
  from jarvis.jarvis_platform.base import BasePlatform
8
- from jarvis.jarvis_utils.config import get_normal_model_name, get_normal_platform_name, get_thinking_model_name, get_thinking_platform_name, get_data_dir
9
+ from jarvis.jarvis_utils.config import (get_data_dir, get_normal_model_name,
10
+ get_normal_platform_name,
11
+ get_thinking_model_name,
12
+ get_thinking_platform_name)
9
13
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
10
14
 
11
15
  REQUIRED_METHODS = [