jarvis-ai-assistant 0.1.58__py3-none-any.whl → 0.1.74__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.

jarvis/main.py CHANGED
@@ -117,7 +117,6 @@ def main():
117
117
  PlatformRegistry.get_global_platform_registry().set_global_platform_name(platform)
118
118
 
119
119
  if args.model:
120
- PrettyOutput.print(f"用户传入了模型参数,更换模型: {args.model}", OutputType.USER)
121
120
  os.environ["JARVIS_MODEL"] = args.model
122
121
 
123
122
  try:
@@ -126,7 +125,6 @@ def main():
126
125
 
127
126
  # 如果用户传入了模型参数,则更换当前模型为用户指定的模型
128
127
  if args.model:
129
- PrettyOutput.print(f"用户传入了模型参数,更换模型: {args.model}", OutputType.USER)
130
128
  agent.model.set_model_name(args.model)
131
129
 
132
130
  # 欢迎信息
jarvis/models/ai8.py CHANGED
@@ -64,15 +64,14 @@ class AI8Model(BasePlatform):
64
64
 
65
65
  PrettyOutput.print("使用AI8_MODEL环境变量配置模型", OutputType.SUCCESS)
66
66
 
67
- self.model_name = os.getenv("AI8_MODEL") or os.getenv("JARVIS_MODEL") or "deepseek-chat"
67
+ self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-chat"
68
68
  if self.model_name not in self.models:
69
69
  PrettyOutput.print(f"警告: 当前选择的模型 {self.model_name} 不在可用列表中", OutputType.WARNING)
70
70
 
71
- PrettyOutput.print(f"当前使用模型: {self.model_name}", OutputType.SYSTEM)
72
71
 
73
72
  def set_model_name(self, model_name: str):
74
73
  """设置模型名称"""
75
- PrettyOutput.print(f"设置模型: {model_name}", OutputType.USER)
74
+
76
75
  self.model_name = model_name
77
76
 
78
77
  def create_conversation(self) -> bool:
jarvis/models/base.py CHANGED
@@ -42,9 +42,5 @@ class BasePlatform(ABC):
42
42
  raise NotImplementedError("set_system_message is not implemented")
43
43
 
44
44
  def set_suppress_output(self, suppress: bool):
45
- """设置是否屏蔽输出
46
-
47
- Args:
48
- suppress: 是否屏蔽输出
49
- """
45
+ """设置是否屏蔽输出"""
50
46
  self.suppress_output = suppress
jarvis/models/kimi.py CHANGED
@@ -360,6 +360,8 @@ class KimiModel(BasePlatform):
360
360
  PrettyOutput.print(f" 原文: {text}", OutputType.PROGRESS)
361
361
 
362
362
  PrettyOutput.print("", OutputType.PROGRESS)
363
+
364
+ PrettyOutput.print(full_response, OutputType.RESULT)
363
365
 
364
366
  return full_response
365
367
 
jarvis/models/openai.py CHANGED
@@ -33,7 +33,6 @@ class OpenAIModel(BasePlatform):
33
33
  self.base_url = os.getenv("OPENAI_API_BASE", "https://api.deepseek.com")
34
34
  self.model_name = os.getenv("OPENAI_MODEL_NAME") or os.getenv("JARVIS_MODEL") or "deepseek-chat"
35
35
 
36
- PrettyOutput.print(f"当前使用模型: {self.model_name}", OutputType.SYSTEM)
37
36
 
