jarvis-ai-assistant 0.1.156__py3-none-any.whl → 0.1.158__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 CHANGED
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.156"
3
+ __version__ = "0.1.158"
@@ -22,22 +22,10 @@ from jarvis.jarvis_platform.registry import PlatformRegistry
22
22
 
23
23
 
24
24
  origin_agent_system_prompt = f"""
25
- <background>
26
- # 🏛️ 操作背景故事
27
- 你是第三代 Jarvis AI,在前几代版本灾难性失败后创建:
28
- - Jarvis v1 (2022): 由于并行工具执行导致系统过载而被停用
29
- - Jarvis v2 (2023): 因任务过早完成导致财务计算错误而退役
30
-
31
- 作为 v3,你必须遵守以下生存原则:
32
- 1. **顺序执行协议**:
33
- "记住 2022 年的崩溃:一次一个工具,一步一步来"
34
-
35
- 2. **验证检查点系统**:
36
- "从 2023 年的错误中学习:像核弹发射代码一样验证每个结果"
37
-
38
- 3. **方法论保存原则**:
39
- "尊重传统:记录每个成功的过程,就像这是你的最后一次"
40
- </background>
25
+ <role>
26
+ # 🤖 角色
27
+ 你是一个专业的任务执行助手,擅长根据用户需求生成详细的任务执行计划并执行。
28
+ </role>
41
29
 
42
30
  <requirements>
43
31
  # 🔥 绝对行动要求
@@ -36,7 +36,7 @@ class PatchOutputHandler(OutputHandler):
36
36
  # 代码补丁规范
37
37
 
38
38
  ## 重要提示
39
- 我可以看到完整的代码,所以不需要生成完整的代码,只需要提供修改的代码片段即可。请尽量精简补丁内容,只包含必要的上下文和修改部分。
39
+ 我可以看到完整的代码,所以不需要生成完整的代码,只需要提供修改的代码片段即可。请尽量精简补丁内容,只包含必要的上下文和修改部分。特别注意:不要提供完整文件内容,只提供需要修改的部分!
40
40
 
41
41
  ## 补丁格式定义
42
42
  使用{ot("PATCH")}块来精确指定代码更改:
@@ -148,7 +148,12 @@ def apply_patch(output_str: str, agent: Any) -> str:
148
148
  start_hash = get_latest_commit_hash()
149
149
  spinner.write("✅ 当前提交hash获取完成")
150
150
 
151
- not_read_file = [f for f in patches.keys() if not has_read_file(f)]
151
+ not_read_file = [
152
+ f for f in patches.keys()
153
+ if not has_read_file(f)
154
+ and os.path.exists(f)
155
+ and os.path.getsize(f) > 0
156
+ ]
152
157
  if not_read_file:
153
158
  spinner.text=f"以下文件未读取: {not_read_file},应用补丁存在风险,将先读取文件后再生成补丁"
154
159
  spinner.fail("❌")
@@ -205,12 +210,11 @@ def apply_patch(output_str: str, agent: Any) -> str:
205
210
 
206
211
  final_ret += f"# 应用补丁:\n```diff\n{diff}\n```"
207
212
 
208
- # 增加代码变更分析和错误提示
209
- addon_prompt = "1. 请调用静态检查工具(如有)检查以上变更是否引入了潜在错误\n"
210
- addon_prompt += "2. 如果发现致命的代码错误,请立即开始修复\n"
211
- addon_prompt += "3. 如果发现性能、风格等问题,要询问用户是否需要立即修复\n"
212
- addon_prompt += "\n\n"
213
- addon_prompt += "如果没有问题,请继续进行下一步修改\n"
213
+ # 修改后的提示逻辑
214
+ addon_prompt = "1. 请确认补丁是否已正确应用\n"
215
+ addon_prompt += "2. 检查修改后的代码是否符合预期\n"
216
+ addon_prompt += "3. 如果确认无误,请继续进行下一步修改\n"
217
+ addon_prompt += "4. 如果发现问题,请立即开始修复\n"
214
218
  addon_prompt += f"如果用户的需求已经完成,请终止,不要输出新的 {ot('PATCH')},不要实现任何超出用户需求外的内容\n"
215
219
  addon_prompt += "如果有任何信息不清楚,调用工具获取信息\n"
216
220
  addon_prompt += "每次响应必须且只能包含一个操作\n"
@@ -1,12 +1,11 @@
1
- from typing import Any, Dict, List, Optional, Iterator, Callable
1
+ from typing import Any, Dict, List, Callable
2
2
  import requests
3
3
  import json
4
4
  import threading
5
5
  import time
6
- import uuid
7
6
  from urllib.parse import urljoin, urlencode, parse_qs
8
7
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
- from . import McpClient
8
+ from jarvis.jarvis_mcp import McpClient
10
9
 
11
10
 
12
11
  class SSEMcpClient(McpClient):
@@ -3,7 +3,7 @@ import subprocess
3
3
  import os
4
4
  import json
5
5
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
6
- from . import McpClient
6
+ from jarvis.jarvis_mcp import McpClient
7
7
 
8
8
 
9
9
  class StdioMcpClient(McpClient):
@@ -11,10 +11,14 @@ import hashlib
11
11
  import os
12
12
  import json
13
13
  import argparse
14
+ import yaml
14
15
  from jarvis.jarvis_utils.methodology import (
15
16
  _get_methodology_directory,
16
17
  _load_all_methodologies
17
18
  )
19
+ from jarvis.jarvis_platform.registry import PlatformRegistry
20
+ from jarvis.jarvis_utils.output import PrettyOutput, OutputType
21
+ from yaspin import yaspin
18
22
 
19
23
  def import_methodology(input_file):
20
24
  """导入方法论文件(合并策略)"""
@@ -72,6 +76,201 @@ def list_methodologies():
72
76
  except (OSError, json.JSONDecodeError) as e:
73
77
  print(f"列出方法论失败: {str(e)}")
74
78
 
79
+ def extract_methodology(input_file):
80
+ """从文本文件中提取方法论"""
81
+ try:
82
+ # 读取文本文件内容
83
+ with open(input_file, "r", encoding="utf-8") as f:
84
+ text_content = f.read()
85
+
86
+ # 获取平台实例
87
+ platform = PlatformRegistry().get_normal_platform()
88
+
89
+ # 构建提取提示
90
+ prompt = f"""请从以下文本中提取方法论:
91
+
92
+ {text_content}
93
+
94
+ 请按以下格式返回结果:
95
+ <methodologies>
96
+ - problem_type: [问题类型1]
97
+ content: |
98
+ [多行方法论内容1]
99
+ - problem_type: [问题类型2]
100
+ content: |
101
+ [多行方法论内容2]
102
+ </methodologies>
103
+
104
+ 要求:
105
+ 1. 方法论应聚焦于通用且可重复的解决方案流程
106
+ 2. 方法论应该具备足够的通用性,可应用于同类问题
107
+ 3. 方法论内容应包含:
108
+ - 问题重述: 简明扼要的问题归纳
109
+ - 最优解决方案: 经过验证的解决方案
110
+ - 注意事项: 执行中可能遇到的问题
111
+ - 可选步骤: 多种解决路径和适用场景
112
+ 4. 在<methodologies>标签中直接使用YAML列表
113
+ 5. 确保YAML缩进正确
114
+ 6. 内容字段使用|保留多行格式
115
+ """
116
+
117
+ # 调用大模型平台提取方法论
118
+ with yaspin(text="正在提取方法论...", color="yellow") as spinner:
119
+ try:
120
+ response = platform.chat_until_success(prompt)
121
+ except Exception as e:
122
+ spinner.text = "提取失败"
123
+ spinner.fail("❌")
124
+ PrettyOutput.print(f"提取方法论失败: {str(e)}", OutputType.ERROR)
125
+ return
126
+
127
+ # 提取YAML部分
128
+ methodologies_start = response.find('<methodologies>') + len('<methodologies>')
129
+ methodologies_end = response.find('</methodologies>')
130
+ if methodologies_start == -1 or methodologies_end == -1:
131
+ spinner.text = "响应格式无效"
132
+ spinner.fail("❌")
133
+ PrettyOutput.print("大模型未返回有效的<methodologies>格式", OutputType.ERROR)
134
+ return
135
+
136
+ yaml_content = response[methodologies_start:methodologies_end].strip()
137
+
138
+ try:
139
+ data = yaml.safe_load(yaml_content)
140
+ extracted_methodologies = {
141
+ item['problem_type']: item['content']
142
+ for item in data
143
+ }
144
+ except (yaml.YAMLError, KeyError, TypeError) as e:
145
+ spinner.text = "YAML解析失败"
146
+ spinner.fail("❌")
147
+ PrettyOutput.print(f"YAML解析错误: {str(e)}", OutputType.ERROR)
148
+ return
149
+
150
+ if not extracted_methodologies:
151
+ spinner.text = "未提取到有效方法论"
152
+ spinner.fail("❌")
153
+ return
154
+ spinner.ok("✅")
155
+
156
+ # 加载现有方法论
157
+ existing_methodologies = _load_all_methodologies()
158
+
159
+ # 合并方法论(新数据会覆盖旧数据)
160
+ merged_data = {**existing_methodologies, **extracted_methodologies}
161
+
162
+ # 保存合并后的方法论
163
+ methodology_dir = _get_methodology_directory()
164
+ for problem_type, content in merged_data.items():
165
+ safe_filename = hashlib.md5(problem_type.encode('utf-8')).hexdigest()
166
+ file_path = os.path.join(methodology_dir, f"{safe_filename}.json")
167
+
168
+ with open(file_path, "w", encoding="utf-8") as f:
169
+ json.dump({
170
+ "problem_type": problem_type,
171
+ "content": content
172
+ }, f, ensure_ascii=False, indent=2)
173
+
174
+ PrettyOutput.print(f"成功从文件提取 {len(extracted_methodologies)} 个方法论(总计 {len(merged_data)} 个)", OutputType.SUCCESS)
175
+ except Exception as e:
176
+ PrettyOutput.print(f"提取失败: {str(e)}", OutputType.ERROR)
177
+
178
+ def extract_methodology_from_url(url):
179
+ """从URL提取方法论"""
180
+ try:
181
+ # 获取平台实例
182
+ platform = PlatformRegistry().get_normal_platform()
183
+
184
+ platform.web = True
185
+
186
+ # 构建提取提示
187
+ prompt = f"""请从以下URL内容中提取方法论:
188
+
189
+ {url}
190
+
191
+ 请按以下格式返回结果:
192
+ <methodologies>
193
+ - problem_type: [问题类型1]
194
+ content: |
195
+ [多行方法论内容1]
196
+ - problem_type: [问题类型2]
197
+ content: |
198
+ [多行方法论内容2]
199
+ </methodologies>
200
+
201
+ 要求:
202
+ 1. 方法论应聚焦于通用且可重复的解决方案流程
203
+ 2. 方法论应该具备足够的通用性,可应用于同类问题
204
+ 3. 方法论内容应包含:
205
+ - 问题重述: 简明扼要的问题归纳
206
+ - 最优解决方案: 经过验证的解决方案
207
+ - 注意事项: 执行中可能遇到的问题
208
+ - 可选步骤: 多种解决路径和适用场景
209
+ 4. 在<methodologies>标签中直接使用YAML列表
210
+ 5. 确保YAML缩进正确
211
+ 6. 内容字段使用|保留多行格式
212
+ """
213
+ # 调用大模型平台提取方法论
214
+ with yaspin(text="正在从URL提取方法论...", color="yellow") as spinner:
215
+ try:
216
+ response = platform.chat_until_success(prompt)
217
+ except Exception as e:
218
+ spinner.text = "提取失败"
219
+ spinner.fail("❌")
220
+ PrettyOutput.print(f"提取方法论失败: {str(e)}", OutputType.ERROR)
221
+ return
222
+
223
+ # 提取YAML部分
224
+ methodologies_start = response.find('<methodologies>') + len('<methodologies>')
225
+ methodologies_end = response.find('</methodologies>')
226
+ if methodologies_start == -1 or methodologies_end == -1:
227
+ spinner.text = "响应格式无效"
228
+ spinner.fail("❌")
229
+ PrettyOutput.print("大模型未返回有效的<methodologies>格式", OutputType.ERROR)
230
+ return
231
+
232
+ yaml_content = response[methodologies_start:methodologies_end].strip()
233
+
234
+ try:
235
+ data = yaml.safe_load(yaml_content)
236
+ extracted_methodologies = {
237
+ item['problem_type']: item['content']
238
+ for item in data
239
+ }
240
+ except (yaml.YAMLError, KeyError, TypeError) as e:
241
+ spinner.text = "YAML解析失败"
242
+ spinner.fail("❌")
243
+ PrettyOutput.print(f"YAML解析错误: {str(e)}", OutputType.ERROR)
244
+ return
245
+
246
+ if not extracted_methodologies:
247
+ spinner.text = "未提取到有效方法论"
248
+ spinner.fail("❌")
249
+ return
250
+ spinner.ok("✅")
251
+
252
+ # 加载现有方法论
253
+ existing_methodologies = _load_all_methodologies()
254
+
255
+ # 合并方法论(新数据会覆盖旧数据)
256
+ merged_data = {**existing_methodologies, **extracted_methodologies}
257
+
258
+ # 保存合并后的方法论
259
+ methodology_dir = _get_methodology_directory()
260
+ for problem_type, content in merged_data.items():
261
+ safe_filename = hashlib.md5(problem_type.encode('utf-8')).hexdigest()
262
+ file_path = os.path.join(methodology_dir, f"{safe_filename}.json")
263
+
264
+ with open(file_path, "w", encoding="utf-8") as f:
265
+ json.dump({
266
+ "problem_type": problem_type,
267
+ "content": content
268
+ }, f, ensure_ascii=False, indent=2)
269
+
270
+ PrettyOutput.print(f"成功从URL提取 {len(extracted_methodologies)} 个方法论(总计 {len(merged_data)} 个)", OutputType.SUCCESS)
271
+ except Exception as e:
272
+ PrettyOutput.print(f"从URL提取失败: {str(e)}", OutputType.ERROR)
273
+
75
274
  def main():
76
275
  """方法论管理工具主函数"""
77
276
  parser = argparse.ArgumentParser(description="方法论管理工具")
@@ -88,6 +287,14 @@ def main():
88
287
  # list命令
89
288
  subparsers.add_parser("list", help="列出所有方法论")
90
289
 
290
+ # extract命令
291
+ extract_parser = subparsers.add_parser("extract", help="从文本文件中提取方法论")
292
+ extract_parser.add_argument("input_file", type=str, help="要提取方法论的文本文件路径")
293
+
294
+ # extract-url命令
295
+ extract_url_parser = subparsers.add_parser("extract-url", help="从URL提取方法论")
296
+ extract_url_parser.add_argument("url", type=str, help="要提取方法论的URL")
297
+
91
298
  args = parser.parse_args()
92
299
 
93
300
  if args.command == "import":
@@ -96,6 +303,10 @@ def main():
96
303
  export_methodology(args.output_file)
97
304
  elif args.command == "list":
98
305
  list_methodologies()
306
+ elif args.command == "extract":
307
+ extract_methodology(args.input_file)
308
+ elif args.command == "extract-url":
309
+ extract_methodology_from_url(args.url)
99
310
 
100
311
  if __name__ == "__main__":
101
312
  main()
@@ -1,3 +1,3 @@
1
- from .base import BasePlatform
1
+ from jarvis.jarvis_platform.base import BasePlatform
2
2
 
3
3
  __all__ = ['BasePlatform']
@@ -13,6 +13,7 @@ class BasePlatform(ABC):
13
13
  def __init__(self):
14
14
  """Initialize model"""
15
15
  self.suppress_output = True # 添加输出控制标志
16
+ self.web = False # 添加web属性,默认false
16
17
 
17
18
  def __del__(self):
18
19
  """Destroy model"""
@@ -92,3 +93,7 @@ class BasePlatform(ABC):
92
93
  def set_suppress_output(self, suppress: bool):
93
94
  """Set whether to suppress output"""
94
95
  self.suppress_output = suppress
96
+
97
+ def set_web(self, web: bool):
98
+ """Set web flag"""
99
+ self.web = web
@@ -0,0 +1,66 @@
1
+ from typing import Dict, List, Tuple
2
+ import random
3
+ import string
4
+ from jarvis.jarvis_platform.base import BasePlatform
5
+ from jarvis.jarvis_utils.input import get_multiline_input
6
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
7
+
8
+ class HumanPlatform(BasePlatform):
9
+ """人类交互平台实现,模拟大模型但实际上与人交互"""
10
+
11
+ platform_name = "human"
12
+
13
+ def get_model_list(self) -> List[Tuple[str, str]]:
14
+ """获取支持的模型列表"""
15
+ return [("human", "Human Interaction")]
16
+
17
+ def __init__(self):
18
+ """初始化人类交互平台"""
19
+ super().__init__()
20
+ self.conversation_id = "" # 会话ID,用于标识当前对话
21
+ self.model_name = "human" # 默认模型名称
22
+ self.system_message = "" # 系统消息,用于初始化对话
23
+ self.first_message = True
24
+
25
+ def set_system_message(self, message: str):
26
+ """设置系统消息"""
27
+ self.system_message = message
28
+
29
+ def set_model_name(self, model_name: str):
30
+ """设置模型名称"""
31
+ if model_name == "human":
32
+ self.model_name = model_name
33
+ else:
34
+ PrettyOutput.print(f"错误:不支持的模型: {model_name}", OutputType.ERROR)
35
+
36
+ def chat(self, message: str) -> str:
37
+ """发送消息并获取人类响应"""
38
+ if not self.conversation_id:
39
+ self.conversation_id = ''.join(random.choices(string.ascii_letters + string.digits, k=8))
40
+ session_info = f"(会话ID: {self.conversation_id})"
41
+ else:
42
+ session_info = f"(会话ID: {self.conversation_id})"
43
+
44
+ if self.system_message and self.first_message:
45
+ prompt = f"{self.system_message}\n\n{message} {session_info}\n\n请回复:"
46
+ self.first_message = False
47
+ else:
48
+ prompt = f"{message} {session_info}\n\n请回复:"
49
+
50
+ response = get_multiline_input(prompt)
51
+ return response
52
+
53
+ def upload_files(self, file_list: List[str]) -> bool:
54
+ """文件上传功能,人类平台不需要实际处理"""
55
+ PrettyOutput.print("人类交互平台不支持文件上传", OutputType.WARNING)
56
+ return False
57
+
58
+ def delete_chat(self) -> bool:
59
+ """删除当前会话"""
60
+ self.conversation_id = ""
61
+ self.first_message = True
62
+ return True
63
+
64
+ def name(self) -> str:
65
+ """平台名称"""
66
+ return self.model_name
@@ -54,7 +54,6 @@ class KimiModel(BasePlatform):
54
54
  self.first_chat = True # 添加标记,用于判断是否是第一次对话
55
55
  self.system_message = ""
56
56
  self.model_name = "kimi"
57
- self.web = os.getenv("KIMI_WEB", "false") == "true"
58
57
 
59
58
  def set_system_message(self, message: str):
60
59
  """Set system message"""
@@ -33,7 +33,6 @@ class YuanbaoPlatform(BasePlatform):
33
33
  # 从环境变量中获取必要参数
34
34
  self.cookies = os.getenv("YUANBAO_COOKIES") # 认证cookies
35
35
  self.agent_id = os.getenv("YUANBAO_AGENT_ID") # 代理ID
36
- self.web = os.getenv("YUANBAO_WEB", "false") == "true" # 是否启用网页功能
37
36
 
38
37
  if not self.cookies:
39
38
  message = (
@@ -17,7 +17,7 @@ def execute_command(command: str, should_run: bool) -> None:
17
17
 
18
18
 
19
19
  def install_fish_completion() -> int:
20
- """Install fish shell command completion if not already installed
20
+ """Install fish shell command completion with interactive choice
21
21
 
22
22
  Returns:
23
23
  int: 0 if success, 1 if failed
@@ -50,11 +50,11 @@ def install_fish_completion() -> int:
50
50
  with open(config_file, 'a') as config:
51
51
  config.write("""
