jarvis-ai-assistant 0.1.3__py3-none-any.whl → 0.1.6__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 (33) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/__pycache__/__init__.cpython-313.pyc +0 -0
  3. jarvis/__pycache__/agent.cpython-313.pyc +0 -0
  4. jarvis/__pycache__/main.cpython-313.pyc +0 -0
  5. jarvis/__pycache__/models.cpython-313.pyc +0 -0
  6. jarvis/__pycache__/utils.cpython-313.pyc +0 -0
  7. jarvis/__pycache__/zte_llm.cpython-313.pyc +0 -0
  8. jarvis/agent.py +131 -36
  9. jarvis/main.py +44 -24
  10. jarvis/models.py +54 -36
  11. jarvis/tools/__init__.py +3 -9
  12. jarvis/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  13. jarvis/tools/__pycache__/base.cpython-313.pyc +0 -0
  14. jarvis/tools/__pycache__/shell.cpython-313.pyc +0 -0
  15. jarvis/tools/__pycache__/sub_agent.cpython-313.pyc +0 -0
  16. jarvis/tools/__pycache__/user_input.cpython-313.pyc +0 -0
  17. jarvis/tools/base.py +57 -138
  18. jarvis/tools/shell.py +62 -48
  19. jarvis/tools/sub_agent.py +141 -0
  20. jarvis/tools/user_input.py +74 -0
  21. jarvis/utils.py +123 -64
  22. jarvis/zte_llm.py +136 -0
  23. {jarvis_ai_assistant-0.1.3.dist-info → jarvis_ai_assistant-0.1.6.dist-info}/METADATA +6 -4
  24. jarvis_ai_assistant-0.1.6.dist-info/RECORD +38 -0
  25. {jarvis_ai_assistant-0.1.3.dist-info → jarvis_ai_assistant-0.1.6.dist-info}/WHEEL +1 -1
  26. jarvis/.jarvis +0 -1
  27. jarvis/tools/python_script.py +0 -150
  28. jarvis/tools/rag.py +0 -154
  29. jarvis/tools/user_confirmation.py +0 -58
  30. jarvis/tools/user_interaction.py +0 -86
  31. jarvis_ai_assistant-0.1.3.dist-info/RECORD +0 -36
  32. {jarvis_ai_assistant-0.1.3.dist-info → jarvis_ai_assistant-0.1.6.dist-info}/entry_points.txt +0 -0
  33. {jarvis_ai_assistant-0.1.3.dist-info → jarvis_ai_assistant-0.1.6.dist-info}/top_level.txt +0 -0
jarvis/utils.py CHANGED
@@ -1,86 +1,122 @@
1
+ from pathlib import Path
1
2
  import sys
2
3
  import time
3
- import threading
4
- from typing import Optional
4
+ from typing import Dict, Optional
5
5
  from enum import Enum
6
6
  from datetime import datetime
7
7
  import colorama
8
8
  from colorama import Fore, Style
9
+ import os
9
10
 
10
11
  # 初始化colorama
11
12
  colorama.init()
12
13
 
13
- class Spinner:
14
- """加载动画类"""
15
- def __init__(self, message: str = "思考中"):
16
- self.spinner_chars = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
17
- self.message = message
18
- self.running = False
19
- self.spinner_thread = None
20
-
21
- def _spin(self):
22
- i = 0
23
- while self.running:
24
- sys.stdout.write(f"\r{Fore.BLUE}{self.spinner_chars[i]} {self.message}...{Style.RESET_ALL}")
25
- sys.stdout.flush()
26
- time.sleep(0.1)
27
- i = (i + 1) % len(self.spinner_chars)
28
- sys.stdout.write("\r" + " " * (len(self.message) + 10) + "\r")
29
- sys.stdout.flush()
30
-
31
- def start(self):
32
- self.running = True
33
- self.spinner_thread = threading.Thread(target=self._spin)
34
- self.spinner_thread.start()
35
-
36
- def stop(self):
37
- self.running = False
38
- if self.spinner_thread:
39
- self.spinner_thread.join()
40
-
41
14
  class OutputType(Enum):
