jarvis-ai-assistant 0.1.206__py3-none-any.whl → 0.1.208__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 (36) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +71 -61
  3. jarvis/jarvis_agent/edit_file_handler.py +42 -46
  4. jarvis/jarvis_agent/jarvis.py +33 -39
  5. jarvis/jarvis_code_agent/code_agent.py +26 -27
  6. jarvis/jarvis_code_agent/lint.py +5 -5
  7. jarvis/jarvis_code_analysis/code_review.py +164 -175
  8. jarvis/jarvis_data/config_schema.json +1 -1
  9. jarvis/jarvis_git_utils/git_commiter.py +147 -152
  10. jarvis/jarvis_methodology/main.py +70 -81
  11. jarvis/jarvis_platform/base.py +28 -23
  12. jarvis/jarvis_platform/kimi.py +39 -53
  13. jarvis/jarvis_platform/tongyi.py +108 -126
  14. jarvis/jarvis_platform/yuanbao.py +112 -120
  15. jarvis/jarvis_platform_manager/main.py +102 -502
  16. jarvis/jarvis_platform_manager/service.py +432 -0
  17. jarvis/jarvis_smart_shell/main.py +99 -33
  18. jarvis/jarvis_tools/edit_file.py +64 -55
  19. jarvis/jarvis_tools/file_analyzer.py +17 -25
  20. jarvis/jarvis_tools/read_code.py +80 -81
  21. jarvis/jarvis_utils/builtin_replace_map.py +1 -36
  22. jarvis/jarvis_utils/config.py +14 -4
  23. jarvis/jarvis_utils/git_utils.py +36 -35
  24. jarvis/jarvis_utils/methodology.py +12 -17
  25. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/METADATA +7 -16
  26. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/RECORD +30 -35
  27. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/entry_points.txt +0 -1
  28. jarvis/jarvis_dev/main.py +0 -1247
  29. jarvis/jarvis_tools/chdir.py +0 -72
  30. jarvis/jarvis_tools/code_plan.py +0 -218
  31. jarvis/jarvis_tools/create_code_agent.py +0 -95
  32. jarvis/jarvis_tools/create_sub_agent.py +0 -82
  33. jarvis/jarvis_tools/file_operation.py +0 -238
  34. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/WHEEL +0 -0
  35. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/licenses/LICENSE +0 -0
  36. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/top_level.txt +0 -0
@@ -187,68 +187,54 @@ class KimiModel(BasePlatform):
187
187
  if not file_list:
188
188
  return True
189
189
 
190
- from yaspin import yaspin # type: ignore
191
-
192
190
  if not self.chat_id:
193
- with yaspin(text="创建聊天会话...", color="yellow") as spinner:
194
- if not self._create_chat():
195
- yaspin.text = "创建聊天会话失败"
196
- spinner.fail("❌")
197
- return False
198
- spinner.text = "创建聊天会话成功"
199
- spinner.ok("✅")
191
+ print("🚀 正在创建聊天会话...")
192
+ if not self._create_chat():
193
+ print("❌ 创建聊天会话失败")
194
+ return False
195
+ print("✅ 创建聊天会话成功")
200
196
 
201
197
  uploaded_files = []
202
198
  for index, file_path in enumerate(file_list, 1):
203
199
  file_name = os.path.basename(file_path)