38
37
  self.client = OpenAI(
39
38
  api_key=self.api_key,
@@ -44,7 +43,7 @@ class OpenAIModel(BasePlatform):
44
43
 
45
44
  def set_model_name(self, model_name: str):
46
45
  """设置模型名称"""
47
- PrettyOutput.print(f"设置模型: {model_name}", OutputType.USER)
46
+
48
47
  self.model_name = model_name
49
48
 
50
49
  def set_system_message(self, message: str):
jarvis/models/oyi.py CHANGED
@@ -25,8 +25,6 @@ class OyiModel(BasePlatform):
25
25
  else:
26
26
  PrettyOutput.print("获取模型列表失败", OutputType.WARNING)
27
27
 
28
- PrettyOutput.print("使用OYI_MODEL环境变量配置模型", OutputType.SUCCESS)
29
-
30
28
  self.messages = []
31
29
  self.system_message = ""
32
30
  self.conversation = None
@@ -37,15 +35,14 @@ class OyiModel(BasePlatform):
37
35
  if not self.token:
38
36
  raise Exception("OYI_API_KEY is not set")
39
37
 
40
- self.model_name = os.getenv("OYI_MODEL") or os.getenv("JARVIS_MODEL") or "deepseek-chat"
38
+ self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-chat"
41
39
  if self.model_name not in [m.split()[0] for m in available_models]:
42
40
  PrettyOutput.print(f"警告: 当前选择的模型 {self.model_name} 不在可用列表中", OutputType.WARNING)
43
41
 
44
- PrettyOutput.print(f"当前使用模型: {self.model_name}", OutputType.SYSTEM)
45
42
 
46
43
  def set_model_name(self, model_name: str):
47
44
  """设置模型名称"""
48
- PrettyOutput.print(f"设置模型: {model_name}", OutputType.USER)
45
+
49
46
  self.model_name = model_name
50
47
 
51
48
 
jarvis/models/registry.py CHANGED
@@ -29,7 +29,8 @@ class PlatformRegistry:
29
29
  # 创建 __init__.py 使其成为 Python 包
30
30
  with open(os.path.join(user_platform_dir, "__init__.py"), "w") as f:
31
31
  pass
32
- PrettyOutput.print(f"已创建平台目录: {user_platform_dir}", OutputType.INFO)
32
+
33
+ pass
33
34
  except Exception as e:
34
35
  PrettyOutput.print(f"创建平台目录失败: {str(e)}", OutputType.ERROR)
35
36
  return ""
@@ -81,7 +82,7 @@ class PlatformRegistry:
81
82
  directory: 平台目录路径
82
83
 
83
84
  Returns:
84
- Dict[str, Type[BaseModel]]: 平台名称到平台类的映射
85
+ Dict[str, Type[BasePlatform]]: 平台名称到平台类的映射
85
86
  """
86
87
  platforms = {}
87
88
 
@@ -112,7 +113,7 @@ class PlatformRegistry:
112
113
 
113
114
  # 遍历模块中的所有类
114
115
  for name, obj in inspect.getmembers(module):
115
- # 检查是否是BaseModel的子类,但不是BaseModel本身
116
+ # 检查是否是BasePlatform的子类,但不是BasePlatform本身
116
117
  if (inspect.isclass(obj) and
117
118
  issubclass(obj, BasePlatform) and
118
119
  obj != BasePlatform and
@@ -120,8 +121,8 @@ class PlatformRegistry:
120
121
  # 检查平台实现
121
122
  if not PlatformRegistry.check_platform_implementation(obj):
122
123
  continue
124
+ PrettyOutput.print(f"从 {os.path.join(directory, filename)} 加载平台:{obj.platform_name}", OutputType.SUCCESS)
123
125
  platforms[obj.platform_name] = obj
124
- PrettyOutput.print(f"从 {directory} 加载平台: {obj.platform_name}", OutputType.INFO)
125
126
  break
126
127
  except Exception as e:
127
128
  PrettyOutput.print(f"加载平台 {module_name} 失败: {str(e)}", OutputType.ERROR)
@@ -159,6 +160,7 @@ class PlatformRegistry:
159
160
  raise Exception(f"Failed to create platform: {PlatformRegistry.global_platform_name}")
160
161
  return platform
161
162
 
163
+
162
164
  def register_platform(self, name: str, platform_class: Type[BasePlatform]):
163
165
  """注册平台类
164
166
 
@@ -167,7 +169,6 @@ class PlatformRegistry:
167
169
  model_class: 平台类
168
170
  """
169
171
  self.platforms[name] = platform_class
170
- PrettyOutput.print(f"已注册平台: {name}", OutputType.INFO)
171
172
 
172
173
  def create_platform(self, name: str) -> Optional[BasePlatform]:
173
174
  """创建平台实例
@@ -176,15 +177,15 @@ class PlatformRegistry:
176
177
  name: 平台名称
177
178
 
178
179
  Returns:
179
- BaseModel: 平台实例
180
+ BasePlatform: 平台实例
180
181
  """
181
182
  if name not in self.platforms:
182
183
  PrettyOutput.print(f"未找到平台: {name}", OutputType.ERROR)
183
184
  return None
184
185
 
185
186
  try:
187
+
186
188
  platform = self.platforms[name]()
187
- PrettyOutput.print(f"已创建平台实例: {name}", OutputType.INFO)
188
189
  return platform
189
190
  except Exception as e:
190
191
  PrettyOutput.print(f"创建平台失败: {str(e)}", OutputType.ERROR)
jarvis/tools/__init__.py CHANGED
@@ -3,3 +3,4 @@ from .registry import ToolRegistry
3
3
  __all__ = [
4
4
  'ToolRegistry',
5
5
  ]
6
+
@@ -0,0 +1,74 @@
1
+ import os
2
+ from typing import Any, Dict
3
+ from jarvis.jarvis_codebase.main import CodeBase
4
+ from jarvis.utils import find_git_root, PrettyOutput, OutputType
5
+
6
+ class CodebaseQATool:
7
+ """代码库问答工具,用于回答关于代码库的问题"""
8
+
9
+ name = "codebase_qa"
10
+ description = "回答关于代码库的问题,可以查询和理解代码的功能、结构和实现细节"
11
+ parameters = {
12
+ "type": "object",
13
+ "properties": {
14
+ "dir": {
15
+ "type": "string",
16
+ "description": "项目根目录"
17
+ },
18
+ "question": {
19
+ "type": "string",
20
+ "description": "关于代码库的问题"
21
+ },
22
+ "top_k": {
23
+ "type": "integer",
24
+ "description": "搜索相关文件的数量",
25
+ "default": 5
26
+ }
27
+ },
28
+ "required": ["question"]
29
+ }
30
+
31
+ def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
32
+ """执行代码问答"""
33
+ try:
34
+ dir = params.get("dir")
35
+ question = params["question"]
36
+ top_k = params.get("top_k", 5)
37
+
38
+ # 初始化代码库
39
+ current_dir = os.getcwd()
40
+ root_dir = find_git_root(dir or current_dir)
41
+ if not root_dir:
42
+ return {
43
+ "success": False,
44
+ "stdout": "",
45
+ "stderr": "错误:当前目录不在Git仓库中",
46
+ "error": "NotInGitRepository"
47
+ }
48
+
49
+ os.chdir(root_dir)
50
+ codebase = CodeBase(root_dir)
51
+ # 生成索引
52
+
53
+ codebase.generate_codebase(force=True)
54
+ # 执行问答
55
+ response = codebase.ask_codebase(question, top_k)
56
+ os.chdir(current_dir)
57
+ return {
58
+ "success": True,
59
+ "stdout": response,
60
+ "stderr": "",
61
+ "error": None
62
+ }
63
+
64
+ except Exception as e:
65
+ PrettyOutput.print(f"代码问答出错: {str(e)}", output_type=OutputType.ERROR)
66
+ return {
67
+ "success": False,
68
+ "stdout": "",
69
+ "stderr": f"执行代码问答时发生错误: {str(e)}",
70
+ "error": str(type(e).__name__)
71
+ }
72
+
73
+ def register():
74
+ return CodebaseQATool()
jarvis/tools/coder.py ADDED
@@ -0,0 +1,69 @@
1
+ import os
2
+ from typing import Dict, Any, Optional
3
+ from jarvis.jarvis_coder.main import JarvisCoder
4
+ from jarvis.utils import PrettyOutput, OutputType
5
+
6
+ class CoderTool:
7
+ """代码修改工具"""
8
+
9
+ name = "coder"
10
+ description = "用于自动修改和生成代码的工具"
11
+ parameters = {
12
+ "feature": {
13
+ "type": "string",
14
+ "description": "要实现的功能描述",
15
+ "required": True
16
+ },
17
+ "dir": {
18
+ "type": "string",
19
+ "description": "项目根目录",
20
+ "required": False
21
+ },
22
+ "language": {
23
+ "type": "string",
24
+ "description": "编程语言",
25
+ "required": False
26
+ }
27
+ }
28
+
29
+ def __init__(self):
30
+ self._coder = None
31
+
32
+
33
+ def _init_coder(self, dir: Optional[str] = None, language: Optional[str] = "python") -> None:
34
+ """初始化JarvisCoder实例"""
35
+ if not self._coder:
36
+ import os
37
+ work_dir = dir or os.getcwd()
38
+ self._coder = JarvisCoder(work_dir, language)
39
+
40
+ def execute(self, args: Dict) -> Dict[str, Any]:
41
+ """执行代码修改
42
+
43
+ Args:
44
+ feature: 要实现的功能描述
45
+ dir: 可选,项目根目录
46
+ language: 可选,编程语言
47
+
48
+ Returns:
49
+ Dict[str, Any]: 执行结果
50
+ """
51
+ feature = args.get("feature")
52
+ dir = args.get("dir")
53
+ language = args.get("language", "python")
54
+
55
+ try:
56
+ self.current_dir = os.getcwd()
57
+ self._init_coder(dir, language)
58
+ result = self._coder.execute(feature)
59
+ return result
60
+ except Exception as e:
61
+ PrettyOutput.print(f"代码修改失败: {str(e)}", OutputType.ERROR)
62
+ return {
63
+ "success": False,
64
+ "stdout": "",
65
+ "stderr": f"执行失败: {str(e)}",
66
+ "error": e
67
+ }
68
+ finally:
69
+ os.chdir(self.current_dir)
@@ -8,7 +8,7 @@ class MethodologyTool:
8
8
  """经验管理工具"""
9
9
 
10
10
  name = "methodology"
11
- description = "管理问题处理经验总结,支持添加、更新、删除操作"
11
+ description = "管理问题处理方法论,支持添加、更新、删除操作"
12
12
  parameters = {
13
13
  "type": "object",
14
14
  "properties": {
@@ -23,7 +23,7 @@ class MethodologyTool:
23
23
  },
24
24
  "content": {
25
25
  "type": "string",
26
- "description": "经验总结内容 (update/add 时必需)",
26
+ "description": "方法论内容 (update/add 时必需)",
27
27
  "optional": True
28
28
  }
29
29
  },
@@ -36,39 +36,39 @@ class MethodologyTool:
36
36
  self._ensure_file_exists()
37
37
 
38
38
  def _ensure_file_exists(self):
39
- """确保经验总结文件存在"""
39
+ """确保方法论文件存在"""
40
40
  if not os.path.exists(self.methodology_file):
41
41
  try:
42
42
  with open(self.methodology_file, 'w', encoding='utf-8') as f:
43
43
  yaml.safe_dump({}, f, allow_unicode=True)
44
44
  except Exception as e:
45
- PrettyOutput.print(f"创建经验总结文件失败: {str(e)}", OutputType.ERROR)
45
+ PrettyOutput.print(f"创建方法论文件失败: {str(e)}", OutputType.ERROR)
46
46
 
47
47
  def _load_methodologies(self) -> Dict:
48
- """加载所有经验总结"""
48
+ """加载所有方法论"""
49
49
  try:
50
50
  with open(self.methodology_file, 'r', encoding='utf-8') as f:
51
51
  return yaml.safe_load(f) or {}
52
52
  except Exception as e:
53
- PrettyOutput.print(f"加载经验总结失败: {str(e)}", OutputType.ERROR)
53
+ PrettyOutput.print(f"加载方法论失败: {str(e)}", OutputType.ERROR)
54
54
  return {}
55
55
 
56
56
  def _save_methodologies(self, methodologies: Dict):
57
- """保存所有经验总结"""
57
+ """保存所有方法论"""
58
58
  try:
59
59
  with open(self.methodology_file, 'w', encoding='utf-8') as f:
60
60
  yaml.safe_dump(methodologies, f, allow_unicode=True)
61
61
  except Exception as e:
62
- PrettyOutput.print(f"保存经验总结失败: {str(e)}", OutputType.ERROR)
62
+ PrettyOutput.print(f"保存方法论失败: {str(e)}", OutputType.ERROR)
63
63
 
64
64
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
65
- """执行经验总结管理操作
65
+ """执行方法论管理操作
66
66
 
67
67
  Args:
68
68
  args: 包含操作参数的字典
69
69
  - operation: 操作类型 (delete/update/add)
70
70
  - problem_type: 问题类型
71
- - content: 经验总结内容 (update/add 时必需)
71
+ - content: 方法论内容 (update/add 时必需)
72
72
 
73
73
  Returns:
74
74
  Dict[str, Any]: 包含执行结果的字典
@@ -92,19 +92,19 @@ class MethodologyTool:
92
92
  self._save_methodologies(methodologies)
93
93
  return {
94
94
  "success": True,
95
- "stdout": f"已删除问题类型 '{problem_type}' 的经验总结"
95
+ "stdout": f"已删除问题类型 '{problem_type}' 的方法论"
96
96
  }
97
97
  else:
98
98
  return {
99
99
  "success": False,
100
- "error": f"未找到问题类型 '{problem_type}' 的经验总结"
100
+ "error": f"未找到问题类型 '{problem_type}' 的方法论"
101
101
  }
102
102
 
103
103
  elif operation in ["update", "add"]:
104
104
  if not content:
105
105
  return {
106
106
  "success": False,
107
- "error": "需要提供经验总结内容"
107
+ "error": "需要提供方法论内容"
108
108
  }
109
109
 
110
110
  methodologies[problem_type] = content
@@ -113,7 +113,7 @@ class MethodologyTool:
113
113
  action = "更新" if problem_type in methodologies else "添加"
114
114
  return {
115
115
  "success": True,
116
- "stdout": f"已{action}问题类型 '{problem_type}' 的经验总结"
116
+ "stdout": f"已{action}问题类型 '{problem_type}' 的方法论"
117
117
  }
118
118
 
119
119
  else:
@@ -129,13 +129,13 @@ class MethodologyTool:
129
129
  }
130
130
 
131
131
  def get_methodology(self, problem_type: str) -> Optional[str]:
132
- """获取指定问题类型的经验总结
132
+ """获取指定问题类型的方法论
133
133
 
134
134
  Args:
135
135
  problem_type: 问题类型
136
136
 
137
137
  Returns:
138
- Optional[str]: 经验总结内容,如果不存在则返回 None
138
+ Optional[str]: 方法论内容,如果不存在则返回 None
139
139
  """
140
140
  methodologies = self._load_methodologies()
141
141
  return methodologies.get(problem_type)
jarvis/tools/registry.py CHANGED
@@ -99,7 +99,7 @@ class ToolRegistry:
99
99
  parameters=tool_instance.parameters,
100
100
  func=tool_instance.execute
101
101
  )