42
- SYSTEM = "system"
43
- CODE = "code"
44
- RESULT = "result"
45
- ERROR = "error"
46
- INFO = "info"
15
+ SYSTEM = "system" # AI助手消息
16
+ CODE = "code" # 代码相关
17
+ RESULT = "result" # 工具执行结果
18
+ ERROR = "error" # 错误信息
19
+ INFO = "info" # 系统提示
20
+ PLANNING = "planning" # 任务规划
21
+ PROGRESS = "progress" # 执行进度
22
+ SUCCESS = "success" # 成功信息
23
+ WARNING = "warning" # 警告信息
24
+ DEBUG = "debug" # 调试信息
25
+ USER = "user" # 用户输入
26
+ TOOL = "tool" # 工具调用
47
27
 
48
28
  class PrettyOutput:
49
29
  """美化输出类"""
30
+
31
+ # 颜色方案 - 只使用前景色
32
+ COLORS = {
33
+ OutputType.SYSTEM: Fore.CYAN, # 青色 - AI助手
34
+ OutputType.CODE: Fore.GREEN, # 绿色 - 代码
35
+ OutputType.RESULT: Fore.BLUE, # 蓝色 - 结果
36
+ OutputType.ERROR: Fore.RED, # 红色 - 错误
37
+ OutputType.INFO: Fore.YELLOW, # 黄色 - 提示
38
+ OutputType.PLANNING: Fore.MAGENTA, # 紫色 - 规划
39
+ OutputType.PROGRESS: Fore.WHITE, # 白色 - 进度
40
+ OutputType.SUCCESS: Fore.GREEN, # 绿色 - 成功
41
+ OutputType.WARNING: Fore.YELLOW, # 黄色 - 警告
42
+ OutputType.DEBUG: Fore.BLUE, # 蓝色 - 调试
43
+ OutputType.USER: Fore.GREEN, # 绿色 - 用户
44
+ OutputType.TOOL: Fore.YELLOW, # 黄色 - 工具
45
+ }
46
+
47
+ # 图标方案
48
+ ICONS = {
49
+ OutputType.SYSTEM: "🤖", # 机器人 - AI助手
50
+ OutputType.CODE: "📝", # 记事本 - 代码
51
+ OutputType.RESULT: "✨", # 闪光 - 结果
52
+ OutputType.ERROR: "❌", # 错误 - 错误
53
+ OutputType.INFO: "ℹ️", # 信息 - 提示
54
+ OutputType.PLANNING: "📋", # 剪贴板 - 规划
55
+ OutputType.PROGRESS: "⏳", # 沙漏 - 进度
56
+ OutputType.SUCCESS: "✅", # 勾选 - 成功
57
+ OutputType.WARNING: "⚠️", # 警告 - 警告
58
+ OutputType.DEBUG: "🔍", # 放大镜 - 调试
59
+ OutputType.USER: "👤", # 用户 - 用户
60
+ OutputType.TOOL: "🔧", # 扳手 - 工具
61
+ }
62
+
63
+ # 前缀方案
64
+ PREFIXES = {
65
+ OutputType.SYSTEM: "Assistant",
66
+ OutputType.CODE: "Code",
67
+ OutputType.RESULT: "Result",
68
+ OutputType.ERROR: "Error",
69
+ OutputType.INFO: "Info",
70
+ OutputType.PLANNING: "Plan",
71
+ OutputType.PROGRESS: "Progress",
72
+ OutputType.SUCCESS: "Success",
73
+ OutputType.WARNING: "Warning",
74
+ OutputType.DEBUG: "Debug",
75
+ OutputType.USER: "User",
76
+ OutputType.TOOL: "Tool",
77
+ }
78
+
50
79
  @staticmethod