204
- with yaspin(
205
- text=f"处理文件 [{index}/{len(file_list)}]: {file_name}", color="yellow"
206
- ) as spinner:
207
- try:
208
- mime_type, _ = mimetypes.guess_type(file_path)
209
- action = (
210
- "image"
211
- if mime_type and mime_type.startswith("image/")
212
- else "file"
213
- )
214
-
215
- # 获取预签名URL
216
- spinner.text = f"获取上传URL: {file_name}"
217
- presigned_data = self._get_presigned_url(file_path, action)
218
-
219
- # 上传文件
220
- spinner.text = f"上传文件: {file_name}"
221
- if self._upload_file(file_path, presigned_data["url"]):
222
- # 获取文件信息
223
- spinner.text = f"获取文件信息: {file_name}"
224
- file_info = self._get_file_info(
225
- presigned_data, file_name, action
226
- )
227
-
228
- # 只有文件需要解析
229
- if action == "file":
230
- spinner.text = f"等待文件解析: {file_name}"
231
- if self._wait_for_parse(file_info["id"]):
232
- uploaded_files.append(file_info)
233
- spinner.text = f"文件处理完成: {file_name}"
234
- spinner.ok("✅")
235
- else:
236
- spinner.text = f"❌文件解析失败: {file_name}"
237
- spinner.fail("")
238
- return False
239
- else:
200
+ print(f"🔍 处理文件 [{index}/{len(file_list)}]: {file_name}")
201
+ try:
202
+ mime_type, _ = mimetypes.guess_type(file_path)
203
+ action = (
204
+ "image" if mime_type and mime_type.startswith("image/") else "file"
205
+ )
206
+
207
+ # 获取预签名URL
208
+ print(f"🔍 获取上传URL: {file_name}")
209
+ presigned_data = self._get_presigned_url(file_path, action)
210
+
211
+ # 上传文件
212
+ print(f"🔍 上传文件: {file_name}")
213
+ if self._upload_file(file_path, presigned_data["url"]):
214
+ # 获取文件信息
215
+ print(f"🔍 获取文件信息: {file_name}")
216
+ file_info = self._get_file_info(presigned_data, file_name, action)
217
+
218
+ # 只有文件需要解析
219
+ if action == "file":
220
+ print(f"🔍 等待文件解析: {file_name}")
221
+ if self._wait_for_parse(file_info["id"]):
240
222
  uploaded_files.append(file_info)
241
- spinner.write(f"✅图片处理完成: {file_name}")
223
+ print(f" 文件处理完成: {file_name}")
224
+ else:
225
+ print(f"❌ 文件解析失败: {file_name}")
226
+ return False
242
227
  else:
243
- spinner.text = f"文件上传失败: {file_name}"
244
- spinner.fail("")
245
- return False
246
-
247
- except Exception as e:
248
- spinner.text = f"处理文件出错 {file_path}: {str(e)}"
249
- spinner.fail("❌")
228
+ uploaded_files.append(file_info)
229
+ print(f"✅ 图片处理完成: {file_name}")
230
+ else:
231
+ print(f"❌ 文件上传失败: {file_name}")
250
232
  return False
251
233
 
234
+ except Exception as e:
235
+ print(f"❌ 处理文件出错 {file_path}: {str(e)}")
236
+ return False
237
+
252
238
  self.uploaded_files = uploaded_files
253
239
  return True
254
240
 
@@ -5,9 +5,7 @@ import time
5
5
  import uuid
6
6
  from typing import Any, Dict, Generator, List, Tuple
7
7
 
8
- import requests
9
- from yaspin import yaspin
10
- from yaspin.spinners import Spinners
8
+ import requests # type: ignore
11
9
 
12
10
  from jarvis.jarvis_platform.base import BasePlatform
13
11
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
@@ -289,140 +287,124 @@ class TongyiPlatform(BasePlatform):
289
287
 
290
288
  for file_path in file_list:
291
289
  file_name = os.path.basename(file_path)
292
- with yaspin(Spinners.dots, text=f"上传文件 {file_name}") as spinner:
293
- try:
294
- if not os.path.exists(file_path):
295
- spinner.text = f"文件不存在: {file_path}"
296
- spinner.fail("❌")
297
- return False
298
-
299
- # Get file name and content type
300
- content_type = self._get_content_type(file_path)
301
-
302
- spinner.text = f"准备上传文件: {file_name}"
303
-
304
- # Prepare form data
305
- form_data = {
306
- "OSSAccessKeyId": upload_token["accessId"],
307
- "policy": upload_token["policy"],
308
- "signature": upload_token["signature"],
309
- "key": f"{upload_token['dir']}{file_name}",
310
- "dir": upload_token["dir"],
311
- "success_action_status": "200",
312
- }
290
+ print(f"🔍 上传文件 {file_name}")
291
+ try:
292
+ if not os.path.exists(file_path):
293
+ print(f"文件不存在: {file_path}")
294
+ return False
313
295
 
