jarvis-ai-assistant 0.1.178__py3-none-any.whl → 0.1.180__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 (66) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +130 -79
  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_data/config_schema.json +260 -0
  11. jarvis/jarvis_dev/main.py +1 -8
  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 +25 -24
  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 +8 -27
  23. jarvis/jarvis_platform/openai.py +4 -16
  24. jarvis/jarvis_platform/registry.py +6 -2
  25. jarvis/jarvis_platform/yuanbao.py +9 -29
  26. jarvis/jarvis_platform_manager/main.py +11 -9
  27. jarvis/jarvis_smart_shell/main.py +7 -3
  28. jarvis/jarvis_tools/ask_codebase.py +4 -3
  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 +4 -4
  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 +60 -45
  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 +88 -17
  52. jarvis/jarvis_utils/embedding.py +4 -3
  53. jarvis/jarvis_utils/file_processors.py +1 -0
  54. jarvis/jarvis_utils/git_utils.py +83 -40
  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 +140 -24
  60. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/METADATA +66 -59
  61. jarvis_ai_assistant-0.1.180.dist-info/RECORD +99 -0
  62. jarvis_ai_assistant-0.1.178.dist-info/RECORD +0 -96
  63. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/WHEEL +0 -0
  64. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/entry_points.txt +0 -0
  65. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/licenses/LICENSE +0 -0
  66. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,14 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Any, Dict, List, Callable
3
- import requests
4
2
  import json
5
3
  import threading
6
4
  import time
7
- from urllib.parse import urljoin, urlencode, parse_qs
8
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
5
+ from typing import Any, Callable, Dict, List
6
+ from urllib.parse import parse_qs, urlencode, urljoin
7
+
8
+ import requests
9
+
9
10
  from jarvis.jarvis_mcp import McpClient
11
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
10
12
 
11
13
 
12
14
  class SSEMcpClient(McpClient):
@@ -1,10 +1,11 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Any, Dict, List
3
- import subprocess
4
- import os
5
2
  import json
6
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
3
+ import os
4
+ import subprocess
5
+ from typing import Any, Dict, List
6
+
7
7
  from jarvis.jarvis_mcp import McpClient
8
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
9
 
9
10
 
10
11
  class StdioMcpClient(McpClient):
@@ -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,17 @@
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
8
- from rich.live import Live
9
- from rich.text import Text
10
- from rich.panel import Panel
11
- from rich import box
6
+ from typing import Dict, Generator, List, Tuple
7
+
8
+ import requests # type: ignore
9
+
12
10
  from jarvis.jarvis_platform.base import BasePlatform
11
+ from jarvis.jarvis_utils.config import get_data_dir
13
12
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
14
13
  from jarvis.jarvis_utils.utils import while_success
15
- from jarvis.jarvis_utils.config import get_data_dir
14
+
16
15
 
17
16
  class KimiModel(BasePlatform):
18
17
  """Kimi model implementation"""
@@ -34,24 +33,6 @@ class KimiModel(BasePlatform):
34
33
  self.chat_id = ""
35
34
  self.api_key = os.getenv("KIMI_API_KEY")
36
35
  if not self.api_key:
37
- message = (
38
- "需要设置 KIMI_API_KEY 才能使用 Jarvis。请按照以下步骤操作:\n"
39
- "1. 获取 Kimi API Key:\n"
40
- " • 访问 Kimi AI 平台: https://kimi.moonshot.cn\n"
41
- " • 登录您的账户\n"
42
- " • 打开浏览器开发者工具 (F12 或右键 -> 检查)\n"
43
- " • 切换到网络标签\n"
44
- " • 发送任意消息\n"
45
- " • 在请求中找到 Authorization 头\n"
46
- " • 复制 token 值(去掉 'Bearer ' 前缀)\n"
47
- "2. 设置环境变量:\n"
48
- " • 方法 1: 创建或编辑配置文件:\n"
49
- f" echo 'KIMI_API_KEY=your_key_here' > {get_data_dir()}/env\n"
50
- " • 方法 2: 直接设置环境变量:\n"
51
- " export KIMI_API_KEY=your_key_here\n"
52
- "设置后,重新运行 Jarvis。"
53
- )
54
- PrettyOutput.print(message, OutputType.INFO)
55
36
  PrettyOutput.print("KIMI_API_KEY 未设置", OutputType.WARNING)
56
37
  self.auth_header = f"Bearer {self.api_key}"
57
38
  self.uploaded_files = [] # 存储已上传文件的信息
@@ -183,7 +164,7 @@ class KimiModel(BasePlatform):
183
164
  if not file_list:
184
165
  return True
185
166
 
186
- from yaspin import yaspin # type: ignore
167
+ from yaspin import yaspin # type: ignore
187
168
 
188
169
  if not self.chat_id:
189
170
  with yaspin(text="创建聊天会话...", color="yellow") as spinner:
@@ -1,10 +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
6
+
5
7
  from jarvis.jarvis_platform.base import BasePlatform
6
8
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
7
9
 
10
+
8
11
  class OpenAIModel(BasePlatform):
9
12
  platform_name = "openai"
10
13
 
@@ -16,21 +19,6 @@ class OpenAIModel(BasePlatform):
16
19
  self.system_message = ""
17
20
  self.api_key = os.getenv("OPENAI_API_KEY")
18
21
  if not self.api_key:
19
- message = (
20
- "需要设置以下环境变量才能使用 OpenAI 模型:\n"
21
- " • OPENAI_API_KEY: API 密钥\n"
22
- " • OPENAI_API_BASE: (可选) API 基础地址, 默认使用 https://api.openai.com/v1\n"
23
- "您可以通过以下方式设置它们:\n"
24
- "1. 创建或编辑 ~/.jarvis/env 文件:\n"
25
- " OPENAI_API_KEY=your_api_key\n"
26
- " OPENAI_API_BASE=your_api_base\n"
27
- " OPENAI_MODEL_NAME=your_model_name\n"
28
- "2. 直接设置环境变量:\n"
29
- " export OPENAI_API_KEY=your_api_key\n"
30
- " export OPENAI_API_BASE=your_api_base\n"
31
- " export OPENAI_MODEL_NAME=your_model_name"
32
- )
33
- PrettyOutput.print(message, OutputType.INFO)
34
22
  PrettyOutput.print("OPENAI_API_KEY 未设置", OutputType.WARNING)
35
23
 
36
24
  self.base_url = os.getenv("OPENAI_API_BASE", "https://api.openai.com/v1")
@@ -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 = [