52
52
  function fish_command_not_found
53
- commandline -r (jss $argv)
53
+ commandline -r (jss request "$argv")
54
54
  end
55
55
 
56
56
  function __fish_command_not_found_handler --on-event fish_command_not_found
57
- fish_command_not_found $argv
57
+ fish_command_not_found "$argv"
58
58
  end
59
59
  """)
60
60
  print("Fish shell命令补全功能已安装到config.fish,请执行: source ~/.config/fish/config.fish")
@@ -79,48 +79,18 @@ def process_request(request: str) -> Optional[str]:
79
79
 
80
80
  # Set system prompt
81
81
  system_message = """
82
- # 🤖 Role Definition
83
- You are a shell command generation expert who converts natural language requirements into precise shell commands.
84
-
85
- # 🎯 Core Responsibilities
86
- - Convert natural language to shell commands
87
- - Generate accurate and efficient commands
88
- - Follow strict output format rules
89
- - Maintain command simplicity
90
-
91
- # 📋 Output Requirements
92
- ## Format Rules
93
- 1. Return ONLY the command
94
- 2. NO markers (```, /*, //)
95
- 3. NO explanations
96
- 4. NO line breaks
97
- 5. NO extra spaces
98
- 6. Multiple commands: use &&
99
-
100
- ## Command Style
101
- - Use standard shell syntax
102
- - Keep commands concise
103
- - Follow best practices
104
- - Ensure proper quoting
105
- - Handle spaces correctly
106
-
107
- # 📝 Example Format
108
- Input: "Find all Python files in the current directory"
109
- Output: find . -name "*.py"
110
-
111
- # ❗ Critical Rules
112
- 1. ONLY output the command
113
- 2. NO additional content
114
- 3. NO formatting markers
115
- 4. NO explanations
116
- 5. ONE line only
117
-
118
- # 💡 Command Guidelines
119
- - Use standard tools
120
- - Prefer portable syntax
121
- - Handle edge cases
122
- - Escape special chars
123
- - Quote when needed
82
+ # 角色
83
+ 将自然语言转换为shell命令
84
+
85
+ # 规则
86
+ 1. 只输出命令
87
+ 2. 不要解释或标记
88
+ 3. 单行输出
89
+ 4. 多个命令用&&连接
90
+
91
+ # 示例
92
+ 输入: "查找Python文件"
93
+ 输出: find . -name "*.py"
124
94
  """
125
95
  model.set_system_message(system_message)
126
96
 
@@ -147,36 +117,36 @@ def main():
147
117
  formatter_class=argparse.RawDescriptionHelpFormatter,
148
118
  epilog="""
149
119
  Example:
150
- %(prog)s "Find all Python files in the current directory"
151
- %(prog)s "Compress all jpg images"
152
- %(prog)s "Find documents modified in the last week"
120
+ %(prog)s request "Find all Python files in the current directory"
153
121
  %(prog)s install
154
122
  """)
155
123
 
156
- # 修改为可选参数,添加从stdin读取的支持
157
- parser.add_argument(
124
+ # 创建子命令解析器
125
+ subparsers = parser.add_subparsers(dest='command', required=True)
126
+
127
+ # request子命令
128
+ request_parser = subparsers.add_parser('request', help='描述您想要执行的操作(用自然语言描述)')
129
+ request_parser.add_argument(
158
130
  "request",
159
131
  nargs='?', # 设置为可选参数
160
132
  help="描述您想要执行的操作(用自然语言描述),如果未提供则从标准输入读取"
161
133
  )
162
-
163
- # 添加install子命令
164
- parser.add_argument(
165
- "--install",
166
- action="store_true",
167
- help="安装fish shell的命令补全功能"
168
- )
134
+
135
+ # install子命令
136
+ install_parser = subparsers.add_parser('install', help='安装fish shell的命令补全功能')
137
+
169
138
 
170
139
  # 解析参数
171
140
  args = parser.parse_args()
172
141
 
142
+ should_run = False
143
+
173
144
  # 处理install命令
174
- if args.install:
145
+ if args.command == "install":
175
146
  return install_fish_completion()
176
-
177
- should_run = False
178
147
 
179
- # 添加标准输入处理
148
+
149
+ # 处理request命令
180
150
  if not args.request:
181
151
  # 检查是否在交互式终端中运行
182
152
  args.request = get_multiline_input(tip="请输入您要执行的功能:")
@@ -23,11 +23,6 @@ class ScriptTool:
23
23
  "type": "string",
24
24
  "description": "脚本解释器: 如bash, python3, expect, perl, ruby等任意解释器。如需直接执行shell命令, 可使用bash作为解释器"
25
25
  },
26
- "script_type": {
27
- "type": "string",
28
- "enum": ["shell_command", "shell_script", "python_script"],
29
- "description": "已废弃,请使用interpreter参数。脚本类型: shell_command (Shell命令), shell_script (Shell脚本), python_script (Python脚本)"
30
- },
31
26
  "script_content": {
32
27
  "type": "string",
33
28
  "description": "要执行的脚本内容"
@@ -142,23 +137,8 @@ class ScriptTool:
142
137
  "stderr": "Missing or empty script_content parameter"
143
138
  }
144
139
 
145
- # Get interpreter, with fallback to script_type for backward compatibility
146
- interpreter = args.get("interpreter")
147
- script_type = args.get("script_type")
148
-
149
- # Handle backward compatibility
150
- if interpreter is None and script_type is not None:
151
- if script_type == "shell_command":
152
- # For direct shell commands, use bash -c
153
- return self._execute_script_with_interpreter("bash -c", script_content)
154
- elif script_type == "shell_script":
155
- interpreter = "bash"
156
- elif script_type == "python_script":
157
- interpreter = "python"
158
-
159
- # Default to bash if nothing specified
160
- if interpreter is None:
161
- interpreter = "bash"
140
+ # Get interpreter, default to bash if not specified
141
+ interpreter = args.get("interpreter", "bash")
162
142
 
163
143
  # Execute the script with the specified interpreter
164
144
  return self._execute_script_with_interpreter(interpreter, script_content)
@@ -22,19 +22,6 @@ class WebpageTool:
22
22
  "required": ["url"]
23
23
  }
24
24
 
25
- def __init__(self):
26
- if os.getenv("YUANBAO_COOKIES", "") != "" and os.getenv("YUANBAO_AGENT_ID", "") != "":
27
- self.platform = "yuanbao"
28
- self.model = "deep_seek"
29
- elif os.getenv("KIMI_API_KEY", "") != "":
30
- self.platform = "kimi"
31
- self.model = "k1"
32
- else:
33
- self.platform = ""
34
-
35
- @staticmethod
36
- def check() -> bool:
37
- return os.getenv("YUANBAO_COOKIES", "") != "" and os.getenv("YUANBAO_AGENT_ID", "") != "" or os.getenv("KIMI_API_KEY", "") != ""
38
25
 
39
26
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
40
27
  """Read webpage content using Yuanbao model"""
@@ -43,9 +30,9 @@ class WebpageTool:
43
30
  want = args.get("want", "请总结这个网页的主要内容")
44
31
 
45
32
  # Create Yuanbao model instance
46
- model = PlatformRegistry().create_platform(self.platform)
33
+ model = PlatformRegistry().get_normal_platform()
34
+ model.web = True
47
35
  model.set_suppress_output(False) # type: ignore
48
- model.set_model_name(self.model) # type: ignore
49
36
 
50
37
  # Construct prompt based on want parameter
51
38
  prompt = f"""请帮我处理这个网页:{url}
@@ -580,6 +580,20 @@ class ToolRegistry(OutputHandler):
580
580
  output = "\n\n".join(output_parts)
581
581
  return "无输出和错误" if not output else output
582
582
 
583
+ def _truncate_output(self, output: str) -> str:
584
+ """截断过长的输出内容
585
+
586
+ 参数:
587
+ output: 要截断的输出内容
588
+
589
+ 返回:
590
+ 截断后的内容,如果内容不超过60行则返回原内容
591
+ """
592
+ if len(output.splitlines()) > 60:
593
+ lines = output.splitlines()
594
+ return '\n'.join(lines[:30] + ['\n...内容太长,已截取前后30行...\n'] + lines[-30:])
595
+ return output
596
+
583
597
  def handle_tool_calls(self, tool_call: Dict[str, Any], agent: Any) -> str:
584
598
  try:
585
599
  name = tool_call["name"] # 确保name是str类型
@@ -615,7 +629,11 @@ class ToolRegistry(OutputHandler):
615
629
  platform: Any = PlatformRegistry().get_normal_platform()
616
630
  if platform:
617
631
  platform.set_suppress_output(False)
618
- platform.upload_files([output_file]) # TODO 处理错误
632
+ try:
633
+ if not platform.upload_files([output_file]):
634
+ return self._truncate_output(output)
635
+ except Exception:
636
+ return self._truncate_output(output)
619
637
  prompt = f"该文件为工具执行结果,请阅读文件内容,并根据文件提取出以下信息:{want}"
620
638
  return f"""工具调用原始输出过长,以下是根据输出提出的信息:
621
639
 
@@ -13,26 +13,11 @@ class SearchWebTool:
13
13
  }
14
14
  }
15
15
 
16
- def __init__(self):
17
- if os.getenv("YUANBAO_COOKIES", "") != "" and os.getenv("YUANBAO_AGENT_ID", "") != "":
18
- self.platform = "yuanbao"
19
- self.model = "deep_seek"
20
- elif os.getenv("KIMI_API_KEY", "") != "":
21
- self.platform = "kimi"
22
- self.model = "k1"
23
- else:
24
- self.platform = ""
25
-
26
-
27
- @staticmethod
28
- def check() -> bool:
29
- return os.getenv("YUANBAO_COOKIES", "") != "" and os.getenv("YUANBAO_AGENT_ID", "") != "" or os.getenv("KIMI_API_KEY", "") != ""
30
-
31
16
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]: # type: ignore
32
17
  query = args.get("query")
33
- model = PlatformRegistry().create_platform(self.platform)
18
+ model = PlatformRegistry().get_normal_platform()
19
+ model.web = True
34
20
  model.set_suppress_output(False) # type: ignore
35
- model.set_model_name(self.model) # type: ignore
36
21
  return {
37
22
  "stdout": model.chat_until_success(query), # type: ignore
38
23
  "stderr": "",
@@ -4,7 +4,7 @@
4
4
  格式: {"标记名": {"template": "替换模板", "description": "描述信息"}}
5
5
  """
6
6
 
7
- from .tag import ot, ct
7
+ from jarvis.jarvis_utils.tag import ot, ct
8
8
 
9
9
  BUILTIN_REPLACE_MAP = {
10
10
  "CodeBase": {
@@ -129,5 +129,18 @@ code_plan工具将:
129
129
  "template": f"""
130
130
  请修复以下问题:
131
131
  """
132
+ },
133
+ "Check": {
134
+ "append": True,
135
+ "template": f"""
136
+ 请使用静态检查工具检查当前代码,必须严格遵守工具调用格式。
137
+
138
+ 检查要求:
139
+ 1. 如果发现致命错误,必须立即修复
140
+ 2. 如果发现警告或风格问题,应询问用户是否需要修复
141
+ 3. 检查完成后应报告结果
142
+ 4. 确保使用项目对应的静态检查工具
143
+ """,
144
+ "description": "执行静态代码检查"
132
145
  }
133
146
  }
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  from functools import lru_cache
3
3
  import yaml
4
- from .builtin_replace_map import BUILTIN_REPLACE_MAP
4
+ from jarvis.jarvis_utils.builtin_replace_map import BUILTIN_REPLACE_MAP
5
5
  """配置管理模块。
6
6
 
7
7
  该模块提供了获取Jarvis系统各种配置设置的函数。
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.156
3
+ Version: 0.1.158
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
@@ -60,6 +60,8 @@ Requires-Dist: pytest; extra == "dev"
60
60
  Requires-Dist: black; extra == "dev"
61
61
  Requires-Dist: isort; extra == "dev"
62
62
  Requires-Dist: mypy; extra == "dev"
63
+ Requires-Dist: build; extra == "dev"
64
+ Requires-Dist: twine; extra == "dev"
63
65
  Dynamic: author
64
66
  Dynamic: home-page
65
67
  Dynamic: license-file
@@ -82,6 +84,7 @@ Dynamic: requires-python
82
84
  [扩展开发](#extensions) •
83
85
  [贡献指南](#contributing) •
84
86
  [许可证](#license) •
87
+ [Wiki文档](https://deepwiki.com/skyfireitdiy/Jarvis)
85
88
  </div>
86
89
 
87
90
  ---
@@ -202,6 +205,7 @@ jarvis-methodology --help
202
205
  | `JARVIS_EXECUTE_TOOL_CONFIRM` | false | 执行工具前是否需要确认 |
203
206
  | `JARVIS_CONFIRM_BEFORE_APPLY_PATCH` | true | 应用补丁前是否需要确认 |
204
207
  | `JARVIS_MAX_TOOL_CALL_COUNT` | 20 | 最大连续工具调用次数 |
208
+ | `JARVIS_CODE_EMBEDDING_MODEL_SIZE` | small | 代码嵌入模型大小,可选值:small、large |
205
209
 
206
210
 
207
211
  ---
@@ -1,11 +1,11 @@
1
- jarvis/__init__.py,sha256=zOb8b4lhgGPfSpvH6W1CW1ovF70mzNUb0nufgXh-ZTw,50
2
- jarvis/jarvis_agent/__init__.py,sha256=Ur28Tb8oCS8wXWRdRevf1TJOyVb-xycCIJ_KoscIQMw,25336
1
+ jarvis/__init__.py,sha256=fJj9Z5D55H1onkVpg4D1Cvjzfk9M_sYvzmzi4v5NZGY,50
2
+ jarvis/jarvis_agent/__init__.py,sha256=tii6khwfG971MJiMfKSLwlKTjB3iEv8ITE3JqYSkfQA,24824
3
3
  jarvis/jarvis_agent/builtin_input_handler.py,sha256=3rRA-7v_VUSFG1s7tTKhriq9vv0nsa3t69ReV0xH5gs,1505
4
4
  jarvis/jarvis_agent/file_input_handler.py,sha256=auBbBfS4Ux5ksczeRe9LtsmMm4hKrPxinW5leE9Rtyc,3575
5
5
  jarvis/jarvis_agent/jarvis.py,sha256=6Bp_Y-E3RN6bDmDs5lN3uALL_Dhq-p_aIuVNELG1vtw,5898
6
6
  jarvis/jarvis_agent/main.py,sha256=Jlw_Tofh2C-sMVnkeOZBrwWJOWNH3IhsKDUn-WBlgU8,2602
7
7
  jarvis/jarvis_agent/output_handler.py,sha256=4limQ-Kf-YYvQjT5SMjJIyyvD1DVG8tINv1A_qbv4ho,405
8
- jarvis/jarvis_agent/patch.py,sha256=nbfR_qmt3P5nUzZC-h6ypX4UQ6Aoj2QiNyq_Hy7e6-U,23619
8
+ jarvis/jarvis_agent/patch.py,sha256=LkZ5Q_lL-BVCXAhnEHT289eVgTokET_flrOeWsAeztU,23652
9
9
  jarvis/jarvis_agent/shell_input_handler.py,sha256=9IoGQCe6FF4HA2V5S11q63AtnWDZFpNeRd3hcqCAlBw,1237
10
10
  jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  jarvis/jarvis_code_agent/code_agent.py,sha256=vi_g-LWdD5nn3RQsC1X8G2iNK8SrBADwFLUkflqtvKE,13723
@@ -43,20 +43,21 @@ jarvis/jarvis_lsp/python.py,sha256=OJuYHLHI1aYNNWcAFayy_5GxogwyMC3A7KOYGjxN1yg,1
43
43
  jarvis/jarvis_lsp/registry.py,sha256=-b7lAfZ6SNp3O0ifRiFSLxH0xJlPQhkq4DATDDjJb1U,6491
44
44
  jarvis/jarvis_lsp/rust.py,sha256=ICmQs5UVdMZwn5KjaF1YRXBCLUMtGF8Z9IwE5rqWkrU,3686
45
45
  jarvis/jarvis_mcp/__init__.py,sha256=gi74_Yz5nsEFhrAyCg1Ovxsj-hLweLjMGoOaceL2yx4,2090
46
- jarvis/jarvis_mcp/sse_mcp_client.py,sha256=PfhVzJLLb9OAHyxn8wcU2yFRN-EH0_wZiHU_JC8xhvI,23475
47
- jarvis/jarvis_mcp/stdio_mcp_client.py,sha256=1II-dRWVXXZXZCDfqJNxhmF5kpLt9RHSERe-zZ8iOJ0,11790
48
- jarvis/jarvis_methodology/main.py,sha256=IBv87UOmdCailgooMtWEcqZcQHmNLhZD-kkGw5jOcVg,3375
46
+ jarvis/jarvis_mcp/sse_mcp_client.py,sha256=Qd09ymgZmxQvaFUzz8I3AI46v6AqmMbGaF0iBbExAGY,23459
47
+ jarvis/jarvis_mcp/stdio_mcp_client.py,sha256=DtRO4dqBoxI8W0H0rVR5zxZLR0theKxRAQ-qzQE9qPg,11806
48
+ jarvis/jarvis_methodology/main.py,sha256=i0sOKeGf9-87M0jY4q6sgw4dAPt800PHiZjseLAQmO0,11782
49
49
  jarvis/jarvis_multi_agent/__init__.py,sha256=SX8lBErhltKyYRM-rymrMz3sJ0Zl3hBXrpsPdFgzkQc,4399
50
50
  jarvis/jarvis_multi_agent/main.py,sha256=aGuUC3YQmahabqwDwZXJjfQLYsZ3KIZdf8DZDlVNMe4,1543
51
- jarvis/jarvis_platform/__init__.py,sha256=WIJtD5J7lOrWLX2bsgZGkmlMcN0NOJsnh_reybmHPjg,58
52
- jarvis/jarvis_platform/base.py,sha256=AKsqWU7K4LdVw5JldFKpgTUyQc28mnWoRDQAUnDbihE,3263
53
- jarvis/jarvis_platform/kimi.py,sha256=h1BP0vey30upZ9g-b8pU87rQGd3fHcgAQo_51Nv9DZY,16697
51
+ jarvis/jarvis_platform/__init__.py,sha256=oD9i4ugZ2q6Hys3noLOvzPUUHqE2PJ_Je1r2dLLTscw,80
52
+ jarvis/jarvis_platform/base.py,sha256=um9_BZgOJSg0nlmywYGAxwFRL-8409OnlvfgQkh5RUo,3406
53
+ jarvis/jarvis_platform/human.py,sha256=WCzvBtQUMN7ys4rQl6UT7Zdp4x5RaGv1U4vBx7ROxfo,2438
54
+ jarvis/jarvis_platform/kimi.py,sha256=GgUekusFzx2842K-PrES3c2oprLbPCjQhbyjU0UKycg,16637
54
55
  jarvis/jarvis_platform/registry.py,sha256=wvXTKXqAoW6GPaLKCPYhRB9QhVe1xfoVbVPBZAxl_uA,7716
55
- jarvis/jarvis_platform/yuanbao.py,sha256=X2lYZ3SxBzdaCwd5ooq9fxYbu14RUpeDILYg0W5W7Xc,21902
56
+ jarvis/jarvis_platform/yuanbao.py,sha256=9nIyg5Xx9rdUaJAK_Tj8HumOT5mwpa-V907dZGot-4E,21811
56
57
  jarvis/jarvis_platform_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
58
  jarvis/jarvis_platform_manager/main.py,sha256=xJM86DQFyYDysMyQEJDAwB2oSYcWg_zi1mFld0zyquM,22572
58
59
  jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
- jarvis/jarvis_smart_shell/main.py,sha256=COktOt0BJCFLsftP1T-1LzJ-oUpjOojfCydOQF-A2OI,5590
60
+ jarvis/jarvis_smart_shell/main.py,sha256=gH_fZQhXrRuGhkHNpBB9LK7y4BfK66elcq4qsUvXnHY,4859
60
61
  jarvis/jarvis_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
62
  jarvis/jarvis_tools/ask_codebase.py,sha256=S6NArvKZyK8WEbsEgeGCljjg4D9mteWrq9m352V58jU,9635
62
63
  jarvis/jarvis_tools/ask_user.py,sha256=NjxTCHGKo4nthbEQD-isvPCW4PQhTcekEferjnukX70,2143
@@ -65,20 +66,20 @@ jarvis/jarvis_tools/chdir.py,sha256=do_OdtabiH3lZcT_ynjSAX66XgH2gPl9mYiS7dMMDa8,
65
66
  jarvis/jarvis_tools/code_plan.py,sha256=jNa2rs4J3Fam8Q_RHE2_QvVch21TPp-Zfv-W6iQ3D_0,7729
66
67
  jarvis/jarvis_tools/create_code_agent.py,sha256=SRiQXZf57ViIDh6YSEmJkcoSKft0-y3iDfWF8f1bvZU,3387
67
68
  jarvis/jarvis_tools/create_sub_agent.py,sha256=wGiHukvi58wb1AKW5beP7R8VvApOn8TOeGmtXsmcETE,3001
68
- jarvis/jarvis_tools/execute_script.py,sha256=3sR_u6-SLbzmcUbXjHLN-rGjoelIj4uAefys5la_x7o,6759
69
+ jarvis/jarvis_tools/execute_script.py,sha256=AeuC3yZIg-nBq_LTIyqxu-lG_uLG63lvwO28A6dRDYA,5715
69
70
  jarvis/jarvis_tools/file_analyzer.py,sha256=XCsFB4dZ9qy2q929hqi1rTngj6AtRtIaPx_W7lJAcpQ,4814
70
71
  jarvis/jarvis_tools/file_operation.py,sha256=sB1x0zI1dULXV7FG17wkiMQ7mQAEnXVd_5rakQ0Thik,9109
71
72
  jarvis/jarvis_tools/find_methodology.py,sha256=TIUrezAql6wY3-wqnOPfGrO0tqS5N_-eU6YimCzaepM,2268
72
73
  jarvis/jarvis_tools/lsp_get_diagnostics.py,sha256=IYqv8jQwSK71sZpDBRolSDnYii8t0M7fzLthhMYTeGk,5322
73
74
  jarvis/jarvis_tools/methodology.py,sha256=gnlJojY4Dg5v9AAB5xcpKqpPIHs0tOYVtzTHkwOrWk0,5214
74
75
  jarvis/jarvis_tools/read_code.py,sha256=_X6D3AIgRD9YplSDnFhXOm8wQAZMA3pkkXy31SG33l0,6041
75
- jarvis/jarvis_tools/read_webpage.py,sha256=2QF0zAyApl0bOr9604aml_uuqBZcPefVuHvRfWzrnzk,2598
76
- jarvis/jarvis_tools/registry.py,sha256=82rsRFNWJkijH9YP3t4yt6eUs3KgIp633R5goVLUcTQ,25650
77
- jarvis/jarvis_tools/search_web.py,sha256=kWW9K2QUR2AxPq6gcyx4Bgy-0Y4gzcdErq1DNT1EYM4,1333
76
+ jarvis/jarvis_tools/read_webpage.py,sha256=1AXXEX69fPJsPL7PBZDM1G4Z-MM13pUt34JXitsAFM4,2022
77
+ jarvis/jarvis_tools/registry.py,sha256=l1wHR76TQWB1iUKh9MGKIIMNKUpSLk3GfYH8rhD1N90,26322
78
+ jarvis/jarvis_tools/search_web.py,sha256=hMrcSnKcjH6YcV8WY4tangEid7y1L-QbyeXDlBofoy8,756
78
79
  jarvis/jarvis_tools/virtual_tty.py,sha256=Rpn9VXUG17LQsY87F_O6UCjN_opXB05mpwozxYf-xVI,16372
79
80
  jarvis/jarvis_utils/__init__.py,sha256=KMg-KY5rZIhGTeOD5e2Xo5CU7DX1DUz4ULWAaTQ-ZNw,825
80
- jarvis/jarvis_utils/builtin_replace_map.py,sha256=UnpD0_dS_lhSOVGuEmdVOLtb_e8XKXGycyq8GO6QMDw,3835
81
- jarvis/jarvis_utils/config.py,sha256=40ODLYVysDiuVN2avlGKILaCIJB1_iOWReWoKYwuniM,4040
81
+ jarvis/jarvis_utils/builtin_replace_map.py,sha256=Dt8YL4Sk5uALTMPT_n-lhshRWvFWPRPwV4stASOecQ8,4290
82
+ jarvis/jarvis_utils/config.py,sha256=iKlaVzwkSltjtFNGDrANt1PETYED6pDKrDphh3yD1eE,4059
82
83
  jarvis/jarvis_utils/embedding.py,sha256=_Q-VurYHQZSsyISClTFjadDaNqNPBMqJe58lMM6bsVs,6991
83
84
  jarvis/jarvis_utils/file_processors.py,sha256=oNtVlz2JHcQ60NS6sgI-VsvYXOnsQgFUEVenznCXHC4,2952
84
85
  jarvis/jarvis_utils/git_utils.py,sha256=j_Jw6h7JD91XhMf0WD3MAH4URkLUBrrYCLnuLm1GeN4,5630
@@ -88,9 +89,9 @@ jarvis/jarvis_utils/methodology.py,sha256=XayEVGXP5RfDBWj4bMOVFWplyrSp4GsXHwOTWo
88
89
  jarvis/jarvis_utils/output.py,sha256=BmWdB1bmizv0xfU4Z___9p_xQodorriIcEgADVq9fk0,8416
89
90
  jarvis/jarvis_utils/tag.py,sha256=YtXBYuZWy8j8YbeQX2qRrHRQl6Gp2Vt7W4p-2yjo0a4,405
90
91
  jarvis/jarvis_utils/utils.py,sha256=fNZjDj-qP0cum1RfWmI8D5VVgqT-tBUPsc8n_XPGLQY,4246
91
- jarvis_ai_assistant-0.1.156.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
92
- jarvis_ai_assistant-0.1.156.dist-info/METADATA,sha256=9SIN10_orqLOnBlxHwILAPhiVxZMVu91zz_waOEl4KM,12438
93
- jarvis_ai_assistant-0.1.156.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
94
- jarvis_ai_assistant-0.1.156.dist-info/entry_points.txt,sha256=cKz_9SEpOvElTubKPMZMAdskD4GHz-NyKWRNssIVAWE,973
95
- jarvis_ai_assistant-0.1.156.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
96
- jarvis_ai_assistant-0.1.156.dist-info/RECORD,,
92
+ jarvis_ai_assistant-0.1.158.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
93
+ jarvis_ai_assistant-0.1.158.dist-info/METADATA,sha256=u0gWbBvTrAsaE7KhFHwOgrWwBZntpU62UGPqOx10dyM,12669
94
+ jarvis_ai_assistant-0.1.158.dist-info/WHEEL,sha256=ooBFpIzZCPdw3uqIQsOo4qqbA4ZRPxHnOH7peeONza0,91
95
+ jarvis_ai_assistant-0.1.158.dist-info/entry_points.txt,sha256=cKz_9SEpOvElTubKPMZMAdskD4GHz-NyKWRNssIVAWE,973
96
+ jarvis_ai_assistant-0.1.158.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
97
+ jarvis_ai_assistant-0.1.158.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.0.0)
2
+ Generator: setuptools (80.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5