51
80
  def format(text: str, output_type: OutputType, timestamp: bool = True) -> str:
52
- # 颜色映射
53
- colors = {
54
- OutputType.SYSTEM: Fore.CYAN,
55
- OutputType.CODE: Fore.GREEN,
56
- OutputType.RESULT: Fore.BLUE,
57
- OutputType.ERROR: Fore.RED,
58
- OutputType.INFO: Fore.YELLOW
59
- }
60
-
61
- # 图标映射
62
- icons = {
63
- OutputType.SYSTEM: "🤖",
64
- OutputType.CODE: "📝",
65
- OutputType.RESULT: "✨",
66
- OutputType.ERROR: "❌",
67
- OutputType.INFO: "ℹ️"
68
- }
69
-
70
- color = colors.get(output_type, "")
71
- icon = icons.get(output_type, "")
81
+ """格式化输出文本"""
82
+ color = PrettyOutput.COLORS.get(output_type, "")
83
+ icon = PrettyOutput.ICONS.get(output_type, "")
84
+ prefix = PrettyOutput.PREFIXES.get(output_type, "")
72
85
 
73
- # 添加时间戳
74
- time_str = f"[{datetime.now().strftime('%H:%M:%S')}] " if timestamp else ""
86
+ # 添加时间戳 - 使用白色
87
+ time_str = f"{Fore.WHITE}[{datetime.now().strftime('%H:%M:%S')}]{Style.RESET_ALL} " if timestamp else ""
75
88
 
76
89
  # 格式化输出
77
- formatted_text = f"{color}{time_str}{icon} {text}{Style.RESET_ALL}"
90
+ formatted_text = f"{time_str}{color}{icon} {prefix}: {text}{Style.RESET_ALL}"
78
91
 
79
92
  return formatted_text
80
93
 
81
94
  @staticmethod
82
95
  def print(text: str, output_type: OutputType, timestamp: bool = True):
83
- print(PrettyOutput.format(text, output_type, timestamp))
96
+ """打印格式化的输出"""
97
+ print(PrettyOutput.format(text, output_type, timestamp))
98
+
99
+ @staticmethod
100
+ def section(title: str, output_type: OutputType = OutputType.INFO):
101
+ """打印带分隔线的段落标题"""
102
+ width = 60
103
+ color = PrettyOutput.COLORS.get(output_type, "")
104
+ print(f"\n{color}" + "=" * width + f"{Style.RESET_ALL}")
105
+ PrettyOutput.print(title.center(width - 10), output_type, timestamp=False)
106
+ print(f"{color}" + "=" * width + f"{Style.RESET_ALL}\n")
107
+
108
+ @staticmethod
109
+ def print_stream(text: str, output_type: OutputType):
110
+ """打印流式输出,不换行"""
111
+ color = PrettyOutput.COLORS.get(output_type, "")
112
+ sys.stdout.write(f"{color}{text}{Style.RESET_ALL}")
113
+ sys.stdout.flush()
114
+
115
+ @staticmethod
116
+ def print_stream_end():
117
+ """流式输出结束,打印换行"""
118
+ sys.stdout.write("\n")
119
+ sys.stdout.flush()
84
120
 
85
121
  def get_multiline_input(tip: str) -> str:
86
122
  """获取多行输入"""
@@ -89,10 +125,13 @@ def get_multiline_input(tip: str) -> str:
89
125
 
90
126
  while True:
91
127
  try:
92
- line = input("... " if lines else ">>> ").strip()
93
- # 检查是否结束输入
128
+ prompt = "... " if lines else ">>> "
129
+ sys.stdout.write(f"{Fore.GREEN}{prompt}{Style.RESET_ALL}")
130
+ sys.stdout.flush()
131
+
132
+ line = input().strip()
94
133
  if not line:
95
- if not lines: # 如果是第一行就输入空行或finish
134
+ if not lines: # 如果是第一行就输入空行
96
135
  return ""
