jarvis-ai-assistant 0.1.126__py3-none-any.whl → 0.1.129__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 (42) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +108 -95
  3. jarvis/jarvis_agent/main.py +77 -0
  4. jarvis/jarvis_code_agent/builtin_input_handler.py +43 -0
  5. jarvis/jarvis_code_agent/code_agent.py +17 -81
  6. jarvis/jarvis_code_agent/file_input_handler.py +88 -0
  7. jarvis/jarvis_code_agent/patch.py +142 -114
  8. jarvis/jarvis_code_agent/shell_input_handler.py +8 -2
  9. jarvis/jarvis_codebase/main.py +240 -213
  10. jarvis/jarvis_dev/main.py +4 -3
  11. jarvis/jarvis_multi_agent/__init__.py +51 -40
  12. jarvis/jarvis_platform/base.py +6 -5
  13. jarvis/jarvis_platform_manager/main.py +1 -1
  14. jarvis/jarvis_rag/main.py +250 -186
  15. jarvis/jarvis_smart_shell/main.py +0 -1
  16. jarvis/jarvis_tools/ask_codebase.py +4 -3
  17. jarvis/jarvis_tools/chdir.py +22 -22
  18. jarvis/jarvis_tools/code_review.py +38 -33
  19. jarvis/jarvis_tools/execute_shell.py +0 -3
  20. jarvis/jarvis_tools/file_operation.py +56 -55
  21. jarvis/jarvis_tools/git_commiter.py +60 -50
  22. jarvis/jarvis_tools/read_code.py +143 -0
  23. jarvis/jarvis_tools/read_webpage.py +50 -30
  24. jarvis/jarvis_tools/registry.py +4 -21
  25. jarvis/jarvis_tools/search_web.py +61 -36
  26. jarvis/jarvis_tools/tool_generator.py +78 -36
  27. jarvis/jarvis_utils/__init__.py +17 -17
  28. jarvis/jarvis_utils/config.py +87 -51
  29. jarvis/jarvis_utils/embedding.py +49 -48
  30. jarvis/jarvis_utils/git_utils.py +34 -34
  31. jarvis/jarvis_utils/globals.py +26 -26
  32. jarvis/jarvis_utils/input.py +61 -45
  33. jarvis/jarvis_utils/methodology.py +94 -76
  34. jarvis/jarvis_utils/output.py +63 -62
  35. jarvis/jarvis_utils/utils.py +2 -2
  36. {jarvis_ai_assistant-0.1.126.dist-info → jarvis_ai_assistant-0.1.129.dist-info}/METADATA +1 -1
  37. jarvis_ai_assistant-0.1.129.dist-info/RECORD +78 -0
  38. {jarvis_ai_assistant-0.1.126.dist-info → jarvis_ai_assistant-0.1.129.dist-info}/entry_points.txt +2 -0
  39. jarvis_ai_assistant-0.1.126.dist-info/RECORD +0 -74
  40. {jarvis_ai_assistant-0.1.126.dist-info → jarvis_ai_assistant-0.1.129.dist-info}/LICENSE +0 -0
  41. {jarvis_ai_assistant-0.1.126.dist-info → jarvis_ai_assistant-0.1.129.dist-info}/WHEEL +0 -0
  42. {jarvis_ai_assistant-0.1.126.dist-info → jarvis_ai_assistant-0.1.129.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
1
1
  from typing import Dict, Any
2
2
  import requests
3
3
  from bs4 import BeautifulSoup
4
+ from yaspin import yaspin
4
5
 
5
6
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
6
7
 
@@ -29,48 +30,67 @@ class WebpageTool:
29
30
  }
30
31
 
31
32
  # Send request
32
- PrettyOutput.print(f"正在读取网页:{url}", OutputType.INFO)
33
- response = requests.get(url, headers=headers, timeout=10)
34
- response.raise_for_status()
33
+ with yaspin(text="正在读取网页...", color="cyan") as spinner:
34
+ response = requests.get(url, headers=headers, timeout=10)
35
+ response.raise_for_status()
36
+ spinner.text = "网页读取完成"
37
+ spinner.ok("✅")
38
+
35
39
 
