jarvis-ai-assistant 0.1.217__tar.gz → 0.1.219__tar.gz

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.
Files changed (104) hide show
  1. {jarvis_ai_assistant-0.1.217/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.219}/PKG-INFO +4 -1
  2. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/pyproject.toml +4 -1
  3. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/setup.py +5 -2
  4. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/__init__.py +1 -1
  5. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_agent/__init__.py +1 -3
  6. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_agent/shell_input_handler.py +1 -1
  7. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_agent/code_agent.py +10 -5
  8. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_git_squash/main.py +2 -1
  9. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform/human.py +2 -7
  10. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/edit_file.py +6 -6
  11. jarvis_ai_assistant-0.1.219/src/jarvis/jarvis_tools/search_web.py +145 -0
  12. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/git_utils.py +27 -18
  13. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/input.py +23 -9
  14. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/utils.py +43 -20
  15. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219/src/jarvis_ai_assistant.egg-info}/PKG-INFO +4 -1
  16. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis_ai_assistant.egg-info/requires.txt +3 -0
  17. jarvis_ai_assistant-0.1.217/src/jarvis/jarvis_tools/search_web.py +0 -29
  18. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/LICENSE +0 -0
  19. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/MANIFEST.in +0 -0
  20. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/README.md +0 -0
  21. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/setup.cfg +0 -0
  22. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_agent/builtin_input_handler.py +0 -0
  23. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_agent/edit_file_handler.py +0 -0
  24. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_agent/jarvis.py +0 -0
  25. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_agent/main.py +0 -0
  26. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_agent/output_handler.py +0 -0
  27. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_agent/__init__.py +0 -0
  28. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_agent/lint.py +0 -0
  29. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/__init__.py +0 -0
  30. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/c_cpp.py +0 -0
  31. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/csharp.py +0 -0
  32. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/data_format.py +0 -0
  33. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/devops.py +0 -0
  34. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/docs.py +0 -0
  35. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/go.py +0 -0
  36. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/infrastructure.py +0 -0
  37. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/java.py +0 -0
  38. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/javascript.py +0 -0
  39. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/kotlin.py +0 -0
  40. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/loader.py +0 -0
  41. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/php.py +0 -0
  42. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/python.py +0 -0
  43. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/ruby.py +0 -0
  44. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/rust.py +0 -0
  45. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/shell.py +0 -0
  46. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/sql.py +0 -0
  47. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/swift.py +0 -0
  48. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/checklists/web.py +0 -0
  49. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_code_analysis/code_review.py +0 -0
  50. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_data/config_schema.json +0 -0
  51. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_data/tiktoken/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
  52. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_git_details/__init__.py +0 -0
  53. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_git_details/main.py +0 -0
  54. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_git_squash/__init__.py +0 -0
  55. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_git_utils/git_commiter.py +0 -0
  56. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_mcp/__init__.py +0 -0
  57. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_mcp/sse_mcp_client.py +0 -0
  58. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_mcp/stdio_mcp_client.py +0 -0
  59. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_mcp/streamable_mcp_client.py +0 -0
  60. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_methodology/main.py +0 -0
  61. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_multi_agent/__init__.py +0 -0
  62. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_multi_agent/main.py +0 -0
  63. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform/__init__.py +0 -0
  64. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform/ai8.py +0 -0
  65. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform/base.py +0 -0
  66. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform/kimi.py +0 -0
  67. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform/openai.py +0 -0
  68. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform/oyi.py +0 -0
  69. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform/registry.py +0 -0
  70. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform/tongyi.py +0 -0
  71. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform/yuanbao.py +0 -0
  72. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform_manager/__init__.py +0 -0
  73. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform_manager/main.py +0 -0
  74. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_platform_manager/service.py +0 -0
  75. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
  76. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_smart_shell/main.py +0 -0
  77. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/__init__.py +0 -0
  78. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/ask_user.py +0 -0
  79. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/base.py +0 -0
  80. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/cli/__init__.py +0 -0
  81. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/cli/main.py +0 -0
  82. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/execute_script.py +0 -0
  83. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/file_analyzer.py +0 -0
  84. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/generate_new_tool.py +0 -0
  85. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/methodology.py +0 -0
  86. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/read_code.py +0 -0
  87. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/read_webpage.py +0 -0
  88. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/registry.py +0 -0
  89. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/rewrite_file.py +0 -0
  90. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_tools/virtual_tty.py +0 -0
  91. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/__init__.py +0 -0
  92. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/builtin_replace_map.py +0 -0
  93. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/config.py +0 -0
  94. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/embedding.py +0 -0
  95. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/file_processors.py +0 -0
  96. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/globals.py +0 -0
  97. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/http.py +0 -0
  98. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/methodology.py +0 -0
  99. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/output.py +0 -0
  100. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis/jarvis_utils/tag.py +0 -0
  101. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +0 -0
  102. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
  103. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis_ai_assistant.egg-info/entry_points.txt +0 -0
  104. {jarvis_ai_assistant-0.1.217 → jarvis_ai_assistant-0.1.219}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.217
