jarvis-ai-assistant 0.1.223__py3-none-any.whl → 0.1.225__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.
jarvis/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Jarvis AI Assistant"""
3
3
 
4
- __version__ = "0.1.223"
4
+ __version__ = "0.1.225"
@@ -92,6 +92,10 @@ class Agent:
92
92
  # 只有在记录启动时才停止记录
93
93
  delete_agent(self.name)
94
94
 
95
+ def get_tool_usage_prompt(self) -> str:
96
+ """获取工具使用提示"""
97
+ return build_action_prompt(self.output_handler) # type: ignore
98
+
95
99
  def __init__(
96
100
  self,
97
101
  system_prompt: str,
@@ -199,7 +203,7 @@ class Agent:
199
203
 
200
204
  PrettyOutput.print(welcome_message, OutputType.SYSTEM)
201
205
 
202
- action_prompt = build_action_prompt(self.output_handler) # type: ignore
206
+ action_prompt = self.get_tool_usage_prompt()
203
207
 
204
208
  self.model.set_system_prompt(
205
209
  f"""
@@ -209,6 +213,7 @@ class Agent:
209
213
  """
210
214
  )
211
215
  self.first = True
216
+ self.run_input_handlers_next_turn = False
212
217
 
213
218
  def set_user_data(self, key: str, value: Any):
214
219
  """Sets user data in the session."""
@@ -232,6 +237,10 @@ class Agent:
232
237
  """Sets the addon prompt in the session."""
233
238
  self.session.set_addon_prompt(addon_prompt)
234
239
 
240
+ def set_run_input_handlers_next_turn(self, value: bool):
241
+ """Sets the flag to run input handlers on the next turn."""
242
+ self.run_input_handlers_next_turn = value
243
+
235
244
  def set_after_tool_call_cb(self, cb: Callable[[Any], None]): # type: ignore
236
245
  """设置工具调用后回调函数。
237
246
 
@@ -260,7 +269,9 @@ class Agent:
260
269
  return handler
261
270
  return None
262
271
 
263
- def _call_model(self, message: str, need_complete: bool = False) -> str:
272
+ def _call_model(
273
+ self, message: str, need_complete: bool = False, run_input_handlers: bool = True
274
+ ) -> str:
264
275
  """调用AI模型并实现重试逻辑
265
276
 
266
277
  参数:
@@ -276,10 +287,11 @@ class Agent:
276
287
  3. 会自动添加附加提示
277
288
  4. 会检查并处理上下文长度限制
278
289
  """
279
- for handler in self.input_handler:
280
- message, need_return = handler(message, self)
281
- if need_return:
282
- return message
290
+ if run_input_handlers:
291
+ for handler in self.input_handler:
292
+ message, need_return = handler(message, self)
293
+ if need_return:
294
+ return message
283
295
 
284
296
  if self.session.addon_prompt:
285
297
  message += f"\n\n{self.session.addon_prompt}"
@@ -474,12 +486,20 @@ class Agent:
474
486
  try:
475
487
  set_agent(self.name, self)
476
488
 
489
+ run_input_handlers = True
477
490
  while True:
491
+ if self.run_input_handlers_next_turn:
492
+ run_input_handlers = True
493
+ self.run_input_handlers_next_turn = False
494
+
478
495
  if self.first:
479
496
  self._first_run()
480
497
  try:
481
- current_response = self._call_model(self.session.prompt, True)
498
+ current_response = self._call_model(
499
+ self.session.prompt, True, run_input_handlers
500
+ )
482
501
  self.session.prompt = ""
502
+ run_input_handlers = False
483
503
 
484
504
  if get_interrupt():
485
505
  set_interrupt(False)
@@ -487,6 +507,7 @@ class Agent:
487
507
  f"模型交互期间被中断,请输入用户干预信息:"
488
508
  )
489
509
  if user_input:
510
+ run_input_handlers = True
490
511
  # 如果有工具调用且用户确认继续,则将干预信息和工具执行结果拼接为prompt
