jarvis-ai-assistant 0.2.1__py3-none-any.whl → 0.2.3__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 (41) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/jarvis.py +61 -59
  3. jarvis/jarvis_agent/main.py +42 -40
  4. jarvis/jarvis_agent/prompts.py +26 -4
  5. jarvis/jarvis_code_agent/code_agent.py +35 -31
  6. jarvis/jarvis_code_analysis/code_review.py +73 -39
  7. jarvis/jarvis_data/config_schema.json +67 -12
  8. jarvis/jarvis_git_squash/main.py +16 -12
  9. jarvis/jarvis_git_utils/git_commiter.py +25 -20
  10. jarvis/jarvis_methodology/main.py +34 -49
  11. jarvis/jarvis_multi_agent/main.py +28 -23
  12. jarvis/jarvis_platform/ai8.py +31 -22
  13. jarvis/jarvis_platform/kimi.py +31 -61
  14. jarvis/jarvis_platform/tongyi.py +71 -85
  15. jarvis/jarvis_platform/yuanbao.py +44 -50
  16. jarvis/jarvis_platform_manager/main.py +55 -90
  17. jarvis/jarvis_rag/cli.py +79 -23
  18. jarvis/jarvis_rag/query_rewriter.py +61 -12
  19. jarvis/jarvis_rag/rag_pipeline.py +143 -34
  20. jarvis/jarvis_rag/retriever.py +5 -5
  21. jarvis/jarvis_smart_shell/main.py +58 -87
  22. jarvis/jarvis_tools/cli/main.py +120 -153
  23. jarvis/jarvis_tools/generate_new_tool.py +22 -1
  24. jarvis/jarvis_tools/registry.py +1 -7
  25. jarvis/jarvis_tools/search_web.py +12 -10
  26. jarvis/jarvis_utils/config.py +92 -11
  27. jarvis/jarvis_utils/globals.py +29 -8
  28. jarvis/jarvis_utils/http.py +58 -79
  29. jarvis/jarvis_utils/input.py +114 -121
  30. jarvis/jarvis_utils/output.py +1 -1
  31. jarvis/jarvis_utils/utils.py +3 -0
  32. jarvis_ai_assistant-0.2.3.dist-info/METADATA +301 -0
  33. {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.3.dist-info}/RECORD +37 -40
  34. {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.3.dist-info}/entry_points.txt +0 -2
  35. jarvis/jarvis_git_details/__init__.py +0 -0
  36. jarvis/jarvis_git_details/main.py +0 -265
  37. jarvis/jarvis_platform/oyi.py +0 -357
  38. jarvis_ai_assistant-0.2.1.dist-info/METADATA +0 -845
  39. {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.3.dist-info}/WHEEL +0 -0
  40. {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.3.dist-info}/licenses/LICENSE +0 -0
  41. {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.3.dist-info}/top_level.txt +0 -0