36
40
  # Use correct encoding
41
+
37
42
  response.encoding = response.apparent_encoding
38
43
 
39
44
  # Parse HTML
40
- soup = BeautifulSoup(response.text, 'html.parser')
45
+ with yaspin(text="正在解析网页...", color="cyan") as spinner:
46
+ soup = BeautifulSoup(response.text, 'html.parser')
47
+ spinner.text = "网页解析完成"
48
+ spinner.ok("✅")
41
49
 
42
50
  # Remove script and style tags
43
- for script in soup(["script", "style"]):
44
- script.decompose()
51
+ with yaspin(text="正在移除脚本和样式...", color="cyan") as spinner:
52
+ for script in soup(["script", "style"]):
53
+ script.decompose()
54
+ spinner.text = "脚本和样式移除完成"
55
+ spinner.ok("✅")
45
56
 
46
57
  # Extract title
47
- title = soup.title.string if soup.title else ""
48
- title = title.strip() if title else "No title"
49
-
50
- # Extract text and links
51
- text_parts = []
52
- links = []
58
+ with yaspin(text="正在提取标题...", color="cyan") as spinner:
59
+ title = soup.title.string if soup.title else ""
60
+ title = title.strip() if title else "No title"
61
+ spinner.text = "标题提取完成"
62
+ spinner.ok("✅")
53
63
 
54
- # Process content and collect links
55
- for element in soup.descendants:
56
- if element.name == 'a' and element.get('href'): # type: ignore
57
- href = element.get('href') # type: ignore
58
- text = element.get_text(strip=True)
59
- if text and href:
60
- links.append(f"[{text}]({href})")
61
- elif isinstance(element, str) and element.strip():
62
- text_parts.append(element.strip())
64
+ with yaspin(text="正在提取文本和链接...", color="cyan") as spinner:
65
+ # Extract text and links
66
+ text_parts = []
67
+ links = []
68
+
69
+ # Process content and collect links
70
+ for element in soup.descendants:
71
+ if element.name == 'a' and element.get('href'): # type: ignore
72
+ href = element.get('href') # type: ignore
73
+ text = element.get_text(strip=True)
74
+ if text and href:
75
+ links.append(f"[{text}]({href})")
76
+ elif isinstance(element, str) and element.strip():
77
+ text_parts.append(element.strip())
78
+ spinner.text = "文本和链接提取完成"
79
+ spinner.ok("✅")
63
80
 
64
81
  # Build output
65
- output = [
66
- f"Title: {title}",
67
- "",
68
- "Text content:",
69
- "\n".join(text_parts),
70
- "",
71
- "Links found:",
72
- "\n".join(links) if links else "No links found"
73
- ]
82
+ with yaspin(text="正在构建输出...", color="cyan") as spinner:
83
+ output = [
84
+ f"Title: {title}",
85
+ "",
86
+ "Text content:",
87
+ "\n".join(text_parts),
88
+ "",
89
+ "Links found:",
90
+ "\n".join(links) if links else "No links found"
91
+ ]
92
+ spinner.text = "输出构建完成"
93
+ spinner.ok("✅")
74
94
 
