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.
- jarvis/__init__.py +1 -1
- jarvis/__pycache__/__init__.cpython-313.pyc +0 -0
- jarvis/__pycache__/agent.cpython-313.pyc +0 -0
- jarvis/__pycache__/main.cpython-313.pyc +0 -0
- jarvis/__pycache__/models.cpython-313.pyc +0 -0
- jarvis/__pycache__/utils.cpython-313.pyc +0 -0
- jarvis/__pycache__/zte_llm.cpython-313.pyc +0 -0
- jarvis/agent.py +131 -36
- jarvis/main.py +44 -24
- jarvis/models.py +54 -36
- jarvis/tools/__init__.py +3 -9
- jarvis/tools/__pycache__/__init__.cpython-313.pyc +0 -0
- jarvis/tools/__pycache__/base.cpython-313.pyc +0 -0
- jarvis/tools/__pycache__/shell.cpython-313.pyc +0 -0
- jarvis/tools/__pycache__/sub_agent.cpython-313.pyc +0 -0
- jarvis/tools/__pycache__/user_input.cpython-313.pyc +0 -0
- jarvis/tools/base.py +57 -138
- jarvis/tools/shell.py +62 -48
- jarvis/tools/sub_agent.py +141 -0
- jarvis/tools/user_input.py +74 -0
- jarvis/utils.py +123 -64
- jarvis/zte_llm.py +136 -0
- {jarvis_ai_assistant-0.1.3.dist-info → jarvis_ai_assistant-0.1.6.dist-info}/METADATA +6 -4
- jarvis_ai_assistant-0.1.6.dist-info/RECORD +38 -0
- {jarvis_ai_assistant-0.1.3.dist-info → jarvis_ai_assistant-0.1.6.dist-info}/WHEEL +1 -1
- jarvis/.jarvis +0 -1
- jarvis/tools/python_script.py +0 -150
- jarvis/tools/rag.py +0 -154
- jarvis/tools/user_confirmation.py +0 -58
- jarvis/tools/user_interaction.py +0 -86
- jarvis_ai_assistant-0.1.3.dist-info/RECORD +0 -36
- {jarvis_ai_assistant-0.1.3.dist-info → jarvis_ai_assistant-0.1.6.dist-info}/entry_points.txt +0 -0
- {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
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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"{
|
|
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
|
-
|
|
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
|
-
|
|
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: #
|
|
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
|
-
|
|
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
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: jarvis-ai-assistant
|
|
3
|
-
Version: 0.1.
|
|
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:
|
|
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,,
|
jarvis/.jarvis
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
- 查看当前git仓库状态,如果有未提交的变更,自动根据当前仓库的文件修改内容总结生成一个git commit,然后执行git push推送到远端仓库,全流程不要询问用户
|
jarvis/tools/python_script.py
DELETED
|
@@ -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
|
-
}
|