314
- # Prepare files
315
- files = {
316
- "file": (file_name, open(file_path, "rb"), content_type)
317
- }
296
+ # Get file name and content type
297
+ content_type = self._get_content_type(file_path)
318
298
 
319
- spinner.text = f"正在上传文件: {file_name}"
299
+ print(f"🔍 准备上传文件: {file_name}")
320
300
 
321
- # Upload file
322
- response = requests.post(
323
- upload_token["host"], data=form_data, files=files
324
- )
301
+ # Prepare form data
302
+ form_data = {
303
+ "OSSAccessKeyId": upload_token["accessId"],
304
+ "policy": upload_token["policy"],
305
+ "signature": upload_token["signature"],
306
+ "key": f"{upload_token['dir']}{file_name}",
307
+ "dir": upload_token["dir"],
308
+ "success_action_status": "200",
309
+ }
325
310
 
326
- if response.status_code != 200:
327
- spinner.text = (
328
- f"上传失败 {file_name}: HTTP {response.status_code}"
329
- )
330
- spinner.fail("❌")
331
- return False
332
-
333
- # Determine file type based on extension
334
- file_ext = os.path.splitext(file_path)[1].lower()
335
- is_image = file_ext in self.IMAGE_EXTENSIONS
336
-
337
- uploaded_files.append(
338
- {
339
- "fileKey": file_name,
340
- "fileType": "image" if is_image else "file",
341
- "dir": upload_token["dir"],
342
- }
343
- )
311
+ # Prepare files
312
+ files = {"file": (file_name, open(file_path, "rb"), content_type)}
313
+
314
+ print(f"📤 正在上传文件: {file_name}")
315
+
316
+ # Upload file
317
+ response = requests.post(
318
+ upload_token["host"], data=form_data, files=files
319
+ )
320
+
321
+ if response.status_code != 200:
322
+ print(f"❌ 上传失败 {file_name}: HTTP {response.status_code}")
323
+ return False
324
+
325
+ # Determine file type based on extension
326
+ file_ext = os.path.splitext(file_path)[1].lower()
327
+ is_image = file_ext in self.IMAGE_EXTENSIONS
344
328
 