@@ -1,357 +0,0 @@
1
- import mimetypes
2
- import os
3
- from typing import Dict, Generator, List, Tuple
4
- from jarvis.jarvis_platform.base import BasePlatform
5
- import json
6
-
7
- from jarvis.jarvis_utils import http
8
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
- from jarvis.jarvis_utils.utils import while_success
10
-
11
-
12
- class OyiModel(BasePlatform):
13
- """Oyi model implementation"""
14
-
15
- BASE_URL = "https://api-10086.rcouyi.com"
16
-
17
- def get_model_list(self) -> List[Tuple[str, str]]:
18
- """Get model list"""
19
- self.get_available_models()
20
- return [(name, info["desc"]) for name, info in self.models.items()]
21
-
22
- def __init__(self):
23
- """Initialize model"""
24
- super().__init__()
25
- self.models = {}
26
- self.messages = []
27
- self.system_prompt = ""
28
- self.conversation = None
29
- self.first_chat = True
30
-
31
- self.token = os.getenv("OYI_API_KEY")
32
- if not self.token:
33
- PrettyOutput.print("OYI_API_KEY 未设置", OutputType.WARNING)
34
-
35
- self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-chat"
36
- if self.model_name not in [m.split()[0] for m in self.get_available_models()]:
37
- PrettyOutput.print(
38
- f"警告: 选择的模型 {self.model_name} 不在可用列表中", OutputType.WARNING
39
- )
40
-
41
- def set_model_name(self, model_name: str):
42
- """Set model name"""
43
-
44
- self.model_name = model_name
45
-
46
- def create_conversation(self) -> bool:
47
- """Create a new conversation"""
48
- try:
49
- headers = {
50
- "Authorization": f"Bearer {self.token}",
51
- "Content-Type": "application/json",
52
- "Accept": "application/json",
53
- "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",
54
- }
55
-
56
- payload = {
57
- "id": 0,
58
- "roleId": 0,
59
- "title": "New conversation",
60
- "isLock": False,
61
- "systemMessage": "",
62
- "params": json.dumps(
63
- {
64
- "model": self.model_name,
65
- "is_webSearch": True,
66
- "message": [],
67
- "systemMessage": None,
68
- "requestMsgCount": 65536,
69
- "temperature": 0.8,
70
- "speechVoice": "Alloy",
71
- "max_tokens": 8192,
72
- "chatPluginIds": [],
73
- }
74
- ),
75
- }
76
-
77
- response = while_success(
78
- lambda: http.post(
79
- f"{self.BASE_URL}/chatapi/chat/save", headers=headers, json=payload
80
- ),
81
- sleep_time=5,
82
- )
83
-
84
- data = response.json()
85
- if data["code"] == 200 and data["type"] == "success":
86
- self.conversation = data
87
- return True
88
- else:
89
- PrettyOutput.print(
90
- f"创建会话失败: {data['message']}", OutputType.WARNING
91
- )
92
- return False
93
-
94
- except Exception as e:
95
- PrettyOutput.print(f"创建会话失败: {str(e)}", OutputType.ERROR)
96
- return False
97
-
98
- def set_system_prompt(self, message: str):
99
- """Set system message"""
100
- self.system_prompt = message
101
-
102
- def chat(self, message: str) -> Generator[str, None, None]:
103
- """Execute chat with the model
104
-
105
- Args:
106
- message: User input message
107
-
108
- Returns:
109
- str: Model response
110
- """
111
- try:
112
- # 确保有会话ID
113
- if not self.conversation:
114
- if not self.create_conversation():
115
- raise Exception("Failed to create conversation")
116
-
117
- # 1. 发送消息
118
- headers = {
119
- "Authorization": f"Bearer {self.token}",
120
- "Content-Type": "application/json",
121
- "Accept": "application/json, text/plain, */*",
122
- "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",
123
- "Origin": "https://ai.rcouyi.com",
124
- "Referer": "https://ai.rcouyi.com/",
125
- }
126
-
127
- payload = {
128
- "topicId": (
129
- self.conversation["result"]["id"] if self.conversation else None
130
- ),
131
- "messages": self.messages,
132
- "content": message,
133
- "contentFiles": [],
134
- }
135
-
136
- # 如果有上传的文件,添加到请求中
137
- if self.first_chat:
138
- message = self.system_prompt + "\n" + message
139
- payload["content"] = message
140
- self.first_chat = False
141
-
142
- self.messages.append({"role": "user", "content": message})
143
-
144
- # 发送消息
145
- response = while_success(
146
- lambda: http.post(
147
- f"{self.BASE_URL}/chatapi/chat/message",
148
- headers=headers,
149
- json=payload,
150
- ),
151
- sleep_time=5,
152
- )
153
-
154
- data = response.json()
155
- if data["code"] != 200 or data["type"] != "success":
156
- error_msg = f"聊天失败: {data.get('message', '未知错误')}"
157
- PrettyOutput.print(error_msg, OutputType.WARNING)
158
- raise Exception(error_msg)
159
-
160
- message_id = data["result"][-1]
161
-
162
- # 获取响应内容
163
- response = while_success(
164
- lambda: http.stream_post(
165
- f"{self.BASE_URL}/chatapi/chat/message/{message_id}",
166
- headers=headers,
167
- ),
168
- sleep_time=5,
169
- )
170
-
171
- full_response = ""
172
- bin = b""
173
- for chunk in response:
174
- if chunk:
175
- bin += chunk
176
- try:
177
- text = bin.decode("utf-8")
178
- except UnicodeDecodeError:
179
- continue
180
- full_response += text
181
- bin = b""
182
- yield text
183
-
184
- self.messages.append({"role": "assistant", "content": full_response})
185
- return None
186
- except Exception as e:
187
- PrettyOutput.print(f"聊天失败: {str(e)}", OutputType.ERROR)
188
- raise e
189
-
190
- def name(self) -> str:
191
- """Return model name"""
192
- return self.model_name
193
-
194
- @classmethod
195
- def platform_name(cls) -> str:
196
- """Return platform name"""
197
- return "oyi"
198
-
199
- def delete_chat(self) -> bool:
200
- """Delete current chat session"""
201
- try:
202
- if not self.conversation:
203
- return True
204
-
205
- headers = {
206
- "Authorization": f"Bearer {self.token}",
207
- "Content-Type": "application/json",
208
- "Accept": "application/json, text/plain, */*",
209
- "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",
210
- "Origin": "https://ai.rcouyi.com",
211
- "Referer": "https://ai.rcouyi.com/",
212
- }
213
-
214
- response = while_success(
215
- lambda: http.post(
216
- f"{self.BASE_URL}/chatapi/chat/{self.conversation['result']['id']}", # type: ignore
217
- headers=headers,
218
- json={},
219
- ),
220
- sleep_time=5,
221
- )
222
-
223
- data = response.json()
224
- if data["code"] == 200 and data["type"] == "success":
225
- self.messages = []
226
- self.conversation = None
227
- self.first_chat = True
228
- return True
229
- else:
230
- error_msg = f"删除会话失败: {data.get('message', '未知错误')}"
231
- PrettyOutput.print(error_msg, OutputType.WARNING)
232
- return False
233
-
234
- except Exception as e:
235
- PrettyOutput.print(f"删除会话失败: {str(e)}", OutputType.ERROR)
236
- return False
237
-
238
- def save(self, file_path: str) -> bool:
239
- """Save chat session to a file."""
240
- if not self.conversation:
241
- PrettyOutput.print("没有活动的会话可供保存", OutputType.WARNING)
242
- return False
243
-
244
- state = {
245
- "conversation": self.conversation,
246
- "messages": self.messages,
247
- "model_name": self.model_name,
248
- "system_prompt": self.system_prompt,
249
- "first_chat": self.first_chat,
250
- }
251
-
252
- try:
253
- with open(file_path, "w", encoding="utf-8") as f:
254
- json.dump(state, f, ensure_ascii=False, indent=4)
255
- self._saved = True
256
- PrettyOutput.print(f"会话已成功保存到 {file_path}", OutputType.SUCCESS)
257
- return True
258
- except Exception as e:
259
- PrettyOutput.print(f"保存会话失败: {str(e)}", OutputType.ERROR)
260
- return False
261
-
262
- def restore(self, file_path: str) -> bool:
263
- """Restore chat session from a file."""
264
- try:
265
- with open(file_path, "r", encoding="utf-8") as f:
266
- state = json.load(f)
267
-
268
- self.conversation = state.get("conversation")
269
- self.messages = state.get("messages", [])
270
- self.model_name = state.get("model_name", "deepseek-chat")
271
- self.system_prompt = state.get("system_prompt", "")
272
- self.first_chat = state.get("first_chat", True)
273
- self._saved = True
274
-
275
- PrettyOutput.print(f"从 {file_path} 成功恢复会话", OutputType.SUCCESS)
276
- return True
277
- except FileNotFoundError:
278
- PrettyOutput.print(f"会话文件未找到: {file_path}", OutputType.ERROR)
279
- return False
280
- except Exception as e:
281
- PrettyOutput.print(f"恢复会话失败: {str(e)}", OutputType.ERROR)
282
- return False
283
-
284
- def get_available_models(self) -> List[str]:
285
- """Get available model list
286
-
287
- Returns:
288
- List[str]: Available model name list
289
- """
290
- try:
291
- if self.models:
292
- return list(self.models.keys())
293
-
294
- headers = {
295
- "Content-Type": "application/json",
296
- "Accept": "application/json, text/plain, */*",
297
- "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",
298
- "Origin": "https://ai.rcouyi.com",
299
- "Referer": "https://ai.rcouyi.com/",
300
- }
301
-
302
- response = while_success(
303
- lambda: http.get(
304
- "https://ai.rcouyi.com/config/system.json", headers=headers
305
- ),
306
- sleep_time=5,
307
- )
308
-
309
- data = response.json()
310
-
311
- # 保存模型信息
312
- self.models = {
313
- model["value"]: model
314
- for model in data.get("model", [])
315
- if model.get("enable", False) # 只保存启用的模型
316
- }
317
-
318
- # 格式化显示
319
- models = []
320
- for model in self.models.values():
321
- # 基本信息
322
- model_name = model["value"]
323
- model_str = model["label"]
324
-
325
- # 添加后缀标签
326
- suffix = model.get("suffix", [])
327
- if suffix:
328
- # 处理新格式的suffix (字典列表)
329
- if suffix and isinstance(suffix[0], dict):
330
- suffix_str = ", ".join(s.get("tag", "") for s in suffix)
331
- # 处理旧格式的suffix (字符串列表)
332
- else:
333
- suffix_str = ", ".join(str(s) for s in suffix)
334
- model_str += f" ({suffix_str})"
335
-
336
- # 添加描述或提示
337
- info = model.get("tooltip") or model.get("description", "")
338
- if info:
339
- model_str += f" - {info}"
340
-
341
- model["desc"] = model_str
342
- models.append(model_name)
343
-
344
- return sorted(models)
345
-
346
- except Exception as e:
347
- PrettyOutput.print(f"获取模型列表失败: {str(e)}", OutputType.WARNING)
348
- return []
349
-
350
- def support_upload_files(self) -> bool:
351
- return False
352
-
353
- def support_web(self) -> bool:
354
- return False
355
-
356
- def upload_files(self, file_list: List[str]) -> bool:
357
- return False