491
512
  if any(
492
513
  handler.can_handle(current_response)
@@ -498,6 +519,7 @@ class Agent:
498
519
  self.session.prompt = (
499
520
  f"{user_input}\n\n{current_response}"
500
521
  )
522
+ run_input_handlers = False
501
523
  continue
502
524
  self.session.prompt += f"{user_input}"
503
525
  continue
@@ -525,6 +547,7 @@ class Agent:
525
547
 
526
548
  if user_input:
527
549
  self.session.prompt = user_input
550
+ run_input_handlers = True
528
551
  continue
529
552
 
530
553
  if not user_input:
@@ -38,10 +38,7 @@ def builtin_input_handler(user_input: str, agent_: Any) -> Tuple[str, bool]:
38
38
  agent.clear()
39
39
  return "", True
40
40
  elif tag == "ToolUsage":
41
- from jarvis.jarvis_tools.registry import ToolRegistry
42
- from jarvis.jarvis_agent.prompt_builder import build_action_prompt
43
- action_prompt = build_action_prompt(agent.output_handler) # type: ignore
44
- agent.set_addon_prompt(action_prompt)
41
+ agent.set_addon_prompt(agent.get_tool_usage_prompt())
45
42
  return "", False
46
43
  elif tag == "ReloadConfig":
47
44
  from jarvis.jarvis_utils.utils import load_config
@@ -1,8 +1,11 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import argparse
3
3
  import os
4
+ import shutil
5
+ import subprocess
4
6
  import sys
5
- from typing import Dict
7
+ from pathlib import Path
8
+ from typing import Dict, Optional
6
9
 
7
10
  import yaml # type: ignore
8
11
  from prompt_toolkit import prompt # type: ignore
@@ -106,8 +109,8 @@ def _select_task(tasks: Dict[str, str]) -> str:
106
109
  PrettyOutput.print(f"选择任务失败: {str(val_err)}", OutputType.ERROR)
107
110
 
108
111
 
109
- def main() -> None:
110
-
112
+ def _parse_args() -> argparse.Namespace:
113
+ """Parse command line arguments."""
111
114
  parser = argparse.ArgumentParser(description="Jarvis AI assistant")
112
115
  parser.add_argument(
113
116
  "--llm_type",
@@ -129,44 +132,90 @@ def main() -> None:
129
132
  help="Restore session from .jarvis/saved_session.json",
130
133
  default=False,
131
134
  )
132
- args = parser.parse_args()
133
- init_env(
134
- "欢迎使用 Jarvis AI 助手,您的智能助理已准备就绪!", config_file=args.config
135
+ parser.add_argument(
136
+ "-e", "--edit", action="store_true", help="Edit the configuration file"
135
137
  )
138
+ return parser.parse_args()
136
139
 
137
- try:
138
- agent = Agent(
139
- system_prompt=origin_agent_system_prompt,
140
- llm_type=args.llm_type,
141
- input_handler=[shell_input_handler, builtin_input_handler],
142
- output_handler=[ToolRegistry()],
143
- need_summary=False,
144
- )
145
140
 
146
- # 尝试恢复会话
147
- if args.restore_session:
148
- if agent.restore_session():
149
- PrettyOutput.print("会话已成功恢复。", OutputType.SUCCESS)
150
- else:
151
- PrettyOutput.print("无法恢复会话。", OutputType.WARNING)
141
+ def _handle_edit_mode(args: argparse.Namespace) -> None:
142
+ """If edit flag is set, open config file in editor and exit."""
143
+ if not args.edit:
144
+ return
152
145
 
153
- # 优先处理命令行直接传入的任务
154
- if args.task:
155
- agent.run(args.task)
146
+ config_file_path = (
147
+ Path(args.config)
148
+ if args.config
149
+ else Path(os.path.expanduser("~/.jarvis/config.yaml"))
150
+ )
151
+ editors = ["nvim", "vim", "vi"]
152
+ editor = next((e for e in editors if shutil.which(e)), None)
153
+
154
+ if editor:
155
+ try:
156
+ subprocess.run([editor, str(config_file_path)], check=True)
156
157
  sys.exit(0)
158
+ except (subprocess.CalledProcessError, FileNotFoundError) as e:
159
+ PrettyOutput.print(f"Failed to open editor: {e}", OutputType.ERROR)
160
+ sys.exit(1)
161
+ else:
162
+ PrettyOutput.print(
163
+ "No suitable editor found (nvim, vim, vi).", OutputType.ERROR
164
+ )
165
+ sys.exit(1)
166
+
157
167
 
158
- if agent.first:
159
- tasks = _load_tasks()
160
- if tasks and (selected_task := _select_task(tasks)):
161
- PrettyOutput.print(f"开始执行任务: \n{selected_task}", OutputType.INFO)
162
- agent.run(selected_task)
163
- sys.exit(0)
168
+ def _initialize_agent(args: argparse.Namespace) -> Agent:
169
+ """Initialize the agent and restore session if requested."""
170
+ agent = Agent(
171
+ system_prompt=origin_agent_system_prompt,
172
+ llm_type=args.llm_type,
173
+ input_handler=[shell_input_handler, builtin_input_handler],
174
+ output_handler=[ToolRegistry()], # type: ignore
175
+ need_summary=False,
176
+ )
164
177
 
165
- user_input = get_multiline_input("请输入你的任务(输入空行退出):")
166
- if user_input:
167
- agent.run(user_input)
178
+ # 尝试恢复会话
179
+ if args.restore_session:
180
+ if agent.restore_session():
181
+ PrettyOutput.print("会话已成功恢复。", OutputType.SUCCESS)
182
+ else:
183
+ PrettyOutput.print("无法恢复会话。", OutputType.WARNING)
184
+ return agent
185
+
186
+
187
+ def _get_and_run_task(agent: Agent, task_content: Optional[str] = None) -> None:
188
+ """Get task from various sources and run it."""
189
+ # 优先处理命令行直接传入的任务
190
+ if task_content:
191
+ agent.run(task_content)
168
192
  sys.exit(0)
169
193
 
194
+ if agent.first:
195
+ tasks = _load_tasks()
196
+ if tasks and (selected_task := _select_task(tasks)):
197
+ PrettyOutput.print(f"开始执行任务: \n{selected_task}", OutputType.INFO)
198
+ agent.run(selected_task)
199
+ sys.exit(0)
200
+
201
+ user_input = get_multiline_input("请输入你的任务(输入空行退出):")
202
+ if user_input:
203
+ agent.run(user_input)
204
+ sys.exit(0)
205
+
206
+
207
+ def main() -> None:
208
+ """Main function for Jarvis AI assistant."""
209
+ args = _parse_args()
210
+ _handle_edit_mode(args)
211
+
212
+ init_env(
213
+ "欢迎使用 Jarvis AI 助手,您的智能助理已准备就绪!", config_file=args.config
214
+ )
215
+
216
+ try:
217
+ agent = _initialize_agent(args)
218
+ _get_and_run_task(agent, args.task)
170
219
  except Exception as err: # pylint: disable=broad-except
171
220
  PrettyOutput.print(f"初始化错误: {str(err)}", OutputType.ERROR)
172
221
  sys.exit(1)
@@ -20,7 +20,9 @@ def load_config(config_path: str) -> dict:
20
20
  dict: 配置字典
21
21
  """
22
22
  if not os.path.exists(config_path):
23
- PrettyOutput.print(f"配置文件 {config_path} 不存在,使用默认配置", OutputType.WARNING)
23
+ PrettyOutput.print(
24
+ f"配置文件 {config_path} 不存在,使用默认配置", OutputType.WARNING
25
+ )
24
26
  return {}
25
27
 
26
28
  with open(config_path, "r", encoding="utf-8", errors="ignore") as f:
@@ -53,7 +55,9 @@ def main():
53
55
  args = parser.parse_args()
54
56
 
55
57
  # Initialize environment
56
- init_env("欢迎使用 Jarvis AI 助手,您的智能助理已准备就绪!", config_file=args.config)
58
+ init_env(
59
+ "欢迎使用 Jarvis AI 助手,您的智能助理已准备就绪!", config_file=args.config
60
+ )
57
61
 
58
62
  # Load configuration
59
63
  config = load_config(args.agent_definition) if args.agent_definition else {}
@@ -18,7 +18,10 @@ from jarvis.jarvis_code_agent.lint import get_lint_tools
18
18
  from jarvis.jarvis_git_utils.git_commiter import GitCommitTool
19
19
  from jarvis.jarvis_platform.registry import PlatformRegistry
20
20
  from jarvis.jarvis_tools.registry import ToolRegistry
21
- from jarvis.jarvis_utils.config import is_confirm_before_apply_patch, is_enable_static_analysis
21
+ from jarvis.jarvis_utils.config import (
22
+ is_confirm_before_apply_patch,
23
+ is_enable_static_analysis,
24
+ )
22
25
  from jarvis.jarvis_utils.git_utils import (
23
26
  confirm_add_new_files,
24
27
  find_git_root_and_cd,
@@ -54,7 +57,6 @@ class CodeAgent:
54
57
  "search_web",
55
58
  "ask_user",
56
59
  "read_code",
57
- "methodology",
58
60
  "rewrite_file",
59
61
  ]
60
62
  )
@@ -116,7 +118,7 @@ class CodeAgent:
116
118
  system_prompt=code_system_prompt,
117
119
  name="CodeAgent",
118
120
  auto_complete=False,
119
- output_handler=[tool_registry, EditFileHandler()],
121
+ output_handler=[tool_registry, EditFileHandler()], # type: ignore
120
122
  llm_type=llm_type,
121
123
  input_handler=[shell_input_handler, builtin_input_handler],
122
124
  need_summary=need_summary,
@@ -5,12 +5,26 @@ Utility module for loading language-specific code review checklists.
5
5
  from typing import Dict, Optional
6
6
 
7
7
  # Import checklist modules
8
- from jarvis.jarvis_code_analysis.checklists import (c_cpp, csharp, data_format,
9
- devops, docs, go,
10
- infrastructure, java,
11
- javascript, kotlin, php,
12
- python, ruby, rust, shell,
13
- sql, swift, web)
8
+ from jarvis.jarvis_code_analysis.checklists import (
9
+ c_cpp,
10
+ csharp,
11
+ data_format,
12
+ devops,
13
+ docs,
14
+ go,
15
+ infrastructure,
16
+ java,
17
+ javascript,
18
+ kotlin,
19
+ php,
20
+ python,
21
+ ruby,
22
+ rust,
23
+ shell,
24
+ sql,
25
+ swift,
26
+ web,
27
+ )
14
28
 
15
29
  # Map of language identifiers to their checklist content
16
30
  CHECKLIST_MAP = {
@@ -176,6 +176,14 @@
176
176
  "description": "是否启用任务分析",
177
177
  "default": true
178
178
  },
179
+ "JARVIS_TOOL_LOAD_DIRS": {
180
+ "type": "array",
181
+ "description": "自定义工具加载目录",
182
+ "items": {
183
+ "type": "string"
184
+ },
185
+ "default": []
186
+ },
179
187
  "JARVIS_PRINT_PROMPT": {
180
188
  "type": "boolean",
181
189
  "description": "是否打印提示",
@@ -229,7 +237,35 @@
229
237
  "template"
230
238
  ]
231
239
  }
240
+ },
241
+ "OPENAI_API_KEY": {
242
+ "type": "string",
243
+ "description": "OpenAI API Key"
244
+ },
245
+ "OPENAI_API_BASE": {
246
+ "type": "string",
247
+ "description": "OpenAI API Base URL"
248
+ },
249
+ "KIMI_API_KEY": {
250
+ "type": "string",
251
+ "description": "Kimi API Key"
252
+ },
253
+ "TONGYI_COOKIES": {
254
+ "type": "string",
255
+ "description": "Tongyi Cookies"
256
+ },
257
+ "YUANBAO_COOKIES": {
258
+ "type": "string",
259
+ "description": "Yuanbao Cookies"
260
+ },
261
+ "AI8_API_KEY": {
262
+ "type": "string",
263
+ "description": "AI8 API Key"
264
+ },
265
+ "OYI_API_KEY": {
266
+ "type": "string",
267
+ "description": "Oyi API Key"
232
268
  }
233
269
  },
234
- "additionalProperties": false
270
+ "additionalProperties": true
235
271
  }
@@ -188,9 +188,13 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
188
188
  for entry in conversation_history:
189
189
  file_obj.write(f"{entry['role']}: {entry['content']}\n\n")
190
190
 
191
- PrettyOutput.print(f"所有对话已保存到 {file_path}", OutputType.SUCCESS)
191
+ PrettyOutput.print(
192
+ f"所有对话已保存到 {file_path}", OutputType.SUCCESS
193
+ )
192
194
  except Exception as exc:
193
- PrettyOutput.print(f"保存所有对话失败: {str(exc)}", OutputType.ERROR)
195
+ PrettyOutput.print(
196
+ f"保存所有对话失败: {str(exc)}", OutputType.ERROR
197
+ )
194
198
  continue
195
199
 
196
200
  # Check if it is a save_session command
@@ -211,7 +215,9 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
211
215
  file_path = file_path[1:-1]
212
216
 
213
217
  if platform.save(file_path):
214
- PrettyOutput.print(f"会话已保存到 {file_path}", OutputType.SUCCESS)
218
+ PrettyOutput.print(
219
+ f"会话已保存到 {file_path}", OutputType.SUCCESS
220
+ )
215
221
  else:
216
222
  PrettyOutput.print("保存会话失败", OutputType.ERROR)
217
223
  except Exception as exc:
@@ -237,7 +243,9 @@ def chat_with_model(platform_name: str, model_name: str, system_prompt: str) ->
237
243
 
238
244
  if platform.restore(file_path):
239
245
  conversation_history = [] # Clear local history after loading
240
- PrettyOutput.print(f"会话已从 {file_path} 加载", OutputType.SUCCESS)
246
+ PrettyOutput.print(
247
+ f"会话已从 {file_path} 加载", OutputType.SUCCESS
248
+ )
241
249
  else:
242
250
  PrettyOutput.print("加载会话失败", OutputType.ERROR)
243
251
  except Exception as exc:
@@ -433,8 +441,12 @@ def main() -> None:
433
441
  service_parser.add_argument(
434
442
  "--port", type=int, default=8000, help="服务端口 (默认: 8000)"
435
443
  )
436
- service_parser.add_argument("--platform", "-p", help="指定默认平台,当客户端未指定平台时使用")
437
- service_parser.add_argument("--model", "-m", help="指定默认模型,当客户端未指定平台时使用")
444
+ service_parser.add_argument(
445
+ "--platform", "-p", help="指定默认平台,当客户端未指定平台时使用"
446
+ )
447
+ service_parser.add_argument(
448
+ "--model", "-m", help="指定默认模型,当客户端未指定平台时使用"
449
+ )
438
450
  service_parser.set_defaults(func=service_command)
439
451
 
440
452
  # role subcommand
jarvis/jarvis_rag/cli.py CHANGED
@@ -4,7 +4,7 @@ from pathlib import Path
4
4
  from typing import Optional, List, Literal, cast
5
5
  import mimetypes
6
6
 
7
- import pathspec
7
+ import pathspec # type: ignore
8
8
  import typer
9
9
  from langchain.docstore.document import Document
10
10
  from langchain_community.document_loaders import (
@@ -101,9 +101,7 @@ class JarvisPlatform_LLM(LLMInterface):
101
101
  try:
102
102
  self.registry = PlatformRegistry.get_global_platform_registry()
103
103
  self.platform: BasePlatform = self.registry.get_normal_platform()
104
- self.platform.set_suppress_output(
105
- False
106
- ) # 确保模型没有控制台输出
104
+ self.platform.set_suppress_output(False) # 确保模型没有控制台输出
107
105
  print(f"🚀 已初始化 Jarvis 平台 LLM,模型: {self.platform.name()}")
108
106
  except Exception as e:
109
107
  print(f"❌ 初始化 Jarvis 平台 LLM 失败: {e}")
@@ -20,34 +20,37 @@ def execute_command(command: str, should_run: bool) -> None:
20
20
 
21
21
  def _check_fish_shell() -> bool:
22
22
  """Check if current shell is fish
23
-
23
+
24
24
  Returns:
25
25
  bool: True if fish shell, False otherwise
26
26
  """
27
27
  return get_shell_name() == "fish"
28
28
 
29
+
29
30
  def _get_config_file() -> str:
30
31
  """Get fish config file path
31
-
32
+
32
33
  Returns:
33
34
  str: Path to fish config file
34
35
  """
35
36
  return os.path.expanduser("~/.config/fish/config.fish")
36
37
 
38
+
37
39
  def _get_markers() -> Tuple[str, str]:
38
40
  """Get start and end markers for JSS completion
39
-
41
+
40
42
  Returns:
41
43
  Tuple[str, str]: (start_marker, end_marker)
42
44
  """
43
45
  return (
44
46
  "# ===== JARVIS JSS FISH COMPLETION START =====",
45
- "# ===== JARVIS JSS FISH COMPLETION END ====="
47
+ "# ===== JARVIS JSS FISH COMPLETION END =====",
46
48
  )
47
49
 
50
+
48
51
  def install_jss_completion() -> int:
49
52
  """Install JSS fish shell command completion
50
-
53
+
51
54
  Returns:
52
55
  int: 0 if success, 1 if failed
53
56
  """
@@ -70,7 +73,8 @@ def install_jss_completion() -> int:
70
73
  return 0
71
74
 
72
75
  with open(config_file, "a") as f:
73
- f.write(f"""
76
+ f.write(
77
+ f"""
74
78
  {start_marker}
75
79
  function fish_command_not_found
76
80
  if test (string length "$argv") -lt 10
@@ -83,13 +87,15 @@ function __fish_command_not_found_handler --on-event fish_command_not_found
83
87
  fish_command_not_found "$argv"
84
88
  end
85
89
  {end_marker}
86
- """)
90
+ """
91
+ )
87
92
  print("JSS fish completion已安装,请执行: source ~/.config/fish/config.fish")
88
93
  return 0
89
94
 
95
+
90
96
  def uninstall_jss_completion() -> int:
91
97
  """Uninstall JSS fish shell command completion
92
-
98
+
93
99
  Returns:
94
100
  int: 0 if success, 1 if failed
95
101
  """
@@ -112,10 +118,10 @@ def uninstall_jss_completion() -> int:
112
118
  return 0
113
119
 
114
120
  new_content = content.split(start_marker)[0] + content.split(end_marker)[-1]
115
-
121
+
116
122
  with open(config_file, "w") as f:
117
123
  f.write(new_content)
118
-
124
+
119
125
  print("JSS fish completion已卸载,请执行: source ~/.config/fish/config.fish")
120
126
  return 0
121
127
 
@@ -205,7 +211,7 @@ Example:
205
211
  install_parser.add_argument(
206
212
  "--shell", choices=["fish"], default="fish", help="指定shell类型(仅支持fish)"
207
213
  )
208
-
214
+
209
215
  # 添加uninstall子命令
210
216
  uninstall_parser = subparsers.add_parser(
211
217
  "uninstall", help="卸载JSS fish shell命令补全功能"
@@ -232,7 +238,7 @@ Example:
232
238
  print(f"错误: 不支持的shell类型: {args.shell}, 仅支持fish")
233
239
  return 1
234
240
  return uninstall_jss_completion()
235
-
241
+
236
242
  # 处理request命令
237
243
  if not args.request:
238
244
  # 检查是否在交互式终端中运行
@@ -34,6 +34,7 @@ class AskUserTool:
34
34
 
35
35
  # 获取agent对象并重置工具调用计数
36
36
  agent = args["agent"]
37
+ agent.set_run_input_handlers_next_turn(True)
37
38
 
38
39
  # 显示问题给用户
39
40
  PrettyOutput.print(f"问题: {question}", OutputType.SYSTEM)
@@ -14,7 +14,7 @@ from jarvis.jarvis_mcp.sse_mcp_client import SSEMcpClient
14
14
  from jarvis.jarvis_mcp.stdio_mcp_client import StdioMcpClient
15
15
  from jarvis.jarvis_mcp.streamable_mcp_client import StreamableMcpClient
16
16
  from jarvis.jarvis_tools.base import Tool
17
- from jarvis.jarvis_utils.config import get_data_dir
17
+ from jarvis.jarvis_utils.config import get_data_dir, get_tool_load_dirs
18
18
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
19
19
  from jarvis.jarvis_utils.tag import ct, ot
20
20
  from jarvis.jarvis_utils.utils import is_context_overflow
@@ -118,7 +118,7 @@ class ToolRegistry(OutputHandlerProtocol):
118
118
  return "TOOL_CALL"
119
119
 
120
120
  def can_handle(self, response: str) -> bool:
121
- return ToolRegistry._has_tool_calls_block(response)
121
+ return ot("TOOL_CALL") in response
122
122
 
123
123
  def prompt(self) -> str:
124
124
  """加载工具"""
@@ -165,11 +165,21 @@ class ToolRegistry(OutputHandlerProtocol):
165
165
  return tools_prompt
166
166
  return ""
167
167
 
168
- def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
169
- tool_call, err_msg = self._extract_tool_calls(response)
170
- if err_msg:
171
- return False, err_msg
172
- return False, self.handle_tool_calls(tool_call, agent)
168
+ def handle(self, response: str, agent_: Any) -> Tuple[bool, Any]:
169
+ try:
170
+ tool_call, err_msg = self._extract_tool_calls(response)
171
+ if err_msg:
172
+ return False, err_msg
173
+ return False, self.handle_tool_calls(tool_call, agent_)
174
+ except Exception as e:
175
+ PrettyOutput.print(f"工具调用处理失败: {str(e)}", OutputType.ERROR)
176
+ from jarvis.jarvis_agent import Agent
177
+
178
+ agent: Agent = agent_
179
+ return (
180
+ False,
181
+ f"工具调用处理失败: {str(e)}\n\n{agent.get_tool_usage_prompt()}",
182
+ )
173
183
 
174
184
  def __init__(self) -> None:
175
185
  """初始化工具注册表"""
@@ -276,18 +286,22 @@ class ToolRegistry(OutputHandlerProtocol):
276
286
  self.register_tool_by_file(str(file_path))
277
287
 
278
288
  def _load_external_tools(self) -> None:
279
- """从jarvis_data/tools加载外部工具"""
280
- external_tools_dir = Path(get_data_dir()) / "tools"
281
- if not external_tools_dir.exists():
282
- return
289
+ """从jarvis_data/tools和配置的目录加载外部工具"""
290
+ tool_dirs = [Path(get_data_dir()) / "tools"] + [
291
+ Path(p) for p in get_tool_load_dirs()
292
+ ]
283
293
 
284
- # 遍历目录中的所有.py文件
285
- for file_path in external_tools_dir.glob("*.py"):
286
- # 跳过__init__.py
287
- if file_path.name == "__init__.py":
294
+ for tool_dir in tool_dirs:
295
+ if not tool_dir.exists():
288
296
  continue
289
297
 
290
- self.register_tool_by_file(str(file_path))
298
+ # 遍历目录中的所有.py文件
299
+ for file_path in tool_dir.glob("*.py"):
300
+ # 跳过__init__.py
301
+ if file_path.name == "__init__.py":
302
+ continue
303
+
304
+ self.register_tool_by_file(str(file_path))
291
305
 
292
306
  def register_mcp_tool_by_config(self, config: Dict[str, Any]) -> bool:
293
307
  """从配置字典加载并注册工具
@@ -396,12 +410,13 @@ class ToolRegistry(OutputHandlerProtocol):
396
410
  return False
397
411
 
398
412
  # 创建MCP客户端
413
+ mcp_client: McpClient
399
414
  if config["type"] == "stdio":
400
- mcp_client: McpClient = StdioMcpClient(config)
415
+ mcp_client = StdioMcpClient(config)
401
416
  elif config["type"] == "sse":
402
- mcp_client: McpClient = SSEMcpClient(config)
417
+ mcp_client = SSEMcpClient(config)
403
418
  elif config["type"] == "streamable":
404
- mcp_client: McpClient = StreamableMcpClient(config)
419
+ mcp_client = StreamableMcpClient(config)
405
420
  else:
406
421
  raise ValueError(f"不支持的MCP客户端类型: {config['type']}")
407
422
 
@@ -549,6 +564,11 @@ class ToolRegistry(OutputHandlerProtocol):
549
564
  data = re.findall(
550
565
  ot("TOOL_CALL") + r"(.*?)" + ct("TOOL_CALL"), content, re.DOTALL
551
566
  )
567
+ if not data:
568
+ return (
569
+ {},
570
+ f"只有{ot('TOOL_CALL')}标签,未找到{ct('TOOL_CALL')}标签,调用格式错误,请检查工具调用格式。\n{tool_call_help}",
571
+ )
552
572
  ret = []
553
573
  for item in data:
554
574
  try:
@@ -3,7 +3,7 @@
3
3
  from typing import Any, Dict
4
4
 
5
5
  import httpx
6
- from bs4 import BeautifulSoup
6
+ from markdownify import markdownify as md
7
7
  from ddgs import DDGS
8
8
 
9
9
  from jarvis.jarvis_agent import Agent
@@ -27,7 +27,7 @@ class SearchWebTool:
27
27
  """Performs a web search, scrapes content, and summarizes the results."""
28
28
  try:
29
29
  PrettyOutput.print("▶️ 使用 DuckDuckGo 开始网页搜索...", OutputType.INFO)
30
- results = list(DDGS().text(query, max_results=5))
30
+ results = list(DDGS().text(query, max_results=50))
31
31
 
32
32
  if not results:
33
33
  return {
@@ -36,19 +36,29 @@ class SearchWebTool:
36
36
  "success": False,
37
37
  }
38
38
 
39
- urls = [r["href"] for r in results]
40
39
  full_content = ""
41
40
  visited_urls = []
41
+ visited_count = 0
42
+
43
+ for r in results:
44
+ if visited_count >= 10:
45
+ PrettyOutput.print("ℹ️ 已成功获取10个网页,停止抓取。", OutputType.INFO)
46
+ break
47
+
48
+ url = r["href"]
49
+ title = r.get("title", url)
42
50
 
43
- for url in urls:
44
51
  try:
45
- PrettyOutput.print(f"📄 正在抓取内容: {url}", OutputType.INFO)
52
+ PrettyOutput.print(
53
+ f"📄 ({visited_count + 1}/10) 正在抓取: {title} ({url})",
54
+ OutputType.INFO,
55
+ )
46
56
  response = http_get(url, timeout=10.0, follow_redirects=True)
47
- soup = BeautifulSoup(response.text, "lxml")
48
- body = soup.find("body")
49
- if body:
50
- full_content += body.get_text(" ", strip=True) + "\n\n"
57
+ content = md(response.text, strip=['script', 'style'])
58
+ if content:
59
+ full_content += content + "\n\n"
51
60
  visited_urls.append(url)
61
+ visited_count += 1
52
62
  except httpx.HTTPStatusError as e:
53
63
  PrettyOutput.print(
54
64
  f"⚠️ HTTP错误 {e.response.status_code} 访问 {url}",
@@ -29,7 +29,6 @@ arguments:
29
29
  """,
30
30
  "description": "网页搜索",
31
31
  },
32
-
33
32
  "FindRelatedFiles": {
34
33
  "append": False,
35
34
  "template": f"""
@@ -3,7 +3,6 @@ import os
3
3
  from functools import lru_cache
4
4
  from typing import Any, Dict, List
5
5
 
6
- import torch
7
6
  import yaml # type: ignore
8
7
 
9
8
  from jarvis.jarvis_utils.builtin_replace_map import BUILTIN_REPLACE_MAP
@@ -231,6 +230,16 @@ def is_use_analysis() -> bool:
231
230
  return GLOBAL_CONFIG_DATA.get("JARVIS_USE_ANALYSIS", True) == True
232
231
 
233
232
 
233
+ def get_tool_load_dirs() -> List[str]:
234
+ """
235
+ 获取工具加载目录。
236
+
237
+ 返回:
238
+ List[str]: 工具加载目录列表
239
+ """
240
+ return GLOBAL_CONFIG_DATA.get("JARVIS_TOOL_LOAD_DIRS", [])
241
+
242
+
234
243
  def is_print_prompt() -> bool:
235
244
  """
236
245
  获取是否打印提示。
@@ -16,7 +16,7 @@ import subprocess
16
16
  import sys
17
17
  from typing import Any, Dict, List, Set, Tuple
18
18
 
19
- from jarvis.jarvis_utils.config import is_confirm_before_apply_patch
19
+ from jarvis.jarvis_utils.config import get_data_dir, is_confirm_before_apply_patch
20
20
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
21
21
  from jarvis.jarvis_utils.input import user_confirm
22
22
 
@@ -339,25 +339,21 @@ def check_and_update_git_repo(repo_path: str) -> bool:
339
339
  返回:
340
340
  bool: 是否执行了更新
341
341
  """
342
+ # 检查上次检查日期
343
+ last_check_file = os.path.join(get_data_dir(), "last_git_check")
344
+ today_str = datetime.date.today().strftime("%Y-%m-%d")
345
+ if os.path.exists(last_check_file):
346
+ with open(last_check_file, "r") as f:
347
+ last_check_date = f.read().strip()
348
+ if last_check_date == today_str:
349
+ return False
350
+
342
351
  curr_dir = os.path.abspath(os.getcwd())
343
352
  git_root = find_git_root_and_cd(repo_path)
344
353
  if git_root is None:
345
354
  return False
346
355
 
347
356
  try:
348
- # 检查最新提交时间是否为今天
349
- commit_date_result = subprocess.run(
350
- ["git", "log", "-1", "--format=%cd", "--date=short"],
351
- cwd=git_root,
352
- capture_output=True,
353
- text=True,
354
- )
355
- if commit_date_result.returncode == 0:
356
- commit_date = commit_date_result.stdout.strip()
357
- today = datetime.date.today().strftime("%Y-%m-%d")
358
- if commit_date == today:
359
- return False
360
-
361
357
  # 检查是否有未提交的修改
362
358
  if has_uncommitted_changes():
363
359
  return False
@@ -454,6 +450,9 @@ def check_and_update_git_repo(repo_path: str) -> bool:
454
450
  f"安装过程中发生意外错误: {str(e)}", OutputType.ERROR
455
451
  )
456
452
  return False
453
+ # 更新检查日期文件
454
+ with open(last_check_file, "w") as f:
455
+ f.write(today_str)
457
456
  return False
458
457
  except Exception as e:
459
458
  PrettyOutput.print(f"Git仓库更新检查失败: {e}", OutputType.WARNING)
@@ -129,6 +129,7 @@ def load_config():
129
129
  PrettyOutput.print(
130
130
  f"已生成默认配置文件: {config_file_path}", OutputType.INFO
131
131
  )
132
+ sys.exit(0)
132
133
  except Exception as e:
133
134
  PrettyOutput.print(f"生成默认配置文件失败: {e}", OutputType.ERROR)
134
135
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.223
3
+ Version: 0.1.225
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
@@ -57,8 +57,8 @@ Requires-Dist: pyte==0.8.2
57
57
  Requires-Dist: httpx>=0.28.1
58
58
  Requires-Dist: pyyaml>=5.3.1
59
59
  Requires-Dist: ddgs==9.0.2
60
- Requires-Dist: beautifulsoup4==4.13.4
61
60
  Requires-Dist: lxml==6.0.0
61
+ Requires-Dist: markdownify>=1.1.0
62
62
  Provides-Extra: dev
63
63
  Requires-Dist: pytest; extra == "dev"
64
64
  Requires-Dist: black; extra == "dev"
@@ -158,6 +158,7 @@ jarvis --llm_type thinking -t "初始任务"
158
158
  | `-t/--task` | 直接从命令行输入任务内容 |
159
159
  | `-f/--config` | 自定义配置文件的路径 |
160
160
  | `--restore-session` | 从 .jarvis/saved_session.json 恢复会话 |
161
+ | `-e/--edit` | 编辑配置文件 |
161
162
 
162
163
  #### 4. 工作流程
163
164
  1. 初始化环境
@@ -1,9 +1,9 @@
1
- jarvis/__init__.py,sha256=YlYf-txS383hefwOHMnCEByeqa-lDVLEbMwcCc7hY3Q,75
2
- jarvis/jarvis_agent/__init__.py,sha256=l37t2lnXsPeQEwPkqrQWmqQ0ogh37GY-iAOQxkjttzY,21479
3
- jarvis/jarvis_agent/builtin_input_handler.py,sha256=MtPm7N78hPJJJ9PV_p8pkyDE7epBmtngrE9Xn-wbnH8,2682
1
+ jarvis/__init__.py,sha256=46Ob6ZTm4a9stXblcxcvfaE4NlTYqHOyTFezByeVN_Y,75
2
+ jarvis/jarvis_agent/__init__.py,sha256=mpNT4SPLYyUP3vb4zR8GM04pOej8MpnMqfkoz5ZARSQ,22412
3
+ jarvis/jarvis_agent/builtin_input_handler.py,sha256=Qs4LAr4xdKLBJpQE81YP4CkucAop86ms0iVoKa1nnso,2468
4
4
  jarvis/jarvis_agent/edit_file_handler.py,sha256=ml1o-BE2Ca1-ybPlKuhstLQYwdJag39o0_-PXTUvFaE,11646
5
- jarvis/jarvis_agent/jarvis.py,sha256=2Ilt-eLs-dCvD6V1-UGyJ3PleY0AozkYhi8Rx6_zUr4,6315
6
- jarvis/jarvis_agent/main.py,sha256=nXOw2mewhYYmj_8rohcEmETjUFqror1NiRwDusFMUKQ,3055
5
+ jarvis/jarvis_agent/jarvis.py,sha256=5Lkh2RbVqL_se8ZWcXxlh7XiJDhac8fxRtWmMHHO-q8,7803
6
+ jarvis/jarvis_agent/main.py,sha256=W23ORF8mIxZv4GTLPuR1SlrioJLT0dLeFXrYAAMSc1A,3091
7
7
  jarvis/jarvis_agent/output_handler.py,sha256=P7oWpXBGFfOsWq7cIhS_z9crkQ19ES7qU5pM92KKjAs,1172
8
8
  jarvis/jarvis_agent/prompt_builder.py,sha256=PH1fPDVa8z_RXkoXHJFNDf8PQjUoLNLYwkh2lC__p40,1705
9
9
  jarvis/jarvis_agent/prompts.py,sha256=e8i-3kaGr96mlzL3UUhQUHFDfbJSoE4xiF9TDksNDm4,7720
@@ -12,7 +12,7 @@ jarvis/jarvis_agent/session_manager.py,sha256=DnvI9rWkVmkyO1XfKZyo9lTn4ajg4ccwzE
12
12
  jarvis/jarvis_agent/shell_input_handler.py,sha256=1IboqdxcJuoIqRpmDU10GugR9fWXUHyCEbVF4nIWbyo,1328
13
13
  jarvis/jarvis_agent/tool_executor.py,sha256=nIq-sPNgrtimtM-IHpN09cWmId8jDzWRdCFoRzXnnoo,1721
14
14
  jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- jarvis/jarvis_code_agent/code_agent.py,sha256=h6wynQYZ1pPW5efU9ufY_I1di-YzRaQBOPn9IgAuxmo,18376
15
+ jarvis/jarvis_code_agent/code_agent.py,sha256=ZTvZ6tCVMv6nJBteLy39q0qtsg4OsvcIeg3ip7szVnc,18374
16
16
  jarvis/jarvis_code_agent/lint.py,sha256=LZPsfyZPMo7Wm7LN4osZocuNJwZx1ojacO3MlF870x8,4009
17
17
  jarvis/jarvis_code_analysis/code_review.py,sha256=Huia4w1SkhxfzAk2GNC75uo3a_BcVTCDbj0rx8_t0r4,30424
18
18
  jarvis/jarvis_code_analysis/checklists/__init__.py,sha256=LIXAYa1sW3l7foP6kohLWnE98I_EQ0T7z5bYKHq6rJA,78
@@ -26,7 +26,7 @@ jarvis/jarvis_code_analysis/checklists/infrastructure.py,sha256=7z5MZnOUT3FpMrTQ
26
26
  jarvis/jarvis_code_analysis/checklists/java.py,sha256=gWRVhXfsNhRFdthjIiQTkviqLwisuKCrr6gjxP0S9Z4,2085
27
27
  jarvis/jarvis_code_analysis/checklists/javascript.py,sha256=SQkw2I09DaaLxD_WTZjuHn4leUKil68IEPB03BoSYuo,2340
28
28
  jarvis/jarvis_code_analysis/checklists/kotlin.py,sha256=dNSHM1u3R7lxe8BU8ADtDyKJxmj3NUh9ZQuC7HHWHGY,4436
29
- jarvis/jarvis_code_analysis/checklists/loader.py,sha256=XYqVBOM6ouWXMfFuYPE6tMBONkuP3VKQByyB7MFUw9E,2088
29
+ jarvis/jarvis_code_analysis/checklists/loader.py,sha256=bjE4On6WMLt41bfkCZsHnBpfXF61VPthFPsgNcbH90c,1903
30
30
  jarvis/jarvis_code_analysis/checklists/php.py,sha256=qW34sF9AqLuSVuOVP5yJUHnB9V3-YRQjNPuB3lFI5UY,2481
31
31
  jarvis/jarvis_code_analysis/checklists/python.py,sha256=gjyJ0QPY1CAwqhbDnIyLYruvFduZU5hiKyehAXMHu-I,1452
32
32
  jarvis/jarvis_code_analysis/checklists/ruby.py,sha256=kzwd7Wl6gKrkAANq7_MvA5X5du5r1MeE-EY2Xb43n7U,4274
@@ -35,7 +35,7 @@ jarvis/jarvis_code_analysis/checklists/shell.py,sha256=aRFYhQQvTgbYd-uY5pc8UHIUA
35
35
  jarvis/jarvis_code_analysis/checklists/sql.py,sha256=vR0T6qC7b4dURjJVAd7kSVxyvZEQXPG1Jqc2sNTGp5c,2355
36
36
  jarvis/jarvis_code_analysis/checklists/swift.py,sha256=TPx4I6Gupvs6tSerRKmTSKEPQpOLEbH2Y7LXg1uBgxc,2566
37
37
  jarvis/jarvis_code_analysis/checklists/web.py,sha256=25gGD7pDadZQybNFvALYxWvK0VRjGQb1NVJQElwjyk0,3943
38
- jarvis/jarvis_data/config_schema.json,sha256=t51JvUc2IEe-QWP5bbocB7sqQAkmtUrPEHSHPfqzDjU,6668
38
+ jarvis/jarvis_data/config_schema.json,sha256=uuDN-25NJRnKfb6KuuqxOnfRGMphkKQbjxfu0Me6pAI,7494
39
39
  jarvis/jarvis_data/tiktoken/9b5ad71b2ce5302211f9c61530b329a4922fc6a4,sha256=Ijkht27pm96ZW3_3OFE-7xAPtR0YyTWXoRO8_-hlsqc,1681126
40
40
  jarvis/jarvis_git_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  jarvis/jarvis_git_details/main.py,sha256=DE1DcX-1lvUsb_K-FExpHs3NBRmo5KZb53PGa8QFBOc,8875
@@ -60,21 +60,21 @@ jarvis/jarvis_platform/registry.py,sha256=1bMy0YZUa8NLzuZlKfC4CBtpa0iniypTxUZk0H
60
60
  jarvis/jarvis_platform/tongyi.py,sha256=vSK1b4NhTeHbNhTgGRj4PANXptwCAwitczwK8VXwWwU,22921
61
61
  jarvis/jarvis_platform/yuanbao.py,sha256=AIGQ0VOD_IAwWLnU9G19OG0XAbHpcJDzVWX2VazsyAI,23092
62
62
  jarvis/jarvis_platform_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
- jarvis/jarvis_platform_manager/main.py,sha256=LxlXSfIfmkYNcajOG_XvvlmwlSWSGb0DmbzIDSHHYOU,18330
63
+ jarvis/jarvis_platform_manager/main.py,sha256=ysdM-_2vdOorqQiXiJOpZ50ukD5yPmakRHthK-JIl30,18558
64
64
  jarvis/jarvis_platform_manager/service.py,sha256=hQGWQ2qAlzm_C_lNQDuLORQ4rmjR1P1-V3ou7l2Bv0s,13622
65
65
  jarvis/jarvis_rag/__init__.py,sha256=HRTXgnQxDuaE9x-e3r6SYqhJ5d4DSI_rrIxy2IGY6qk,320
66
66
  jarvis/jarvis_rag/cache.py,sha256=Tqx_Oe-AhuWlMXHGHUaIuG6OEHoHBVZq7mL3kldtFFU,2723
67
- jarvis/jarvis_rag/cli.py,sha256=iR26y7ZLj4HECl3zveY4fxwn-mhMnQ__IxHQo2NAwD0,13143
67
+ jarvis/jarvis_rag/cli.py,sha256=q1W7XWZ7u7oMckqeNUX7YQoiQ3PzT3Rh-FZvTeG_U3I,13159
68
68
  jarvis/jarvis_rag/embedding_manager.py,sha256=BoV6Vr_3F4zbjBAOQ1FdEBnJXGPwBkv1IEkdRP9CgFw,3338
69
- jarvis/jarvis_rag/llm_interface.py,sha256=44Uu04v2_MxweLmMdR0YWbnxlfchAPAzLBEQmJdLjeU,4368
69
+ jarvis/jarvis_rag/llm_interface.py,sha256=eZHibNHD5dFK9yolr3hYNNhAEZUsPA-cIf1uHapI2h8,4338
70
70
  jarvis/jarvis_rag/query_rewriter.py,sha256=JM1Q23zZISze77BleRgTPgNAtLUtLAXkEo3G70kaTK8,2190
71
71
  jarvis/jarvis_rag/rag_pipeline.py,sha256=9yeNRv6qOS2zo7o0b0u3gFmiW_XSivesvPKVJ8e5DlE,6209
72
72
  jarvis/jarvis_rag/reranker.py,sha256=wYUDIMHQL8_tFcQ7GFn_zYHTE1AbKk4a9TRoN2lKtA8,1767
73
73
  jarvis/jarvis_rag/retriever.py,sha256=B6oq1SAh7QAE9G5o0sXyNtLjFodukd8p-Was2QJZXg0,7637
74
74
  jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
- jarvis/jarvis_smart_shell/main.py,sha256=DbhRSP1sZfSIaTltP1YWVDSQOTYEsbiOnfO9kSYwcNs,6959
75
+ jarvis/jarvis_smart_shell/main.py,sha256=3oAl4LbpkiJWCpxqwXF6-vmydZr5HMFKCvkQR94dzLc,6946
76
76
  jarvis/jarvis_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
- jarvis/jarvis_tools/ask_user.py,sha256=iz2PTGx66IRL8e4DOpj3XhEGHFWeKQl0ggEOl_zOwQ0,1972
77
+ jarvis/jarvis_tools/ask_user.py,sha256=M6DdLNryCE8y1JcdZHEifUgZkPUEPNKc-zDW5p0Mb1k,2029
78
78
  jarvis/jarvis_tools/base.py,sha256=tFVmK6ppsImW2BzHZmrNmMRiOJdW-4aZP6Me3VxdYcA,1194
79
79
  jarvis/jarvis_tools/edit_file.py,sha256=hM345E9rxS-EkqCZpwwizL6fmPdTadtB798tEO5Ce3g,10417
80
80
  jarvis/jarvis_tools/execute_script.py,sha256=gMarE5yCCSPU6Dp6HlcL2KT-2xCzR-1p-oQNlYOJK58,6157
@@ -83,28 +83,28 @@ jarvis/jarvis_tools/generate_new_tool.py,sha256=2YAs8DC7fJnxOkjSmhmSAwqSpBlicVhY
83
83
  jarvis/jarvis_tools/methodology.py,sha256=_K4GIDUodGEma3SvNRo7Qs5rliijgNespVLyAPN35JU,5233
84
84
  jarvis/jarvis_tools/read_code.py,sha256=EnI-R-5HyIQYhMD391nZWXHIuHHBF-OJIRE0QpLcPX4,6417
85
85
  jarvis/jarvis_tools/read_webpage.py,sha256=NmDUboVZd4CGHBPRFK6dp3uqVhuGopW1bOi3TcaLDF4,2092
86
- jarvis/jarvis_tools/registry.py,sha256=0SdgBi-b1qnd3QX0VvQy7UVU7Pq9BZGYLiAe7t0DjpQ,25690
86
+ jarvis/jarvis_tools/registry.py,sha256=Lfp6UcEw-Gbva-7OUTHOBrT9xYwrGrolvjaSpYhWFwU,26435
87
87
  jarvis/jarvis_tools/rewrite_file.py,sha256=eG_WKg6cVAXmuGwUqlWkcuyay5S8DOzEi8vZCmX3O8w,7255
88
- jarvis/jarvis_tools/search_web.py,sha256=DqBwNGFK3vZleZ7_4Go3q27DzPCp4m0ZeEi1N7UEFc4,5363
88
+ jarvis/jarvis_tools/search_web.py,sha256=DDAPjYWTFaF85zsnhJ6VNDSc1BcY8EHus5ymKP9nnPs,5703
89
89
  jarvis/jarvis_tools/virtual_tty.py,sha256=KKr3jpvQWWMPr2o40hlmN6fuXJCN8H4_ma5QU40Citc,16089
90
90
  jarvis/jarvis_tools/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
91
  jarvis/jarvis_tools/cli/main.py,sha256=Mg6TQDxMdzB1Ua1UrZ2EE-uQWsbaeojWaEGHJp2HimA,6375
92
92
  jarvis/jarvis_utils/__init__.py,sha256=67h0ldisGlh3oK4DAeNEL2Bl_VsI3tSmfclasyVlueM,850
93
- jarvis/jarvis_utils/builtin_replace_map.py,sha256=EI8JnHqr-ZpAhpwocTu48DhHUMHNd8tNUpDNYI47OLE,1717
94
- jarvis/jarvis_utils/config.py,sha256=E8GhbpbdGyrAxTC89wN7KGE2rJ9zwhmL-HMIgTl9q18,8051
93
+ jarvis/jarvis_utils/builtin_replace_map.py,sha256=4BurljGuiG_I93EBs7mlFlPm9wYC_4CmdTG5tQWpF6g,1712
94
+ jarvis/jarvis_utils/config.py,sha256=eTarDAeBdFZx2jX4KQrzanEu4W6hpS5Cw1DHmiB5nN0,8247
95
95
  jarvis/jarvis_utils/embedding.py,sha256=oEOEM2qf16DMYwPsQe6srET9BknyjOdY2ef0jsp3Or8,2714
96
96
  jarvis/jarvis_utils/file_processors.py,sha256=XiM248SHS7lLgQDCbORVFWqinbVDUawYxWDOsLXDxP8,3043
97
- jarvis/jarvis_utils/git_utils.py,sha256=4mNbEgV0icMnB1UL1RWhE9Nxik3mwam2qcGMpd1ODJM,21707
97
+ jarvis/jarvis_utils/git_utils.py,sha256=EpyS8AvvK9M9WnkObtQsU2gXq45PnY-WJo2c4kMtyFM,21702
98
98
  jarvis/jarvis_utils/globals.py,sha256=WzZh_acNfHJj1LDulhyLQ7cojksBy0gdrITe0vH1XA0,3901
99
99
  jarvis/jarvis_utils/http.py,sha256=Uqt1kcz0HWnAfXHHi1fNGwLb2lcVUqpbrG2Uk_-kcIU,4882
100
100
  jarvis/jarvis_utils/input.py,sha256=V2w3xV0MO73c4Y4XY_yy9jVNg7MmN76FmAnpKRiJUog,9160
101
101
  jarvis/jarvis_utils/methodology.py,sha256=-cvM6pwgJK7BXCYg2uVjIId_j3v5RUh2z2PBcK_2vj4,8155
102
102
  jarvis/jarvis_utils/output.py,sha256=PRCgudPOB8gMEP3u-g0FGD2c6tBgJhLXUMqNPglfjV8,10813
103
103
  jarvis/jarvis_utils/tag.py,sha256=f211opbbbTcSyzCDwuIK_oCnKhXPNK-RknYyGzY1yD0,431
104
- jarvis/jarvis_utils/utils.py,sha256=ojupkZQfFIE6ysTyCy0jUdePucpwpvZlZJSXkGsdyQE,15263
105
- jarvis_ai_assistant-0.1.223.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
106
- jarvis_ai_assistant-0.1.223.dist-info/METADATA,sha256=Fn58Cq6CpCpo9MjyYGrSWjI9Y2M90LA6VW9IjOu2tOE,24061
107
- jarvis_ai_assistant-0.1.223.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
108
- jarvis_ai_assistant-0.1.223.dist-info/entry_points.txt,sha256=JXK_n-d9HZ_RLz959CvpK5-UPOCwssn5oAH8dAHuebA,1277
109
- jarvis_ai_assistant-0.1.223.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
110
- jarvis_ai_assistant-0.1.223.dist-info/RECORD,,
104
+ jarvis/jarvis_utils/utils.py,sha256=OXZ57qTB3dY5e_V6lWZRivYu1cMT1e2VftW7AQBd2X0,15295
105
+ jarvis_ai_assistant-0.1.225.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
106
+ jarvis_ai_assistant-0.1.225.dist-info/METADATA,sha256=s60vmDTdhXx9eGKHz22DIMFUqjqZF_G-r9PwzApQJr4,24094
107
+ jarvis_ai_assistant-0.1.225.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
108
+ jarvis_ai_assistant-0.1.225.dist-info/entry_points.txt,sha256=JXK_n-d9HZ_RLz959CvpK5-UPOCwssn5oAH8dAHuebA,1277
109
+ jarvis_ai_assistant-0.1.225.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
110
+ jarvis_ai_assistant-0.1.225.dist-info/RECORD,,