345
- spinner.text = f"获取下载链接: {file_name}"
346
-
347
- # Get download links for uploaded files
348
- url = "https://api.tongyi.com/dialog/downloadLink/batch"
349
- headers = self._get_base_headers()
350
- payload = {
351
- "fileKeys": [f["fileKey"] for f in uploaded_files],
352
- "fileType": (
353
- "image"
354
- if any(f["fileType"] == "image" for f in uploaded_files)
355
- else "file"
356
- ),
329
+ uploaded_files.append(
330
+ {
331
+ "fileKey": file_name,
332
+ "fileType": "image" if is_image else "file",
357
333
  "dir": upload_token["dir"],
358
334
  }
335
+ )
336
+
337
+ print(f"🔍 获取下载链接: {file_name}")
338
+
339
+ # Get download links for uploaded files
340
+ url = "https://api.tongyi.com/dialog/downloadLink/batch"
341
+ headers = self._get_base_headers()
342
+ payload = {
343
+ "fileKeys": [f["fileKey"] for f in uploaded_files],
344
+ "fileType": (
345
+ "image"
346
+ if any(f["fileType"] == "image" for f in uploaded_files)
347
+ else "file"
348
+ ),
349
+ "dir": upload_token["dir"],
350
+ }
359
351
 
360
- response = requests.post(url, headers=headers, json=payload)
361
- if response.status_code != 200:
362
- spinner.text = (
363
- f"获取下载链接失败: HTTP {response.status_code}"
364
- )
365
- spinner.fail("❌")
366
- return False
367
-
368
- result = response.json()
369
- if not result.get("success"):
370
- spinner.text = f"获取下载链接失败: {result.get('errorMsg')}"
371
- spinner.fail("")
372
- return False
373
-
374
- # Add files to chat
375
- self.uploaded_file_info = result.get("data", {}).get(
376
- "results", []
352
+ response = requests.post(url, headers=headers, json=payload)
353
+ if response.status_code != 200:
354
+ print(f"❌ 获取下载链接失败: HTTP {response.status_code}")
355
+ return False
356
+
357
+ result = response.json()
358
+ if not result.get("success"):
359
+ print(f"❌ 获取下载链接失败: {result.get('errorMsg')}")
360
+ return False
361
+
362
+ # Add files to chat
363
+ self.uploaded_file_info = result.get("data", {}).get("results", [])
364
+ for file_info in self.uploaded_file_info:
365
+ print(f"🔍 添加文件到对话: {file_name}")
366
+ add_url = "https://api.tongyi.com/assistant/api/chat/file/add"
367
+ add_payload = {
368
+ "workSource": "chat",
369
+ "terminal": "web",
370
+ "workCode": "0",
371
+ "channel": "home",
372
+ "workType": "file",
373
+ "module": "uploadhistory",
374
+ "workName": file_info["fileKey"],
375
+ "workId": file_info["docId"],
376
+ "workResourcePath": file_info["url"],
377
+ "sessionId": "",
378
+ "batchId": str(uuid.uuid4()).replace("-", "")[
379
+ :32
380
+ ], # Generate random batchId
381
+ "fileSize": os.path.getsize(file_path),
382
+ }
383
+
384
+ add_response = requests.post(
385
+ add_url, headers=headers, json=add_payload
377
386
  )
378
- for file_info in self.uploaded_file_info:
379
- spinner.text = f"添加文件到对话: {file_name}"
380
- add_url = (
381
- "https://api.tongyi.com/assistant/api/chat/file/add"
387
+ if add_response.status_code != 200:
388
+ print(
389
+ f"❌ 添加文件到对话失败: HTTP {add_response.status_code}"
382
390
  )
383
- add_payload = {
384
- "workSource": "chat",
385
- "terminal": "web",
386
- "workCode": "0",
387
- "channel": "home",
388
- "workType": "file",
389
- "module": "uploadhistory",
390
- "workName": file_info["fileKey"],
391
- "workId": file_info["docId"],
392
- "workResourcePath": file_info["url"],
393
- "sessionId": "",
394
- "batchId": str(uuid.uuid4()).replace("-", "")[
395
- :32
396
- ], # Generate random batchId
397
- "fileSize": os.path.getsize(file_path),
398
- }
399
-
400
- add_response = requests.post(
401
- add_url, headers=headers, json=add_payload
391
+ continue
392
+
393
+ add_result = add_response.json()
394
+ if not add_result.get("success"):
395
+ print(
396
+ f" 添加文件到对话失败: {add_result.get('errorMsg')}"
402
397
  )
403
- if add_response.status_code != 200:
404
- spinner.text = f"添加文件到对话失败: HTTP {add_response.status_code}"
405
- spinner.fail("")
406
- continue
407
-
408
- add_result = add_response.json()
409
- if not add_result.get("success"):
410
- spinner.text = (
411
- f"添加文件到对话失败: {add_result.get('errorMsg')}"
412
- )
413
- spinner.fail("❌")
414
- continue
415
-
416
- file_info.update(add_result.get("data", {}))
417
-
418
- spinner.text = f"文件 {file_name} 上传成功"
419
- spinner.ok("✅")
420
- time.sleep(1) # 短暂暂停以便用户看到成功状态
421
-
422
- except Exception as e:
423
- spinner.text = f"上传文件 {file_name} 时出错: {str(e)}"
424
- spinner.fail("❌")
425
- return False
398
+ continue
399
+
400
+ file_info.update(add_result.get("data", {}))
401
+
402
+ print(f"✅ 文件 {file_name} 上传成功")
403
+ time.sleep(1) # 短暂暂停以便用户看到成功状态
404
+
405
+ except Exception as e:
406
+ print(f" 上传文件 {file_name} 时出错: {str(e)}")
407
+ return False
426
408
  return True
427
409
 
428
410
  except Exception as e: