jarvis-ai-assistant 0.1.159__py3-none-any.whl → 0.1.160__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of jarvis-ai-assistant might be problematic. Click here for more details.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/file_input_handler.py +2 -3
- jarvis/jarvis_agent/patch.py +74 -78
- jarvis/jarvis_code_analysis/code_review.py +29 -35
- jarvis/jarvis_git_utils/git_commiter.py +27 -59
- jarvis/jarvis_methodology/main.py +2 -2
- jarvis/jarvis_platform/base.py +43 -30
- jarvis/jarvis_platform/kimi.py +2 -2
- jarvis/jarvis_tools/file_analyzer.py +2 -2
- jarvis/jarvis_tools/file_operation.py +1 -1
- jarvis/jarvis_tools/read_webpage.py +1 -1
- jarvis/jarvis_tools/registry.py +33 -41
- jarvis/jarvis_tools/search_web.py +1 -1
- jarvis/jarvis_utils/methodology.py +71 -61
- jarvis/jarvis_utils/utils.py +5 -12
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.160.dist-info}/METADATA +2 -2
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.160.dist-info}/RECORD +21 -21
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.160.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.160.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.160.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.160.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
|
@@ -7,9 +7,8 @@ from typing import Any, Tuple
|
|
|
7
7
|
from yaspin import yaspin
|
|
8
8
|
|
|
9
9
|
from jarvis.jarvis_tools.file_operation import FileOperationTool
|
|
10
|
-
from jarvis.jarvis_utils.config import INPUT_WINDOW_REVERSE_SIZE, get_max_input_token_count
|
|
11
|
-
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
12
10
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
11
|
+
from jarvis.jarvis_utils.utils import is_context_overflow
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
def file_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
|
@@ -86,7 +85,7 @@ def file_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
|
|
86
85
|
spinner.text = "文件读取完成"
|
|
87
86
|
spinner.ok("✅")
|
|
88
87
|
prompt = result["stdout"] + "\n" + prompt
|
|
89
|
-
if
|
|
88
|
+
if is_context_overflow(prompt):
|
|
90
89
|
return old_prompt, False
|
|
91
90
|
|
|
92
91
|
return prompt, False
|
jarvis/jarvis_agent/patch.py
CHANGED
|
@@ -2,20 +2,19 @@ import re
|
|
|
2
2
|
from typing import Dict, Any, Tuple
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
|
-
from yaspin import yaspin
|
|
5
|
+
from yaspin import yaspin # type: ignore
|
|
6
6
|
|
|
7
7
|
from jarvis.jarvis_agent.output_handler import OutputHandler
|
|
8
8
|
from jarvis.jarvis_platform.base import BasePlatform
|
|
9
9
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
10
10
|
from jarvis.jarvis_git_utils.git_commiter import GitCommitTool
|
|
11
11
|
from jarvis.jarvis_tools.file_operation import FileOperationTool
|
|
12
|
-
from jarvis.jarvis_utils.config import
|
|
13
|
-
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
12
|
+
from jarvis.jarvis_utils.config import is_confirm_before_apply_patch
|
|
14
13
|
from jarvis.jarvis_utils.git_utils import get_commits_between, get_latest_commit_hash
|
|
15
14
|
from jarvis.jarvis_utils.globals import add_read_file_record, has_read_file
|
|
16
15
|
from jarvis.jarvis_utils.input import get_multiline_input
|
|
17
16
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
18
|
-
from jarvis.jarvis_utils.utils import get_file_line_count, user_confirm
|
|
17
|
+
from jarvis.jarvis_utils.utils import is_context_overflow, get_file_line_count, user_confirm
|
|
19
18
|
from jarvis.jarvis_utils.tag import ot, ct
|
|
20
19
|
|
|
21
20
|
|
|
@@ -95,7 +94,7 @@ def add(a, b):
|
|
|
95
94
|
- 保持代码风格一致性,遵循项目现有的编码规范
|
|
96
95
|
- 在修改前仔细分析原代码的格式风格,确保补丁与之完全兼容
|
|
97
96
|
- 绝不提供完整文件内容,除非是新建文件
|
|
98
|
-
-
|
|
97
|
+
- 每个文件的修改是独立的,不能出现“参照xxx文件的修改”这样的描述
|
|
99
98
|
- 不要出现未实现的代码,如:TODO
|
|
100
99
|
"""
|
|
101
100
|
|
|
@@ -377,6 +376,7 @@ def handle_small_code_operation(filepath: str, patch_content: str) -> bool:
|
|
|
377
376
|
try:
|
|
378
377
|
model = PlatformRegistry().get_normal_platform()
|
|
379
378
|
file_content = FileOperationTool().execute({"operation":"read", "files":[{"path":filepath}]})["stdout"]
|
|
379
|
+
|
|
380
380
|
model.set_suppress_output(True)
|
|
381
381
|
|
|
382
382
|
prompt = f"""
|
|
@@ -407,6 +407,7 @@ def handle_small_code_operation(filepath: str, patch_content: str) -> bool:
|
|
|
407
407
|
{ot("MERGED_CODE")}
|
|
408
408
|
[合并后的完整代码,包括所有空行和缩进]
|
|
409
409
|
{ct("MERGED_CODE")}
|
|
410
|
+
|
|
410
411
|
# 原始代码
|
|
411
412
|
{file_content}
|
|
412
413
|
"""
|
|
@@ -466,18 +467,23 @@ def handle_small_code_operation(filepath: str, patch_content: str) -> bool:
|
|
|
466
467
|
return False
|
|
467
468
|
|
|
468
469
|
|
|
470
|
+
|
|
469
471
|
def handle_large_code_operation(filepath: str, patch_content: str, model: BasePlatform) -> bool:
|
|
470
472
|
"""处理大型代码文件的补丁操作,使用差异化补丁格式"""
|
|
471
473
|
with yaspin(text=f"正在处理文件 {filepath}...", color="cyan") as spinner:
|
|
472
474
|
try:
|
|
473
475
|
file_content = FileOperationTool().execute({"operation":"read", "files":[{"path":filepath}]})["stdout"]
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
476
|
+
need_upload_file = is_context_overflow(file_content)
|
|
477
|
+
upload_success = False
|
|
478
|
+
# 读取原始文件内容
|
|
479
|
+
with spinner.hidden():
|
|
480
|
+
if need_upload_file and model.upload_files([filepath]):
|
|
481
|
+
upload_success = True
|
|
482
|
+
|
|
483
|
+
|
|
478
484
|
model.set_suppress_output(True)
|
|
479
485
|
|
|
480
|
-
|
|
486
|
+
main_prompt = f"""
|
|
481
487
|
# 代码补丁生成专家指南
|
|
482
488
|
|
|
483
489
|
## 任务描述
|
|
@@ -487,8 +493,7 @@ def handle_large_code_operation(filepath: str, patch_content: str, model: BasePl
|
|
|
487
493
|
```
|
|
488
494
|
{patch_content}
|
|
489
495
|
```
|
|
490
|
-
|
|
491
|
-
suffix_prompt = """
|
|
496
|
+
|
|
492
497
|
## 补丁生成要求
|
|
493
498
|
1. **精确性**:严格按照补丁的意图修改代码
|
|
494
499
|
2. **格式一致性**:严格保持原始代码的格式风格
|
|
@@ -523,77 +528,68 @@ def handle_large_code_operation(filepath: str, patch_content: str, model: BasePl
|
|
|
523
528
|
<<<<<< REPLACE
|
|
524
529
|
{ct("DIFF")}
|
|
525
530
|
"""
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
response = model.chat_until_success(
|
|
531
|
+
|
|
532
|
+
for _ in range(3):
|
|
533
|
+
file_prompt = ""
|
|
534
|
+
if not need_upload_file:
|
|
535
|
+
file_prompt = f"""
|
|
536
|
+
# 原始代码
|
|
537
|
+
{file_content}
|
|
538
|
+
"""
|
|
539
|
+
response = model.chat_until_success(main_prompt + file_prompt)
|
|
535
540
|
else:
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
model,
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
if modified_content.count(search_text) > 1:
|
|
573
|
-
prompt = f"补丁 #{patch_count} 应用失败:找到多个匹配的代码段"
|
|
574
|
-
spinner.write(f"❌ 补丁 #{patch_count} 应用失败:找到多个匹配的代码段")
|
|
541
|
+
if upload_success:
|
|
542
|
+
response = model.chat_until_success(main_prompt)
|
|
543
|
+
else:
|
|
544
|
+
response = model.chat_big_content(file_content, main_prompt)
|
|
545
|
+
|
|
546
|
+
# 解析差异化补丁
|
|
547
|
+
diff_blocks = re.finditer(ot("DIFF")+r'\s*>{4,} SEARCH\n?(.*?)\n?={4,}\n?(.*?)\s*<{4,} REPLACE\n?'+ct("DIFF"),
|
|
548
|
+
response, re.DOTALL)
|
|
549
|
+
|
|
550
|
+
# 读取原始文件内容
|
|
551
|
+
with open(filepath, 'r', encoding='utf-8', errors="ignore") as f:
|
|
552
|
+
file_content = f.read()
|
|
553
|
+
|
|
554
|
+
# 应用所有差异化补丁
|
|
555
|
+
modified_content = file_content
|
|
556
|
+
patch_count = 0
|
|
557
|
+
success = True
|
|
558
|
+
for match in diff_blocks:
|
|
559
|
+
search_text = match.group(1).strip()
|
|
560
|
+
replace_text = match.group(2).strip()
|
|
561
|
+
patch_count += 1
|
|
562
|
+
# 检查搜索文本是否存在于文件中
|
|
563
|
+
if search_text in modified_content:
|
|
564
|
+
# 如果有多处,报错
|
|
565
|
+
if modified_content.count(search_text) > 1:
|
|
566
|
+
prompt = f"补丁 #{patch_count} 应用失败:找到多个匹配的代码段"
|
|
567
|
+
spinner.write(f"❌ 补丁 #{patch_count} 应用失败:找到多个匹配的代码段")
|
|
568
|
+
success = False
|
|
569
|
+
break
|
|
570
|
+
# 应用替换
|
|
571
|
+
modified_content = modified_content.replace(
|
|
572
|
+
search_text, replace_text)
|
|
573
|
+
spinner.write(f"✅ 补丁 #{patch_count} 应用成功")
|
|
574
|
+
else:
|
|
575
|
+
spinner.write(f"❌ 补丁 #{patch_count} 应用失败:无法找到匹配的代码段")
|
|
576
|
+
prompt = f"补丁 #{patch_count} 应用失败:无法找到匹配的代码段"
|
|
575
577
|
success = False
|
|
576
578
|
break
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
spinner.write(f"✅ 补丁 #{patch_count} 应用成功")
|
|
581
|
-
else:
|
|
582
|
-
spinner.write(f"❌ 补丁 #{patch_count} 应用失败:无法找到匹配的代码段")
|
|
583
|
-
prompt = f"补丁 #{patch_count} 应用失败:无法找到匹配的代码段"
|
|
584
|
-
success = False
|
|
585
|
-
break
|
|
586
|
-
if not success:
|
|
587
|
-
revert_file(filepath)
|
|
588
|
-
return False
|
|
579
|
+
if not success:
|
|
580
|
+
revert_file(filepath)
|
|
581
|
+
continue
|
|
589
582
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
583
|
+
# 写入修改后的内容
|
|
584
|
+
with open(filepath, 'w', encoding='utf-8', errors="ignore") as f:
|
|
585
|
+
f.write(modified_content)
|
|
593
586
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
587
|
+
spinner.text = f"文件 {filepath} 修改完成,应用了 {patch_count} 个补丁"
|
|
588
|
+
spinner.ok("✅")
|
|
589
|
+
return True
|
|
590
|
+
spinner.text = f"文件 {filepath} 修改失败"
|
|
591
|
+
spinner.fail("❌")
|
|
592
|
+
return False
|
|
597
593
|
|
|
598
594
|
except Exception as e:
|
|
599
595
|
spinner.text = f"文件修改失败: {str(e)}"
|
|
@@ -10,10 +10,8 @@ from jarvis.jarvis_tools.read_code import ReadCodeTool
|
|
|
10
10
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
11
11
|
from jarvis.jarvis_agent import Agent
|
|
12
12
|
|
|
13
|
-
from jarvis.jarvis_utils.config import INPUT_WINDOW_REVERSE_SIZE, get_max_input_token_count
|
|
14
|
-
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
15
13
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
16
|
-
from jarvis.jarvis_utils.utils import init_env,
|
|
14
|
+
from jarvis.jarvis_utils.utils import init_env, is_context_overflow
|
|
17
15
|
from jarvis.jarvis_utils.tag import ot, ct
|
|
18
16
|
from jarvis.jarvis_code_analysis.checklists.loader import get_language_checklist
|
|
19
17
|
|
|
@@ -587,28 +585,27 @@ class CodeReviewTool:
|
|
|
587
585
|
temp_file.flush()
|
|
588
586
|
|
|
589
587
|
try:
|
|
590
|
-
|
|
591
|
-
|
|
588
|
+
upload_success = False
|
|
589
|
+
# Check if content is too large
|
|
590
|
+
is_large_content = is_context_overflow(diff_output)
|
|
592
591
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
if
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
spinner.ok("✅")
|
|
601
|
-
PrettyOutput.print(f"已成功上传代码差异文件", OutputType.SUCCESS)
|
|
602
|
-
else:
|
|
603
|
-
spinner.fail("❌")
|
|
604
|
-
PrettyOutput.print(f"文件上传失败,将使用chat_with_files处理", OutputType.WARNING)
|
|
592
|
+
# Upload the file to the agent's model
|
|
593
|
+
with yaspin(text="正在上传代码差异文件...", color="cyan") as spinner:
|
|
594
|
+
if is_large_content and agent.model and hasattr(agent.model, 'upload_files'):
|
|
595
|
+
upload_success = agent.model.upload_files([temp_file_path])
|
|
596
|
+
if upload_success:
|
|
597
|
+
spinner.ok("✅")
|
|
598
|
+
PrettyOutput.print(f"已成功上传代码差异文件", OutputType.SUCCESS)
|
|
605
599
|
else:
|
|
606
600
|
spinner.fail("❌")
|
|
607
|
-
PrettyOutput.print(f"
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
601
|
+
PrettyOutput.print(f"上传代码差异文件失败,将使用分块处理", OutputType.WARNING)
|
|
602
|
+
else:
|
|
603
|
+
upload_success = False
|
|
604
|
+
|
|
605
|
+
# Prepare the prompt based on upload status
|
|
606
|
+
if upload_success:
|
|
607
|
+
# When file is uploaded, reference it in the prompt
|
|
608
|
+
complete_prompt = user_prompt + f"""
|
|
612
609
|
|
|
613
610
|
我已上传了一个包含代码差异的文件。该文件包含:
|
|
614
611
|
- 审查类型: {review_type}
|
|
@@ -616,20 +613,17 @@ class CodeReviewTool:
|
|
|
616
613
|
- 检测到的编程语言: {', '.join(detected_languages) if detected_languages else '未检测到特定语言'}
|
|
617
614
|
|
|
618
615
|
请基于上传的代码差异文件进行全面审查,并生成详细的代码审查报告。"""
|
|
619
|
-
|
|
620
|
-
else:
|
|
621
|
-
# 文件上传失败,使用chat_with_files
|
|
622
|
-
PrettyOutput.print("使用chat_with_files处理大文件...", OutputType.INFO)
|
|
623
|
-
result = chat_with_files(
|
|
624
|
-
[temp_file_path],
|
|
625
|
-
agent.model,
|
|
626
|
-
user_prompt,
|
|
627
|
-
"请基于以上代码差异进行全面审查,并生成详细的代码审查报告。"
|
|
628
|
-
)
|
|
629
|
-
else:
|
|
630
|
-
# 文件较小,直接包含在prompt中
|
|
631
|
-
complete_prompt = user_prompt + "\n\n代码差异内容:\n```diff\n" + diff_output + "\n```"
|
|
616
|
+
# Run the agent with the prompt
|
|
632
617
|
result = agent.run(complete_prompt)
|
|
618
|
+
else:
|
|
619
|
+
# If upload failed or not needed, handle based on context size
|
|
620
|
+
if is_large_content and agent.model and hasattr(agent.model, 'chat_big_content'):
|
|
621
|
+
# Use chat_big_content for large content when upload fails
|
|
622
|
+
result = agent.model.chat_big_content(diff_output, user_prompt)
|
|
623
|
+
else:
|
|
624
|
+
# Include the diff directly in the prompt for smaller content
|
|
625
|
+
complete_prompt = user_prompt + "\n\n代码差异内容:\n```diff\n" + diff_output + "\n```"
|
|
626
|
+
result = agent.run(complete_prompt)
|
|
633
627
|
finally:
|
|
634
628
|
# Clean up the temporary file
|
|
635
629
|
if os.path.exists(temp_file_path):
|
|
@@ -10,11 +10,9 @@ import sys
|
|
|
10
10
|
import argparse
|
|
11
11
|
import os
|
|
12
12
|
|
|
13
|
-
from jarvis.jarvis_utils.config import INPUT_WINDOW_REVERSE_SIZE, get_max_input_token_count
|
|
14
|
-
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
15
13
|
from jarvis.jarvis_utils.git_utils import find_git_root, has_uncommitted_changes
|
|
16
14
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
17
|
-
from jarvis.jarvis_utils.utils import init_env,
|
|
15
|
+
from jarvis.jarvis_utils.utils import init_env, is_context_overflow
|
|
18
16
|
from jarvis.jarvis_utils.tag import ot, ct
|
|
19
17
|
|
|
20
18
|
|
|
@@ -107,7 +105,7 @@ class GitCommitTool:
|
|
|
107
105
|
diff = process.communicate()[0].decode()
|
|
108
106
|
spinner.write(f"✅ 获取差异 ({file_count} 个文件)")
|
|
109
107
|
try:
|
|
110
|
-
|
|
108
|
+
temp_diff_file_path = None
|
|
111
109
|
# 生成提交信息
|
|
112
110
|
spinner.text = "正在生成提交消息..."
|
|
113
111
|
|
|
@@ -132,13 +130,12 @@ class GitCommitTool:
|
|
|
132
130
|
|
|
133
131
|
# 获取模型并尝试上传文件
|
|
134
132
|
platform = PlatformRegistry().get_normal_platform()
|
|
133
|
+
upload_success = False
|
|
135
134
|
|
|
136
|
-
#
|
|
137
|
-
|
|
135
|
+
# Check if content is too large
|
|
136
|
+
is_large_content = is_context_overflow(diff)
|
|
138
137
|
|
|
139
|
-
if
|
|
140
|
-
# 文件较大,尝试上传
|
|
141
|
-
upload_success = False
|
|
138
|
+
if is_large_content and hasattr(platform, 'upload_files'):
|
|
142
139
|
spinner.text = "正在上传代码差异文件..."
|
|
143
140
|
try:
|
|
144
141
|
with spinner.hidden():
|
|
@@ -148,72 +145,43 @@ class GitCommitTool:
|
|
|
148
145
|
temp_diff_file.write(diff)
|
|
149
146
|
temp_diff_file.flush()
|
|
150
147
|
spinner.write(f"✅ 差异内容已写入临时文件")
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
else:
|
|
157
|
-
spinner.write("⚠️ 上传代码差异文件失败,将使用chat_with_files处理")
|
|
158
|
-
else:
|
|
159
|
-
spinner.write("⚠️ 模型不支持文件上传,将使用chat_with_files处理")
|
|
148
|
+
upload_success = platform.upload_files([temp_diff_file_path])
|
|
149
|
+
if upload_success:
|
|
150
|
+
spinner.write("✅ 成功上传代码差异文件")
|
|
151
|
+
else:
|
|
152
|
+
spinner.write("⚠️ 上传代码差异文件失败,将使用分块处理")
|
|
160
153
|
except Exception as e:
|
|
161
154
|
spinner.write(f"⚠️ 上传文件时出错: {str(e)}")
|
|
162
155
|
upload_success = False
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
156
|
+
|
|
157
|
+
# 根据上传状态准备完整的提示
|
|
158
|
+
if upload_success:
|
|
159
|
+
# 使用上传的文件
|
|
160
|
+
prompt = base_prompt + f'''
|
|
167
161
|
# 变更概述
|
|
168
162
|
- 变更文件数量: {file_count} 个文件
|
|
169
163
|
- 已上传包含完整代码差异的文件
|
|
170
164
|
|
|
171
165
|
请详细分析已上传的代码差异文件,生成符合上述格式的提交信息。
|
|
172
166
|
'''
|
|
173
|
-
else:
|
|
174
|
-
# 使用chat_with_files处理大文件
|
|
175
|
-
spinner.write("使用chat_with_files处理大文件...")
|
|
176
|
-
commit_message = chat_with_files(
|
|
177
|
-
[temp_diff_file_path],
|
|
178
|
-
platform,
|
|
179
|
-
base_prompt,
|
|
180
|
-
"请基于以上代码差异生成符合格式的提交信息。"
|
|
181
|
-
)
|
|
182
|
-
commit_message = self._extract_commit_message(commit_message)
|
|
183
|
-
if commit_message:
|
|
184
|
-
spinner.write("✅ 生成提交消息")
|
|
185
|
-
# 执行提交
|
|
186
|
-
spinner.text = "正在准备提交..."
|
|
187
|
-
with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_file:
|
|
188
|
-
tmp_file.write(commit_message)
|
|
189
|
-
tmp_file.flush()
|
|
190
|
-
spinner.text = "正在执行提交..."
|
|
191
|
-
commit_cmd = ["git", "commit", "-F", tmp_file.name]
|
|
192
|
-
subprocess.Popen(
|
|
193
|
-
commit_cmd,
|
|
194
|
-
stdout=subprocess.DEVNULL,
|
|
195
|
-
stderr=subprocess.DEVNULL
|
|
196
|
-
).wait()
|
|
197
|
-
spinner.write("✅ 提交")
|
|
198
|
-
return {
|
|
199
|
-
"success": True,
|
|
200
|
-
"stdout": yaml.safe_dump({
|
|
201
|
-
"commit_hash": self._get_last_commit_hash(),
|
|
202
|
-
"commit_message": commit_message
|
|
203
|
-
}),
|
|
204
|
-
"stderr": ""
|
|
205
|
-
}
|
|
206
167
|
else:
|
|
207
|
-
#
|
|
208
|
-
|
|
168
|
+
# 如果上传失败但内容较大,使用chat_big_content
|
|
169
|
+
if is_large_content and hasattr(platform, 'chat_big_content'):
|
|
170
|
+
spinner.text = "正在使用分块处理生成提交信息..."
|
|
171
|
+
commit_message = platform.chat_big_content(diff, base_prompt)
|
|
172
|
+
else:
|
|
173
|
+
# 直接在提示中包含差异内容
|
|
174
|
+
prompt = base_prompt + f'''
|
|
209
175
|
# 分析材料
|
|
210
176
|
{diff}
|
|
211
177
|
'''
|
|
178
|
+
commit_message = platform.chat_until_success(prompt)
|
|
212
179
|
|
|
213
180
|
# 尝试生成提交信息
|
|
214
181
|
spinner.text = "正在生成提交消息..."
|
|
215
182
|
while True:
|
|
216
|
-
|
|
183
|
+
if not upload_success and not is_large_content:
|
|
184
|
+
commit_message = platform.chat_until_success(prompt)
|
|
217
185
|
commit_message = self._extract_commit_message(commit_message)
|
|
218
186
|
# 如果成功提取,就跳出循环
|
|
219
187
|
if commit_message:
|
|
@@ -246,7 +214,7 @@ class GitCommitTool:
|
|
|
246
214
|
spinner.ok("✅")
|
|
247
215
|
finally:
|
|
248
216
|
# 清理临时差异文件
|
|
249
|
-
if
|
|
217
|
+
if temp_diff_file_path is not None and os.path.exists(temp_diff_file_path):
|
|
250
218
|
try:
|
|
251
219
|
os.unlink(temp_diff_file_path)
|
|
252
220
|
except Exception as e:
|
|
@@ -11,14 +11,14 @@ import hashlib
|
|
|
11
11
|
import os
|
|
12
12
|
import json
|
|
13
13
|
import argparse
|
|
14
|
-
import yaml
|
|
14
|
+
import yaml # type: ignore
|
|
15
15
|
from jarvis.jarvis_utils.methodology import (
|
|
16
16
|
_get_methodology_directory,
|
|
17
17
|
_load_all_methodologies
|
|
18
18
|
)
|
|
19
19
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
20
20
|
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
|
21
|
-
from yaspin import yaspin
|
|
21
|
+
from yaspin import yaspin # type: ignore
|
|
22
22
|
|
|
23
23
|
def import_methodology(input_file):
|
|
24
24
|
"""导入方法论文件(合并策略)"""
|
jarvis/jarvis_platform/base.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
import re
|
|
3
3
|
from typing import List, Tuple
|
|
4
|
+
from jarvis.jarvis_utils.config import get_max_input_token_count
|
|
5
|
+
from jarvis.jarvis_utils.embedding import split_text_into_chunks
|
|
4
6
|
from jarvis.jarvis_utils.globals import clear_read_file_record
|
|
5
7
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
6
8
|
from jarvis.jarvis_utils.utils import get_context_token_count, while_success, while_true
|
|
@@ -37,38 +39,49 @@ class BasePlatform(ABC):
|
|
|
37
39
|
@abstractmethod
|
|
38
40
|
def upload_files(self, file_list: List[str]) -> bool:
|
|
39
41
|
raise NotImplementedError("upload_files is not implemented")
|
|
42
|
+
|
|
43
|
+
def chat_big_content(self, content: str, prompt: str) -> str:
|
|
44
|
+
prefix_prompt = f"""
|
|
45
|
+
我将分多次提供大量的上下文内容,在我明确告诉你内容已经全部提供完毕之前,每次仅需要输出“已收到”。
|
|
46
|
+
"""
|
|
47
|
+
self.chat_until_success(prefix_prompt)
|
|
48
|
+
split_content = split_text_into_chunks(content, get_max_input_token_count() - 1024)
|
|
49
|
+
for chunk in split_content:
|
|
50
|
+
self.chat_until_success(f"<part_content>{chunk}</part_content>")
|
|
51
|
+
return self.chat_until_success(f"内容已经全部提供完毕\n\n{prompt}")
|
|
40
52
|
|
|
53
|
+
|
|
54
|
+
def _chat(self, message: str):
|
|
55
|
+
import time
|
|
56
|
+
start_time = time.time()
|
|
57
|
+
response = self.chat(message)
|
|
58
|
+
|
|
59
|
+
end_time = time.time()
|
|
60
|
+
duration = end_time - start_time
|
|
61
|
+
char_count = len(response)
|
|
62
|
+
|
|
63
|
+
# Calculate token count and tokens per second
|
|
64
|
+
try:
|
|
65
|
+
token_count = get_context_token_count(response)
|
|
66
|
+
tokens_per_second = token_count / duration if duration > 0 else 0
|
|
67
|
+
except Exception as e:
|
|
68
|
+
PrettyOutput.print(f"Tokenization failed: {str(e)}", OutputType.WARNING)
|
|
69
|
+
token_count = 0
|
|
70
|
+
tokens_per_second = 0
|
|
71
|
+
|
|
72
|
+
# Print statistics
|
|
73
|
+
if not self.suppress_output:
|
|
74
|
+
PrettyOutput.print(
|
|
75
|
+
f"对话完成 - 耗时: {duration:.2f}秒, 输出字符数: {char_count}, 输出Token数量: {token_count}, 每秒Token数量: {tokens_per_second:.2f}",
|
|
76
|
+
OutputType.INFO,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Keep original think tag handling
|
|
80
|
+
response = re.sub(ot("think")+r'.*?'+ct("think"), '', response, flags=re.DOTALL)
|
|
81
|
+
return response
|
|
82
|
+
|
|
41
83
|
def chat_until_success(self, message: str) -> str:
|
|
42
|
-
|
|
43
|
-
import time
|
|
44
|
-
start_time = time.time()
|
|
45
|
-
response = self.chat(message)
|
|
46
|
-
|
|
47
|
-
end_time = time.time()
|
|
48
|
-
duration = end_time - start_time
|
|
49
|
-
char_count = len(response)
|
|
50
|
-
|
|
51
|
-
# Calculate token count and tokens per second
|
|
52
|
-
try:
|
|
53
|
-
token_count = get_context_token_count(response)
|
|
54
|
-
tokens_per_second = token_count / duration if duration > 0 else 0
|
|
55
|
-
except Exception as e:
|
|
56
|
-
PrettyOutput.print(f"Tokenization failed: {str(e)}", OutputType.WARNING)
|
|
57
|
-
token_count = 0
|
|
58
|
-
tokens_per_second = 0
|
|
59
|
-
|
|
60
|
-
# Print statistics
|
|
61
|
-
if not self.suppress_output:
|
|
62
|
-
PrettyOutput.print(
|
|
63
|
-
f"对话完成 - 耗时: {duration:.2f}秒, 输出字符数: {char_count}, 输出Token数量: {token_count}, 每秒Token数量: {tokens_per_second:.2f}",
|
|
64
|
-
OutputType.INFO,
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
# Keep original think tag handling
|
|
68
|
-
response = re.sub(ot("think")+r'.*?'+ct("think"), '', response, flags=re.DOTALL)
|
|
69
|
-
return response
|
|
70
|
-
|
|
71
|
-
return while_true(lambda: while_success(lambda: _chat(), 5), 5)
|
|
84
|
+
return while_true(lambda: while_success(lambda: self._chat(message), 5), 5)
|
|
72
85
|
|
|
73
86
|
@abstractmethod
|
|
74
87
|
def name(self) -> str:
|
jarvis/jarvis_platform/kimi.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import Dict, List, Tuple
|
|
2
|
-
import requests
|
|
2
|
+
import requests # type: ignore
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
5
|
import mimetypes
|
|
@@ -178,7 +178,7 @@ class KimiModel(BasePlatform):
|
|
|
178
178
|
if not file_list:
|
|
179
179
|
return True
|
|
180
180
|
|
|
181
|
-
from yaspin import yaspin
|
|
181
|
+
from yaspin import yaspin # type: ignore
|
|
182
182
|
|
|
183
183
|
if not self.chat_id:
|
|
184
184
|
with yaspin(text="创建聊天会话...", color="yellow") as spinner:
|
|
@@ -3,8 +3,8 @@ import os
|
|
|
3
3
|
|
|
4
4
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
5
5
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
6
|
-
from yaspin import yaspin
|
|
7
|
-
from yaspin.spinners import Spinners
|
|
6
|
+
from yaspin import yaspin # type: ignore
|
|
7
|
+
from yaspin.spinners import Spinners # type: ignore
|
|
8
8
|
|
|
9
9
|
class FileAnalyzerTool:
|
|
10
10
|
name = "file_analyzer"
|
|
@@ -2,7 +2,7 @@ from typing import Dict, Any
|
|
|
2
2
|
import os
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
-
from yaspin import yaspin
|
|
5
|
+
from yaspin import yaspin # type: ignore
|
|
6
6
|
|
|
7
7
|
from jarvis.jarvis_utils.globals import add_read_file_record
|
|
8
8
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
jarvis/jarvis_tools/registry.py
CHANGED
|
@@ -3,6 +3,7 @@ from pathlib import Path
|
|
|
3
3
|
import re
|
|
4
4
|
import sys
|
|
5
5
|
import tempfile
|
|
6
|
+
import os
|
|
6
7
|
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
7
8
|
|
|
8
9
|
import yaml
|
|
@@ -10,14 +11,9 @@ import yaml
|
|
|
10
11
|
from jarvis.jarvis_agent.output_handler import OutputHandler
|
|
11
12
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
12
13
|
from jarvis.jarvis_tools.base import Tool
|
|
13
|
-
from jarvis.jarvis_utils.config import
|
|
14
|
-
INPUT_WINDOW_REVERSE_SIZE,
|
|
15
|
-
get_max_input_token_count,
|
|
16
|
-
get_data_dir,
|
|
17
|
-
)
|
|
18
|
-
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
14
|
+
from jarvis.jarvis_utils.config import get_data_dir
|
|
19
15
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
20
|
-
from jarvis.jarvis_utils.utils import init_env
|
|
16
|
+
from jarvis.jarvis_utils.utils import init_env, is_context_overflow
|
|
21
17
|
from jarvis.jarvis_utils.tag import ot, ct
|
|
22
18
|
from jarvis.jarvis_mcp.stdio_mcp_client import StdioMcpClient
|
|
23
19
|
from jarvis.jarvis_mcp.sse_mcp_client import SSEMcpClient
|
|
@@ -175,9 +171,6 @@ class ToolRegistry(OutputHandler):
|
|
|
175
171
|
self._load_builtin_tools()
|
|
176
172
|
self._load_external_tools()
|
|
177
173
|
self._load_mcp_tools()
|
|
178
|
-
self.max_input_token_count = (
|
|
179
|
-
get_max_input_token_count() - INPUT_WINDOW_REVERSE_SIZE
|
|
180
|
-
)
|
|
181
174
|
|
|
182
175
|
def use_tools(self, name: List[str]) -> None:
|
|
183
176
|
"""使用指定工具
|
|
@@ -618,46 +611,45 @@ class ToolRegistry(OutputHandler):
|
|
|
618
611
|
result["stdout"], result.get("stderr", "")
|
|
619
612
|
)
|
|
620
613
|
|
|
621
|
-
#
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
614
|
+
# 检查内容是否过大
|
|
615
|
+
is_large_content = is_context_overflow(output)
|
|
616
|
+
|
|
617
|
+
if is_large_content:
|
|
618
|
+
# 创建临时文件
|
|
619
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as tmp_file:
|
|
626
620
|
output_file = tmp_file.name
|
|
627
621
|
tmp_file.write(output)
|
|
628
622
|
tmp_file.flush()
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
623
|
+
|
|
624
|
+
try:
|
|
625
|
+
# 获取平台实例
|
|
626
|
+
platform = PlatformRegistry().get_normal_platform()
|
|
627
|
+
if platform and hasattr(platform, 'upload_files'):
|
|
628
|
+
platform.set_suppress_output(False)
|
|
633
629
|
# 尝试上传文件
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
2. 如果文件内容包含错误信息,请特别关注并提取
|
|
640
|
-
3. 提取的信息应该直接回答用户的问题,不要包含无关内容"""
|
|
630
|
+
upload_success = platform.upload_files([output_file])
|
|
631
|
+
|
|
632
|
+
if upload_success:
|
|
633
|
+
# 使用上传的文件生成摘要
|
|
634
|
+
prompt = f"该文件为工具执行结果,请阅读文件内容,并根据文件提取出以下信息:{want}"
|
|
641
635
|
return f"""工具调用原始输出过长,以下是根据输出提出的信息:
|
|
642
636
|
|
|
643
637
|
{platform.chat_until_success(prompt)}"""
|
|
644
|
-
|
|
645
|
-
#
|
|
646
|
-
|
|
647
|
-
from jarvis.jarvis_utils.utils import chat_with_files
|
|
648
|
-
prompt = f"""请阅读以下文件内容,并根据文件提取出以下信息:{want}
|
|
649
|
-
|
|
650
|
-
注意:
|
|
651
|
-
1. 请仔细阅读文件内容,确保提取的信息准确完整
|
|
652
|
-
2. 如果文件内容包含错误信息,请特别关注并提取
|
|
653
|
-
3. 提取的信息应该直接回答用户的问题,不要包含无关内容"""
|
|
638
|
+
elif hasattr(platform, 'chat_big_content'):
|
|
639
|
+
# 如果上传失败但支持大内容处理,使用chat_big_content
|
|
640
|
+
prompt = f"以下内容为工具执行结果,请阅读内容,并根据内容提取出以下信息:{want}\n\n{output}"
|
|
654
641
|
return f"""工具调用原始输出过长,以下是根据输出提出的信息:
|
|
655
642
|
|
|
656
|
-
{
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
643
|
+
{platform.chat_big_content(output, prompt)}"""
|
|
644
|
+
|
|
645
|
+
# 如果都不支持,返回截断的输出
|
|
646
|
+
return self._truncate_output(output)
|
|
647
|
+
finally:
|
|
648
|
+
# 清理临时文件
|
|
649
|
+
try:
|
|
650
|
+
os.unlink(output_file)
|
|
651
|
+
except Exception:
|
|
652
|
+
pass
|
|
661
653
|
|
|
662
654
|
return output
|
|
663
655
|
|
|
@@ -16,7 +16,7 @@ class SearchWebTool:
|
|
|
16
16
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]: # type: ignore
|
|
17
17
|
query = args.get("query")
|
|
18
18
|
model = PlatformRegistry().get_normal_platform()
|
|
19
|
-
model.
|
|
19
|
+
model.set_web(True)
|
|
20
20
|
model.set_suppress_output(False) # type: ignore
|
|
21
21
|
return {
|
|
22
22
|
"stdout": model.chat_until_success(query), # type: ignore
|
|
@@ -11,10 +11,10 @@ import json
|
|
|
11
11
|
import tempfile
|
|
12
12
|
from typing import Dict, Optional
|
|
13
13
|
|
|
14
|
-
from jarvis.jarvis_utils.config import
|
|
15
|
-
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
14
|
+
from jarvis.jarvis_utils.config import get_data_dir
|
|
16
15
|
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
|
17
16
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
17
|
+
from jarvis.jarvis_utils.utils import is_context_overflow
|
|
18
18
|
|
|
19
19
|
def _get_methodology_directory() -> str:
|
|
20
20
|
"""
|
|
@@ -101,7 +101,7 @@ def load_methodology(user_input: str) -> str:
|
|
|
101
101
|
返回:
|
|
102
102
|
str: 相关的方法论提示,如果未找到方法论则返回空字符串
|
|
103
103
|
"""
|
|
104
|
-
from yaspin import yaspin
|
|
104
|
+
from yaspin import yaspin # type: ignore
|
|
105
105
|
|
|
106
106
|
# 获取方法论目录
|
|
107
107
|
methodology_dir = _get_methodology_directory()
|
|
@@ -121,33 +121,21 @@ def load_methodology(user_input: str) -> str:
|
|
|
121
121
|
|
|
122
122
|
# 获取当前平台
|
|
123
123
|
platform = PlatformRegistry().get_normal_platform()
|
|
124
|
+
if not platform:
|
|
125
|
+
return ""
|
|
126
|
+
|
|
127
|
+
# 构建基础提示信息
|
|
128
|
+
base_prompt = f"""以下是所有可用的方法论内容:
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
# 构建完整内容
|
|
132
|
+
full_content = base_prompt
|
|
133
|
+
for problem_type, content in methodologies.items():
|
|
134
|
+
full_content += f"## {problem_type}\n\n{content}\n\n---\n\n"
|
|
124
135
|
|
|
125
|
-
#
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
with yaspin(text="创建方法论临时文件...", color="yellow") as spinner:
|
|
129
|
-
temp_file_path = _create_methodology_temp_file(methodologies)
|
|
130
|
-
if not temp_file_path:
|
|
131
|
-
spinner.text = "创建方法论临时文件失败"
|
|
132
|
-
spinner.fail("❌")
|
|
133
|
-
return ""
|
|
134
|
-
spinner.text = f"创建方法论临时文件完成: {temp_file_path}"
|
|
135
|
-
spinner.ok("✅")
|
|
136
|
-
|
|
137
|
-
# 尝试上传文件
|
|
138
|
-
upload_success = False
|
|
139
|
-
try:
|
|
140
|
-
if platform.upload_files([temp_file_path]):
|
|
141
|
-
upload_success = True
|
|
142
|
-
spinner.write("✅ 成功上传方法论文件")
|
|
143
|
-
else:
|
|
144
|
-
spinner.write("⚠️ 上传方法论文件失败,将使用chat_with_files处理")
|
|
145
|
-
except Exception as e:
|
|
146
|
-
spinner.write(f"⚠️ 上传文件时出错: {str(e)}")
|
|
147
|
-
upload_success = False
|
|
148
|
-
|
|
149
|
-
# 构建提示信息
|
|
150
|
-
prompt = f"""请根据以下方法论内容,总结出与以下用户需求相关的方法论: {user_input}
|
|
136
|
+
# 添加用户输入和输出要求
|
|
137
|
+
full_content += f"""
|
|
138
|
+
请根据以上方法论内容,总结出与以下用户需求相关的方法论: {user_input}
|
|
151
139
|
|
|
152
140
|
请按以下格式回复:
|
|
153
141
|
### 与该任务/需求相关的方法论
|
|
@@ -157,24 +145,48 @@ def load_methodology(user_input: str) -> str:
|
|
|
157
145
|
[总结的方法论内容]
|
|
158
146
|
|
|
159
147
|
如果没有匹配的方法论,请输出:没有历史方法论可参考
|
|
160
|
-
除以上要求外,不要输出任何内容
|
|
161
|
-
|
|
162
|
-
if upload_success:
|
|
163
|
-
# 使用上传的文件
|
|
164
|
-
return platform.chat_until_success(prompt)
|
|
165
|
-
else:
|
|
166
|
-
# 使用chat_with_files处理大文件
|
|
167
|
-
from jarvis.jarvis_utils.utils import chat_with_files
|
|
168
|
-
return chat_with_files([temp_file_path], platform, prompt, "")
|
|
169
|
-
else:
|
|
170
|
-
# 上下文足够,直接在prompt中包含方法论内容
|
|
171
|
-
prompt = f"""以下是所有可用的方法论内容:
|
|
172
|
-
|
|
148
|
+
除以上要求外,不要输出任何内容
|
|
173
149
|
"""
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
150
|
+
|
|
151
|
+
# 检查内容是否过大
|
|
152
|
+
is_large_content = is_context_overflow(full_content)
|
|
153
|
+
temp_file_path = None
|
|
154
|
+
|
|
155
|
+
try:
|
|
156
|
+
if is_large_content:
|
|
157
|
+
# 创建临时文件
|
|
158
|
+
with yaspin(text="创建方法论临时文件...", color="yellow") as spinner:
|
|
159
|
+
temp_file_path = _create_methodology_temp_file(methodologies)
|
|
160
|
+
if not temp_file_path:
|
|
161
|
+
spinner.text = "创建方法论临时文件失败"
|
|
162
|
+
spinner.fail("❌")
|
|
163
|
+
return ""
|
|
164
|
+
spinner.text = f"创建方法论临时文件完成: {temp_file_path}"
|
|
165
|
+
spinner.ok("✅")
|
|
166
|
+
|
|
167
|
+
# 尝试上传文件
|
|
168
|
+
if hasattr(platform, 'upload_files'):
|
|
169
|
+
platform.set_suppress_output(False)
|
|
170
|
+
upload_success = platform.upload_files([temp_file_path])
|
|
171
|
+
|
|
172
|
+
if upload_success:
|
|
173
|
+
# 使用上传的文件生成摘要
|
|
174
|
+
return platform.chat_until_success(base_prompt + f"""
|
|
175
|
+
请根据已上传的方法论文件内容,总结出与以下用户需求相关的方法论: {user_input}
|
|
176
|
+
|
|
177
|
+
请按以下格式回复:
|
|
178
|
+
### 与该任务/需求相关的方法论
|
|
179
|
+
1. [方法论名字]
|
|
180
|
+
2. [方法论名字]
|
|
181
|
+
### 根据以上方法论,总结出方法论内容
|
|
182
|
+
[总结的方法论内容]
|
|
183
|
+
|
|
184
|
+
如果没有匹配的方法论,请输出:没有历史方法论可参考
|
|
185
|
+
除以上要求外,不要输出任何内容
|
|
186
|
+
""")
|
|
187
|
+
elif hasattr(platform, 'chat_big_content'):
|
|
188
|
+
# 如果上传失败但支持大内容处理,使用chat_big_content
|
|
189
|
+
return platform.chat_big_content(full_content, base_prompt + f"""
|
|
178
190
|
请根据以上方法论内容,总结出与以下用户需求相关的方法论: {user_input}
|
|
179
191
|
|
|
180
192
|
请按以下格式回复:
|
|
@@ -185,22 +197,20 @@ def load_methodology(user_input: str) -> str:
|
|
|
185
197
|
[总结的方法论内容]
|
|
186
198
|
|
|
187
199
|
如果没有匹配的方法论,请输出:没有历史方法论可参考
|
|
188
|
-
除以上要求外,不要输出任何内容
|
|
189
|
-
|
|
200
|
+
除以上要求外,不要输出任何内容
|
|
201
|
+
""")
|
|
202
|
+
|
|
203
|
+
# 如果内容不大或上传失败,直接使用chat_until_success
|
|
204
|
+
return platform.chat_until_success(full_content)
|
|
205
|
+
|
|
206
|
+
finally:
|
|
207
|
+
# 清理临时文件
|
|
208
|
+
if temp_file_path and os.path.exists(temp_file_path):
|
|
209
|
+
try:
|
|
210
|
+
os.remove(temp_file_path)
|
|
211
|
+
except Exception:
|
|
212
|
+
pass
|
|
190
213
|
|
|
191
214
|
except Exception as e:
|
|
192
215
|
PrettyOutput.print(f"加载方法论失败: {str(e)}", OutputType.ERROR)
|
|
193
|
-
# 清理临时文件
|
|
194
|
-
if 'temp_file_path' in locals() and temp_file_path and os.path.exists(temp_file_path):
|
|
195
|
-
try:
|
|
196
|
-
os.remove(temp_file_path)
|
|
197
|
-
except:
|
|
198
|
-
pass
|
|
199
216
|
return ""
|
|
200
|
-
finally:
|
|
201
|
-
# 确保清理临时文件
|
|
202
|
-
if 'temp_file_path' in locals() and temp_file_path and os.path.exists(temp_file_path):
|
|
203
|
-
try:
|
|
204
|
-
os.remove(temp_file_path)
|
|
205
|
-
except:
|
|
206
|
-
pass
|
jarvis/jarvis_utils/utils.py
CHANGED
|
@@ -3,8 +3,8 @@ import time
|
|
|
3
3
|
import hashlib
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import List, Any, Callable
|
|
6
|
-
from jarvis.jarvis_utils.config import get_max_input_token_count, get_data_dir
|
|
7
|
-
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
6
|
+
from jarvis.jarvis_utils.config import INPUT_WINDOW_REVERSE_SIZE, get_max_input_token_count, get_data_dir
|
|
7
|
+
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
8
8
|
from jarvis.jarvis_utils.input import get_single_line_input
|
|
9
9
|
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
|
10
10
|
def init_env() -> None:
|
|
@@ -130,13 +130,6 @@ def is_long_context(files: List[str]) -> bool:
|
|
|
130
130
|
return total_tokens > threshold
|
|
131
131
|
|
|
132
132
|
|
|
133
|
-
def
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
platform_: BasePlatform = platform
|
|
137
|
-
file_content = FileOperationTool().execute({"operation":"read", "files":files})["stdout"]
|
|
138
|
-
file_content_chuck = split_text_into_chunks(file_content, get_max_input_token_count()-2048)
|
|
139
|
-
platform_.chat_until_success(prompt_prefix)
|
|
140
|
-
for file_content_chunk in file_content_chuck:
|
|
141
|
-
platform_.chat_until_success(file_content_chunk)
|
|
142
|
-
return platform_.chat_until_success(prompt_suffix)
|
|
133
|
+
def is_context_overflow(file_content: str) -> bool:
|
|
134
|
+
"""判断文件内容是否超出上下文限制"""
|
|
135
|
+
return get_context_token_count(file_content) > get_max_input_token_count() - INPUT_WINDOW_REVERSE_SIZE
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jarvis-ai-assistant
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.160
|
|
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
|
|
@@ -194,7 +194,7 @@ jarvis-methodology --help
|
|
|
194
194
|
### 环境变量配置
|
|
195
195
|
| 变量名称 | 默认值 | 说明 |
|
|
196
196
|
|----------|--------|------|
|
|
197
|
-
| `JARVIS_MAX_TOKEN_COUNT` | 102400000 |
|
|
197
|
+
| `JARVIS_MAX_TOKEN_COUNT` | 102400000 | 上下文窗口的最大token数量 |
|
|
198
198
|
| `JARVIS_MAX_INPUT_TOKEN_COUNT` | 32000 | 输入的最大token数量 |
|
|
199
199
|
| `JARVIS_AUTO_COMPLETE` | false | 是否启用自动完成功能(任务判定完成的时候会自动终止) |
|
|
200
200
|
| `JARVIS_SHELL_NAME` | bash | 系统shell名称 |
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
jarvis/__init__.py,sha256=
|
|
1
|
+
jarvis/__init__.py,sha256=2BC-X3PyDiJd9_Z7-M3Dz_vjF41hQuACD5kortAXRDM,50
|
|
2
2
|
jarvis/jarvis_agent/__init__.py,sha256=tii6khwfG971MJiMfKSLwlKTjB3iEv8ITE3JqYSkfQA,24824
|
|
3
3
|
jarvis/jarvis_agent/builtin_input_handler.py,sha256=3rRA-7v_VUSFG1s7tTKhriq9vv0nsa3t69ReV0xH5gs,1505
|
|
4
|
-
jarvis/jarvis_agent/file_input_handler.py,sha256=
|
|
4
|
+
jarvis/jarvis_agent/file_input_handler.py,sha256=88VqJLe3oO9GtIRsqyx3KwZl10Apob2ddFMH3HQ2RMg,3413
|
|
5
5
|
jarvis/jarvis_agent/jarvis.py,sha256=6Bp_Y-E3RN6bDmDs5lN3uALL_Dhq-p_aIuVNELG1vtw,5898
|
|
6
6
|
jarvis/jarvis_agent/main.py,sha256=Jlw_Tofh2C-sMVnkeOZBrwWJOWNH3IhsKDUn-WBlgU8,2602
|
|
7
7
|
jarvis/jarvis_agent/output_handler.py,sha256=4limQ-Kf-YYvQjT5SMjJIyyvD1DVG8tINv1A_qbv4ho,405
|
|
8
|
-
jarvis/jarvis_agent/patch.py,sha256=
|
|
8
|
+
jarvis/jarvis_agent/patch.py,sha256=qeRZ6r1qpgHnWpX5uOX4dB3qRCPI1ibk4J50NmoJ74s,23531
|
|
9
9
|
jarvis/jarvis_agent/shell_input_handler.py,sha256=9IoGQCe6FF4HA2V5S11q63AtnWDZFpNeRd3hcqCAlBw,1237
|
|
10
10
|
jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
jarvis/jarvis_code_agent/code_agent.py,sha256=vi_g-LWdD5nn3RQsC1X8G2iNK8SrBADwFLUkflqtvKE,13723
|
|
12
|
-
jarvis/jarvis_code_analysis/code_review.py,sha256=
|
|
12
|
+
jarvis/jarvis_code_analysis/code_review.py,sha256=gB9Xo0-FT6zciDzZb3jF6zxxWA_Aj8QU5008Tmu_Tr4,30192
|
|
13
13
|
jarvis/jarvis_code_analysis/checklists/__init__.py,sha256=PCjlyxLa939613cAzS7pfEPgP57setO-1RvcdzzPivw,54
|
|
14
14
|
jarvis/jarvis_code_analysis/checklists/c_cpp.py,sha256=8lfWmhImAxeTBdHPOgVXDjMllaq280Qki1ZOOSDBnvk,1293
|
|
15
15
|
jarvis/jarvis_code_analysis/checklists/csharp.py,sha256=fg35Iima2nIsirEmAjianfAybVjwRYml9BtbSQFff7w,2396
|
|
@@ -35,7 +35,7 @@ jarvis/jarvis_git_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
|
35
35
|
jarvis/jarvis_git_details/main.py,sha256=YowncVxYyJ3y2EvGrZhAJeR4yizXp6aB3dqvoYTepFY,6117
|
|
36
36
|
jarvis/jarvis_git_squash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
37
|
jarvis/jarvis_git_squash/main.py,sha256=xBNkAl7_8_pQC-C6RcUImA1mEU4KTqhjtA57rG_mMJ8,2179
|
|
38
|
-
jarvis/jarvis_git_utils/git_commiter.py,sha256=
|
|
38
|
+
jarvis/jarvis_git_utils/git_commiter.py,sha256=nOzM5Zio6CYxuo14YfZHrdr5rPS-yjM0_UbRhsXjPy4,11644
|
|
39
39
|
jarvis/jarvis_lsp/base.py,sha256=f-76xgNijfQ4G3Q0t8IfOGtCu-q2TSQ7a_in6XwDb_8,2030
|
|
40
40
|
jarvis/jarvis_lsp/cpp.py,sha256=ekci2M9_UtkCSEe9__72h26Gat93r9_knL2VmFr8X5M,3141
|
|
41
41
|
jarvis/jarvis_lsp/go.py,sha256=sSypuQSP5X2YtrVMC8XCc5nXkgfG93SO7sC89lHzoR8,3458
|
|
@@ -45,13 +45,13 @@ jarvis/jarvis_lsp/rust.py,sha256=ICmQs5UVdMZwn5KjaF1YRXBCLUMtGF8Z9IwE5rqWkrU,368
|
|
|
45
45
|
jarvis/jarvis_mcp/__init__.py,sha256=gi74_Yz5nsEFhrAyCg1Ovxsj-hLweLjMGoOaceL2yx4,2090
|
|
46
46
|
jarvis/jarvis_mcp/sse_mcp_client.py,sha256=Qd09ymgZmxQvaFUzz8I3AI46v6AqmMbGaF0iBbExAGY,23459
|
|
47
47
|
jarvis/jarvis_mcp/stdio_mcp_client.py,sha256=DtRO4dqBoxI8W0H0rVR5zxZLR0theKxRAQ-qzQE9qPg,11806
|
|
48
|
-
jarvis/jarvis_methodology/main.py,sha256=
|
|
48
|
+
jarvis/jarvis_methodology/main.py,sha256=JrUqWKN0gQeiO_tY2Tn14pnT_jClqlNgpbBfoc-q8SM,11812
|
|
49
49
|
jarvis/jarvis_multi_agent/__init__.py,sha256=SX8lBErhltKyYRM-rymrMz3sJ0Zl3hBXrpsPdFgzkQc,4399
|
|
50
50
|
jarvis/jarvis_multi_agent/main.py,sha256=aGuUC3YQmahabqwDwZXJjfQLYsZ3KIZdf8DZDlVNMe4,1543
|
|
51
51
|
jarvis/jarvis_platform/__init__.py,sha256=oD9i4ugZ2q6Hys3noLOvzPUUHqE2PJ_Je1r2dLLTscw,80
|
|
52
|
-
jarvis/jarvis_platform/base.py,sha256=
|
|
52
|
+
jarvis/jarvis_platform/base.py,sha256=OfVG7jw-0han9yEooJLL0Sk3ZlgzItZwJOgRxZdFLfs,4085
|
|
53
53
|
jarvis/jarvis_platform/human.py,sha256=WCzvBtQUMN7ys4rQl6UT7Zdp4x5RaGv1U4vBx7ROxfo,2438
|
|
54
|
-
jarvis/jarvis_platform/kimi.py,sha256=
|
|
54
|
+
jarvis/jarvis_platform/kimi.py,sha256=Wno9PFZ92v9fjBHS29sFUwoc6gk6akD7yelVaWOpp-Q,16667
|
|
55
55
|
jarvis/jarvis_platform/registry.py,sha256=wvXTKXqAoW6GPaLKCPYhRB9QhVe1xfoVbVPBZAxl_uA,7716
|
|
56
56
|
jarvis/jarvis_platform/yuanbao.py,sha256=9nIyg5Xx9rdUaJAK_Tj8HumOT5mwpa-V907dZGot-4E,21811
|
|
57
57
|
jarvis/jarvis_platform_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -67,15 +67,15 @@ jarvis/jarvis_tools/code_plan.py,sha256=jNa2rs4J3Fam8Q_RHE2_QvVch21TPp-Zfv-W6iQ3
|
|
|
67
67
|
jarvis/jarvis_tools/create_code_agent.py,sha256=SRiQXZf57ViIDh6YSEmJkcoSKft0-y3iDfWF8f1bvZU,3387
|
|
68
68
|
jarvis/jarvis_tools/create_sub_agent.py,sha256=wGiHukvi58wb1AKW5beP7R8VvApOn8TOeGmtXsmcETE,3001
|
|
69
69
|
jarvis/jarvis_tools/execute_script.py,sha256=AeuC3yZIg-nBq_LTIyqxu-lG_uLG63lvwO28A6dRDYA,5715
|
|
70
|
-
jarvis/jarvis_tools/file_analyzer.py,sha256=
|
|
71
|
-
jarvis/jarvis_tools/file_operation.py,sha256=
|
|
70
|
+
jarvis/jarvis_tools/file_analyzer.py,sha256=EVl7WqGgZoaQXqEX8vLynpqZDE3aug1hVBJbycT7YiY,4844
|
|
71
|
+
jarvis/jarvis_tools/file_operation.py,sha256=zbc1zX_aJ-9x1wpuUUbZOgg0aN8f5sd9ryaCQ-bi870,9124
|
|
72
72
|
jarvis/jarvis_tools/find_methodology.py,sha256=TIUrezAql6wY3-wqnOPfGrO0tqS5N_-eU6YimCzaepM,2268
|
|
73
73
|
jarvis/jarvis_tools/lsp_get_diagnostics.py,sha256=IYqv8jQwSK71sZpDBRolSDnYii8t0M7fzLthhMYTeGk,5322
|
|
74
74
|
jarvis/jarvis_tools/methodology.py,sha256=gnlJojY4Dg5v9AAB5xcpKqpPIHs0tOYVtzTHkwOrWk0,5214
|
|
75
75
|
jarvis/jarvis_tools/read_code.py,sha256=_X6D3AIgRD9YplSDnFhXOm8wQAZMA3pkkXy31SG33l0,6041
|
|
76
|
-
jarvis/jarvis_tools/read_webpage.py,sha256=
|
|
77
|
-
jarvis/jarvis_tools/registry.py,sha256=
|
|
78
|
-
jarvis/jarvis_tools/search_web.py,sha256=
|
|
76
|
+
jarvis/jarvis_tools/read_webpage.py,sha256=ECcMnPnUpIeiSA1IRdUf7uLWMe34Ian9pExSxekwpcg,2025
|
|
77
|
+
jarvis/jarvis_tools/registry.py,sha256=6md5Fm-Uv0dhTHj0qubHRj0VQkNIcNn0A1cshBOQY5o,27109
|
|
78
|
+
jarvis/jarvis_tools/search_web.py,sha256=p1oahjSmSeBO9ZzgWkxIHsfcAGah22ju0xipXmuqnzg,759
|
|
79
79
|
jarvis/jarvis_tools/virtual_tty.py,sha256=Rpn9VXUG17LQsY87F_O6UCjN_opXB05mpwozxYf-xVI,16372
|
|
80
80
|
jarvis/jarvis_utils/__init__.py,sha256=KMg-KY5rZIhGTeOD5e2Xo5CU7DX1DUz4ULWAaTQ-ZNw,825
|
|
81
81
|
jarvis/jarvis_utils/builtin_replace_map.py,sha256=Dt8YL4Sk5uALTMPT_n-lhshRWvFWPRPwV4stASOecQ8,4290
|
|
@@ -85,13 +85,13 @@ jarvis/jarvis_utils/file_processors.py,sha256=oNtVlz2JHcQ60NS6sgI-VsvYXOnsQgFUEV
|
|
|
85
85
|
jarvis/jarvis_utils/git_utils.py,sha256=j_Jw6h7JD91XhMf0WD3MAH4URkLUBrrYCLnuLm1GeN4,5630
|
|
86
86
|
jarvis/jarvis_utils/globals.py,sha256=Ed2d6diWXCgI74HVV_tI4qW7yXxLpNvQKN2yG0IH9hc,3388
|
|
87
87
|
jarvis/jarvis_utils/input.py,sha256=zvL-JQSJvkmsZB7ApJsaVpk46BkpmJA3I_BnWSl_D-4,7299
|
|
88
|
-
jarvis/jarvis_utils/methodology.py,sha256=
|
|
88
|
+
jarvis/jarvis_utils/methodology.py,sha256=a1QJLqZ-_RwhL6i7C6mixhT1BmOvZ0mKmh3PTOiNT9M,7744
|
|
89
89
|
jarvis/jarvis_utils/output.py,sha256=BmWdB1bmizv0xfU4Z___9p_xQodorriIcEgADVq9fk0,8416
|
|
90
90
|
jarvis/jarvis_utils/tag.py,sha256=YtXBYuZWy8j8YbeQX2qRrHRQl6Gp2Vt7W4p-2yjo0a4,405
|
|
91
|
-
jarvis/jarvis_utils/utils.py,sha256=
|
|
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.
|
|
97
|
-
jarvis_ai_assistant-0.1.
|
|
91
|
+
jarvis/jarvis_utils/utils.py,sha256=neokG_C9Djw6shwLcBxpQmRF5KFp9P6v52bMJMEFozg,4487
|
|
92
|
+
jarvis_ai_assistant-0.1.160.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
|
93
|
+
jarvis_ai_assistant-0.1.160.dist-info/METADATA,sha256=yjL-ZV1dnisJxbtkjiQH9fOeGGv0hI7SUGKIPWnz_h8,12669
|
|
94
|
+
jarvis_ai_assistant-0.1.160.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
95
|
+
jarvis_ai_assistant-0.1.160.dist-info/entry_points.txt,sha256=cKz_9SEpOvElTubKPMZMAdskD4GHz-NyKWRNssIVAWE,973
|
|
96
|
+
jarvis_ai_assistant-0.1.160.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
|
97
|
+
jarvis_ai_assistant-0.1.160.dist-info/RECORD,,
|
|
File without changes
|
{jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.160.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.160.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{jarvis_ai_assistant-0.1.159.dist-info → jarvis_ai_assistant-0.1.160.dist-info}/top_level.txt
RENAMED
|
File without changes
|