75
95
  return {
76
96
  "success": True,
@@ -5,6 +5,7 @@ import sys
5
5
  from typing import Any, Callable, Dict, List, Optional, Tuple
6
6
 
7
7
  import yaml
8
+ from yaspin import yaspin
8
9
 
9
10
  from jarvis.jarvis_agent.output_handler import OutputHandler
10
11
  from jarvis.jarvis_platform.registry import PlatformRegistry
@@ -335,17 +336,6 @@ arguments:
335
336
  except json.JSONDecodeError:
336
337
  PrettyOutput.print(f"工具参数格式无效: {name} {tool_call_help}", OutputType.ERROR)
337
338
  return ""
338
-
339
- # Display tool call information
340
- PrettyOutput.section(f"执行工具: {name}", OutputType.TOOL)
341
- params = "参数:\n"
342
- if isinstance(args, dict):
343
- for key, value in args.items():
344
- params += f"{key} = {value}\n"
345
- else:
346
- params += f"{args}"
347
-
348
- PrettyOutput.print(params, OutputType.INFO)
349
339
 
350
340
  # Execute tool call
351
341
  result = self.execute_tool(name, args)
@@ -362,15 +352,13 @@ arguments:
362
352
 
363
353
  # Process the result
364
354
  if result["success"]:
365
-
366
- PrettyOutput.section("执行成功", OutputType.SUCCESS)
367
-
368
355
  # If the output exceeds 4k characters, use a large model to summarize
369
356
  if get_context_token_count(output) > self.max_token_count:
357
+ PrettyOutput.section("输出过长,正在总结...", OutputType.SYSTEM)
370
358
  try:
371
- PrettyOutput.print("输出过长,正在总结...", OutputType.PROGRESS)
372
- model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
373
359
 
360
+ model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
361
+ model.set_suppress_output(False)
374
362
  # If the output exceeds the maximum context length, only take the last part
375
363
  max_count = self.max_token_count
376
364
  if get_context_token_count(output) > max_count:
@@ -398,14 +386,9 @@ arguments:
398
386
  {summary}
399
387
 
400
388
  --- 总结结束 ---"""
401
-
402
389
  except Exception as e:
403
390
  PrettyOutput.print(f"总结失败: {str(e)}", OutputType.ERROR)
404
391
  output = f"输出过长 ({len(output)} 字符),建议查看原始输出。\n前300字符预览:\n{output[:300]}..."
405
-
406
- else:
407
- PrettyOutput.section("执行失败", OutputType.WARNING)
408
- PrettyOutput.print(result["stderr"], OutputType.WARNING)
409
392
  return output
410
393
 
411
394
  except Exception as e:
@@ -1,4 +1,7 @@
1
1
  from typing import Dict, Any, List
2
+
3
+ from regex import W
4
+ from yaspin import yaspin
2
5
  from jarvis.jarvis_platform.registry import PlatformRegistry
3
6
  from jarvis.jarvis_tools.read_webpage import WebpageTool
4
7
  from playwright.sync_api import sync_playwright
@@ -12,52 +15,72 @@ def bing_search(query):
12
15
  try:
13
16
  with sync_playwright() as p:
14
17
  # Set parameters when starting the browser
15
- browser = p.chromium.launch(
16
- headless=True, # Headless mode
17
- args=['--disable-gpu', '--no-sandbox', '--disable-dev-shm-usage']
18
- )
18
+ with yaspin(text="正在启动浏览器...", color="cyan") as spinner:
19
+ browser = p.chromium.launch(
20
+ headless=True, # Headless mode
21
+ args=['--disable-gpu', '--no-sandbox', '--disable-dev-shm-usage']
22
+ )
23
+ spinner.text = "浏览器启动完成"
24
+ spinner.ok("✅")
19
25
 
20
26
  # Create a new page and set timeout
21
- page = browser.new_page(
22
- user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
23
- viewport={'width': 1920, 'height': 1080}
24
- )
27
+ with yaspin(text="正在创建新页面...", color="cyan") as spinner:
28
+ page = browser.new_page(
29
+ user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
30
+ viewport={'width': 1920, 'height': 1080}
31
+ )
32
+ spinner.text = "新页面创建完成"
33
+ spinner.ok("✅")
25
34
 
26
35
  # Set page timeout
27
- page.set_default_timeout(60000)
36
+ with yaspin(text="正在设置页面超时...", color="cyan") as spinner:
37
+ page.set_default_timeout(60000)
38
+ spinner.text = "页面超时设置完成"
39
+ spinner.ok("✅")
28
40
 
29
41
  # Visit search page
30
- url = f"https://www.bing.com/search?q={quote(query)}&form=QBLH&sp=-1"
31
- page.goto(url, wait_until="networkidle")
42
+ with yaspin(text=f"正在搜索 {query}...", color="cyan") as spinner:
43
+ url = f"https://www.bing.com/search?q={quote(query)}&form=QBLH&sp=-1"
44
+ page.goto(url, wait_until="networkidle")
45
+ spinner.text = "搜索完成"
46
+ spinner.ok("✅")
32
47
 
33
48
  # Wait for search results to load
34
- page.wait_for_selector("#b_results", state="visible", timeout=30000)
35
-
36
- # Wait for a moment to ensure the results are fully loaded
37
- page.wait_for_timeout(1000)
49
+ with yaspin(text="正在等待搜索结果加载...", color="cyan") as spinner:
50
+ page.wait_for_selector("#b_results", state="visible", timeout=30000)
51
+ # Wait for a moment to ensure the results are fully loaded
52
+ page.wait_for_timeout(1000)
53
+ spinner.text = "搜索结果加载完成"
54
+ spinner.ok("✅")
38
55
 
39
56
  # Extract search results
40
- summaries = page.evaluate("""() => {
41
- const results = [];
42
- const elements = document.querySelectorAll("#b_results > .b_algo");
43
-
44
- for (const el of elements) {
45
- const titleEl = el.querySelector("h2");
46
- const linkEl = titleEl ? titleEl.querySelector("a") : null;
47
- const abstractEl = el.querySelector(".b_caption p");
57
+ with yaspin(text="正在提取搜索结果...", color="cyan") as spinner:
58
+ summaries = page.evaluate("""() => {
59
+ const results = [];
60
+ const elements = document.querySelectorAll("#b_results > .b_algo");
48
61
 
49
- if (linkEl) {
50
- results.push({
51
- title: titleEl.innerText.trim(),
52
- href: linkEl.href,
53
- abstract: abstractEl ? abstractEl.innerText.trim() : ""
54
- });
62
+ for (const el of elements) {
63
+ const titleEl = el.querySelector("h2");
64
+ const linkEl = titleEl ? titleEl.querySelector("a") : null;
65
+ const abstractEl = el.querySelector(".b_caption p");
66
+
67
+ if (linkEl) {
68
+ results.push({
69
+ title: titleEl.innerText.trim(),
70
+ href: linkEl.href,
71
+ abstract: abstractEl ? abstractEl.innerText.trim() : ""
72
+ });
73
+ }
55
74
  }
56
- }
57
- return results;
58
- }""")
59
-
60
- browser.close()
75
+ return results;
76
+ }""")
77
+ spinner.text = "搜索结果提取完成"
78
+ spinner.ok("✅")
79
+
80
+ with yaspin(text="正在关闭浏览器...", color="cyan") as spinner:
81
+ browser.close()
82
+ spinner.text = "浏览器关闭完成"
83
+ spinner.ok("✅")
61
84
  return summaries
62
85
 
63
86
  except Exception as error:
@@ -235,8 +258,10 @@ Please synthesize a final answer that:
235
258
  }
236
259
 
237
260
  # Extract information
238
- PrettyOutput.print("正在分析搜索结果...", OutputType.PROGRESS)
239
- analysis = self._extract_info(contents, question)
261
+ with yaspin(text="正在提取信息...", color="cyan") as spinner:
262
+ analysis = self._extract_info(contents, question)
263
+ spinner.text = "信息提取完成"
264
+ spinner.ok("✅")
240
265
 
241
266
  return {
242
267
  "success": True,
@@ -4,9 +4,13 @@ Tool Generator Tool - Automatically creates new tools using LLM
4
4
  from pathlib import Path
5
5
  import re
6
6
  from typing import Dict, Any
7
+
8
+ from yaspin import yaspin
7
9
  from jarvis.jarvis_platform.registry import PlatformRegistry
8
10
 
9
11
  class ToolGenerator:
12
+ """工具生成器类,用于自动创建与Jarvis系统集成的新工具"""
13
+
10
14
  name = "tool_generator"
11
15
  description = "使用LLM自动生成与系统集成的新工具"
12
16
  parameters = {
@@ -29,8 +33,14 @@ class ToolGenerator:
29
33
  }
30
34
 
31
35
  def execute(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
32
- """Generate and save a new tool using LLM"""
33
- # Get fresh model instance for each execution
36
+ """
37
+ 执行工具生成过程
38
+ Args:
39
+ arguments: 包含工具生成所需参数的字典
40
+ Returns:
41
+ 包含执行结果的字典,包含success、stdout和stderr字段
42
+ """
43
+ # 获取代码生成平台实例
34
44
  model = PlatformRegistry.get_global_platform_registry().get_codegen_platform()
35
45
 
36
46
  try:
@@ -38,38 +48,50 @@ class ToolGenerator:
38
48
  description = arguments["description"]
39
49
  input_spec = arguments["input_spec"]
40
50
 
41
- # Generate tool implementation using LLM
42
- prompt = self._create_prompt(tool_name, description, input_spec)
43
- llm_response = model.chat_until_success(prompt)
44
-
45
- # Extract implementation with more flexible parsing
46
- implementation = self._extract_code(llm_response)
47
- if not implementation:
48
- return {
49
- "success": False,
50
- "stdout": "",
51
- "stderr": "Could not extract valid Python code from LLM response"
52
- }
51
+ # 使用LLM生成工具实现代码
52
+ with yaspin(text="正在生成工具...", color="cyan") as spinner:
53
+ prompt = self._create_prompt(tool_name, description, input_spec)
54
+ llm_response = model.chat_until_success(prompt)
55
+ spinner.text = "工具生成完成"
56
+ spinner.ok("✅")
53
57
 
54
- # Validate return value format
55
- if not self._validate_return_value_format(implementation):
56
- return {
57
- "success": False,
58
- "stdout": "",
59
- "stderr": "Generated tool does not follow required return value format"
60
- }
58
+ # 从LLM响应中提取实现代码
59
+ with yaspin(text="正在提取工具实现...", color="cyan") as spinner:
60
+ implementation = self._extract_code(llm_response)
61
+ if not implementation:
62
+ return {
63
+ "success": False,
64
+ "stdout": "",
65
+ "stderr": "无法从LLM响应中提取有效的Python代码"
66
+ }
67
+ spinner.text = "工具实现提取完成"
68
+ spinner.ok("✅")
61
69
 
62
- # Save the new tool
63
- tools_dir = Path.home() / ".jarvis" / "tools"
64
- tools_dir.mkdir(parents=True, exist_ok=True)
65
- tool_file = tools_dir / f"{tool_name}.py"
70
+ # 验证生成的工具代码是否符合返回值格式要求
71
+ with yaspin(text="正在验证工具返回值格式...", color="cyan") as spinner:
72
+ if not self._validate_return_value_format(implementation):
73
+ return {
74
+ "success": False,
75
+ "stdout": "",
76
+ "stderr": "生成的工具不符合要求的返回值格式"
77
+ }
78
+ spinner.text = "工具返回值格式验证完成"
79
+ spinner.ok("✅")
66
80
 
67
- with open(tool_file, "w") as f:
68
- f.write(implementation)
81
+ # 保存生成的新工具
82
+ with yaspin(text="正在保存工具...", color="cyan") as spinner:
83
+ tools_dir = Path.home() / ".jarvis" / "tools"
84
+ tools_dir.mkdir(parents=True, exist_ok=True)
85
+ tool_file = tools_dir / f"{tool_name}.py"
86
+
87
+ with open(tool_file, "w") as f:
88
+ f.write(implementation)
89
+ spinner.text = "工具保存完成"
90
+ spinner.ok("✅")
69
91
 
70
92
  return {
71
93
  "success": True,
72
- "stdout": f"Tool successfully generated at: {tool_file}",
94
+ "stdout": f"工具成功生成于: {tool_file}",
73
95
  "stderr": ""
74
96
  }
75
97
 
@@ -77,11 +99,19 @@ class ToolGenerator:
77
99
  return {
78
100
  "success": False,
79
101
  "stdout": "",
80
- "stderr": f"Tool generation failed: {str(e)}"
102
+ "stderr": f"工具生成失败: {str(e)}"
81
103
  }
82
104
 
83
105
  def _create_prompt(self, tool_name: str, description: str, input_spec: str) -> str:
84
- """创建用于工具生成的LLM提示"""
106
+ """
107
+ 创建用于工具生成的LLM提示
108
+ Args:
109
+ tool_name: 工具名称
110
+ description: 工具描述
111
+ input_spec: 输入规范
112
+ Returns:
113
+ 格式化后的提示字符串
114
+ """
85
115
  example_code = '''
86
116
  <TOOL>
87
117
  from typing import Dict, Any
@@ -162,20 +192,32 @@ class CustomTool:
162
192
  '''
163
193
 
164
194
  def _extract_code(self, response: str) -> str:
165
- """Flexibly extract Python code from LLM response"""
166
- # Find the first occurrence of <TOOL> and </TOOL>
195
+ """
196
+ 从LLM响应中提取Python代码
197
+ Args:
198
+ response: LLM的响应字符串
199
+ Returns:
200
+ 提取到的Python代码字符串
201
+ """
202
+ # 查找第一个<TOOL>和</TOOL>标签之间的内容
167
203
  sm = re.search(r'<TOOL>(.*?)</TOOL>', response, re.DOTALL)
168
204
  if sm:
169
205
  return sm.group(1)
170
206
  return ""
171
207
 
172
208
  def _validate_return_value_format(self, code: str) -> bool:
173
- """Validate that execute method returns correct format"""
209
+ """
210
+ 验证execute方法的返回值格式是否正确
211
+ Args:
212
+ code: 要验证的代码字符串
213
+ Returns:
214
+ 布尔值,表示格式是否正确
215
+ """
174
216
  required_fields = ["success", "stdout", "stderr"]
175
- # Look for execute method
217
+ # 检查execute方法是否存在
176
218
  if "def execute(self, args: Dict) -> Dict:" not in code and \
177
219
  "def execute(self, args: Dict) -> Dict[str, Any]:" not in code:
178
220
  return False
179
221
 
180
- # Check for required fields in return statement
181
- return all(field in code for field in required_fields)
222
+ # 检查返回值中是否包含所有必需字段
223
+ return all(field in code for field in required_fields)
@@ -1,24 +1,24 @@
1
1
  """
2
- Jarvis Utils Module
3
- This module provides utility functions and classes used throughout the Jarvis system.
4
- It includes various helper functions, configuration management, and common operations.
5
- The module is organized into several submodules:
6
- - config: Configuration management
7
- - embedding: Text embedding utilities
8
- - git_utils: Git repository operations
9
- - input: User input handling
10
- - methodology: Methodology management
11
- - output: Output formatting
12
- - utils: General utilities
2
+ Jarvis工具模块
3
+ 该模块提供了Jarvis系统中使用的各种实用函数和类。
4
+ 包含多种辅助函数、配置管理和常见操作。
5
+ 该模块组织为以下几个子模块:
6
+ - config: 配置管理
7
+ - embedding: 文本嵌入工具
8
+ - git_utils: Git仓库操作
9
+ - input: 用户输入处理
10
+ - methodology: 方法论管理
11
+ - output: 输出格式化
12
+ - utils: 通用工具
13
13
  """
14
14
  import os
15
15
  import colorama
16
16
  from rich.traceback import install as install_rich_traceback
17
- # Re-export from new modules
18
- # These imports are required for project functionality and may be used dynamically
19
- # Initialize colorama for cross-platform colored text
17
+ # 从新模块重新导出
18
+ # 这些导入是项目功能所必需的,可能会被动态使用
19
+ # 初始化colorama以支持跨平台的彩色文本
20
20
  colorama.init()
21
- # Disable tokenizers parallelism to avoid issues with multiprocessing
21
+ # 禁用tokenizers并行以避免多进程问题
22
22
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
23
- # Install rich traceback handler for better error messages
24
- install_rich_traceback()
23
+ # 安装rich traceback处理器以获得更好的错误信息
24
+ install_rich_traceback()