97
136
  break
98
137
 
@@ -100,6 +139,26 @@ def get_multiline_input(tip: str) -> str:
100
139
 
101
140
  except KeyboardInterrupt:
102
141
  PrettyOutput.print("\n输入已取消", OutputType.ERROR)
103
- return ""
142
+ return "__interrupt__"
143
+
144
+ return "\n".join(lines).strip()
145
+
146
+ def load_env_from_file():
147
+ """从~/.jarvis_env加载环境变量"""
148
+ env_file = Path.home() / ".jarvis_env"
149
+
150
+ if env_file.exists():
151
+ try:
152
+ with open(env_file, "r", encoding="utf-8") as f:
153
+ for line in f:
154
+ line = line.strip()
155
+ if line and not line.startswith("#"):
156
+ try:
157
+ key, value = line.split("=", 1)
158
+ os.environ[key.strip()] = value.strip().strip("'").strip('"')
159
+ except ValueError:
160
+ continue
161
+ except Exception as e:
162
+ PrettyOutput.print(f"Warning: Failed to read ~/.jarvis_env: {e}", OutputType.WARNING)
104
163
 
105
- return "\n".join(lines).strip()
164
+
jarvis/zte_llm.py ADDED
@@ -0,0 +1,136 @@
1
+ import requests
2
+ import json
3
+ import os
4
+ from pathlib import Path
5
+ from typing import Dict, Any, List, Optional
6
+
7
+ from jarvis.utils import OutputType, PrettyOutput
8
+ from .models import BaseModel
9
+
10
+ class ZteLLM(BaseModel):
11
+ """ZTE Nebula LLM implementation"""
12
+
13
+ def __init__(self,
14
+ app_id: str,
15
+ app_key: str,
16
+ emp_no: str,
17
+ auth_value: str,
18
+ model: str = "nebulacoder",
19
+ ):
20
+ """Initialize ZTE LLM with required credentials"""
21
+ self.app_id = str(app_id)
22
+ self.app_key = str(app_key)
23
+ self.emp_no = str(emp_no)
24
+ self.auth_value = str(auth_value)
25
+ self.model = model
26
+ self.base_url = "https://studio.zte.com.cn/zte-studio-ai-platform/openapi/v1"
27
+
28
+ def _make_request(self, endpoint: str, data: Dict[str, Any]) -> Dict[str, Any]:
29
+ """Make request to ZTE API"""
30
+ headers = {
31
+ 'Content-Type': 'application/json',
32
+ 'Authorization': f'Bearer {self.app_id}-{self.app_key}',
33
+ 'X-Emp-No': self.emp_no,
34
+ 'X-Auth-Value': self.auth_value
35
+ }
36
+
37
+ response = requests.post(
38
+ f"{self.base_url}/{endpoint}",
39
+ headers=headers,
40
+ json=data
41
+ )
42
+
43
+ response.raise_for_status()
44
+ result = response.json()
45
+
46
+ if result["code"]["code"] != "0000":
47
+ raise Exception(f"API Error: {result['code']['msg']}")
48
+
49
+ ret = result["bo"]
50
+ PrettyOutput.print_stream(ret, OutputType.SYSTEM)
51
+ return ret
52
+
53
+ def chat(self, messages: List[Dict[str, Any]], tools: Optional[List[Dict]] = None) -> Dict[str, Any]:
54
+ """Chat with ZTE LLM"""
55
+ # Convert messages to prompt
56
+ prompt = self._convert_messages_to_prompt(messages)
57
+
58
+ # Prepare data for API call
59
+ data = {
60
+ "chatUuid": "",
61
+ "chatName": "",
62
+ "stream": False,
63
+ "keep": False,
64
+ "text": prompt,
65
+ "model": self.model
66
+ }
67
+
68
+ # If tools are provided, add them to the prompt
69
+ if tools:
70
+ tools_desc = "Available tools:\n\n" + json.dumps(tools, indent=2, ensure_ascii=False)
71
+ data["text"] = tools_desc + "\n\n" + data["text"]
72
+
73
+ try:
74
+ result = self._make_request("chat", data)
75
+
76
+ # Parse the response to extract potential tool calls
77
+ response_text = result["result"]
78
+ tool_calls = BaseModel.extract_tool_calls(response_text)
79
+
80
+ return {
81
+ "message": {
82
+ "content": response_text,
83
+ "tool_calls": tool_calls
84
+ }
85
+ }
86
+
87
+ except Exception as e:
88
+ raise Exception(f"ZTE LLM chat failed: {str(e)}")
89
+
90
+ def _convert_messages_to_prompt(self, messages: List[Dict[str, Any]]) -> str:
91
+ """Convert message list to a single prompt string"""
92
+ prompt_parts = []
93
+
94
+ for message in messages:
95
+ role = message["role"]
96
+ content = message.get("content", "")
97
+
98
+ if role == "system":
99
+ prompt_parts.append(f"System: {content}")
100
+ elif role == "user":
101
+ prompt_parts.append(f"User: {content}")
102
+ elif role == "assistant":
103
+ prompt_parts.append(f"Assistant: {content}")
104
+ elif role == "tool":
105
+ prompt_parts.append(f"Tool Result: {content}")
106
+
107
+ return "\n\n".join(prompt_parts)
108
+
109
+
110
+ def create_zte_llm(model_name: str = "NebulaBiz") -> ZteLLM:
111
+ """Create ZTE LLM instance with provided parameters"""
112
+ # Load environment variables from file
113
+
114
+ # Get credentials from parameters, env file, or system environment variables
115
+ app_id = os.getenv('ZTE_APP_ID')
116
+ app_key = os.getenv('ZTE_APP_KEY')
117
+ emp_no = os.getenv('ZTE_EMP_NO')
118
+ auth_value = os.getenv('ZTE_AUTH_VALUE')
119
+
120
+ # Validate required credentials
121
+ if not all([app_id, app_key, emp_no, auth_value]):
122
+ raise ValueError(
123
+ "Missing required credentials. Please provide through either:\n"
124
+ "1. Function parameters\n"
125
+ "2. ~/.jarvis_env file\n"
126
+ "3. System environment variables\n\n"
127
+ "Required variables: ZTE_APP_ID, ZTE_APP_KEY, ZTE_EMP_NO, ZTE_AUTH_VALUE"
128
+ )
129
+
130
+ return ZteLLM(
131
+ app_id=app_id,
132
+ app_key=app_key,
133
+ emp_no=emp_no,
134
+ auth_value=auth_value,
135
+ model=model_name
136
+ )
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.3
3
+ Version: 0.1.6
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
@@ -21,13 +21,15 @@ Requires-Dist: beautifulsoup4>=4.9.3
21
21
  Requires-Dist: duckduckgo-search>=3.0.0
