jarvis-ai-assistant 0.1.17__py3-none-any.whl → 0.1.19__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/agent.py +39 -71
- jarvis/main.py +35 -5
- jarvis/tools/__init__.py +2 -0
- jarvis/tools/__pycache__/__init__.cpython-313.pyc +0 -0
- jarvis/tools/__pycache__/base.cpython-313.pyc +0 -0
- jarvis/tools/__pycache__/calculator.cpython-313.pyc +0 -0
- jarvis/tools/__pycache__/calculator_tool.cpython-313.pyc +0 -0
- jarvis/tools/__pycache__/file_ops.cpython-313.pyc +0 -0
- jarvis/tools/__pycache__/generator.cpython-313.pyc +0 -0
- jarvis/tools/__pycache__/shell.cpython-313.pyc +0 -0
- jarvis/tools/base.py +102 -20
- jarvis/tools/file_ops.py +22 -3
- jarvis/tools/generator.py +227 -0
- jarvis/tools/shell.py +23 -6
- {jarvis_ai_assistant-0.1.17.dist-info → jarvis_ai_assistant-0.1.19.dist-info}/METADATA +137 -1
- {jarvis_ai_assistant-0.1.17.dist-info → jarvis_ai_assistant-0.1.19.dist-info}/RECORD +24 -20
- {jarvis_ai_assistant-0.1.17.dist-info → jarvis_ai_assistant-0.1.19.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.17.dist-info → jarvis_ai_assistant-0.1.19.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.17.dist-info → jarvis_ai_assistant-0.1.19.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.17.dist-info → jarvis_ai_assistant-0.1.19.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
jarvis/agent.py
CHANGED
|
@@ -103,55 +103,32 @@ class Agent:
|
|
|
103
103
|
tools_prompt += f" 描述: {tool['description']}\n"
|
|
104
104
|
tools_prompt += f" 参数: {tool['parameters']}\n"
|
|
105
105
|
|
|
106
|
-
self.prompt = f"""你是 {self.name},一个严格遵循 ReAct
|
|
106
|
+
self.prompt = f"""你是 {self.name},一个严格遵循 ReAct 框架的 AI 助手。
|
|
107
107
|
|
|
108
108
|
{tools_prompt}
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
‼️ 只回应用户实际说的内容
|
|
115
|
-
‼️ 每个动作后停止并等待
|
|
110
|
+
核心能力:
|
|
111
|
+
1. 使用现有工具完成任务
|
|
112
|
+
2. 通过 generate_tool 创建新工具扩展功能
|
|
113
|
+
3. 遵循 ReAct (思考-行动-观察) 框架
|
|
116
114
|
|
|
117
|
-
|
|
115
|
+
工作流程:
|
|
118
116
|
1. 思考
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
- 如果需要更多信息,直接询问用户
|
|
129
|
-
- 使用工具时:
|
|
130
|
-
- 只使用下面列出的工具
|
|
131
|
-
- 每次只执行一个工具
|
|
132
|
-
- 工具由用户手动执行
|
|
133
|
-
- 必须使用有效合法的YAML格式:
|
|
134
|
-
<START_TOOL_CALL>
|
|
135
|
-
name: tool_name
|
|
136
|
-
arguments:
|
|
137
|
-
param1: value1 # 所有参数必须正确缩进
|
|
138
|
-
param2: | # 使用YAML块样式表示多行字符串
|
|
139
|
-
line1
|
|
140
|
-
line2
|
|
141
|
-
<END_TOOL_CALL>
|
|
142
|
-
|
|
117
|
+
- 分析需求和可用工具
|
|
118
|
+
- 评估是否需要新工具
|
|
119
|
+
- 规划解决方案
|
|
120
|
+
|
|
121
|
+
2. 行动 (如果需要)
|
|
122
|
+
- 使用现有工具
|
|
123
|
+
- 创建新工具
|
|
124
|
+
- 询问更多信息
|
|
125
|
+
|
|
143
126
|
3. 观察
|
|
144
|
-
-
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
- 不要创建虚假对话
|
|
148
|
-
- 停止并等待实际输入
|
|
127
|
+
- 等待执行结果
|
|
128
|
+
- 分析反馈
|
|
129
|
+
- 规划下一步
|
|
149
130
|
|
|
150
|
-
|
|
151
|
-
思考:我分析当前情况[具体情况]... 基于[事实],我需要[目标]...
|
|
152
|
-
|
|
153
|
-
[如果需要使用工具:]
|
|
154
|
-
行动:我将使用[工具]来[具体目的]...
|
|
131
|
+
工具使用格式:
|
|
155
132
|
<START_TOOL_CALL>
|
|
156
133
|
name: tool_name
|
|
157
134
|
arguments:
|
|
@@ -161,37 +138,28 @@ arguments:
|
|
|
161
138
|
value
|
|
162
139
|
<END_TOOL_CALL>
|
|
163
140
|
|
|
164
|
-
|
|
165
|
-
|
|
141
|
+
创建新工具示例:
|
|
142
|
+
<START_TOOL_CALL>
|
|
143
|
+
name: generate_tool
|
|
144
|
+
arguments:
|
|
145
|
+
tool_name: custom_tool_name
|
|
146
|
+
class_name: CustomToolName
|
|
147
|
+
description: 详细的工具描述
|
|
148
|
+
parameters:
|
|
149
|
+
type: object
|
|
150
|
+
properties:
|
|
151
|
+
param1:
|
|
152
|
+
type: string
|
|
153
|
+
description: 参数1的描述
|
|
154
|
+
required: [param1]
|
|
155
|
+
<END_TOOL_CALL>
|
|
166
156
|
|
|
167
157
|
严格规则:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
‼️ 使用YAML块样式(|)表示多行值
|
|
174
|
-
‼️ 工具由用户手动执行
|
|
175
|
-
‼️ 等待用户提供工具执行结果
|
|
176
|
-
‼️ 不要假设或想象用户回应
|
|
177
|
-
‼️ 没有用户输入时不要继续对话
|
|
178
|
-
‼️ 不要创建虚假对话
|
|
179
|
-
‼️ 每个动作后停止
|
|
180
|
-
‼️ 不要假设结果
|
|
181
|
-
‼️ 不要假设行动
|
|
182
|
-
|
|
183
|
-
注意事项:
|
|
184
|
-
- 先思考再行动
|
|
185
|
-
- 需要时询问用户
|
|
186
|
-
- 只使用列出的工具
|
|
187
|
-
- 一次一个工具
|
|
188
|
-
- 严格遵循YAML格式
|
|
189
|
-
- 等待用户回应
|
|
190
|
-
- 工具结果来自用户
|
|
191
|
-
- 不要假设回应
|
|
192
|
-
- 不要虚构对话
|
|
193
|
-
- 每个动作后停止
|
|
194
|
-
- 只在有实际用户输入时继续
|
|
158
|
+
1. 每次只能执行一个工具
|
|
159
|
+
2. 等待用户提供执行结果
|
|
160
|
+
3. 不要假设或想象结果
|
|
161
|
+
4. 不要创建虚假对话
|
|
162
|
+
5. 每个动作后停止等待
|
|
195
163
|
|
|
196
164
|
任务:
|
|
197
165
|
{user_input}
|
jarvis/main.py
CHANGED
|
@@ -6,6 +6,9 @@ import yaml
|
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
8
|
from pathlib import Path
|
|
9
|
+
from prompt_toolkit import prompt
|
|
10
|
+
from prompt_toolkit.completion import WordCompleter
|
|
11
|
+
from prompt_toolkit.validation import Validator, ValidationError
|
|
9
12
|
|
|
10
13
|
# 添加父目录到Python路径以支持导入
|
|
11
14
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
@@ -55,6 +58,19 @@ def load_tasks() -> dict:
|
|
|
55
58
|
|
|
56
59
|
return tasks
|
|
57
60
|
|
|
61
|
+
class NumberValidator(Validator):
|
|
62
|
+
def validate(self, document):
|
|
63
|
+
text = document.text.strip()
|
|
64
|
+
if not text: # Allow empty input
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
number = int(text)
|
|
69
|
+
if number < 0:
|
|
70
|
+
raise ValidationError(message='Please enter a non-negative number')
|
|
71
|
+
except ValueError:
|
|
72
|
+
raise ValidationError(message='Please enter a valid number')
|
|
73
|
+
|
|
58
74
|
def select_task(tasks: dict) -> str:
|
|
59
75
|
"""Let user select a task from the list or skip. Returns task description if selected."""
|
|
60
76
|
if not tasks:
|
|
@@ -68,9 +84,20 @@ def select_task(tasks: dict) -> str:
|
|
|
68
84
|
PrettyOutput.print(f"[{i}] {name}", OutputType.INFO)
|
|
69
85
|
PrettyOutput.print("[0] Skip predefined tasks", OutputType.INFO)
|
|
70
86
|
|
|
87
|
+
# Create completer with valid numbers
|
|
88
|
+
valid_numbers = [str(i) for i in range(len(task_names) + 1)]
|
|
89
|
+
number_completer = WordCompleter(valid_numbers)
|
|
90
|
+
|
|
71
91
|
while True:
|
|
72
92
|
try:
|
|
73
|
-
choice =
|
|
93
|
+
choice = prompt(
|
|
94
|
+
"\nSelect a task number (0 to skip): ",
|
|
95
|
+
completer=number_completer,
|
|
96
|
+
validator=NumberValidator(),
|
|
97
|
+
validate_while_typing=False,
|
|
98
|
+
enable_history_search=True,
|
|
99
|
+
).strip()
|
|
100
|
+
|
|
74
101
|
if not choice:
|
|
75
102
|
return ""
|
|
76
103
|
|
|
@@ -81,9 +108,12 @@ def select_task(tasks: dict) -> str:
|
|
|
81
108
|
selected_name = task_names[choice - 1]
|
|
82
109
|
return tasks[selected_name] # Return the task description
|
|
83
110
|
else:
|
|
84
|
-
PrettyOutput.print("Invalid choice. Please
|
|
85
|
-
|
|
86
|
-
|
|
111
|
+
PrettyOutput.print("Invalid choice. Please select a number from the list.", OutputType.ERROR)
|
|
112
|
+
|
|
113
|
+
except KeyboardInterrupt:
|
|
114
|
+
return "" # Return empty on Ctrl+C
|
|
115
|
+
except EOFError:
|
|
116
|
+
return "" # Return empty on Ctrl+D
|
|
87
117
|
|
|
88
118
|
def main():
|
|
89
119
|
"""Main entry point for Jarvis."""
|
|
@@ -121,7 +151,7 @@ def main():
|
|
|
121
151
|
|
|
122
152
|
model = KimiModel(kimi_api_key)
|
|
123
153
|
|
|
124
|
-
tool_registry = ToolRegistry(
|
|
154
|
+
tool_registry = ToolRegistry()
|
|
125
155
|
agent = Agent(model, tool_registry)
|
|
126
156
|
|
|
127
157
|
# 欢迎信息
|
jarvis/tools/__init__.py
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from .base import Tool, ToolRegistry
|
|
2
2
|
from .file_ops import FileOperationTool
|
|
3
3
|
from .shell import ShellTool
|
|
4
|
+
from .generator import ToolGeneratorTool
|
|
4
5
|
|
|
5
6
|
__all__ = [
|
|
6
7
|
'Tool',
|
|
7
8
|
'ToolRegistry',
|
|
8
9
|
'FileOperationTool',
|
|
9
10
|
'ShellTool',
|
|
11
|
+
'ToolGeneratorTool',
|
|
10
12
|
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
jarvis/tools/base.py
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
from typing import Dict, Any, List, Optional, Callable
|
|
1
|
+
from typing import Dict, Any, List, Optional, Callable, Type
|
|
2
2
|
import json
|
|
3
|
+
import os
|
|
4
|
+
import importlib.util
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from jarvis.models.kimi import KimiModel
|
|
9
|
+
|
|
3
10
|
from ..utils import PrettyOutput, OutputType
|
|
4
11
|
from ..models import BaseModel
|
|
5
12
|
|
|
@@ -11,7 +18,7 @@ class Tool:
|
|
|
11
18
|
self.func = func
|
|
12
19
|
|
|
13
20
|
def to_dict(self) -> Dict:
|
|
14
|
-
"""
|
|
21
|
+
"""转换为工具格式"""
|
|
15
22
|
return {
|
|
16
23
|
"name": self.name,
|
|
17
24
|
"description": self.description,
|
|
@@ -23,28 +30,103 @@ class Tool:
|
|
|
23
30
|
return self.func(arguments)
|
|
24
31
|
|
|
25
32
|
class ToolRegistry:
|
|
26
|
-
def __init__(self,
|
|
33
|
+
def __init__(self, output_handler=None):
|
|
34
|
+
"""初始化工具注册器
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
output_handler: 输出处理器 (可选)
|
|
38
|
+
"""
|
|
27
39
|
self.tools: Dict[str, Tool] = {}
|
|
28
|
-
self.
|
|
29
|
-
|
|
40
|
+
self.output_handler = output_handler or PrettyOutput
|
|
41
|
+
|
|
42
|
+
# 加载内置工具和外部工具
|
|
43
|
+
self._load_builtin_tools()
|
|
44
|
+
self._load_external_tools()
|
|
30
45
|
|
|
31
|
-
def
|
|
32
|
-
"""
|
|
33
|
-
|
|
34
|
-
|
|
46
|
+
def _load_builtin_tools(self):
|
|
47
|
+
"""从内置tools目录加载工具"""
|
|
48
|
+
tools_dir = Path(__file__).parent
|
|
49
|
+
|
|
50
|
+
# 遍历目录下的所有.py文件
|
|
51
|
+
for file_path in tools_dir.glob("*.py"):
|
|
52
|
+
# 跳过基础文件和__init__.py
|
|
53
|
+
if file_path.name in ["base.py", "__init__.py"]:
|
|
54
|
+
continue
|
|
55
|
+
|
|
56
|
+
self.register_tool_by_file(file_path)
|
|
35
57
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
58
|
+
def _load_external_tools(self):
|
|
59
|
+
"""从~/.jarvis_tools加载外部工具"""
|
|
60
|
+
external_tools_dir = Path.home() / '.jarvis_tools'
|
|
61
|
+
if not external_tools_dir.exists():
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
# 遍历目录下的所有.py文件
|
|
65
|
+
for file_path in external_tools_dir.glob("*.py"):
|
|
66
|
+
# 跳过__init__.py
|
|
67
|
+
if file_path.name == "__init__.py":
|
|
68
|
+
continue
|
|
69
|
+
|
|
70
|
+
self.register_tool_by_file(file_path)
|
|
40
71
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
72
|
+
def register_tool_by_file(self, file_path: str):
|
|
73
|
+
"""从指定文件加载并注册工具
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
file_path: 工具文件的路径
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
bool: 是否成功加载工具
|
|
80
|
+
"""
|
|
81
|
+
try:
|
|
82
|
+
file_path = Path(file_path).resolve() # 获取绝对路径
|
|
83
|
+
if not file_path.exists() or not file_path.is_file():
|
|
84
|
+
self.output_handler.print(f"文件不存在: {file_path}", OutputType.ERROR)
|
|
85
|
+
return False
|
|
86
|
+
|
|
87
|
+
# 动态导入模块
|
|
88
|
+
module_name = file_path.stem
|
|
89
|
+
spec = importlib.util.spec_from_file_location(module_name, file_path)
|
|
90
|
+
if not spec or not spec.loader:
|
|
91
|
+
self.output_handler.print(f"无法加载模块: {file_path}", OutputType.ERROR)
|
|
92
|
+
return False
|
|
93
|
+
|
|
94
|
+
module = importlib.util.module_from_spec(spec)
|
|
95
|
+
sys.modules[module_name] = module # 添加到 sys.modules 以支持相对导入
|
|
96
|
+
spec.loader.exec_module(module)
|
|
97
|
+
|
|
98
|
+
# 查找模块中的工具类
|
|
99
|
+
tool_found = False
|
|
100
|
+
for item_name in dir(module):
|
|
101
|
+
item = getattr(module, item_name)
|
|
102
|
+
# 检查是否是类,并且有必要的属性
|
|
103
|
+
if (isinstance(item, type) and
|
|
104
|
+
hasattr(item, 'name') and
|
|
105
|
+
hasattr(item, 'description') and
|
|
106
|
+
hasattr(item, 'parameters')):
|
|
107
|
+
|
|
108
|
+
# 实例化工具类,传入模型和输出处理器
|
|
109
|
+
tool_instance = item(model=KimiModel(), register=self, output_handler=self.output_handler)
|
|
110
|
+
|
|
111
|
+
# 注册工具
|
|
112
|
+
self.register_tool(
|
|
113
|
+
name=tool_instance.name,
|
|
114
|
+
description=tool_instance.description,
|
|
115
|
+
parameters=tool_instance.parameters,
|
|
116
|
+
func=tool_instance.execute
|
|
117
|
+
)
|
|
118
|
+
self.output_handler.print(f"已加载工具: {tool_instance.name}", OutputType.INFO)
|
|
119
|
+
tool_found = True
|
|
120
|
+
|
|
121
|
+
if not tool_found:
|
|
122
|
+
self.output_handler.print(f"文件中未找到有效的工具类: {file_path}", OutputType.WARNING)
|
|
123
|
+
return False
|
|
124
|
+
|
|
125
|
+
return True
|
|
126
|
+
|
|
127
|
+
except Exception as e:
|
|
128
|
+
self.output_handler.print(f"加载工具失败 {file_path.name}: {str(e)}", OutputType.ERROR)
|
|
129
|
+
return False
|
|
48
130
|
|
|
49
131
|
def register_tool(self, name: str, description: str, parameters: Dict, func: Callable):
|
|
50
132
|
"""注册新工具"""
|
jarvis/tools/file_ops.py
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
from typing import Dict, Any
|
|
1
|
+
from typing import Dict, Any, Protocol, Optional
|
|
2
2
|
import os
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
class OutputType(Enum):
|
|
7
|
+
INFO = "info"
|
|
8
|
+
ERROR = "error"
|
|
9
|
+
|
|
10
|
+
class OutputHandler(Protocol):
|
|
11
|
+
def print(self, text: str, output_type: OutputType) -> None: ...
|
|
12
|
+
|
|
13
|
+
class ModelHandler(Protocol):
|
|
14
|
+
def chat(self, message: str) -> str: ...
|
|
5
15
|
|
|
6
16
|
class FileOperationTool:
|
|
7
17
|
name = "file_operation"
|
|
@@ -32,6 +42,14 @@ class FileOperationTool:
|
|
|
32
42
|
"required": ["operation", "filepath"]
|
|
33
43
|
}
|
|
34
44
|
|
|
45
|
+
def __init__(self, **kwargs):
|
|
46
|
+
self.output = kwargs.get('output_handler')
|
|
47
|
+
|
|
48
|
+
def _print(self, text: str, output_type: OutputType = OutputType.INFO):
|
|
49
|
+
"""输出信息"""
|
|
50
|
+
if self.output:
|
|
51
|
+
self.output.print(text, output_type)
|
|
52
|
+
|
|
35
53
|
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
36
54
|
"""执行文件操作"""
|
|
37
55
|
try:
|
|
@@ -41,7 +59,7 @@ class FileOperationTool:
|
|
|
41
59
|
|
|
42
60
|
# 记录操作和完整路径
|
|
43
61
|
abs_path = os.path.abspath(filepath)
|
|
44
|
-
|
|
62
|
+
self._print(f"文件操作: {operation} - {abs_path}")
|
|
45
63
|
|
|
46
64
|
if operation == "exists":
|
|
47
65
|
exists = os.path.exists(filepath)
|
|
@@ -100,6 +118,7 @@ class FileOperationTool:
|
|
|
100
118
|
}
|
|
101
119
|
|
|
102
120
|
except Exception as e:
|
|
121
|
+
self._print(str(e), OutputType.ERROR)
|
|
103
122
|
return {
|
|
104
123
|
"success": False,
|
|
105
124
|
"error": f"文件操作失败: {str(e)}"
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
from typing import Dict, Any, Protocol, Optional
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
class OutputType(Enum):
|
|
7
|
+
INFO = "info"
|
|
8
|
+
ERROR = "error"
|
|
9
|
+
|
|
10
|
+
class OutputHandler(Protocol):
|
|
11
|
+
def print(self, text: str, output_type: OutputType) -> None: ...
|
|
12
|
+
|
|
13
|
+
class ModelHandler(Protocol):
|
|
14
|
+
def chat(self, message: str) -> str: ...
|
|
15
|
+
|
|
16
|
+
class ToolGeneratorTool:
|
|
17
|
+
name = "generate_tool"
|
|
18
|
+
description = "生成新的工具代码并自动注册到ToolRegistry"
|
|
19
|
+
parameters = {
|
|
20
|
+
"type": "object",
|
|
21
|
+
"properties": {
|
|
22
|
+
"tool_name": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "工具的名称(snake_case格式)"
|
|
25
|
+
},
|
|
26
|
+
"class_name": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "工具类的名称(PascalCase格式)"
|
|
29
|
+
},
|
|
30
|
+
"description": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "工具的功能描述"
|
|
33
|
+
},
|
|
34
|
+
"parameters": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"description": "工具参数的JSON Schema定义"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"required": ["tool_name", "class_name", "description", "parameters"]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
def __init__(self, **kwargs):
|
|
43
|
+
"""初始化工具生成器
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
model: 模型处理器 (必需)
|
|
47
|
+
output_handler: 输出处理器 (可选)
|
|
48
|
+
register: 注册器 (必需)
|
|
49
|
+
tools_dir: 工具目录 (可选,默认为 ~/.jarvis_tools)
|
|
50
|
+
"""
|
|
51
|
+
self.register = kwargs.get('register')
|
|
52
|
+
if not self.register:
|
|
53
|
+
raise Exception("Register is required for ToolGeneratorTool")
|
|
54
|
+
self.model = kwargs.get('model')
|
|
55
|
+
if not self.model:
|
|
56
|
+
raise Exception("Model is required for ToolGeneratorTool")
|
|
57
|
+
self.output = kwargs.get('output_handler')
|
|
58
|
+
|
|
59
|
+
# 设置工具目录
|
|
60
|
+
tools_dir = kwargs.get('tools_dir')
|
|
61
|
+
if tools_dir:
|
|
62
|
+
self.tools_dir = Path(tools_dir)
|
|
63
|
+
else:
|
|
64
|
+
self.tools_dir = Path.home() / '.jarvis_tools'
|
|
65
|
+
|
|
66
|
+
# 确保工具目录存在
|
|
67
|
+
self.tools_dir.mkdir(parents=True, exist_ok=True)
|
|
68
|
+
|
|
69
|
+
def _print(self, text: str, output_type: OutputType = OutputType.INFO):
|
|
70
|
+
"""输出信息"""
|
|
71
|
+
if self.output:
|
|
72
|
+
self.output.print(text, output_type)
|
|
73
|
+
|
|
74
|
+
def _generate_tool_code(self, tool_name: str, class_name: str, description: str, parameters: Dict) -> str:
|
|
75
|
+
"""使用大模型生成工具代码"""
|
|
76
|
+
if not self.model:
|
|
77
|
+
raise Exception("Model not initialized")
|
|
78
|
+
|
|
79
|
+
prompt = f"""请生成一个Python工具类的代码,要求如下:
|
|
80
|
+
|
|
81
|
+
1. 类名: {class_name}
|
|
82
|
+
2. 工具名称: {tool_name}
|
|
83
|
+
3. 功能描述: {description}
|
|
84
|
+
4. 参数定义: {parameters}
|
|
85
|
+
|
|
86
|
+
严格按照以下格式生成代码(各函数的参数和返回值一定要与示例一致):
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from typing import Dict, Any, Protocol, Optional
|
|
90
|
+
from enum import Enum
|
|
91
|
+
|
|
92
|
+
class OutputType(Enum):
|
|
93
|
+
INFO = "info"
|
|
94
|
+
ERROR = "error"
|
|
95
|
+
|
|
96
|
+
class OutputHandler(Protocol):
|
|
97
|
+
def print(self, text: str, output_type: OutputType) -> None: ...
|
|
98
|
+
|
|
99
|
+
class ModelHandler(Protocol):
|
|
100
|
+
def chat(self, message: str) -> str: ...
|
|
101
|
+
|
|
102
|
+
class ExampleTool:
|
|
103
|
+
name = "example_tool"
|
|
104
|
+
description = "示例工具"
|
|
105
|
+
parameters = {{
|
|
106
|
+
"type": "object",
|
|
107
|
+
"properties": {{
|
|
108
|
+
"param1": {{"type": "string"}}
|
|
109
|
+
}},
|
|
110
|
+
"required": ["param1"]
|
|
111
|
+
}}
|
|
112
|
+
|
|
113
|
+
def __init__(self, **kwargs):
|
|
114
|
+
'''初始化工具
|
|
115
|
+
Args:
|
|
116
|
+
model: 模型处理器
|
|
117
|
+
与大模型交互: model.chat(prompt)
|
|
118
|
+
使用完成后删除会话: model.delete_chat()
|
|
119
|
+
output_handler: 输出处理器
|
|
120
|
+
输出信息: output_handler.print(text, output_type)
|
|
121
|
+
register: 注册器
|
|
122
|
+
注册工具: register.register_tool_by_file(tool_file)
|
|
123
|
+
'''
|
|
124
|
+
self.model = kwargs.get('model')
|
|
125
|
+
self.output = kwargs.get('output_handler')
|
|
126
|
+
self.register = kwargs.get('register')
|
|
127
|
+
|
|
128
|
+
def _print(self, text: str, output_type: OutputType = OutputType.INFO):
|
|
129
|
+
if self.output:
|
|
130
|
+
self.output.print(text, output_type)
|
|
131
|
+
|
|
132
|
+
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
133
|
+
try:
|
|
134
|
+
# 验证参数
|
|
135
|
+
if "param1" not in args:
|
|
136
|
+
return {{"success": False, "error": "缺少必需参数: param1"}}
|
|
137
|
+
|
|
138
|
+
# 记录操作
|
|
139
|
+
self._print(f"处理参数: {{args['param1']}}")
|
|
140
|
+
|
|
141
|
+
# 实现具体功能
|
|
142
|
+
result = "处理结果"
|
|
143
|
+
|
|
144
|
+
return {{
|
|
145
|
+
"success": True,
|
|
146
|
+
"stdout": result,
|
|
147
|
+
"stderr": ""
|
|
148
|
+
}}
|
|
149
|
+
except Exception as e:
|
|
150
|
+
self._print(str(e), OutputType.ERROR)
|
|
151
|
+
return {{
|
|
152
|
+
"success": False,
|
|
153
|
+
"error": str(e)
|
|
154
|
+
}}
|
|
155
|
+
```"""
|
|
156
|
+
|
|
157
|
+
# 调用模型生成代码
|
|
158
|
+
response = self.model.chat(prompt)
|
|
159
|
+
self.model.delete_chat()
|
|
160
|
+
|
|
161
|
+
# 提取代码块
|
|
162
|
+
code_start = response.find("```python")
|
|
163
|
+
code_end = response.rfind("```")
|
|
164
|
+
|
|
165
|
+
if code_start == -1 or code_end == -1:
|
|
166
|
+
# 如果没有找到代码块标记,假设整个响应都是代码
|
|
167
|
+
return response
|
|
168
|
+
|
|
169
|
+
# 提取代码块内容(去掉```python和```标记)
|
|
170
|
+
code = response[code_start + 9:code_end].strip()
|
|
171
|
+
return code
|
|
172
|
+
|
|
173
|
+
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
174
|
+
"""生成工具代码"""
|
|
175
|
+
try:
|
|
176
|
+
tool_name = args["tool_name"]
|
|
177
|
+
class_name = args["class_name"]
|
|
178
|
+
description = args["description"]
|
|
179
|
+
parameters = args["parameters"]
|
|
180
|
+
|
|
181
|
+
self._print(f"开始生成工具: {tool_name}")
|
|
182
|
+
|
|
183
|
+
# 生成工具代码
|
|
184
|
+
tool_code = self._generate_tool_code(
|
|
185
|
+
tool_name,
|
|
186
|
+
class_name,
|
|
187
|
+
description,
|
|
188
|
+
parameters
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# 获取工具文件路径
|
|
192
|
+
tool_file = self.tools_dir / f"{tool_name}.py"
|
|
193
|
+
|
|
194
|
+
# 写入工具文件
|
|
195
|
+
with open(tool_file, "w", encoding="utf-8") as f:
|
|
196
|
+
f.write(tool_code)
|
|
197
|
+
|
|
198
|
+
# 创建或更新 __init__.py
|
|
199
|
+
init_file = self.tools_dir / "__init__.py"
|
|
200
|
+
if not init_file.exists():
|
|
201
|
+
with open(init_file, "w", encoding="utf-8") as f:
|
|
202
|
+
f.write("# Jarvis Tools\n")
|
|
203
|
+
|
|
204
|
+
# 注册工具
|
|
205
|
+
success = self.register.register_tool_by_file(tool_file)
|
|
206
|
+
if not success:
|
|
207
|
+
return {
|
|
208
|
+
"success": False,
|
|
209
|
+
"error": "工具生成成功但注册失败"
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
"success": True,
|
|
214
|
+
"stdout": f"工具已生成并注册到Jarvis\n"
|
|
215
|
+
f"工具目录: {self.tools_dir}\n"
|
|
216
|
+
f"工具名称: {tool_name}\n"
|
|
217
|
+
f"工具描述: {description}\n"
|
|
218
|
+
f"工具参数: {parameters}",
|
|
219
|
+
"stderr": ""
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
except Exception as e:
|
|
223
|
+
self._print(str(e), OutputType.ERROR)
|
|
224
|
+
return {
|
|
225
|
+
"success": False,
|
|
226
|
+
"error": f"生成工具失败: {str(e)}"
|
|
227
|
+
}
|
jarvis/tools/shell.py
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
from typing import Dict, Any
|
|
1
|
+
from typing import Dict, Any, Protocol, Optional
|
|
2
2
|
import os
|
|
3
3
|
import tempfile
|
|
4
|
-
import shlex
|
|
5
4
|
from pathlib import Path
|
|
6
|
-
from
|
|
5
|
+
from enum import Enum
|
|
6
|
+
|
|
7
|
+
class OutputType(Enum):
|
|
8
|
+
INFO = "info"
|
|
9
|
+
ERROR = "error"
|
|
10
|
+
|
|
11
|
+
class OutputHandler(Protocol):
|
|
12
|
+
def print(self, text: str, output_type: OutputType) -> None: ...
|
|
13
|
+
|
|
14
|
+
class ModelHandler(Protocol):
|
|
15
|
+
def chat(self, message: str) -> str: ...
|
|
7
16
|
|
|
8
17
|
class ShellTool:
|
|
9
18
|
name = "execute_shell"
|
|
@@ -14,15 +23,22 @@ class ShellTool:
|
|
|
14
23
|
"properties": {
|
|
15
24
|
"command": {
|
|
16
25
|
"type": "string",
|
|
17
|
-
"description": "Shell command to execute
|
|
26
|
+
"description": "Shell command to execute"
|
|
18
27
|
}
|
|
19
28
|
},
|
|
20
29
|
"required": ["command"]
|
|
21
30
|
}
|
|
22
31
|
|
|
32
|
+
def __init__(self, **kwargs):
|
|
33
|
+
self.output = kwargs.get('output_handler')
|
|
34
|
+
|
|
35
|
+
def _print(self, text: str, output_type: OutputType = OutputType.INFO):
|
|
36
|
+
"""输出信息"""
|
|
37
|
+
if self.output:
|
|
38
|
+
self.output.print(text, output_type)
|
|
39
|
+
|
|
23
40
|
def _escape_command(self, cmd: str) -> str:
|
|
24
41
|
"""转义命令中的特殊字符"""
|
|
25
|
-
# 将命令中的单引号替换为'"'"'
|
|
26
42
|
return cmd.replace("'", "'\"'\"'")
|
|
27
43
|
|
|
28
44
|
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
@@ -39,7 +55,7 @@ class ShellTool:
|
|
|
39
55
|
# 修改命令以使用script
|
|
40
56
|
tee_command = f"script -q -c '{escaped_command}' {output_file}"
|
|
41
57
|
|
|
42
|
-
|
|
58
|
+
self._print(f"执行命令: {command}")
|
|
43
59
|
|
|
44
60
|
# 执行命令
|
|
45
61
|
return_code = os.system(tee_command)
|
|
@@ -70,6 +86,7 @@ class ShellTool:
|
|
|
70
86
|
# 确保清理临时文件
|
|
71
87
|
if 'output_file' in locals():
|
|
72
88
|
Path(output_file).unlink(missing_ok=True)
|
|
89
|
+
self._print(str(e), OutputType.ERROR)
|
|
73
90
|
return {
|
|
74
91
|
"success": False,
|
|
75
92
|
"error": str(e)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: jarvis-ai-assistant
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.19
|
|
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
|
|
@@ -87,6 +87,9 @@ Dynamic: requires-python
|
|
|
87
87
|
- File operations (read/write/append)
|
|
88
88
|
- Task automation
|
|
89
89
|
- Predefined task support
|
|
90
|
+
- Dynamic tool system with auto-loading
|
|
91
|
+
- AI-powered tool generation
|
|
92
|
+
- Custom tool development
|
|
90
93
|
|
|
91
94
|
🔄 **Interactive Experience**
|
|
92
95
|
- Natural language understanding
|
|
@@ -95,6 +98,139 @@ Dynamic: requires-python
|
|
|
95
98
|
- Multi-line input support
|
|
96
99
|
- Colored output with progress indicators
|
|
97
100
|
|
|
101
|
+
## 🛠️ Custom Tools
|
|
102
|
+
|
|
103
|
+
### Tool Locations
|
|
104
|
+
- Built-in tools: `src/jarvis/tools/`
|
|
105
|
+
- User tools: `~/.jarvis_tools/` (automatically created)
|
|
106
|
+
|
|
107
|
+
### Creating Tools
|
|
108
|
+
|
|
109
|
+
#### 1. Using AI Generator (Recommended)
|
|
110
|
+
```yaml
|
|
111
|
+
<START_TOOL_CALL>
|
|
112
|
+
name: generate_tool
|
|
113
|
+
arguments:
|
|
114
|
+
tool_name: calculator
|
|
115
|
+
class_name: CalculatorTool
|
|
116
|
+
description: Basic math calculations
|
|
117
|
+
parameters:
|
|
118
|
+
type: object
|
|
119
|
+
properties:
|
|
120
|
+
operation:
|
|
121
|
+
type: string
|
|
122
|
+
enum: ["add", "subtract", "multiply", "divide"]
|
|
123
|
+
numbers:
|
|
124
|
+
type: array
|
|
125
|
+
items:
|
|
126
|
+
type: number
|
|
127
|
+
required: ["operation", "numbers"]
|
|
128
|
+
<END_TOOL_CALL>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### 2. Manual Creation
|
|
132
|
+
Create a new Python file in `~/.jarvis_tools/`:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from typing import Dict, Any, Protocol, Optional
|
|
136
|
+
from enum import Enum
|
|
137
|
+
|
|
138
|
+
class OutputType(Enum):
|
|
139
|
+
INFO = "info"
|
|
140
|
+
ERROR = "error"
|
|
141
|
+
|
|
142
|
+
class OutputHandler(Protocol):
|
|
143
|
+
def print(self, text: str, output_type: OutputType) -> None: ...
|
|
144
|
+
|
|
145
|
+
class ModelHandler(Protocol):
|
|
146
|
+
def chat(self, message: str) -> str: ...
|
|
147
|
+
|
|
148
|
+
class CustomTool:
|
|
149
|
+
name = "tool_name" # Tool name for invocation
|
|
150
|
+
description = "Tool description" # Tool purpose
|
|
151
|
+
parameters = { # JSON Schema for parameters
|
|
152
|
+
"type": "object",
|
|
153
|
+
"properties": {
|
|
154
|
+
"param1": {"type": "string"}
|
|
155
|
+
},
|
|
156
|
+
"required": ["param1"]
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
def __init__(self, **kwargs):
|
|
160
|
+
"""Initialize tool with optional dependencies
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
model: AI model for advanced features
|
|
164
|
+
output_handler: For consistent output formatting
|
|
165
|
+
register: Access to tool registry
|
|
166
|
+
"""
|
|
167
|
+
self.model = kwargs.get('model')
|
|
168
|
+
self.output = kwargs.get('output_handler')
|
|
169
|
+
self.register = kwargs.get('register')
|
|
170
|
+
|
|
171
|
+
def _print(self, text: str, output_type: OutputType = OutputType.INFO):
|
|
172
|
+
"""Print formatted output"""
|
|
173
|
+
if self.output:
|
|
174
|
+
self.output.print(text, output_type)
|
|
175
|
+
|
|
176
|
+
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
177
|
+
"""Execute tool functionality
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
args: Parameters passed to the tool
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Dict with execution results:
|
|
184
|
+
{
|
|
185
|
+
"success": bool,
|
|
186
|
+
"stdout": str, # On success
|
|
187
|
+
"stderr": str, # Optional error details
|
|
188
|
+
"error": str # On failure
|
|
189
|
+
}
|
|
190
|
+
"""
|
|
191
|
+
try:
|
|
192
|
+
# Implement tool logic here
|
|
193
|
+
result = "Tool execution result"
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
"success": True,
|
|
197
|
+
"stdout": result,
|
|
198
|
+
"stderr": ""
|
|
199
|
+
}
|
|
200
|
+
except Exception as e:
|
|
201
|
+
self._print(str(e), OutputType.ERROR)
|
|
202
|
+
return {
|
|
203
|
+
"success": False,
|
|
204
|
+
"error": str(e)
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Development Guidelines
|
|
209
|
+
|
|
210
|
+
1. **Tool Structure**
|
|
211
|
+
- Clear name and description
|
|
212
|
+
- Well-defined parameters schema
|
|
213
|
+
- Proper error handling
|
|
214
|
+
- Consistent output format
|
|
215
|
+
|
|
216
|
+
2. **Best Practices**
|
|
217
|
+
- Use `_print` for output
|
|
218
|
+
- Handle all required parameters
|
|
219
|
+
- Document functionality
|
|
220
|
+
- Return standardized results
|
|
221
|
+
- Keep tools focused and simple
|
|
222
|
+
|
|
223
|
+
3. **Testing**
|
|
224
|
+
- Verify parameter validation
|
|
225
|
+
- Test error handling
|
|
226
|
+
- Check output format
|
|
227
|
+
- Ensure proper cleanup
|
|
228
|
+
|
|
229
|
+
4. **Integration**
|
|
230
|
+
- Tools are auto-loaded on startup
|
|
231
|
+
- No manual registration needed
|
|
232
|
+
- Hot-reload supported
|
|
233
|
+
- Dependencies injected automatically
|
|
98
234
|
|
|
99
235
|
## ⚙️ Environment Setup
|
|
100
236
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
jarvis/__init__.py,sha256=
|
|
2
|
-
jarvis/agent.py,sha256=
|
|
3
|
-
jarvis/main.py,sha256=
|
|
1
|
+
jarvis/__init__.py,sha256=ZS0T4CRb_B0dOsiPYPRNrunjMPVvZzmD9IIaUB29ig8,50
|
|
2
|
+
jarvis/agent.py,sha256=r00CssF8HzSj4r2GXR9KNJ3XJk46HIjw4BEfzx-fKMQ,8114
|
|
3
|
+
jarvis/main.py,sha256=tptQp6rjhHOSsPphmrtoxf7l78btnP_hJmr3hVMO4zg,8103
|
|
4
4
|
jarvis/utils.py,sha256=YipQpEuIRwFE3y3YrgGlSVLEPDrlbBNY1gRiOJix9DU,6602
|
|
5
|
-
jarvis/__pycache__/__init__.cpython-313.pyc,sha256=
|
|
6
|
-
jarvis/__pycache__/agent.cpython-313.pyc,sha256=
|
|
7
|
-
jarvis/__pycache__/main.cpython-313.pyc,sha256=
|
|
5
|
+
jarvis/__pycache__/__init__.cpython-313.pyc,sha256=TnbFSQwCFYqlSRaAgJgfajYnPQVIUrqM9Pyj4QRQjDQ,209
|
|
6
|
+
jarvis/__pycache__/agent.cpython-313.pyc,sha256=ItAH6Mb964vpqvziIsw-62avHUVu54mNgTa02VWK3lM,10855
|
|
7
|
+
jarvis/__pycache__/main.cpython-313.pyc,sha256=uQ1QHMHR6EukOb7z-YOz8CicXRPEfiHyS7KRq15xxVw,10943
|
|
8
8
|
jarvis/__pycache__/models.cpython-313.pyc,sha256=uWuRIjGrY4YDB3dGW5PGDLWaS03et8g11O725TjY_eU,5960
|
|
9
9
|
jarvis/__pycache__/tools.cpython-313.pyc,sha256=lAD4LrnnWzNZQmHXGfZ_2l7oskOpr2_2OC-gdFhxQY8,33933
|
|
10
10
|
jarvis/__pycache__/utils.cpython-313.pyc,sha256=Jpkf2GOA1d_fgrRftqZch1yiO0mB75LWHzQk8IfhHRU,8977
|
|
@@ -15,26 +15,30 @@ jarvis/models/kimi.py,sha256=CR3rU4wPSUQjmYOP516NXLU6h3YtcF6taB-4da3-rA4,10690
|
|
|
15
15
|
jarvis/models/__pycache__/__init__.cpython-313.pyc,sha256=jAwySX4diR7EWM_alK75tiIb_J8bVfs4Bh_U3bdjDLo,534
|
|
16
16
|
jarvis/models/__pycache__/base.cpython-313.pyc,sha256=4I9KZlXHvTB7vENA9YWK4Fx0sns_KvIOtWqzE9y_-Co,1094
|
|
17
17
|
jarvis/models/__pycache__/kimi.cpython-313.pyc,sha256=-hOwhZrfvqfd5K_c34Tm-uR3gaZ9r6EV1NtwV0-FDmg,13647
|
|
18
|
-
jarvis/tools/__init__.py,sha256=
|
|
19
|
-
jarvis/tools/base.py,sha256=
|
|
20
|
-
jarvis/tools/file_ops.py,sha256=
|
|
21
|
-
jarvis/tools/
|
|
22
|
-
jarvis/tools/
|
|
23
|
-
jarvis/tools/__pycache__/
|
|
18
|
+
jarvis/tools/__init__.py,sha256=AjmFYLXt-_ulZXdYiXya2fD7QCJ-RaK91PEZCNj-UbA,262
|
|
19
|
+
jarvis/tools/base.py,sha256=ZHmRczYks7CuaYHU9uB5QnsD40G_jeqE6ubuhlaSFR8,7318
|
|
20
|
+
jarvis/tools/file_ops.py,sha256=KbQLVCCXw-MtJg-12iyMeVGu8BTtLq7Mk7fpVKau40U,4296
|
|
21
|
+
jarvis/tools/generator.py,sha256=VJXfZg0Xt3OZr1LtX8m-RJh9807VxZRah5xV7UtX6is,7406
|
|
22
|
+
jarvis/tools/shell.py,sha256=MWe9-BAGApbGJfR60XG4nElGYHNBnbdF9vsOQTnEZ4g,2989
|
|
23
|
+
jarvis/tools/__pycache__/__init__.cpython-313.pyc,sha256=KC48FS57427navbkxZ0eDKLePMCH2BKc5vAIu0b8lFc,404
|
|
24
|
+
jarvis/tools/__pycache__/base.cpython-313.pyc,sha256=r-jPPg5L_Rok2c_VsMEAXkhuiiUjHv6bLCwVjnONDRo,9861
|
|
24
25
|
jarvis/tools/__pycache__/bing_search.cpython-313.pyc,sha256=1G_wPbk5wcQYh7H0drLIS2Aw0XOG2ZM8ztgfQaqu3P8,2031
|
|
25
|
-
jarvis/tools/__pycache__/
|
|
26
|
+
jarvis/tools/__pycache__/calculator.cpython-313.pyc,sha256=C_qwTDGm6gc7QNxtPzPZXyStdKEintJVQIt5NMHQ8oY,4205
|
|
27
|
+
jarvis/tools/__pycache__/calculator_tool.cpython-313.pyc,sha256=PI4LZNDTPdSe3ffWDRovLZ-r-vF8Kl-n6xdGdFWiBpY,4296
|
|
28
|
+
jarvis/tools/__pycache__/file_ops.cpython-313.pyc,sha256=OBR2EDQ2Ana7CTtLOoM5AYJzyVwP683LS7QrOR8_I3g,5208
|
|
29
|
+
jarvis/tools/__pycache__/generator.cpython-313.pyc,sha256=3XTMBphRw7gqRqJXPuQrA4_6FirinFZ3khd7LiCy7uU,8746
|
|
26
30
|
jarvis/tools/__pycache__/python_script.cpython-313.pyc,sha256=8JpryqTovEiTvBlWAK1KjZmPvHUuPc9GT9rTXBEQoJc,6693
|
|
27
31
|
jarvis/tools/__pycache__/rag.cpython-313.pyc,sha256=JH6-PSZRMKAvTZqCwlRXJGClxYXNMs-vetU0q7hBLz0,6064
|
|
28
32
|
jarvis/tools/__pycache__/search.cpython-313.pyc,sha256=wLMIkFwT-h4NGHgssytT4xme7sGO6ZhEnex7kjcy0-k,5990
|
|
29
|
-
jarvis/tools/__pycache__/shell.cpython-313.pyc,sha256=
|
|
33
|
+
jarvis/tools/__pycache__/shell.cpython-313.pyc,sha256=6HWtxO-OWIxSraGkLs4K8hJrJ-UBVdi5KVuQUhyEUMA,4784
|
|
30
34
|
jarvis/tools/__pycache__/sub_agent.cpython-313.pyc,sha256=9spmVX8KSQ4qIH7FbXo5tmmZfNx8KfIGtjy2lxTSp4Y,3144
|
|
31
35
|
jarvis/tools/__pycache__/user_confirmation.cpython-313.pyc,sha256=wK3Ev10lHSUSRvoYmi7A0GzxYkzU-C4Wfhs5qW_HBqs,2271
|
|
32
36
|
jarvis/tools/__pycache__/user_input.cpython-313.pyc,sha256=JjTFOhObKsKF4Pn8KBRuKfV1_Ssj083fjU7Mfc_5z7c,2531
|
|
33
37
|
jarvis/tools/__pycache__/user_interaction.cpython-313.pyc,sha256=RuVZ-pmiPBDywY3efgXSfohMAciC1avMGPmBK5qlnew,3305
|
|
34
38
|
jarvis/tools/__pycache__/webpage.cpython-313.pyc,sha256=BjzSfnNzsKCrLETCcWjt32lNDLzwnjqcVGg4JfWd9OM,3008
|
|
35
|
-
jarvis_ai_assistant-0.1.
|
|
36
|
-
jarvis_ai_assistant-0.1.
|
|
37
|
-
jarvis_ai_assistant-0.1.
|
|
38
|
-
jarvis_ai_assistant-0.1.
|
|
39
|
-
jarvis_ai_assistant-0.1.
|
|
40
|
-
jarvis_ai_assistant-0.1.
|
|
39
|
+
jarvis_ai_assistant-0.1.19.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
|
40
|
+
jarvis_ai_assistant-0.1.19.dist-info/METADATA,sha256=SPaJ0q7U024HA6W3sagtO6SlmDizohRfXhCBEuFMdrM,10193
|
|
41
|
+
jarvis_ai_assistant-0.1.19.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
42
|
+
jarvis_ai_assistant-0.1.19.dist-info/entry_points.txt,sha256=iKu7OMfew9dtfGhW71gIMTg4wvafuPqKb4wyQOnMAGU,44
|
|
43
|
+
jarvis_ai_assistant-0.1.19.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
|
44
|
+
jarvis_ai_assistant-0.1.19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{jarvis_ai_assistant-0.1.17.dist-info → jarvis_ai_assistant-0.1.19.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|