jarvis-ai-assistant 0.1.217__py3-none-any.whl → 0.1.219__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 +1 -1
- jarvis/jarvis_agent/__init__.py +1 -3
- jarvis/jarvis_agent/shell_input_handler.py +1 -1
- jarvis/jarvis_code_agent/code_agent.py +10 -5
- jarvis/jarvis_git_squash/main.py +2 -1
- jarvis/jarvis_platform/human.py +2 -7
- jarvis/jarvis_tools/edit_file.py +6 -6
- jarvis/jarvis_tools/search_web.py +127 -11
- jarvis/jarvis_utils/git_utils.py +27 -18
- jarvis/jarvis_utils/input.py +23 -9
- jarvis/jarvis_utils/utils.py +43 -20
- {jarvis_ai_assistant-0.1.217.dist-info → jarvis_ai_assistant-0.1.219.dist-info}/METADATA +4 -1
- {jarvis_ai_assistant-0.1.217.dist-info → jarvis_ai_assistant-0.1.219.dist-info}/RECORD +17 -17
- {jarvis_ai_assistant-0.1.217.dist-info → jarvis_ai_assistant-0.1.219.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.217.dist-info → jarvis_ai_assistant-0.1.219.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.217.dist-info → jarvis_ai_assistant-0.1.219.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.217.dist-info → jarvis_ai_assistant-0.1.219.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
jarvis/jarvis_agent/__init__.py
CHANGED
@@ -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.
|
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
|
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 +=
|
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",
|
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
|
|
jarvis/jarvis_git_squash/main.py
CHANGED
@@ -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
|
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:
|
jarvis/jarvis_platform/human.py
CHANGED
@@ -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
|
-
|
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
|
jarvis/jarvis_tools/edit_file.py
CHANGED
@@ -32,8 +32,8 @@ class FileSearchReplaceTool:
|
|
32
32
|
1. 指定需要修改的文件路径(单个或多个)
|
33
33
|
2. 提供一组或多组修改,每个修改包含:
|
34
34
|
- reason: 修改原因描述
|
35
|
-
-
|
36
|
-
-
|
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
|
-
"
|
67
|
+
"SEARCH": {
|
68
68
|
"type": "string",
|
69
69
|
"description": "需要查找的原始代码",
|
70
70
|
},
|
71
|
-
"
|
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
|
-
-
|
103
|
-
-
|
102
|
+
- SEARCH: 需要查找的原始代码(必须包含足够上下文)
|
103
|
+
- REPLACE: 替换后的新代码
|
104
104
|
|
105
105
|
返回:
|
106
106
|
Dict[str, Any] 包含:
|
@@ -1,10 +1,20 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
+
"""A tool for searching the web."""
|
2
3
|
from typing import Any, Dict
|
3
4
|
|
5
|
+
import httpx
|
6
|
+
from bs4 import BeautifulSoup
|
7
|
+
from ddgs import DDGS
|
8
|
+
|
9
|
+
from jarvis.jarvis_agent import Agent
|
4
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
|
5
13
|
|
6
14
|
|
7
15
|
class SearchWebTool:
|
16
|
+
"""A class to handle web searches."""
|
17
|
+
|
8
18
|
name = "search_web"
|
9
19
|
description = "搜索互联网上的信息"
|
10
20
|
parameters = {
|
@@ -12,18 +22,124 @@ class SearchWebTool:
|
|
12
22
|
"properties": {"query": {"type": "string", "description": "具体的问题"}},
|
13
23
|
}
|
14
24
|
|
15
|
-
def
|
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
|
+
"""
|
16
114
|
query = args.get("query")
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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)
|
25
141
|
|
26
142
|
@staticmethod
|
27
143
|
def check() -> bool:
|
28
|
-
"""
|
29
|
-
return
|
144
|
+
"""Check if the tool is available."""
|
145
|
+
return True
|
jarvis/jarvis_utils/git_utils.py
CHANGED
@@ -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.
|
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,
|
418
|
-
hasattr(sys,
|
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 (
|
437
|
-
|
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(
|
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
|
-
[
|
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
|
)
|
jarvis/jarvis_utils/input.py
CHANGED
@@ -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
|
-
|
225
|
-
|
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
|
{
|
jarvis/jarvis_utils/utils.py
CHANGED
@@ -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.
|
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"
|
@@ -1,13 +1,13 @@
|
|
1
|
-
jarvis/__init__.py,sha256=
|
2
|
-
jarvis/jarvis_agent/__init__.py,sha256=
|
1
|
+
jarvis/__init__.py,sha256=x-8iFMYvuXxwrK7rGOft1XoFsZ5u3LFR6I6NWuFOq0s,75
|
2
|
+
jarvis/jarvis_agent/__init__.py,sha256=9R4dx4Y-DJRNiRPhzp16ih3Jkkc6VIFmyWg_AloW6KU,33198
|
3
3
|
jarvis/jarvis_agent/builtin_input_handler.py,sha256=lcw-VBm8-CVcblxEbGU4dVD6IixgXTLz9uBrv9Y6p20,2710
|
4
4
|
jarvis/jarvis_agent/edit_file_handler.py,sha256=vKx26I4yOQwiQHNfkqMJ44Ybf90n37mojTcXNQQy-hw,17382
|
5
5
|
jarvis/jarvis_agent/jarvis.py,sha256=4LBtAh9_AuQcjvqBFInqY19eyEJVJtGH4py32yu8olc,6287
|
6
6
|
jarvis/jarvis_agent/main.py,sha256=c6bQe-8LXvW2-NBn9Rn_yPYdrwnkJ8KQaSFY2cPvkxw,2775
|
7
7
|
jarvis/jarvis_agent/output_handler.py,sha256=P7oWpXBGFfOsWq7cIhS_z9crkQ19ES7qU5pM92KKjAs,1172
|
8
|
-
jarvis/jarvis_agent/shell_input_handler.py,sha256=
|
8
|
+
jarvis/jarvis_agent/shell_input_handler.py,sha256=1IboqdxcJuoIqRpmDU10GugR9fWXUHyCEbVF4nIWbyo,1328
|
9
9
|
jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
|
-
jarvis/jarvis_code_agent/code_agent.py,sha256=
|
10
|
+
jarvis/jarvis_code_agent/code_agent.py,sha256=JDLEVxT9YIg8crPOjDiYg76kb6v8Igrapj0NBK6Tn6Y,18731
|
11
11
|
jarvis/jarvis_code_agent/lint.py,sha256=LZPsfyZPMo7Wm7LN4osZocuNJwZx1ojacO3MlF870x8,4009
|
12
12
|
jarvis/jarvis_code_analysis/code_review.py,sha256=uCCbGd4Y1RjDzhZoVE8JdN2avlwOfqimSDIrcM-KMew,30456
|
13
13
|
jarvis/jarvis_code_analysis/checklists/__init__.py,sha256=LIXAYa1sW3l7foP6kohLWnE98I_EQ0T7z5bYKHq6rJA,78
|
@@ -35,7 +35,7 @@ jarvis/jarvis_data/tiktoken/9b5ad71b2ce5302211f9c61530b329a4922fc6a4,sha256=Ijkh
|
|
35
35
|
jarvis/jarvis_git_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
36
36
|
jarvis/jarvis_git_details/main.py,sha256=MjpUHB4ErR_SKPBx1TLLK_XLkH427RTtsyVn6EUd88Y,8907
|
37
37
|
jarvis/jarvis_git_squash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
|
-
jarvis/jarvis_git_squash/main.py,sha256=
|
38
|
+
jarvis/jarvis_git_squash/main.py,sha256=2nwX-Ghphn97Ua0SXPJIxix-rgm_Z9KRkrovjpSklUk,2311
|
39
39
|
jarvis/jarvis_git_utils/git_commiter.py,sha256=erZ3wNJuaEgHlKTaYv0UKargG_Yl9OnssTIcErEAdtw,12472
|
40
40
|
jarvis/jarvis_mcp/__init__.py,sha256=OPMtjD-uq9xAaKCRIDyKIosaFfBe1GBPu1az-mQ0rVM,2048
|
41
41
|
jarvis/jarvis_mcp/sse_mcp_client.py,sha256=-3Qy1LyqgHswoc6YbadVRG3ias2op7lUp7Ne2-QUKBM,22474
|
@@ -47,7 +47,7 @@ jarvis/jarvis_multi_agent/main.py,sha256=h7VUSwoPrES0XTK8z5kt3XLX1mmcm8UEuFEHQOU
|
|
47
47
|
jarvis/jarvis_platform/__init__.py,sha256=WLQHSiE87PPket2M50_hHzjdMIgPIBx2VF8JfB_NNRk,105
|
48
48
|
jarvis/jarvis_platform/ai8.py,sha256=yi7xG8ld4Yrf7drz-uu_JT_XCGYRB0obhygt-jKik8o,10871
|
49
49
|
jarvis/jarvis_platform/base.py,sha256=-XegiAS8G_nzwsWPOVEAQ2iTxE33fxu5-TWV4c3Pz-g,8981
|
50
|
-
jarvis/jarvis_platform/human.py,sha256=
|
50
|
+
jarvis/jarvis_platform/human.py,sha256=cSN8Lqf0ts2_pPfS2_v7PaWxQKqcW_3bSmhRTHey7Qo,4674
|
51
51
|
jarvis/jarvis_platform/kimi.py,sha256=OEiRNlC4Ao3PrO_yiogEwgMtTobehoEm_X4CMGT-Aas,15315
|
52
52
|
jarvis/jarvis_platform/openai.py,sha256=ccGqsU2cFfd5324P7SH1tSmFABpvto8fytmxQGkr3BA,6412
|
53
53
|
jarvis/jarvis_platform/oyi.py,sha256=GvVooV8ScRqDb9QxJdINtdZwsx6PUIdo1-bt9k0hmqY,12604
|
@@ -62,7 +62,7 @@ jarvis/jarvis_smart_shell/main.py,sha256=DbhRSP1sZfSIaTltP1YWVDSQOTYEsbiOnfO9kSY
|
|
62
62
|
jarvis/jarvis_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
63
63
|
jarvis/jarvis_tools/ask_user.py,sha256=iz2PTGx66IRL8e4DOpj3XhEGHFWeKQl0ggEOl_zOwQ0,1972
|
64
64
|
jarvis/jarvis_tools/base.py,sha256=tFVmK6ppsImW2BzHZmrNmMRiOJdW-4aZP6Me3VxdYcA,1194
|
65
|
-
jarvis/jarvis_tools/edit_file.py,sha256=
|
65
|
+
jarvis/jarvis_tools/edit_file.py,sha256=AG-u6oT_r9FBu9wIr272uLhRWYllombxseSQXtU3bcM,11757
|
66
66
|
jarvis/jarvis_tools/execute_script.py,sha256=gMarE5yCCSPU6Dp6HlcL2KT-2xCzR-1p-oQNlYOJK58,6157
|
67
67
|
jarvis/jarvis_tools/file_analyzer.py,sha256=aVe1jBSp0YmlypihxrGADJpYrU_7CxDETxGUNySuSlI,4044
|
68
68
|
jarvis/jarvis_tools/generate_new_tool.py,sha256=2YAs8DC7fJnxOkjSmhmSAwqSpBlicVhYc06WZ8YVBls,7679
|
@@ -71,7 +71,7 @@ jarvis/jarvis_tools/read_code.py,sha256=EnI-R-5HyIQYhMD391nZWXHIuHHBF-OJIRE0QpLc
|
|
71
71
|
jarvis/jarvis_tools/read_webpage.py,sha256=NmDUboVZd4CGHBPRFK6dp3uqVhuGopW1bOi3TcaLDF4,2092
|
72
72
|
jarvis/jarvis_tools/registry.py,sha256=0SdgBi-b1qnd3QX0VvQy7UVU7Pq9BZGYLiAe7t0DjpQ,25690
|
73
73
|
jarvis/jarvis_tools/rewrite_file.py,sha256=eG_WKg6cVAXmuGwUqlWkcuyay5S8DOzEi8vZCmX3O8w,7255
|
74
|
-
jarvis/jarvis_tools/search_web.py,sha256=
|
74
|
+
jarvis/jarvis_tools/search_web.py,sha256=DqBwNGFK3vZleZ7_4Go3q27DzPCp4m0ZeEi1N7UEFc4,5363
|
75
75
|
jarvis/jarvis_tools/virtual_tty.py,sha256=KKr3jpvQWWMPr2o40hlmN6fuXJCN8H4_ma5QU40Citc,16089
|
76
76
|
jarvis/jarvis_tools/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
77
77
|
jarvis/jarvis_tools/cli/main.py,sha256=Mg6TQDxMdzB1Ua1UrZ2EE-uQWsbaeojWaEGHJp2HimA,6375
|
@@ -80,17 +80,17 @@ jarvis/jarvis_utils/builtin_replace_map.py,sha256=EI8JnHqr-ZpAhpwocTu48DhHUMHNd8
|
|
80
80
|
jarvis/jarvis_utils/config.py,sha256=MO2-1z_7f3KkSrv7heGK1650Zb0SjnljO2hzLE2jA5c,6598
|
81
81
|
jarvis/jarvis_utils/embedding.py,sha256=oEOEM2qf16DMYwPsQe6srET9BknyjOdY2ef0jsp3Or8,2714
|
82
82
|
jarvis/jarvis_utils/file_processors.py,sha256=XiM248SHS7lLgQDCbORVFWqinbVDUawYxWDOsLXDxP8,3043
|
83
|
-
jarvis/jarvis_utils/git_utils.py,sha256=
|
83
|
+
jarvis/jarvis_utils/git_utils.py,sha256=4mNbEgV0icMnB1UL1RWhE9Nxik3mwam2qcGMpd1ODJM,21707
|
84
84
|
jarvis/jarvis_utils/globals.py,sha256=WzZh_acNfHJj1LDulhyLQ7cojksBy0gdrITe0vH1XA0,3901
|
85
85
|
jarvis/jarvis_utils/http.py,sha256=Uqt1kcz0HWnAfXHHi1fNGwLb2lcVUqpbrG2Uk_-kcIU,4882
|
86
|
-
jarvis/jarvis_utils/input.py,sha256=
|
86
|
+
jarvis/jarvis_utils/input.py,sha256=V2w3xV0MO73c4Y4XY_yy9jVNg7MmN76FmAnpKRiJUog,9160
|
87
87
|
jarvis/jarvis_utils/methodology.py,sha256=-cvM6pwgJK7BXCYg2uVjIId_j3v5RUh2z2PBcK_2vj4,8155
|
88
88
|
jarvis/jarvis_utils/output.py,sha256=PRCgudPOB8gMEP3u-g0FGD2c6tBgJhLXUMqNPglfjV8,10813
|
89
89
|
jarvis/jarvis_utils/tag.py,sha256=f211opbbbTcSyzCDwuIK_oCnKhXPNK-RknYyGzY1yD0,431
|
90
|
-
jarvis/jarvis_utils/utils.py,sha256=
|
91
|
-
jarvis_ai_assistant-0.1.
|
92
|
-
jarvis_ai_assistant-0.1.
|
93
|
-
jarvis_ai_assistant-0.1.
|
94
|
-
jarvis_ai_assistant-0.1.
|
95
|
-
jarvis_ai_assistant-0.1.
|
96
|
-
jarvis_ai_assistant-0.1.
|
90
|
+
jarvis/jarvis_utils/utils.py,sha256=ojupkZQfFIE6ysTyCy0jUdePucpwpvZlZJSXkGsdyQE,15263
|
91
|
+
jarvis_ai_assistant-0.1.219.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
92
|
+
jarvis_ai_assistant-0.1.219.dist-info/METADATA,sha256=Dn-M7q32tMW3ATjIl1ZhI42MDnBPsAkAytgwef8abzM,19706
|
93
|
+
jarvis_ai_assistant-0.1.219.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
94
|
+
jarvis_ai_assistant-0.1.219.dist-info/entry_points.txt,sha256=SF46ViTZcQVZEfbqzJDKKVc9TrN1x-P1mQ6wup7u2HY,875
|
95
|
+
jarvis_ai_assistant-0.1.219.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
96
|
+
jarvis_ai_assistant-0.1.219.dist-info/RECORD,,
|
File without changes
|
{jarvis_ai_assistant-0.1.217.dist-info → jarvis_ai_assistant-0.1.219.dist-info}/entry_points.txt
RENAMED
File without changes
|
{jarvis_ai_assistant-0.1.217.dist-info → jarvis_ai_assistant-0.1.219.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
{jarvis_ai_assistant-0.1.217.dist-info → jarvis_ai_assistant-0.1.219.dist-info}/top_level.txt
RENAMED
File without changes
|