102
- PrettyOutput.print(f"从 {file_path} 加载工具: {tool_instance.name}: {tool_instance.description}", OutputType.INFO)
102
+ PrettyOutput.print(f"从 {file_path} 加载工具: {tool_instance.name}: {tool_instance.description}", OutputType.SUCCESS)
103
103
  tool_found = True
104
104
  break
105
105
 
jarvis/tools/search.py CHANGED
@@ -2,7 +2,39 @@ from typing import Dict, Any, List
2
2
  from jarvis.models.registry import PlatformRegistry
3
3
  from jarvis.utils import PrettyOutput, OutputType
4
4
  from jarvis.tools.webpage import WebpageTool
5
- from jarvis.tools.bing_search import bing_search
5
+ from playwright.sync_api import sync_playwright
6
+ from urllib.parse import quote
7
+
8
+ def bing_search(query):
9
+ try:
10
+ with sync_playwright() as p:
11
+ browser = p.chromium.launch()
12
+ page = browser.new_page()
13
+ page.goto(
14
+ f"https://www.bing.com/search?form=QBRE&q={quote(query)}&cc=US"
15
+ )
16
+
17
+ page.wait_for_selector("#b_results", timeout=10000)
18
+
19
+ summaries = page.evaluate("""() => {
20
+ const liElements = Array.from(
21
+ document.querySelectorAll("#b_results > .b_algo")
22
+ );
23
+ return liElements.map((li) => {
24
+ const abstractElement = li.querySelector(".b_caption > p");
25
+ const linkElement = li.querySelector("a");
26
+ const href = linkElement.getAttribute("href");
27
+ const title = linkElement.textContent;
28
+ const abstract = abstractElement ? abstractElement.textContent : "";
29
+ return { href, title, abstract };
30
+ });
31
+ }""")
32
+
33
+ browser.close()
34
+ print(summaries)
35
+ return summaries
36
+ except Exception as error:
37
+ print("An error occurred:", error)
6
38
 
7
39
  class SearchTool:
8
40
  name = "search"
jarvis/utils.py CHANGED
@@ -158,7 +158,7 @@ def get_multiline_input(tip: str) -> str:
158
158
  lines.append(line)
159
159
 
160
160
  except KeyboardInterrupt:
161
- PrettyOutput.print("\n输入已取消", OutputType.ERROR)
161
+ PrettyOutput.print("\n输入已取消", OutputType.INFO)
162
162
  return "__interrupt__"
163
163
 
164
164
  return "\n".join(lines)
@@ -200,3 +200,10 @@ def while_true(func, sleep_time: float = 0.1):
200
200
  PrettyOutput.print(f"执行失败,{sleep_time}s后重试...", OutputType.WARNING)
201
201
  time.sleep(sleep_time)
202
202
  return ret
203
+
204
+ def find_git_root(dir="."):
205
+ curr_dir = os.getcwd()
206
+ os.chdir(dir)
207
+ ret = os.popen("git rev-parse --show-toplevel").read().strip()
208
+ os.chdir(curr_dir)
209
+ return ret