3
+ Version: 0.1.219
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
@@ -56,6 +56,9 @@ Requires-Dist: tabulate==0.9.0
56
56
  Requires-Dist: pyte==0.8.2
57
57
  Requires-Dist: httpx>=0.28.1
58
58
  Requires-Dist: pyyaml>=5.3.1
59
+ Requires-Dist: ddgs==6.1.8
60
+ Requires-Dist: beautifulsoup4==4.12.3
61
+ Requires-Dist: lxml==5.2.2
59
62
  Provides-Extra: dev
60
63
  Requires-Dist: pytest; extra == "dev"
61
64
  Requires-Dist: black; extra == "dev"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jarvis-ai-assistant"
7
- version = "0.1.217"
7
+ version = "0.1.219"
8
8
  description = "Jarvis: An AI assistant that uses tools to interact with the system"
9
9
  readme = "README.md"
10
10
  authors = [{ name = "skyfire", email = "skyfireitdiy@hotmail.com" }]
@@ -38,6 +38,9 @@ dependencies = [
38
38
  "pyte==0.8.2",
39
39
  "httpx>=0.28.1",
40
40
  "pyyaml>=5.3.1",
41
+ "ddgs==6.1.8",
42
+ "beautifulsoup4==4.12.3",
43
+ "lxml==5.2.2",
41
44
  ]
42
45
  requires-python = ">=3.8"
43
46
 
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages # type: ignore
3
3
 
