jarvis-ai-assistant 0.1.183__py3-none-any.whl → 0.1.184__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.
jarvis/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Jarvis AI Assistant"""
3
3
 
4
- __version__ = "0.1.183"
4
+ __version__ = "0.1.184"
@@ -3,8 +3,11 @@ import json
3
3
  import os
4
4
  from typing import Any, Dict, Generator, List, Tuple
5
5
  import uuid
6
+ import time
6
7
 
7
8
  import requests
9
+ from yaspin import yaspin
10
+ from yaspin.spinners import Spinners
8
11
 
9
12
  from jarvis.jarvis_platform.base import BasePlatform
10
13
  from jarvis.jarvis_utils.output import PrettyOutput, OutputType
@@ -25,6 +28,8 @@ class TongyiPlatform(BasePlatform):
25
28
  self.msg_id = ""
26
29
  self.model_name = ""
27
30
  self.uploaded_file_info = []
31
+ self.system_message = "" # System message for initialization
32
+ self.first_chat = True # Flag for first chat
28
33
 
29
34
 
30
35
  def _get_base_headers(self):
@@ -81,6 +86,21 @@ class TongyiPlatform(BasePlatform):
81
86
  }
82
87
  }]
83
88
 
89
+ # Add system message if it's first chat
90
+ if self.first_chat and self.system_message:
91
+ contents.insert(0, {
92
+ "content": self.system_message,
93
+ "contentType": "text",
94
+ "role": "system",
95
+ "ext": {
96
+ "searchType": "",
97
+ "pptGenerate": False,
98
+ "deepThink": False,
99
+ "deepResearch": False
100
+ }
101
+ })
102
+ self.first_chat = False
103
+
84
104
  # Add uploaded files to contents if available and clear after use
85
105
  if self.uploaded_file_info:
86
106
  for file_info in self.uploaded_file_info:
@@ -238,96 +258,120 @@ class TongyiPlatform(BasePlatform):
238
258
  uploaded_files = []
239
259
 
240
260
  for file_path in file_list:
241
- if not os.path.exists(file_path):
242
- PrettyOutput.print(f"File not found: {file_path}", OutputType.ERROR)
243
- return False
244
-
245
- # Get file name and content type
246
261
  file_name = os.path.basename(file_path)
247
- content_type = self._get_content_type(file_path)
248
-
249
- # Prepare form data
250
- form_data = {
251
- 'OSSAccessKeyId': upload_token['accessId'],
252
- 'policy': upload_token['policy'],
253
- 'signature': upload_token['signature'],
254
- 'key': f"{upload_token['dir']}{file_name}",
255
- 'dir': upload_token['dir'],
256
- 'success_action_status': '200'
257
- }
258
-
259
- # Prepare files
260
- files = {
261
- 'file': (file_name, open(file_path, 'rb'), content_type)
262
- }
263
-
264
- # Upload file
265
- response = requests.post(
266
- upload_token['host'],
267
- data=form_data,
268
- files=files
269
- )
270
-
271
- if response.status_code != 200:
272
- PrettyOutput.print(f"Failed to upload {file_name}: HTTP {response.status_code}", OutputType.ERROR)
273
- return False
274
-
275
- uploaded_files.append({
276
- 'fileKey': file_name,
277
- 'fileType': 'file',
278
- 'dir': upload_token['dir']
279
- })
280
-
281
- # Get download links for uploaded files
282
- url = "https://api.tongyi.com/dialog/downloadLink/batch"
283
- headers = self._get_base_headers()
284
- payload = {
285
- "fileKeys": [f['fileKey'] for f in uploaded_files],
286
- "fileType": "file",
287
- "dir": upload_token['dir']
288
- }
289
-
290
- response = requests.post(url, headers=headers, json=payload)
291
- if response.status_code != 200:
292
- PrettyOutput.print(f"Failed to get download links: HTTP {response.status_code}", OutputType.ERROR)
293
- return False
294
-
295
- result = response.json()
296
- if not result.get("success"):
297
- PrettyOutput.print(f"Failed to get download links: {result.get('errorMsg')}", OutputType.ERROR)
298
- return False
299
-
300
- # Add files to chat
301
- self.uploaded_file_info = result.get("data", {}).get("results", [])
302
- for file_info in self.uploaded_file_info:
303
- add_url = "https://api.tongyi.com/assistant/api/chat/file/add"
304
- add_payload = {
305
- "workSource": "chat",
306
- "terminal": "web",
307
- "workCode": "0",
308
- "channel": "home",
309
- "workType": "file",
310
- "module": "uploadhistory",
311
- "workName": file_info["fileKey"],
312
- "workId": file_info["docId"],
313
- "workResourcePath": file_info["url"],
314
- "sessionId": "",
315
- "batchId": str(uuid.uuid4()).replace('-', '')[:32], # Generate random batchId
316
- "fileSize": os.path.getsize(file_path)
317
- }
318
-
319
- add_response = requests.post(add_url, headers=headers, json=add_payload)
320
- if add_response.status_code != 200:
321
- PrettyOutput.print(f"Failed to add file to chat: HTTP {add_response.status_code}", OutputType.ERROR)
322
- continue
323
-
324
- add_result = add_response.json()
325
- if not add_result.get("success"):
326
- PrettyOutput.print(f"Failed to add file to chat: {add_result.get('errorMsg')}", OutputType.ERROR)
327
- continue
328
-
329
- file_info.update(add_result.get("data", {}))
330
-
262
+ with yaspin(Spinners.dots, text=f"上传文件 {file_name}") as spinner:
263
+ try:
264
+ if not os.path.exists(file_path):
265
+ spinner.text = f"文件不存在: {file_path}"
266
+ spinner.fail("❌")
267
+ return False
268
+
269
+ # Get file name and content type
270
+ content_type = self._get_content_type(file_path)
271
+
272
+ spinner.text = f"准备上传文件: {file_name}"
273
+
274
+ # Prepare form data
275
+ form_data = {
276
+ 'OSSAccessKeyId': upload_token['accessId'],
277
+ 'policy': upload_token['policy'],
278
+ 'signature': upload_token['signature'],
279
+ 'key': f"{upload_token['dir']}{file_name}",
280
+ 'dir': upload_token['dir'],
281
+ 'success_action_status': '200'
282
+ }
283
+
284
+ # Prepare files
285
+ files = {
286
+ 'file': (file_name, open(file_path, 'rb'), content_type)
287
+ }
288
+
289
+ spinner.text = f"正在上传文件: {file_name}"
290
+
291
+ # Upload file
292
+ response = requests.post(
293
+ upload_token['host'],
294
+ data=form_data,
295
+ files=files
296
+ )
297
+
298
+ if response.status_code != 200:
299
+ spinner.text = f"上传失败 {file_name}: HTTP {response.status_code}"
300
+ spinner.fail("")
301
+ return False
302
+
303
+ uploaded_files.append({
304
+ 'fileKey': file_name,
305
+ 'fileType': 'file',
306
+ 'dir': upload_token['dir']
307
+ })
308
+
309
+ spinner.text = f"获取下载链接: {file_name}"
310
+
311
+ # Get download links for uploaded files
312
+ url = "https://api.tongyi.com/dialog/downloadLink/batch"
313
+ headers = self._get_base_headers()
314
+ payload = {
315
+ "fileKeys": [f['fileKey'] for f in uploaded_files],
316
+ "fileType": "file",
317
+ "dir": upload_token['dir']
318
+ }
319
+
320
+ response = requests.post(url, headers=headers, json=payload)
321
+ if response.status_code != 200:
322
+ spinner.text = f"获取下载链接失败: HTTP {response.status_code}"
323
+ spinner.fail("")
324
+ return False
325
+
326
+ result = response.json()
327
+ if not result.get("success"):
328
+ spinner.text = f"获取下载链接失败: {result.get('errorMsg')}"
329
+ spinner.fail("")
330
+ return False
331
+
332
+ # Add files to chat
333
+ self.uploaded_file_info = result.get("data", {}).get("results", [])
334
+ for file_info in self.uploaded_file_info:
335
+ spinner.text = f"添加文件到对话: {file_name}"
336
+ add_url = "https://api.tongyi.com/assistant/api/chat/file/add"
337
+ add_payload = {
338
+ "workSource": "chat",
339
+ "terminal": "web",
340
+ "workCode": "0",
341
+ "channel": "home",
342
+ "workType": "file",
343
+ "module": "uploadhistory",
344
+ "workName": file_info["fileKey"],
345
+ "workId": file_info["docId"],
346
+ "workResourcePath": file_info["url"],
347
+ "sessionId": "",
348
+ "batchId": str(uuid.uuid4()).replace('-', '')[:32], # Generate random batchId
349
+ "fileSize": os.path.getsize(file_path)
350
+ }
351
+
352
+ add_response = requests.post(add_url, headers=headers, json=add_payload)
353
+ if add_response.status_code != 200:
354
+ spinner.text = f"添加文件到对话失败: HTTP {add_response.status_code}"
355
+ spinner.fail("❌")
356
+ continue
357
+
358
+ add_result = add_response.json()
359
+ if not add_result.get("success"):
360
+ spinner.text = f"添加文件到对话失败: {add_result.get('errorMsg')}"
361
+ spinner.fail("❌")
362
+ continue
363
+
364
+ file_info.update(add_result.get("data", {}))
365
+
366
+ spinner.text = f"文件 {file_name} 上传成功"
367
+ spinner.ok("✅")
368
+ time.sleep(1) # 短暂暂停以便用户看到成功状态
369
+
370
+ except Exception as e:
371
+ spinner.text = f"上传文件 {file_name} 时出错: {str(e)}"
372
+ spinner.fail("❌")
373
+ return False
374
+
331
375
  return True
332
376
 
333
377
  except Exception as e:
@@ -393,6 +437,7 @@ class TongyiPlatform(BasePlatform):
393
437
  self.request_id = ""
394
438
  self.session_id = ""
395
439
  self.msg_id = ""
440
+ self.first_chat = True # Reset first_chat flag
396
441
  return True
397
442
  except Exception as e:
398
443
  PrettyOutput.print(f"Error deleting chat: {str(e)}", OutputType.ERROR)
@@ -88,18 +88,9 @@ class generate_new_tool:
88
88
  "stderr": f"工具 '{tool_name}' 已经存在于 {tool_file_path}"
89
89
  }
90
90
 
91
- # 验证并处理工具代码
92
- processed_code, error_msg = self._validate_and_process_code(tool_name, tool_code)
93
- if error_msg:
94
- return {
95
- "success": False,
96
- "stdout": "",
97
- "stderr": error_msg
98
- }
99
-
100
91
  # 写入工具文件
101
92
  with open(tool_file_path, "w", encoding="utf-8") as f:
102
- f.write(processed_code)
93
+ f.write(tool_code)
103
94
 
104
95
  # 注册新工具到当前的工具注册表
105
96
  success_message = f"工具 '{tool_name}' 已成功生成在 {tool_file_path}"
@@ -152,87 +143,4 @@ class generate_new_tool:
152
143
  "success": False,
153
144
  "stdout": "",
154
145
  "stderr": error_msg
155
- }
156
-
157
- def _validate_and_process_code(self, tool_name: str, tool_code: str) -> Tuple[str, str]:
158
- """
159
- 验证并处理工具代码
160
-
161
- 参数:
162
- tool_name: 工具名称
163
- tool_code: 工具代码
164
-
165
- 返回:
166
- Tuple[str, str]: (处理后的代码, 错误信息)
167
- """
168
- # 检查工具代码中是否包含类定义
169
- if f"class {tool_name}" not in tool_code:
170
- # 尝试找到任何类定义
171
- class_match = re.search(r"class\s+(\w+)", tool_code)
172
- if class_match:
173
- old_class_name = class_match.group(1)
174
- # 替换类名为工具名
175
- tool_code = tool_code.replace(f"class {old_class_name}", f"class {tool_name}")
176
- tool_code = tool_code.replace(f'name = "{old_class_name}"', f'name = "{tool_name}"')
177
- else:
178
- # 没有找到类定义,返回错误
179
- return "", f"工具代码中缺少类定义 'class {tool_name}'"
180
-
181
- # 检查工具代码中是否包含必要的属性和方法
182
- missing_components = []
183
-
184
- if f'name = "{tool_name}"' not in tool_code and f"name = '{tool_name}'" not in tool_code:
185
- # 尝试查找任何name属性并修复
186
- name_match = re.search(r'name\s*=\s*["\'](\w+)["\']', tool_code)
187
- if name_match:
188
- old_name = name_match.group(1)
189
- tool_code = re.sub(r'name\s*=\s*["\'](\w+)["\']', f'name = "{tool_name}"', tool_code)
190
- else:
191
- missing_components.append(f"name = \"{tool_name}\"")
192
-
193
- if "description = " not in tool_code:
194
- missing_components.append("description 属性")
195
-
196
- if "parameters = " not in tool_code:
197
- missing_components.append("parameters 属性")
198
-
199
- if "def execute(self, args:" not in tool_code:
200
- missing_components.append("execute 方法")
201
-
202
- if "def check(" not in tool_code:
203
- # 添加默认的check方法
204
- class_match = re.search(r"class\s+(\w+).*?:", tool_code, re.DOTALL)
205
- if class_match:
206
- indent = " " # 默认缩进
207
- # 找到类定义后的第一个属性
208
- first_attr_match = re.search(r"class\s+(\w+).*?:(.*?)(\w+\s*=)", tool_code, re.DOTALL)
209
- if first_attr_match:
210
- # 获取属性前的缩进
211
- attr_indent = re.search(r"\n([ \t]*)\w+\s*=", first_attr_match.group(2))
212
- if attr_indent:
213
- indent = attr_indent.group(1)
214
-
215
- check_method = f"\n{indent}@staticmethod\n{indent}def check() -> bool:\n{indent} \"\"\"检查工具是否可用\"\"\"\n{indent} return True\n"
216
-
217
- # 在类定义后插入check方法
218
- pattern = r"(class\s+(\w+).*?:.*?)(\n\s*\w+\s*=|\n\s*@|\n\s*def)"
219
- replacement = r"\1" + check_method + r"\3"
220
- tool_code = re.sub(pattern, replacement, tool_code, 1, re.DOTALL)
221
-
222
- # 如果缺少必要组件,返回错误信息
223
- if missing_components:
224
- return "", f"工具代码中缺少以下必要组件: {', '.join(missing_components)}"
225
-
226
- # 确保代码有正确的Python文件头部
227
- if not tool_code.startswith("# -*- coding:") and not tool_code.startswith("# coding="):
228
- tool_code = "# -*- coding: utf-8 -*-\n" + tool_code
229
-
230
- # 确保导入了必要的模块
231
- if "from typing import Dict, Any" not in tool_code:
232
- imports_pos = tool_code.find("\n\n")
233
- if imports_pos > 0:
234
- tool_code = tool_code[:imports_pos] + "\nfrom typing import Dict, Any" + tool_code[imports_pos:]
235
- else:
236
- tool_code = "from typing import Dict, Any\n\n" + tool_code
237
-
238
- return tool_code, ""
146
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.183
3
+ Version: 0.1.184
4
4
  Summary: Jarvis: An AI assistant that uses tools to interact with the system
5
5
  Home-page: https://github.com/skyfireitdiy/Jarvis
6
6
  Author: skyfire
@@ -1,4 +1,4 @@
1
- jarvis/__init__.py,sha256=KysQNyO0AUjUMLzRISa3Wf1q9ffBDepVKiOh2ztirYg,74
1
+ jarvis/__init__.py,sha256=UVbYHDbtqKBl_4D6WpfOn7709w_VMH6nNObt9rvVuV0,74
2
2
  jarvis/jarvis_agent/__init__.py,sha256=AxT_2n-IQkbtoQlAS3SJ0tsvcUenWD7_Xrc-RZZCWiA,30352
3
3
  jarvis/jarvis_agent/builtin_input_handler.py,sha256=f4DaEHPakXcAbgykFP-tiOQP6fh_yGFlZx_h91_j2tQ,1529
4
4
  jarvis/jarvis_agent/file_input_handler.py,sha256=LDNXoTtyjhyBmfzDnAdbWZ2BWdu4q-r6thSKRK8Iwjk,4187
@@ -52,7 +52,7 @@ jarvis/jarvis_platform/human.py,sha256=xwaTZ1zdrAYZZFXxkbHvUdECwCGsic0kgAFUncUr4
52
52
  jarvis/jarvis_platform/kimi.py,sha256=b3EpnmHseZwrfCc8sMmvwLJ6Jg2FWf8ATItSDz5G3eQ,11978
53
53
  jarvis/jarvis_platform/openai.py,sha256=VyX3bR1rGxrJdWOtUBf8PgSL9n06KaNbOewL1urzOnk,4741
54
54
  jarvis/jarvis_platform/registry.py,sha256=3djxE8AB4gwrdAOvRSL0612Rt_CcsaZhzZ0_oXHu6xk,7820
55
- jarvis/jarvis_platform/tongyi.py,sha256=m44aZHZ1oCbYdlSMuG3qYPFZbHW4e3VlaFZ2i3H7xrE,16927
55
+ jarvis/jarvis_platform/tongyi.py,sha256=mgnNC9II3TpiNLD8VgqswqoEAFXoMg8ZG29L3f5kYOo,19711
56
56
  jarvis/jarvis_platform/yuanbao.py,sha256=FDi-D9Jnw_MiwI0skPNMYz874o6GhWhdNRdZg-ECoUA,20632
57
57
  jarvis/jarvis_platform_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
58
  jarvis/jarvis_platform_manager/main.py,sha256=OXWj18SqiV0Gl75YT6D9wspCCB4Nes04EY-ShI9kbpU,25677
@@ -69,7 +69,7 @@ jarvis/jarvis_tools/edit_file.py,sha256=gxnVijz-mOHpb9A7WTPIqCwmZHInSHwu_Psa_GvN
69
69
  jarvis/jarvis_tools/execute_script.py,sha256=IA1SkcnwBB9PKG2voBNx5N9GXL303OC7OOtdqRfqWOk,6428
70
70
  jarvis/jarvis_tools/file_analyzer.py,sha256=7ILHkUFm8pPZn1y_s4uT0kaWHP-EmlHnpkovDdA1yRE,4872
71
71
  jarvis/jarvis_tools/file_operation.py,sha256=WloC1-oPJLwgICu4WBc9f7XA8N_Ggl73QQ5CxM2XTlE,9464
72
- jarvis/jarvis_tools/generate_new_tool.py,sha256=k1Vt88kI1bYi1OwxvJqFKr3Ewwwv7lOegYNmZ-1F7x0,10283
72
+ jarvis/jarvis_tools/generate_new_tool.py,sha256=dLfOliIUm0ovLrHcZAhKm7lqhxwACv8mnGxxGtLJ--o,5960
73
73
  jarvis/jarvis_tools/methodology.py,sha256=m7cQmVhhQpUUl_uYTVvcW0JBovQLx5pWTXh_8K77HsU,5237
74
74
  jarvis/jarvis_tools/read_code.py,sha256=pL2SwZDsJbJMXo4stW96quFsLgbtPVIAW-h4sDKsLtM,6274
75
75
  jarvis/jarvis_tools/read_webpage.py,sha256=PFAYuKjay9j6phWzyuZ99ZfNaHJljmRWAgS0bsvbcvE,2219
@@ -91,9 +91,9 @@ jarvis/jarvis_utils/methodology.py,sha256=A8pE8ZqNHvGKaDO4TFtg7Oz-hAXPBcQfhmSPWM
91
91
  jarvis/jarvis_utils/output.py,sha256=QboL42GtG_dnvd1O64sl8o72mEBhXNRADPXQMXgDE7Q,9661
92
92
  jarvis/jarvis_utils/tag.py,sha256=YJHmuedLb7_AiqvKQetHr4R1FxyzIh7HN0RRkWMmYbU,429
93
93
  jarvis/jarvis_utils/utils.py,sha256=atSK-2cUr7_tOIFsQzJnuQxebi7aFN4jtmaoXEaV4jM,10692
94
- jarvis_ai_assistant-0.1.183.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
95
- jarvis_ai_assistant-0.1.183.dist-info/METADATA,sha256=RRkBRiDEeBnEfQQFAufn9jE2RV7BA90P5o5G_PnJUp0,15836
96
- jarvis_ai_assistant-0.1.183.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
97
- jarvis_ai_assistant-0.1.183.dist-info/entry_points.txt,sha256=Gy3DOP1PYLMK0GCj4rrP_9lkOyBQ39EK_lKGUSwn41E,869
98
- jarvis_ai_assistant-0.1.183.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
99
- jarvis_ai_assistant-0.1.183.dist-info/RECORD,,
94
+ jarvis_ai_assistant-0.1.184.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
95
+ jarvis_ai_assistant-0.1.184.dist-info/METADATA,sha256=1H6UQ0hW12J_lgy6Mhq3pOj7BrD1_1a_taBK9JE4oi0,15836
96
+ jarvis_ai_assistant-0.1.184.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
97
+ jarvis_ai_assistant-0.1.184.dist-info/entry_points.txt,sha256=Gy3DOP1PYLMK0GCj4rrP_9lkOyBQ39EK_lKGUSwn41E,869
98
+ jarvis_ai_assistant-0.1.184.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
99
+ jarvis_ai_assistant-0.1.184.dist-info/RECORD,,