22
22
  Requires-Dist: pyyaml>=5.1
23
23
  Requires-Dist: ollama>=0.1.6
24
- Requires-Dist: sentence-transformers>=2.5.1
25
- Requires-Dist: chromadb>=0.4.24
24
+ Requires-Dist: colorama>=0.4.6
26
25
  Provides-Extra: dev
27
26
  Requires-Dist: pytest; extra == "dev"
28
27
  Requires-Dist: black; extra == "dev"
29
28
  Requires-Dist: isort; extra == "dev"
30
29
  Requires-Dist: mypy; extra == "dev"
30
+ Dynamic: author
31
+ Dynamic: home-page
32
+ Dynamic: requires-python
31
33
 
32
34
  <div align="center">
33
35
 
@@ -0,0 +1,38 @@
1
+ jarvis/__init__.py,sha256=IB2q6sPGefOsNYLmp5aaOnkS9qWc9ZMY1HQ6V-l-xaY,49
2
+ jarvis/agent.py,sha256=KLeC4oWUYMRXg4QgjyVbfSaJwaIghfJ6KE4JpIS2blI,7225
3
+ jarvis/main.py,sha256=pRwtXWRnbBC3J-xbtuYTxQ0e9JuwU5XxCzbS5SsQESU,6118
4
+ jarvis/models.py,sha256=ZSdUEdVb3aFgvvMtNZuDh3kVXAlA_0CPWv-BzTsLdv8,4508
5
+ jarvis/utils.py,sha256=3hLtv-HcBL8Ngw69cowhARuIFrjcQ6yRP3Y1o9CvtsI,5992
6
+ jarvis/zte_llm.py,sha256=fACFyhEX2ssGC-VOJucBDF_khCFZtyQEC9r9FChae-Q,4631
7
+ jarvis/__pycache__/__init__.cpython-313.pyc,sha256=---ccXWtkwpa6rJNXmjP8vCpz9eCZLk6M1yN3clIrbk,208
8
+ jarvis/__pycache__/agent.cpython-313.pyc,sha256=_i8Bj7p2cBi8G6y8s-7LF-cLO05V3c8AVDoEGbmZbgg,8362
9
+ jarvis/__pycache__/main.cpython-313.pyc,sha256=gJ8eJXVTDuNplc_yjMOxuM17xHwLi6jMtYlB9yiABBc,7963
10
+ jarvis/__pycache__/models.cpython-313.pyc,sha256=7ofJ31hdS9H_VHVpAi_gQGxIcl25i4VWZUpXOinRAnQ,5548
11
+ jarvis/__pycache__/tools.cpython-313.pyc,sha256=lAD4LrnnWzNZQmHXGfZ_2l7oskOpr2_2OC-gdFhxQY8,33933
12
+ jarvis/__pycache__/utils.cpython-313.pyc,sha256=k4jyAlx4tlW0MKLMLzV7OOH9zsKrK0H955kY6M2SuFU,8772
13
+ jarvis/__pycache__/zte_llm.cpython-313.pyc,sha256=OHFPd1MiNkqoncDIFlCj592Y9bQZ8c0Gq6JKJ0enyPA,5553
14
+ jarvis/tools/__init__.py,sha256=Bv3Djt_To60p248ECO2H_LqsTmUriLsq9MDb1Q-uuzA,356
15
+ jarvis/tools/base.py,sha256=rYLrNEpIdmrDm1WavOTyldXZ5dZWVRAmukiMcX40UZU,4436
16
+ jarvis/tools/file_ops.py,sha256=05Vc4u-NGMjLD15WI52eL_nt_RyYt-Z_cXJnnBepf-c,3781
17
+ jarvis/tools/search.py,sha256=dyJmeP_s2tWv5KQejOl-TuVF12B6SXViiXEyTemD1Wo,1412
18
+ jarvis/tools/shell.py,sha256=P0rSaXt-GOXX_-XwkpiLpOXt8Thou4835xGAedxGoGA,2926
19
+ jarvis/tools/sub_agent.py,sha256=t4Lb61_rLyjrbpL4p17Fd1-Or_K12zsNGkAXbXmZPic,3756
20
+ jarvis/tools/user_input.py,sha256=ux3-FE4m5LJIQaoR4qYWeabBK2t0Dk0Irt6_96qUMIc,2313
21
+ jarvis/tools/webpage.py,sha256=UTEomu5j7jbOw8c5az2jsjv5E7LeokWKj1QahvZO7xc,3077
22
+ jarvis/tools/__pycache__/__init__.cpython-313.pyc,sha256=aptY-PF6DpP4xXXHRVfjPV1jQGXAhqcBaTv_ZNei2FA,497
23
+ jarvis/tools/__pycache__/base.cpython-313.pyc,sha256=fEj3a31NMJpaZug4nohtE9OnSCfM3YtzclYYTJvNYJg,6632
24
+ jarvis/tools/__pycache__/file_ops.cpython-313.pyc,sha256=bawv11xhWSj5wCtW0QeJLI-InhUBUXaSkogq6rZzvTQ,3636
25
+ jarvis/tools/__pycache__/python_script.cpython-313.pyc,sha256=8JpryqTovEiTvBlWAK1KjZmPvHUuPc9GT9rTXBEQoJc,6693
26
+ jarvis/tools/__pycache__/rag.cpython-313.pyc,sha256=JH6-PSZRMKAvTZqCwlRXJGClxYXNMs-vetU0q7hBLz0,6064
27
+ jarvis/tools/__pycache__/search.cpython-313.pyc,sha256=VX9zztOwIsPCkYwev0A0XJGyu4Tr0PQcQkbbqx8vfB0,1870
28
+ jarvis/tools/__pycache__/shell.cpython-313.pyc,sha256=0B-mfYwkkZCCCfBQV6Mut0S2ZtW2W4Cykh4rP2W6LJM,3652
29
+ jarvis/tools/__pycache__/sub_agent.cpython-313.pyc,sha256=vkTS0oWAU-We7j7tPs7IbvDcsLh2QNJVQ9Kv_LiMnUs,4021
30
+ jarvis/tools/__pycache__/user_confirmation.cpython-313.pyc,sha256=wK3Ev10lHSUSRvoYmi7A0GzxYkzU-C4Wfhs5qW_HBqs,2271
31
+ jarvis/tools/__pycache__/user_input.cpython-313.pyc,sha256=JjTFOhObKsKF4Pn8KBRuKfV1_Ssj083fjU7Mfc_5z7c,2531
32
+ jarvis/tools/__pycache__/user_interaction.cpython-313.pyc,sha256=RuVZ-pmiPBDywY3efgXSfohMAciC1avMGPmBK5qlnew,3305
33
+ jarvis/tools/__pycache__/webpage.cpython-313.pyc,sha256=VcpkaV8IyOOtebedXjn8ybjr8AglU-3-Cs80yzE4FYo,3628
34
+ jarvis_ai_assistant-0.1.6.dist-info/METADATA,sha256=3ACjmVA3LVSxIHOWf5hHlm5kEvy9mSOqeSgVgIcYJ7s,3690
35
+ jarvis_ai_assistant-0.1.6.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
36
+ jarvis_ai_assistant-0.1.6.dist-info/entry_points.txt,sha256=iKu7OMfew9dtfGhW71gIMTg4wvafuPqKb4wyQOnMAGU,44
37
+ jarvis_ai_assistant-0.1.6.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
38
+ jarvis_ai_assistant-0.1.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.7.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
jarvis/.jarvis DELETED
@@ -1 +0,0 @@
1
- - 查看当前git仓库状态,如果有未提交的变更,自动根据当前仓库的文件修改内容总结生成一个git commit,然后执行git push推送到远端仓库,全流程不要询问用户
@@ -1,150 +0,0 @@
1
- import os
2
- import time
3
- import subprocess
4
- import sys
5
- import pkgutil
6
- from pathlib import Path
7
- from typing import Dict, Any, Optional
8
- from ..utils import PrettyOutput, OutputType
9
-
10
- class PythonScript:
11
- """Python脚本管理类"""
12
- SCRIPTS_DIR = "/tmp/ai_scripts"
13
-
14
- @classmethod
15
- def init_scripts_dir(cls):
16
- """初始化脚本目录"""
17
- Path(cls.SCRIPTS_DIR).mkdir(parents=True, exist_ok=True)
18
-
19
- @classmethod
20
- def generate_script_path(cls, name: Optional[str] = None) -> str:
21
- """生成脚本文件路径"""
22
- if name:
23
- safe_name = "".join(c for c in name if c.isalnum() or c in "._- ")
24
- filename = f"{int(time.time())}_{safe_name}.py"
25
- else:
26
- filename = f"{int(time.time())}_script.py"
27
- return str(Path(cls.SCRIPTS_DIR) / filename)
28
-
29
- class PythonScriptTool:
30
- name = "execute_python"
31
- description = """Execute Python code and return the results.
32
- Notes:
33
- 1. Use print() to output results
34
- 2. Automatic dependency management
35
- 3. Code saved to temporary file
36
- """
37
- parameters = {
38
- "type": "object",
39
- "properties": {
40
- "code": {
41
- "type": "string",
42
- "description": "Python code to execute"
43
- },
44
- "dependencies": {
45
- "type": "array",
46
- "items": {"type": "string"},
47
- "description": "Python package dependencies",
48
- "default": []
49
- },
50
- "name": {
51
- "type": "string",
52
- "description": "Script name",
53
- "default": ""
54
- }
55
- },
56
- "required": ["code"]
57
- }
58
-
59
- @staticmethod
60
- def _is_builtin_package(package_name: str) -> bool:
61
- package_name = package_name.split("==")[0].strip()
62
- if hasattr(sys.modules, package_name) or package_name in sys.stdlib_module_names:
63
- return True
64
- try:
65
- return pkgutil.find_spec(package_name) is not None
66
- except Exception:
67
- return False
68
-
69
- def execute(self, args: Dict) -> Dict[str, Any]:
70
- """执行Python代码"""
71
- try:
72
- code = args["code"]
73
- dependencies = args.get("dependencies", [])
74
- script_name = args.get("name", "")
75
-
76
- # 初始化脚本目录
77
- PythonScript.init_scripts_dir()
78
-
79
- # 生成脚本路径
80
- script_path = PythonScript.generate_script_path(script_name)
81
-
82
- # 安装依赖
83
- missing_deps = []
84
- for dep in dependencies:
85
- if not self._is_builtin_package(dep):
86
- missing_deps.append(dep)
87
-
88
- if missing_deps:
89
- PrettyOutput.print("正在安装依赖...", OutputType.INFO)
90
- try:
91
- subprocess.run(
92
- [sys.executable, "-m", "pip", "install"] + missing_deps,
93
- check=True,
94
- capture_output=True,
95
- text=True
96
- )
97
- PrettyOutput.print("依赖安装完成", OutputType.INFO)
98
- except subprocess.CalledProcessError as e:
99
- return {
100
- "success": False,
101
- "error": f"依赖安装失败: {e.stderr}"
102
- }
103
-
104
- # 写入脚本文件
105
- with open(script_path, 'w', encoding='utf-8') as f:
106
- f.write(code)
107
-
108
- # 执行脚本
109
- PrettyOutput.print(f"执行脚本: {script_path}", OutputType.INFO)
110
- result = subprocess.run(
111
- [sys.executable, script_path],
112
- capture_output=True,
113
- text=True
114
- )
115
-
116
- # 构建输出
117
- output = []
118
-
119
- # 添加脚本信息
120
- output.append(f"脚本路径: {script_path}")
121
- if dependencies:
122
- output.append(f"依赖项: {', '.join(dependencies)}")
123
- output.append("")
124
-
125
- # 添加执行结果
126
- if result.stdout:
127
- output.append("输出:")
128
- output.append(result.stdout)
129
-
130
- # 添加错误信息(如果有)
131
- if result.stderr:
132
- output.append("错误:")
133
- output.append(result.stderr)
134
-
135
- # 添加返回码
136
- output.append(f"返回码: {result.returncode}")
137
-
138
- return {
139
- "success": result.returncode == 0,
140
- "stdout": "\n".join(output),
141
- "stderr": result.stderr,
142
- "return_code": result.returncode,
143
- "script_path": script_path
144
- }
145
-
146
- except Exception as e:
147
- return {
148
- "success": False,
149
- "error": f"执行Python代码失败: {str(e)}"
150
- }