4
4
  setup(
5
5
  name="jarvis-ai-assistant",
6
- version="0.1.217",
6
+ version="0.1.219",
7
7
  author="skyfire",
8
8
  author_email="skyfireitdiy@hotmail.com",
9
9
  description="An AI assistant that uses various tools to interact with the system",
@@ -31,8 +31,11 @@ setup(
31
31
  "openai==1.78.1",
32
32
  "tabulate==0.9.0",
33
33
  "pyte==0.8.2",
34
- "pyyaml>=5.3.1",
35
34
  "httpx>=0.28.1",
35
+ "pyyaml>=5.3.1",
36
+ "ddgs==6.1.8",
37
+ "beautifulsoup4==4.12.3",
38
+ "lxml==5.2.2",
36
39
  ],
37
40
  extras_require={"dev": ["pytest", "black",
38
41
  "isort", "mypy", "build", "twine"]},
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Jarvis AI Assistant"""
3
3
 
4
- __version__ = "0.1.217"
4
+ __version__ = "0.1.219"
@@ -2,7 +2,6 @@
2
2
  # 标准库导入
3
3
  import datetime
4
4
  import os
5
- from pathlib import Path
6
5
  import platform
7
6
  from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
8
7
 
@@ -29,11 +28,10 @@ from jarvis.jarvis_utils.globals import (
29
28
  set_agent,
30
29
  set_interrupt,
31
30
  )
32
- from jarvis.jarvis_utils.input import get_multiline_input
31
+ from jarvis.jarvis_utils.input import get_multiline_input, user_confirm
33
32
  from jarvis.jarvis_utils.methodology import load_methodology, upload_methodology
34
33
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
35
34
  from jarvis.jarvis_utils.tag import ct, ot
36
- from jarvis.jarvis_utils.utils import user_confirm
37
35
 
38
36
  origin_agent_system_prompt = f"""
39
37
  <role>
@@ -2,7 +2,7 @@
2
2
  from typing import Any, Tuple
3
3
 
4
4
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
5
- from jarvis.jarvis_utils.utils import user_confirm
5
+ from jarvis.jarvis_utils.input import user_confirm
6
6
 
7
7
 
8
8
  def shell_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
@@ -30,9 +30,9 @@ from jarvis.jarvis_utils.git_utils import (
30
30
  handle_commit_workflow,
31
31
  has_uncommitted_changes,
32
32
  )
33
- from jarvis.jarvis_utils.input import get_multiline_input
33
+ from jarvis.jarvis_utils.input import get_multiline_input, user_confirm
34
34
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
35
- from jarvis.jarvis_utils.utils import get_loc_stats, init_env, user_confirm
35
+ from jarvis.jarvis_utils.utils import get_loc_stats, init_env
36
36
 
37
37
 
38
38
  class CodeAgent:
@@ -359,7 +359,9 @@ class CodeAgent:
359
359
 
360
360
  # 添加提交信息到final_ret
361
361
  if commits:
362
- final_ret += f"\n\n代码已修改完成\n补丁内容:\n```diff\n{diff}\n```\n"
362
+ final_ret += (
363
+ f"\n\n代码已修改完成\n补丁内容:\n```diff\n{diff}\n```\n"
364
+ )
363
365
  # 修改后的提示逻辑
364
366
  lint_tools_info = "\n".join(
365
367
  f" - {file}: 使用 {'、'.join(get_lint_tools(file))}"
@@ -378,7 +380,7 @@ class CodeAgent:
378
380
  {file_list}
379
381
  {tool_info}
380
382
  如果本次修改引入了警告和错误,请根据警告和错误信息修复代码
381
- 注意:如果要进行静态检查,需要在所有的修改都完成之后进行集中检查
383
+ 注意:如果要进行静态检查,需要在所有的修改都完成之后进行集中检查,如果文件有多个检查工具,尽量一次全部调用,不要分多次调用
382
384
  """
383
385
  agent.set_addon_prompt(addon_prompt)
384
386
  else:
@@ -420,7 +422,10 @@ def main() -> None:
420
422
  "-r", "--requirement", type=str, help="Requirement to process", default=None
421
423
  )
422
424
  parser.add_argument(
423
- "--restore-session", action="store_true", help="Restore session from .jarvis/saved_session.json", default=False
425
+ "--restore-session",
426
+ action="store_true",
427
+ help="Restore session from .jarvis/saved_session.json",
428
+ default=False,
424
429
  )
425
430
  args = parser.parse_args()
426
431
 
@@ -6,7 +6,8 @@ from typing import Dict
6
6
 
7
7
  from jarvis.jarvis_git_utils.git_commiter import GitCommitTool
8
8
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
- from jarvis.jarvis_utils.utils import init_env, user_confirm
9
+ from jarvis.jarvis_utils.utils import init_env
10
+ from jarvis.jarvis_utils.input import user_confirm
10
11
 
11
12
 
12
13
  class GitSquashTool:
@@ -12,6 +12,7 @@ from typing import Generator, List, Tuple
12
12
  from jarvis.jarvis_platform.base import BasePlatform
13
13
  from jarvis.jarvis_utils.input import get_multiline_input
14
14
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
15
+ from jarvis.jarvis_utils.utils import copy_to_clipboard
15
16
 
16
17
 
17
18
  class HumanPlatform(BasePlatform):
@@ -57,13 +58,7 @@ class HumanPlatform(BasePlatform):
57
58
  prompt = f"{message} {session_info}"
58
59
 
59
60
  # 将prompt复制到剪贴板
60
- import subprocess
61
-
62
- try:
63
- subprocess.run(["xsel", "-ib"], input=prompt.encode("utf-8"), check=True)
64
- PrettyOutput.print("提示已复制到剪贴板", OutputType.INFO)
65
- except subprocess.CalledProcessError as e:
66
- PrettyOutput.print(f"无法复制到剪贴板: {e}", OutputType.WARNING)
61
+ copy_to_clipboard(prompt)
67
62
 
68
63
  response = get_multiline_input(prompt + "\n\n请回复:")
69
64
  yield response
@@ -32,8 +32,8 @@ class FileSearchReplaceTool:
32
32
  1. 指定需要修改的文件路径(单个或多个)
33
33
  2. 提供一组或多组修改,每个修改包含:
34
34
  - reason: 修改原因描述
35
- - search: 需要查找的原始代码(必须包含足够上下文)
36
- - replace: 替换后的新代码
35
+ - SEARCH: 需要查找的原始代码(必须包含足够上下文)
36
+ - REPLACE: 替换后的新代码
37
37
  3. 工具会自动选择最适合的编辑模式
38
38
 
39
39
  ## 核心原则
@@ -64,11 +64,11 @@ class FileSearchReplaceTool:
64
64
  "type": "string",
65
65
  "description": "修改的原因",
66
66
  },
67
- "search": {
67
+ "SEARCH": {
68
68
  "type": "string",
69
69
  "description": "需要查找的原始代码",
70
70
  },
71
- "replace": {
71
+ "REPLACE": {
72
72
  "type": "string",
73
73
  "description": "替换后的新代码",
74
74
  },
@@ -99,8 +99,8 @@ class FileSearchReplaceTool:
99
99
  - path: 要修改的文件路径
100
100
  - changes: 修改列表,每个修改包含:
101
101
  - reason: 修改原因描述
102
- - search: 需要查找的原始代码(必须包含足够上下文)
103
- - replace: 替换后的新代码
102
+ - SEARCH: 需要查找的原始代码(必须包含足够上下文)
103
+ - REPLACE: 替换后的新代码
104
104
 
105
105
  返回:
106
106
  Dict[str, Any] 包含:
@@ -0,0 +1,145 @@
1
+ # -*- coding: utf-8 -*-
2
+ """A tool for searching the web."""
3
+ from typing import Any, Dict
4
+
5
+ import httpx
6
+ from bs4 import BeautifulSoup
7
+ from ddgs import DDGS
8
+
9
+ from jarvis.jarvis_agent import Agent
10
+ from jarvis.jarvis_platform.registry import PlatformRegistry
11
+ from jarvis.jarvis_utils.http import get as http_get
12
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
13
+
14
+
15
+ class SearchWebTool:
16
+ """A class to handle web searches."""
17
+
18
+ name = "search_web"
19
+ description = "搜索互联网上的信息"
20
+ parameters = {
21
+ "type": "object",
22
+ "properties": {"query": {"type": "string", "description": "具体的问题"}},
23
+ }
24
+
25
+ def _search_with_ddgs(self, query: str, agent: Agent) -> Dict[str, Any]:
26
+ # pylint: disable=too-many-locals, broad-except
27
+ """Performs a web search, scrapes content, and summarizes the results."""
28
+ try:
29
+ PrettyOutput.print("▶️ 使用 DuckDuckGo 开始网页搜索...", OutputType.INFO)
30
+ results = list(DDGS().text(query, max_results=5))
31
+
32
+ if not results:
33
+ return {
34
+ "stdout": "未找到搜索结果。",
35
+ "stderr": "未找到搜索结果。",
36
+ "success": False,
37
+ }
38
+
39
+ urls = [r["href"] for r in results]
40
+ full_content = ""
41
+ visited_urls = []
42
+
43
+ for url in urls:
44
+ try:
45
+ PrettyOutput.print(f"📄 正在抓取内容: {url}", OutputType.INFO)
46
+ 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"
51
+ visited_urls.append(url)
52
+ except httpx.HTTPStatusError as e:
53
+ PrettyOutput.print(
54
+ f"⚠️ HTTP错误 {e.response.status_code} 访问 {url}",
55
+ OutputType.WARNING,
56
+ )
57
+ except httpx.RequestError as e:
58
+ PrettyOutput.print(f"⚠️ 请求错误: {e}", OutputType.WARNING)
59
+
60
+ if not full_content.strip():
61
+ return {
62
+ "stdout": "无法从任何URL抓取有效内容。",
63
+ "stderr": "抓取内容失败。",
64
+ "success": False,
65
+ }
66
+
67
+ url_list_str = "\n".join(f" - {u}" for u in visited_urls)
68
+ PrettyOutput.print(
69
+ f"🔍 已成功访问并处理以下URL:\n{url_list_str}", OutputType.INFO
70
+ )
71
+
72
+ PrettyOutput.print("🧠 正在总结内容...", OutputType.INFO)
73
+ summary_prompt = f"请为查询“{query}”总结以下内容:\n\n{full_content}"
74
+
75
+ if not agent.model:
76
+ return {
77
+ "stdout": "",
78
+ "stderr": "用于总结的Agent模型未找到。",
79
+ "success": False,
80
+ }
81
+
82
+ platform_name = agent.model.platform_name()
83
+ model_name = agent.model.name()
84
+
85
+ model = PlatformRegistry().create_platform(platform_name)
86
+ if not model:
87
+ return {
88
+ "stdout": "",
89
+ "stderr": "无法创建用于总结的模型。",
90
+ "success": False,
91
+ }
92
+
93
+ model.set_model_name(model_name)
94
+ model.set_suppress_output(False)
95
+ summary = model.chat_until_success(summary_prompt)
96
+
97
+ return {"stdout": summary, "stderr": "", "success": True}
98
+
99
+ except Exception as e:
100
+ PrettyOutput.print(f"❌ 网页搜索过程中发生错误: {e}", OutputType.ERROR)
101
+ return {
102
+ "stdout": "",
103
+ "stderr": f"网页搜索过程中发生错误: {e}",
104
+ "success": False,
105
+ }
106
+
107
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
108
+ """
109
+ Executes the web search.
110
+
111
+ If the agent's model supports a native web search, it uses it.
112
+ Otherwise, it falls back to using DuckDuckGo Search and scraping pages.
113
+ """
114
+ query = args.get("query")
115
+ agent = args.get("agent")
116
+
117
+ if not query:
118
+ return {"stdout": "", "stderr": "缺少查询参数。", "success": False}
119
+
120
+ if not isinstance(agent, Agent) or not agent.model:
121
+ return {
122
+ "stdout": "",
123
+ "stderr": "Agent或Agent模型未找到。",
124
+ "success": False,
125
+ }
126
+
127
+ if agent.model.support_web():
128
+ model = PlatformRegistry().create_platform(agent.model.platform_name())
129
+ if not model:
130
+ return {"stdout": "", "stderr": "无法创建模型。", "success": False}
131
+ model.set_model_name(agent.model.name())
132
+ model.set_web(True)
133
+ model.set_suppress_output(False)
134
+ return {
135
+ "stdout": model.chat_until_success(query),
136
+ "stderr": "",
137
+ "success": True,
138
+ }
139
+
140
+ return self._search_with_ddgs(query, agent)
141
+
142
+ @staticmethod
143
+ def check() -> bool:
144
+ """Check if the tool is available."""
145
+ return True
@@ -18,7 +18,7 @@ from typing import Any, Dict, List, Set, Tuple
18
18
 
19
19
  from jarvis.jarvis_utils.config import is_confirm_before_apply_patch
20
20
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
21
- from jarvis.jarvis_utils.utils import user_confirm
21
+ from jarvis.jarvis_utils.input import user_confirm
22
22
 
23
23
 
24
24
  def find_git_root_and_cd(start_dir: str = ".") -> str:
@@ -408,48 +408,51 @@ def check_and_update_git_repo(repo_path: str) -> bool:
408
408
  f"Jarvis已更新到tag {remote_tag_result.stdout.strip()}",
409
409
  OutputType.SUCCESS,
410
410
  )
411
-
411
+
412
412
  # 执行pip安装更新代码
413
413
  try:
414
414
  PrettyOutput.print("正在安装更新后的代码...", OutputType.INFO)
415
-
415
+
416
416
  # 检查是否在虚拟环境中
417
- in_venv = hasattr(sys, 'real_prefix') or (
418
- hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix
417
+ in_venv = hasattr(sys, "real_prefix") or (
418
+ hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix
419
419
  )
420
-
420
+
421
421
  # 尝试普通安装
422
422
  install_cmd = [sys.executable, "-m", "pip", "install", "-e", "."]
423
423
  result = subprocess.run(
424
- install_cmd,
425
- cwd=git_root,
426
- capture_output=True,
427
- text=True
424
+ install_cmd, cwd=git_root, capture_output=True, text=True
428
425
  )
429
-
426
+
430
427
  if result.returncode == 0:
431
428
  PrettyOutput.print("代码更新安装成功", OutputType.SUCCESS)
432
429
  return True
433
-
430
+
434
431
  # 处理权限错误
435
432
  error_msg = result.stderr.strip()
436
- if not in_venv and ("Permission denied" in error_msg or "not writeable" in error_msg):
437
- if user_confirm("检测到权限问题,是否尝试用户级安装(--user)?", True):
433
+ if not in_venv and (
434
+ "Permission denied" in error_msg or "not writeable" in error_msg
435
+ ):
436
+ if user_confirm(
437
+ "检测到权限问题,是否尝试用户级安装(--user)?", True
438
+ ):
438
439
  user_result = subprocess.run(
439
440
  install_cmd + ["--user"],
440
441
  cwd=git_root,
441
442
  capture_output=True,
442
- text=True
443
+ text=True,
443
444
  )
444
445
  if user_result.returncode == 0:
445
446
  PrettyOutput.print("用户级代码安装成功", OutputType.SUCCESS)
446
447
  return True
447
448
  error_msg = user_result.stderr.strip()
448
-
449
+
449
450
  PrettyOutput.print(f"代码安装失败: {error_msg}", OutputType.ERROR)
450
451
  return False
451
452
  except Exception as e:
452
- PrettyOutput.print(f"安装过程中发生意外错误: {str(e)}", OutputType.ERROR)
453
+ PrettyOutput.print(
454
+ f"安装过程中发生意外错误: {str(e)}", OutputType.ERROR
455
+ )
453
456
  return False
454
457
  return False
455
458
  except Exception as e:
@@ -522,7 +525,13 @@ def get_recent_commits_with_files() -> List[Dict[str, Any]]:
522
525
 
523
526
  # 获取当前用户最近5次提交的基本信息
524
527
  result = subprocess.run(
525
- ["git", "log", "-5", "--author=" + current_author, "--pretty=format:%H%n%s%n%an%n%ad"],
528
+ [
529
+ "git",
530
+ "log",
531
+ "-5",
532
+ "--author=" + current_author,
533
+ "--pretty=format:%H%n%s%n%an%n%ad",
534
+ ],
526
535
  capture_output=True,
527
536
  text=True,
528
537
  )
@@ -26,6 +26,7 @@ from prompt_toolkit.styles import Style as PromptStyle # type: ignore
26
26
  from jarvis.jarvis_utils.config import get_replace_map
27
27
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
28
28
  from jarvis.jarvis_utils.tag import ot
29
+ from jarvis.jarvis_utils.utils import copy_to_clipboard
29
30
 
30
31
 
31
32
  def get_single_line_input(tip: str) -> str:
@@ -179,6 +180,24 @@ class FileCompleter(Completer):
179
180
  return tag
180
181
 
181
182
 
183
+ def user_confirm(tip: str, default: bool = True) -> bool:
184
+ """提示用户确认是/否问题
185
+
186
+ 参数:
187
+ tip: 显示给用户的消息
188
+ default: 用户直接回车时的默认响应
189
+
190
+ 返回:
191
+ bool: 用户确认返回True,否则返回False
192
+ """
193
+ try:
194
+ suffix = "[Y/n]" if default else "[y/N]"
195
+ ret = get_single_line_input(f"{tip} {suffix}: ")
196
+ return default if ret == "" else ret.lower() == "y"
197
+ except KeyboardInterrupt:
198
+ return False
199
+
200
+
182
201
  def get_multiline_input(tip: str) -> str:
183
202
  """
184
203
  获取带有增强补全和确认功能的多行输入。
@@ -217,21 +236,16 @@ def get_multiline_input(tip: str) -> str:
217
236
  def _(event):
218
237
  """处理Ctrl+O以复制最后一条消息到剪贴板。"""
219
238
  from jarvis.jarvis_utils.globals import get_last_message
220
- import subprocess
221
239
 
222
240
  last_msg = get_last_message()
223
241
  if last_msg:
224
- try:
225
- # 使用xsel将内容复制到剪贴板
226
- subprocess.run(
227
- ["xsel", "-b", "-i"], input=last_msg.encode("utf-8"), check=True
228
- )
229
- PrettyOutput.print("已将最后一条消息复制到剪贴板", OutputType.INFO)
230
- except subprocess.CalledProcessError as e:
231
- PrettyOutput.print(f"复制到剪贴板失败: {e}", OutputType.ERROR)
242
+ print(f"{last_msg}")
243
+ copy_to_clipboard(last_msg)
232
244
  else:
233
245
  PrettyOutput.print("没有可复制的消息", OutputType.INFO)
234
246
 
247
+ event.app.invalidate()
248
+
235
249
  # 配置提示会话
236
250
  style = PromptStyle.from_dict(
237
251
  {
@@ -5,7 +5,6 @@ import os
5
5
  import signal
6
6
  import subprocess
7
7
  import sys
8
- import tarfile
9
8
  import time
10
9
  from pathlib import Path
11
10
  from typing import Any, Callable, Dict, Optional
@@ -20,7 +19,6 @@ from jarvis.jarvis_utils.config import (
20
19
  )
21
20
  from jarvis.jarvis_utils.embedding import get_context_token_count
22
21
  from jarvis.jarvis_utils.globals import get_in_chat, get_interrupt, set_interrupt
23
- from jarvis.jarvis_utils.input import get_single_line_input
24
22
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
25
23
 
26
24
  g_config_file = None
@@ -371,24 +369,6 @@ def get_file_md5(filepath: str) -> str:
371
369
  return hashlib.md5(open(filepath, "rb").read(100 * 1024 * 1024)).hexdigest()
372
370
 
373
371
 
374
- def user_confirm(tip: str, default: bool = True) -> bool:
375
- """提示用户确认是/否问题
376
-
377
- 参数:
378
- tip: 显示给用户的消息
379
- default: 用户直接回车时的默认响应
380
-
381
- 返回:
382
- bool: 用户确认返回True,否则返回False
383
- """
384
- try:
385
- suffix = "[Y/n]" if default else "[y/N]"
386
- ret = get_single_line_input(f"{tip} {suffix}: ")
387
- return default if ret == "" else ret.lower() == "y"
388
- except KeyboardInterrupt:
389
- return False
390
-
391
-
392
372
  def get_file_line_count(filename: str) -> int:
393
373
  """计算文件中的行数
394
374
 
@@ -451,3 +431,46 @@ def get_loc_stats() -> str:
451
431
  return result.stdout if result.returncode == 0 else ""
452
432
  except FileNotFoundError:
453
433
  return ""
434
+
435
+
436
+ def copy_to_clipboard(text: str) -> None:
437
+ """将文本复制到剪贴板,依次尝试xsel和xclip (非阻塞)
438
+
439
+ 参数:
440
+ text: 要复制的文本
441
+ """
442
+ # 尝试使用 xsel
443
+ try:
444
+ process = subprocess.Popen(
445
+ ["xsel", "-b", "-i"],
446
+ stdin=subprocess.PIPE,
447
+ stdout=subprocess.DEVNULL,
448
+ stderr=subprocess.DEVNULL,
449
+ )
450
+ if process.stdin:
451
+ process.stdin.write(text.encode("utf-8"))
452
+ process.stdin.close()
453
+ return
454
+ except FileNotFoundError:
455
+ pass # xsel 未安装,继续尝试下一个
456
+ except Exception as e:
457
+ PrettyOutput.print(f"使用xsel时出错: {e}", OutputType.WARNING)
458
+
459
+ # 尝试使用 xclip
460
+ try:
461
+ process = subprocess.Popen(
462
+ ["xclip", "-selection", "clipboard"],
463
+ stdin=subprocess.PIPE,
464
+ stdout=subprocess.DEVNULL,
465
+ stderr=subprocess.DEVNULL,
466
+ )
467
+ if process.stdin:
468
+ process.stdin.write(text.encode("utf-8"))
469
+ process.stdin.close()
470
+ return
471
+ except FileNotFoundError:
472
+ PrettyOutput.print(
473
+ "xsel 和 xclip 均未安装, 无法复制到剪贴板", OutputType.WARNING
474
+ )
475
+ except Exception as e:
476
+ PrettyOutput.print(f"使用xclip时出错: {e}", OutputType.WARNING)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.217
3
+ Version: 0.1.219
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
@@ -56,6 +56,9 @@ Requires-Dist: tabulate==0.9.0
56
56
  Requires-Dist: pyte==0.8.2
57
57
  Requires-Dist: httpx>=0.28.1
58
58
  Requires-Dist: pyyaml>=5.3.1
59
+ Requires-Dist: ddgs==6.1.8
60
+ Requires-Dist: beautifulsoup4==4.12.3
61
+ Requires-Dist: lxml==5.2.2
59
62
  Provides-Extra: dev
60
63
  Requires-Dist: pytest; extra == "dev"
61
64
  Requires-Dist: black; extra == "dev"
@@ -14,6 +14,9 @@ tabulate==0.9.0
14
14
  pyte==0.8.2
15
15
  httpx>=0.28.1
16
16
  pyyaml>=5.3.1
17
+ ddgs==6.1.8
18
+ beautifulsoup4==4.12.3
19
+ lxml==5.2.2
17
20
 
18
21
  [dev]
19
22
  pytest
@@ -1,29 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- from typing import Any, Dict
3
-
4
- from jarvis.jarvis_platform.registry import PlatformRegistry
5
-
6
-
7
- class SearchWebTool:
8
- name = "search_web"
9
- description = "搜索互联网上的信息"
10
- parameters = {
11
- "type": "object",
12
- "properties": {"query": {"type": "string", "description": "具体的问题"}},
13
- }
14
-
15
- def execute(self, args: Dict[str, Any]) -> Dict[str, Any]: # type: ignore
16
- query = args.get("query")
17
- model = PlatformRegistry().get_normal_platform()
18
- model.set_web(True)
19
- model.set_suppress_output(False) # type: ignore
20
- return {
21
- "stdout": model.chat_until_success(query), # type: ignore
22
- "stderr": "",
23
- "success": True,
24
- }
25
-
26
- @staticmethod
27
- def check() -> bool:
28
- """检查当前平台是否支持web功能"""
29
- return PlatformRegistry().get_normal_platform().support_web()