jarvis-ai-assistant 0.1.138__py3-none-any.whl → 0.1.141__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/__init__.py +62 -14
- jarvis/jarvis_agent/builtin_input_handler.py +4 -14
- jarvis/jarvis_agent/main.py +1 -1
- jarvis/jarvis_agent/patch.py +37 -40
- jarvis/jarvis_agent/shell_input_handler.py +2 -3
- jarvis/jarvis_code_agent/code_agent.py +23 -30
- jarvis/jarvis_code_analysis/checklists/__init__.py +3 -0
- jarvis/jarvis_code_analysis/checklists/c_cpp.py +50 -0
- jarvis/jarvis_code_analysis/checklists/csharp.py +75 -0
- jarvis/jarvis_code_analysis/checklists/data_format.py +82 -0
- jarvis/jarvis_code_analysis/checklists/devops.py +107 -0
- jarvis/jarvis_code_analysis/checklists/docs.py +87 -0
- jarvis/jarvis_code_analysis/checklists/go.py +52 -0
- jarvis/jarvis_code_analysis/checklists/infrastructure.py +98 -0
- jarvis/jarvis_code_analysis/checklists/java.py +66 -0
- jarvis/jarvis_code_analysis/checklists/javascript.py +73 -0
- jarvis/jarvis_code_analysis/checklists/kotlin.py +107 -0
- jarvis/jarvis_code_analysis/checklists/loader.py +76 -0
- jarvis/jarvis_code_analysis/checklists/php.py +77 -0
- jarvis/jarvis_code_analysis/checklists/python.py +56 -0
- jarvis/jarvis_code_analysis/checklists/ruby.py +107 -0
- jarvis/jarvis_code_analysis/checklists/rust.py +58 -0
- jarvis/jarvis_code_analysis/checklists/shell.py +75 -0
- jarvis/jarvis_code_analysis/checklists/sql.py +72 -0
- jarvis/jarvis_code_analysis/checklists/swift.py +77 -0
- jarvis/jarvis_code_analysis/checklists/web.py +97 -0
- jarvis/jarvis_code_analysis/code_review.py +660 -0
- jarvis/jarvis_dev/main.py +61 -88
- jarvis/jarvis_git_squash/main.py +3 -3
- jarvis/jarvis_git_utils/git_commiter.py +242 -0
- jarvis/jarvis_init/main.py +62 -0
- jarvis/jarvis_platform/base.py +4 -0
- jarvis/jarvis_platform/kimi.py +173 -5
- jarvis/jarvis_platform/openai.py +3 -0
- jarvis/jarvis_platform/registry.py +1 -0
- jarvis/jarvis_platform/yuanbao.py +275 -5
- jarvis/jarvis_tools/ask_codebase.py +6 -9
- jarvis/jarvis_tools/ask_user.py +17 -5
- jarvis/jarvis_tools/base.py +3 -1
- jarvis/jarvis_tools/chdir.py +1 -0
- jarvis/jarvis_tools/create_code_agent.py +4 -3
- jarvis/jarvis_tools/create_sub_agent.py +1 -0
- jarvis/jarvis_tools/execute_script.py +170 -0
- jarvis/jarvis_tools/file_analyzer.py +90 -239
- jarvis/jarvis_tools/file_operation.py +99 -31
- jarvis/jarvis_tools/{find_methodolopy.py → find_methodology.py} +2 -1
- jarvis/jarvis_tools/lsp_get_diagnostics.py +2 -0
- jarvis/jarvis_tools/methodology.py +11 -11
- jarvis/jarvis_tools/read_code.py +2 -0
- jarvis/jarvis_tools/read_webpage.py +33 -196
- jarvis/jarvis_tools/registry.py +68 -131
- jarvis/jarvis_tools/search_web.py +14 -6
- jarvis/jarvis_tools/virtual_tty.py +399 -0
- jarvis/jarvis_utils/config.py +29 -3
- jarvis/jarvis_utils/embedding.py +0 -317
- jarvis/jarvis_utils/file_processors.py +343 -0
- jarvis/jarvis_utils/input.py +0 -1
- jarvis/jarvis_utils/methodology.py +94 -435
- jarvis/jarvis_utils/utils.py +207 -9
- {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/METADATA +4 -4
- jarvis_ai_assistant-0.1.141.dist-info/RECORD +94 -0
- {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/entry_points.txt +4 -4
- jarvis/jarvis_code_agent/file_select.py +0 -202
- jarvis/jarvis_platform/ai8.py +0 -268
- jarvis/jarvis_platform/ollama.py +0 -137
- jarvis/jarvis_platform/oyi.py +0 -307
- jarvis/jarvis_rag/file_processors.py +0 -138
- jarvis/jarvis_rag/main.py +0 -1734
- jarvis/jarvis_tools/code_review.py +0 -333
- jarvis/jarvis_tools/execute_python_script.py +0 -58
- jarvis/jarvis_tools/execute_shell.py +0 -97
- jarvis/jarvis_tools/execute_shell_script.py +0 -58
- jarvis/jarvis_tools/find_caller.py +0 -278
- jarvis/jarvis_tools/find_symbol.py +0 -295
- jarvis/jarvis_tools/function_analyzer.py +0 -331
- jarvis/jarvis_tools/git_commiter.py +0 -167
- jarvis/jarvis_tools/project_analyzer.py +0 -304
- jarvis/jarvis_tools/rag.py +0 -143
- jarvis/jarvis_tools/tool_generator.py +0 -221
- jarvis_ai_assistant-0.1.138.dist-info/RECORD +0 -85
- /jarvis/{jarvis_rag → jarvis_init}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/top_level.txt +0 -0
jarvis/jarvis_dev/main.py
CHANGED
|
@@ -55,8 +55,7 @@ PM_PROMPT = f"""
|
|
|
55
55
|
- **ask_user**:获取用户需求和反馈,澄清不明确的需求点
|
|
56
56
|
- **file_operation**:创建和管理项目文档,跟踪项目状态
|
|
57
57
|
- **search_web**:研究相关领域知识,寻找最佳实践
|
|
58
|
-
- **
|
|
59
|
-
- **execute_shell**:监控项目状态,执行自动化任务
|
|
58
|
+
- **execute_script**:监控项目状态,执行自动化任务
|
|
60
59
|
- **read_webpage**:收集行业信息和最新技术动态
|
|
61
60
|
- **project_analyzer**:分析项目结构和架构,了解整体情况
|
|
62
61
|
- **methodology**:采用适当的项目方法论和最佳实践
|
|
@@ -88,13 +87,13 @@ content: |
|
|
|
88
87
|
|
|
89
88
|
## 文档管理规范
|
|
90
89
|
### 项目文档结构
|
|
91
|
-
-
|
|
90
|
+
- `requirements/`:存放需求相关文档
|
|
92
91
|
- `project_requirements_v<version>.md`:项目需求文档
|
|
93
92
|
- `change_log.md`:需求变更记录
|
|
94
|
-
-
|
|
93
|
+
- `status_reports/`:存放状态报告
|
|
95
94
|
- `weekly_status_report.md`:周报
|
|
96
95
|
- `risk_register.md`:风险登记册
|
|
97
|
-
-
|
|
96
|
+
- `communication/`:存放沟通记录
|
|
98
97
|
- `team_communication_log.md`:团队沟通日志
|
|
99
98
|
- `decision_log.md`:决策记录
|
|
100
99
|
|
|
@@ -384,8 +383,7 @@ def create_dev_team() -> MultiAgent:
|
|
|
384
383
|
"ask_user",
|
|
385
384
|
"file_operation",
|
|
386
385
|
"search_web",
|
|
387
|
-
"
|
|
388
|
-
"execute_shell",
|
|
386
|
+
"execute_script",
|
|
389
387
|
"read_webpage",
|
|
390
388
|
"project_analyzer",
|
|
391
389
|
"methodology",
|
|
@@ -397,8 +395,7 @@ def create_dev_team() -> MultiAgent:
|
|
|
397
395
|
"ask_user",
|
|
398
396
|
"file_operation",
|
|
399
397
|
"search_web",
|
|
400
|
-
"
|
|
401
|
-
"execute_shell",
|
|
398
|
+
"execute_script",
|
|
402
399
|
"read_webpage",
|
|
403
400
|
"methodology",
|
|
404
401
|
"ask_codebase"
|
|
@@ -408,12 +405,8 @@ def create_dev_team() -> MultiAgent:
|
|
|
408
405
|
SA_output_handler.use_tools([
|
|
409
406
|
"file_operation",
|
|
410
407
|
"search_web",
|
|
411
|
-
"rag",
|
|
412
408
|
"ask_codebase",
|
|
413
|
-
"
|
|
414
|
-
"project_analyzer",
|
|
415
|
-
"file_analyzer",
|
|
416
|
-
"function_analyzer",
|
|
409
|
+
"execute_script",
|
|
417
410
|
"read_code",
|
|
418
411
|
"methodology"
|
|
419
412
|
])
|
|
@@ -423,12 +416,9 @@ def create_dev_team() -> MultiAgent:
|
|
|
423
416
|
"file_operation",
|
|
424
417
|
"ask_codebase",
|
|
425
418
|
"lsp_get_diagnostics",
|
|
426
|
-
"
|
|
427
|
-
"
|
|
428
|
-
"
|
|
429
|
-
"find_caller",
|
|
430
|
-
"function_analyzer",
|
|
431
|
-
"project_analyzer"
|
|
419
|
+
"execute_script",
|
|
420
|
+
"project_analyzer",
|
|
421
|
+
"methodology",
|
|
432
422
|
])
|
|
433
423
|
|
|
434
424
|
DEV_output_handler = ToolRegistry()
|
|
@@ -436,12 +426,10 @@ def create_dev_team() -> MultiAgent:
|
|
|
436
426
|
"create_code_agent",
|
|
437
427
|
"file_operation",
|
|
438
428
|
"ask_codebase",
|
|
439
|
-
"
|
|
440
|
-
"find_symbol",
|
|
441
|
-
"function_analyzer",
|
|
442
|
-
"file_analyzer",
|
|
429
|
+
"execute_script",
|
|
443
430
|
"read_code",
|
|
444
|
-
"create_sub_agent"
|
|
431
|
+
"create_sub_agent",
|
|
432
|
+
"methodology",
|
|
445
433
|
])
|
|
446
434
|
|
|
447
435
|
QA_output_handler = ToolRegistry()
|
|
@@ -449,11 +437,11 @@ def create_dev_team() -> MultiAgent:
|
|
|
449
437
|
"create_code_agent",
|
|
450
438
|
"file_operation",
|
|
451
439
|
"ask_codebase",
|
|
452
|
-
"
|
|
440
|
+
"execute_script",
|
|
453
441
|
"lsp_get_diagnostics",
|
|
454
|
-
"
|
|
455
|
-
"execute_shell_script",
|
|
442
|
+
"execute_script",
|
|
456
443
|
"read_code",
|
|
444
|
+
"methodology",
|
|
457
445
|
])
|
|
458
446
|
|
|
459
447
|
# Update PM prompt with tool usage guidance
|
|
@@ -462,8 +450,7 @@ def create_dev_team() -> MultiAgent:
|
|
|
462
450
|
- **ask_user**:获取用户需求和反馈,澄清不明确的需求点
|
|
463
451
|
- **file_operation**:创建和管理项目文档,跟踪项目状态
|
|
464
452
|
- **search_web**:研究相关领域知识,寻找最佳实践
|
|
465
|
-
- **
|
|
466
|
-
- **execute_shell**:监控项目状态,执行自动化任务
|
|
453
|
+
- **execute_script**:监控项目状态,执行自动化任务
|
|
467
454
|
- **read_webpage**:收集行业信息和最新技术动态
|
|
468
455
|
- **project_analyzer**:分析项目结构和架构,了解整体情况
|
|
469
456
|
- **methodology**:采用适当的项目方法论和最佳实践
|
|
@@ -471,11 +458,11 @@ def create_dev_team() -> MultiAgent:
|
|
|
471
458
|
|
|
472
459
|
## 文档管理规范
|
|
473
460
|
每一步工作后,必须使用file_operation工具将结论性输出记录到项目文档中:
|
|
474
|
-
1.
|
|
475
|
-
2.
|
|
476
|
-
3.
|
|
477
|
-
4.
|
|
478
|
-
5.
|
|
461
|
+
1. 需求确认后,创建`requirements/project_requirements_v<version>.md`记录需求文档
|
|
462
|
+
2. 任务分配后,创建`status_reports/task_assignments.md`记录任务分配情况
|
|
463
|
+
3. 项目阶段完成后,创建`status_reports/project_status_report.md`记录项目进度
|
|
464
|
+
4. 遇到的风险和问题,记录到`status_reports/risk_register.md`
|
|
465
|
+
5. 重要决策和变更,记录到`communication/decision_log.md`
|
|
479
466
|
|
|
480
467
|
文档命名需规范,内容需要结构化,使用Markdown格式,便于团队成员理解和跟进。
|
|
481
468
|
"""
|
|
@@ -486,20 +473,19 @@ def create_dev_team() -> MultiAgent:
|
|
|
486
473
|
- **ask_user**:深入了解用户需求,进行需求挖掘和验证
|
|
487
474
|
- **file_operation**:创建和管理需求文档与分析资料
|
|
488
475
|
- **search_web**:研究行业标准和最佳实践
|
|
489
|
-
- **
|
|
490
|
-
- **execute_shell**:查询系统环境和配置信息
|
|
476
|
+
- **execute_script**:查询系统环境和配置信息
|
|
491
477
|
- **read_webpage**:收集用户体验和行业趋势信息
|
|
492
478
|
- **methodology**:应用需求分析和用户故事映射方法论
|
|
493
479
|
- **ask_codebase**:分析代码库中的功能实现,了解现有系统能力和限制,分析业务逻辑
|
|
494
480
|
|
|
495
481
|
## 文档管理规范
|
|
496
482
|
每一步分析后,必须使用file_operation工具将结论性输出记录到分析文档中:
|
|
497
|
-
1.
|
|
498
|
-
2.
|
|
499
|
-
3.
|
|
500
|
-
4.
|
|
501
|
-
5.
|
|
502
|
-
6.
|
|
483
|
+
1. 需求分析完成后,创建`analysis/requirements_analysis_v<version>.md`记录分析结果
|
|
484
|
+
2. 用户故事编写后,创建`analysis/user_stories_v<version>.md`记录用户故事
|
|
485
|
+
3. 功能规格确定后,创建`specs/functional_specs.md`记录功能规格
|
|
486
|
+
4. 数据需求确定后,创建`specs/data_dictionary.md`记录数据字典
|
|
487
|
+
5. 业务流程分析后,创建`models/process_flows.md`记录业务流程
|
|
488
|
+
6. 数据模型设计后,创建`models/data_models.md`记录数据模型
|
|
503
489
|
|
|
504
490
|
文档需要结构化,使用Markdown格式,包含清晰的需求描述、优先级、验收标准和依赖关系。
|
|
505
491
|
"""
|
|
@@ -509,23 +495,19 @@ def create_dev_team() -> MultiAgent:
|
|
|
509
495
|
## 工具使用指南
|
|
510
496
|
- **file_operation**:创建和管理架构文档和技术规格
|
|
511
497
|
- **search_web**:研究架构模式和技术趋势
|
|
512
|
-
- **rag**:访问架构知识库,参考历史设计决策
|
|
513
498
|
- **ask_codebase**:分析代码库,理解系统实现
|
|
514
|
-
- **
|
|
515
|
-
- **project_analyzer**:分析项目结构,理解模块划分
|
|
516
|
-
- **file_analyzer**:深入分析关键文件的结构和功能
|
|
517
|
-
- **function_analyzer**:分析核心函数的实现和设计
|
|
499
|
+
- **execute_script**:检查系统环境和依赖关系
|
|
518
500
|
- **read_code**:阅读和理解关键代码段
|
|
519
501
|
- **methodology**:应用架构设计方法论和模式
|
|
520
502
|
|
|
521
503
|
## 文档管理规范
|
|
522
504
|
每一步架构设计后,必须使用file_operation工具将结论性输出记录到架构文档中:
|
|
523
|
-
1.
|
|
524
|
-
2.
|
|
525
|
-
3.
|
|
526
|
-
4. API
|
|
527
|
-
5.
|
|
528
|
-
6.
|
|
505
|
+
1. 系统架构设计后,创建`architecture/system_architecture_v<version>.md`记录架构文档
|
|
506
|
+
2. 架构图创建后,保存到`architecture/architecture_diagrams/`目录
|
|
507
|
+
3. 组件规格定义后,创建`technical_specs/component_specs/<component_name>.md`
|
|
508
|
+
4. API规格设计后,创建`technical_specs/api_specs/<api_name>.md`
|
|
509
|
+
5. 架构决策后,创建`decisions/adr_<number>_<decision_name>.md`记录架构决策
|
|
510
|
+
6. 技术选型评估后,创建`architecture/technology_evaluation.md`记录评估结果
|
|
529
511
|
|
|
530
512
|
文档需使用图表、表格等方式清晰展示架构设计,包含各组件职责、接口、性能考量及安全措施。
|
|
531
513
|
"""
|
|
@@ -536,22 +518,17 @@ def create_dev_team() -> MultiAgent:
|
|
|
536
518
|
- **file_operation**:管理技术文档和指导文件
|
|
537
519
|
- **ask_codebase**:分析代码库,理解实现细节
|
|
538
520
|
- **lsp_get_diagnostics**:检查代码问题和警告
|
|
539
|
-
- **
|
|
540
|
-
- **code_review**:进行代码审查,确保代码质量
|
|
541
|
-
- **find_symbol**:查找关键符号在代码中的使用
|
|
542
|
-
- **find_caller**:分析函数调用关系和依赖
|
|
543
|
-
- **function_analyzer**:深入分析函数实现和优化空间
|
|
544
|
-
- **project_analyzer**:分析项目结构和技术架构
|
|
521
|
+
- **execute_script**:执行开发工具和命令
|
|
545
522
|
|
|
546
523
|
## 文档管理规范
|
|
547
524
|
每一步技术指导或审查后,必须使用file_operation工具将结论性输出记录到技术文档中:
|
|
548
|
-
1.
|
|
549
|
-
2.
|
|
550
|
-
3.
|
|
551
|
-
4.
|
|
552
|
-
5.
|
|
553
|
-
6.
|
|
554
|
-
7.
|
|
525
|
+
1. 实施计划制定后,创建`technical/implementation_plan_v<version>.md`记录实施计划
|
|
526
|
+
2. 任务分解后,创建`technical/task_breakdown.md`记录任务分解详情
|
|
527
|
+
3. 编码标准制定后,创建`guidelines/coding_standards.md`记录编码标准
|
|
528
|
+
4. 审查指南制定后,创建`guidelines/review_guidelines.md`记录审查指南
|
|
529
|
+
5. 代码审查后,创建`quality/code_review_<date>.md`记录审查结果
|
|
530
|
+
6. 技术债务识别后,更新`quality/technical_debt.md`记录技术债务
|
|
531
|
+
7. 性能优化后,创建`quality/performance_metrics.md`记录性能指标
|
|
555
532
|
|
|
556
533
|
文档需包含清晰的技术指导、代码质量标准、任务分解和时间估计,便于开发团队执行。
|
|
557
534
|
"""
|
|
@@ -562,22 +539,19 @@ def create_dev_team() -> MultiAgent:
|
|
|
562
539
|
- **create_code_agent**:创建专业代码开发代理
|
|
563
540
|
- **file_operation**:管理源代码和配置文件
|
|
564
541
|
- **ask_codebase**:了解代码库实现细节
|
|
565
|
-
- **
|
|
566
|
-
- **find_symbol**:查找关键符号在代码中的使用
|
|
567
|
-
- **function_analyzer**:分析函数实现和优化空间
|
|
568
|
-
- **file_analyzer**:分析文件结构和功能
|
|
542
|
+
- **execute_script**:执行开发命令和测试脚本
|
|
569
543
|
- **read_code**:阅读和理解关键代码段
|
|
570
544
|
- **create_sub_agent**:创建专门的子代理处理特定任务
|
|
571
545
|
|
|
572
546
|
## 文档管理规范
|
|
573
547
|
每一步代码实现或优化后,必须使用file_operation工具将结论性输出记录到开发文档中:
|
|
574
|
-
1.
|
|
575
|
-
2. API
|
|
576
|
-
3.
|
|
577
|
-
4.
|
|
578
|
-
5.
|
|
579
|
-
6.
|
|
580
|
-
7.
|
|
548
|
+
1. 功能实现完成后,创建`src/README.md`或更新模块说明文档,记录实现细节
|
|
549
|
+
2. API实现后,更新`docs/api/<module_name>.md`记录API使用说明
|
|
550
|
+
3. 复杂算法实现后,创建`docs/algorithms/<algorithm_name>.md`解释算法原理
|
|
551
|
+
4. 配置变更后,更新`docs/configuration.md`记录配置项变更
|
|
552
|
+
5. 依赖更新后,更新`docs/dependencies.md`记录依赖关系
|
|
553
|
+
6. 开发过程中遇到的问题和解决方案,记录到`docs/troubleshooting.md`
|
|
554
|
+
7. 单元测试完成后,创建`tests/README.md`记录测试覆盖情况
|
|
581
555
|
|
|
582
556
|
文档需要包含功能描述、使用示例、参数说明和注意事项,便于其他开发者理解和使用。
|
|
583
557
|
"""
|
|
@@ -588,21 +562,20 @@ def create_dev_team() -> MultiAgent:
|
|
|
588
562
|
- **create_code_agent**:创建测试代码开发代理
|
|
589
563
|
- **file_operation**:管理测试文档和测试脚本
|
|
590
564
|
- **ask_codebase**:了解代码库实现以设计测试
|
|
591
|
-
- **
|
|
565
|
+
- **execute_script**:执行测试命令和测试套件
|
|
592
566
|
- **lsp_get_diagnostics**:检查代码问题和警告
|
|
593
|
-
- **
|
|
594
|
-
- **execute_shell_script**:执行自动化测试脚本
|
|
567
|
+
- **execute_script**:执行各类脚本(Shell命令、Shell脚本、Python脚本)
|
|
595
568
|
- **read_code**:阅读和理解代码以设计测试用例
|
|
596
569
|
|
|
597
570
|
## 文档管理规范
|
|
598
571
|
每一步测试或质量评估后,必须使用file_operation工具将结论性输出记录到测试文档中:
|
|
599
|
-
1.
|
|
600
|
-
2.
|
|
601
|
-
3.
|
|
602
|
-
4.
|
|
603
|
-
5.
|
|
604
|
-
6.
|
|
605
|
-
7.
|
|
572
|
+
1. 测试计划制定后,创建`testing/test_plan.md`记录测试计划
|
|
573
|
+
2. 测试用例设计后,创建`testing/test_cases/<feature_name>_test_cases.md`记录测试用例
|
|
574
|
+
3. 测试执行后,创建`testing/test_reports/test_report_<date>.md`记录测试报告
|
|
575
|
+
4. 发现缺陷后,更新`defects/defect_log.md`记录缺陷详情
|
|
576
|
+
5. 自动化测试脚本开发后,在`automation/README.md`中记录脚本使用说明
|
|
577
|
+
6. 性能测试结果,记录到`testing/performance_test_results.md`
|
|
578
|
+
7. 缺陷统计和趋势分析,记录到`defects/defect_metrics.md`
|
|
606
579
|
|
|
607
580
|
测试文档需包含测试范围、测试环境、测试用例、预期结果、实际结果和缺陷级别,便于跟踪和修复。
|
|
608
581
|
"""
|
jarvis/jarvis_git_squash/main.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import re
|
|
2
1
|
import sys
|
|
3
2
|
import argparse
|
|
4
|
-
from typing import Dict
|
|
5
|
-
from jarvis.
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from jarvis.jarvis_git_utils.git_commiter import GitCommitTool
|
|
6
5
|
import subprocess
|
|
7
6
|
|
|
8
7
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
@@ -10,6 +9,7 @@ from jarvis.jarvis_utils.utils import init_env, user_confirm
|
|
|
10
9
|
class GitSquashTool:
|
|
11
10
|
name = "git_squash_agent"
|
|
12
11
|
description = "Squash commits interactively using a base commit hash"
|
|
12
|
+
labels = ['git', 'version_control', 'squash']
|
|
13
13
|
|
|
14
14
|
def _confirm_squash(self) -> bool:
|
|
15
15
|
"""Prompt user for confirmation to squash commits"""
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import shlex
|
|
3
|
+
import subprocess
|
|
4
|
+
from typing import Dict, Any, Optional
|
|
5
|
+
import tempfile
|
|
6
|
+
from click import Option
|
|
7
|
+
import yaml
|
|
8
|
+
from yaspin import yaspin
|
|
9
|
+
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
10
|
+
import sys
|
|
11
|
+
import argparse
|
|
12
|
+
import os
|
|
13
|
+
|
|
14
|
+
from jarvis.jarvis_utils.config import get_max_input_token_count
|
|
15
|
+
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
16
|
+
from jarvis.jarvis_utils.git_utils import find_git_root, has_uncommitted_changes
|
|
17
|
+
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
18
|
+
from jarvis.jarvis_utils.utils import ct, ot, init_env
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class GitCommitTool:
|
|
22
|
+
name = "git_commit_agent"
|
|
23
|
+
description = "根据代码变更自动生成并执行Git提交"
|
|
24
|
+
labels = ['git', 'version_control']
|
|
25
|
+
parameters = {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"properties": {
|
|
28
|
+
"lang": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "提交信息的语言",
|
|
31
|
+
"default": "Chinese"
|
|
32
|
+
},
|
|
33
|
+
"root_dir": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"description": "Git仓库的根目录路径(可选)",
|
|
36
|
+
"default": "."
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"required": []
|
|
40
|
+
}
|
|
41
|
+
def _extract_commit_message(self, message)->Optional[str]:
|
|
42
|
+
"""Raw extraction preserving all characters"""
|
|
43
|
+
r = re.search(
|
|
44
|
+
r"(?i)" + ot("COMMIT_MESSAGE") + r"\s*([\s\S]*?)\s*" + ct("COMMIT_MESSAGE"),
|
|
45
|
+
message
|
|
46
|
+
)
|
|
47
|
+
if r:
|
|
48
|
+
# 直接返回原始内容,仅去除外围空白
|
|
49
|
+
return shlex.quote(r.group(1).strip())
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
def _get_last_commit_hash(self):
|
|
53
|
+
process = subprocess.Popen(
|
|
54
|
+
["git", "log", "-1", "--pretty=%H"],
|
|
55
|
+
stdout=subprocess.PIPE,
|
|
56
|
+
stderr=subprocess.PIPE
|
|
57
|
+
)
|
|
58
|
+
stdout, _ = process.communicate()
|
|
59
|
+
return stdout.decode().strip()
|
|
60
|
+
|
|
61
|
+
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
62
|
+
"""Execute automatic commit process with support for multi-line messages and special characters"""
|
|
63
|
+
try:
|
|
64
|
+
root_dir = args.get("root_dir", ".")
|
|
65
|
+
|
|
66
|
+
# Store current directory
|
|
67
|
+
original_dir = os.getcwd()
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
# Change to root_dir
|
|
71
|
+
os.chdir(root_dir)
|
|
72
|
+
|
|
73
|
+
find_git_root()
|
|
74
|
+
if not has_uncommitted_changes():
|
|
75
|
+
PrettyOutput.print("没有未提交的更改", OutputType.SUCCESS)
|
|
76
|
+
return {"success": True, "stdout": "No changes to commit", "stderr": ""}
|
|
77
|
+
|
|
78
|
+
with yaspin(text="正在初始化提交流程...", color="cyan") as spinner:
|
|
79
|
+
# 添加文件
|
|
80
|
+
spinner.text = "正在添加文件到提交..."
|
|
81
|
+
subprocess.Popen(
|
|
82
|
+
["git", "add", "."],
|
|
83
|
+
stdout=subprocess.DEVNULL,
|
|
84
|
+
stderr=subprocess.DEVNULL
|
|
85
|
+
).wait()
|
|
86
|
+
spinner.write("✅ 添加文件到提交")
|
|
87
|
+
|
|
88
|
+
# 获取差异
|
|
89
|
+
spinner.text = "正在获取代码差异..."
|
|
90
|
+
# 获取文件列表
|
|
91
|
+
files_cmd = ["git", "diff", "--cached", "--name-only"]
|
|
92
|
+
process = subprocess.Popen(
|
|
93
|
+
files_cmd,
|
|
94
|
+
stdout=subprocess.PIPE,
|
|
95
|
+
stderr=subprocess.PIPE
|
|
96
|
+
)
|
|
97
|
+
files_output = process.communicate()[0].decode()
|
|
98
|
+
files = [f.strip() for f in files_output.split("\n") if f.strip()]
|
|
99
|
+
file_count = len(files)
|
|
100
|
+
|
|
101
|
+
# 获取完整差异
|
|
102
|
+
process = subprocess.Popen(
|
|
103
|
+
["git", "diff", "--cached", "--exit-code"],
|
|
104
|
+
stdout=subprocess.PIPE,
|
|
105
|
+
stderr=subprocess.PIPE
|
|
106
|
+
)
|
|
107
|
+
diff = process.communicate()[0].decode()
|
|
108
|
+
spinner.write(f"✅ 获取差异 ({file_count} 个文件)")
|
|
109
|
+
|
|
110
|
+
# 写入差异文件
|
|
111
|
+
temp_diff_file = None
|
|
112
|
+
try:
|
|
113
|
+
# 创建临时文件并写入差异内容
|
|
114
|
+
temp_diff_file = tempfile.NamedTemporaryFile(mode='w', suffix='.diff', delete=False)
|
|
115
|
+
temp_diff_file_path = temp_diff_file.name
|
|
116
|
+
temp_diff_file.write(diff)
|
|
117
|
+
temp_diff_file.flush()
|
|
118
|
+
temp_diff_file.close()
|
|
119
|
+
spinner.write(f"✅ 差异内容已写入临时文件")
|
|
120
|
+
# 生成提交信息
|
|
121
|
+
spinner.text = "正在生成提交消息..."
|
|
122
|
+
|
|
123
|
+
# 准备提示信息
|
|
124
|
+
base_prompt = f'''根据代码差异生成提交信息:
|
|
125
|
+
提交信息应使用{args.get('lang', '中文')}书写
|
|
126
|
+
# 必需结构
|
|
127
|
+
必须使用以下格式:
|
|
128
|
+
{ot("COMMIT_MESSAGE")}
|
|
129
|
+
<类型>(<范围>): <主题>
|
|
130
|
+
|
|
131
|
+
[可选] 详细描述变更内容和原因
|
|
132
|
+
{ct("COMMIT_MESSAGE")}
|
|
133
|
+
# 格式规则
|
|
134
|
+
1. 类型: fix(修复bug), feat(新功能), docs(文档), style(格式), refactor(重构), test(测试), chore(其他)
|
|
135
|
+
2. 范围表示变更的模块或组件 (例如: auth, database, ui)
|
|
136
|
+
3. 主题行不超过72个字符,不以句号结尾,使用祈使语气
|
|
137
|
+
4. 如有详细描述,使用空行分隔主题和详细描述
|
|
138
|
+
5. 详细描述部分应解释"是什么"和"为什么",而非"如何"
|
|
139
|
+
6. 仅输出提交信息,不要输出其他内容
|
|
140
|
+
'''
|
|
141
|
+
|
|
142
|
+
# 获取模型并尝试上传文件
|
|
143
|
+
platform = PlatformRegistry().get_normal_platform()
|
|
144
|
+
upload_success = False
|
|
145
|
+
|
|
146
|
+
if hasattr(platform, 'upload_files') and os.path.exists(temp_diff_file_path):
|
|
147
|
+
spinner.text = "正在上传代码差异文件..."
|
|
148
|
+
try:
|
|
149
|
+
with spinner.hidden():
|
|
150
|
+
upload_success = platform.upload_files([temp_diff_file_path])
|
|
151
|
+
if upload_success:
|
|
152
|
+
spinner.write("✅ 成功上传代码差异文件")
|
|
153
|
+
else:
|
|
154
|
+
spinner.write("⚠️ 上传代码差异文件失败,将回退到直接提供差异内容")
|
|
155
|
+
except Exception as e:
|
|
156
|
+
spinner.write(f"⚠️ 上传文件时出错: {str(e)}")
|
|
157
|
+
upload_success = False
|
|
158
|
+
|
|
159
|
+
# 根据上传状态准备完整的提示
|
|
160
|
+
if upload_success:
|
|
161
|
+
# 使用上传的文件
|
|
162
|
+
prompt = base_prompt + f'''
|
|
163
|
+
# 变更概述
|
|
164
|
+
- 变更文件数量: {file_count} 个文件
|
|
165
|
+
- 已上传包含完整代码差异的文件
|
|
166
|
+
|
|
167
|
+
请详细分析已上传的代码差异文件,生成符合上述格式的提交信息。
|
|
168
|
+
'''
|
|
169
|
+
else:
|
|
170
|
+
# 直接在提示中包含差异内容
|
|
171
|
+
prompt = base_prompt + f'''
|
|
172
|
+
# 分析材料
|
|
173
|
+
{diff}
|
|
174
|
+
'''
|
|
175
|
+
|
|
176
|
+
# 尝试生成提交信息
|
|
177
|
+
spinner.text = "正在生成提交消息..."
|
|
178
|
+
while True:
|
|
179
|
+
commit_message = platform.chat_until_success(prompt)
|
|
180
|
+
commit_message = self._extract_commit_message(commit_message)
|
|
181
|
+
# 如果成功提取,就跳出循环
|
|
182
|
+
if commit_message:
|
|
183
|
+
break
|
|
184
|
+
spinner.write("✅ 生成提交消息")
|
|
185
|
+
|
|
186
|
+
# 执行提交
|
|
187
|
+
spinner.text = "正在准备提交..."
|
|
188
|
+
with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_file:
|
|
189
|
+
tmp_file.write(commit_message)
|
|
190
|
+
tmp_file.flush()
|
|
191
|
+
spinner.text = "正在执行提交..."
|
|
192
|
+
commit_cmd = ["git", "commit", "-F", tmp_file.name]
|
|
193
|
+
subprocess.Popen(
|
|
194
|
+
commit_cmd,
|
|
195
|
+
stdout=subprocess.DEVNULL,
|
|
196
|
+
stderr=subprocess.DEVNULL
|
|
197
|
+
).wait()
|
|
198
|
+
spinner.write("✅ 提交")
|
|
199
|
+
|
|
200
|
+
commit_hash = self._get_last_commit_hash()
|
|
201
|
+
spinner.text = "完成提交"
|
|
202
|
+
spinner.ok("✅")
|
|
203
|
+
finally:
|
|
204
|
+
# 清理临时差异文件
|
|
205
|
+
if temp_diff_file is not None and os.path.exists(temp_diff_file_path):
|
|
206
|
+
try:
|
|
207
|
+
os.unlink(temp_diff_file_path)
|
|
208
|
+
except Exception as e:
|
|
209
|
+
spinner.write(f"⚠️ 无法删除临时文件: {str(e)}")
|
|
210
|
+
|
|
211
|
+
PrettyOutput.print(f"提交哈希: {commit_hash}\n提交消息: {commit_message}", OutputType.SUCCESS)
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
"success": True,
|
|
215
|
+
"stdout": yaml.safe_dump({
|
|
216
|
+
"commit_hash": commit_hash,
|
|
217
|
+
"commit_message": commit_message
|
|
218
|
+
}),
|
|
219
|
+
"stderr": ""
|
|
220
|
+
}
|
|
221
|
+
finally:
|
|
222
|
+
# Always restore original directory
|
|
223
|
+
os.chdir(original_dir)
|
|
224
|
+
|
|
225
|
+
except Exception as e:
|
|
226
|
+
return {
|
|
227
|
+
"success": False,
|
|
228
|
+
"stdout": "",
|
|
229
|
+
"stderr": f"Commit failed: {str(e)}"
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
def main():
|
|
233
|
+
init_env()
|
|
234
|
+
parser = argparse.ArgumentParser(description='Git commit tool')
|
|
235
|
+
parser.add_argument('--lang', type=str, default='Chinese', help='Language for commit messages')
|
|
236
|
+
parser.add_argument('--root-dir', type=str, default='.', help='Root directory of the Git repository')
|
|
237
|
+
args = parser.parse_args()
|
|
238
|
+
tool = GitCommitTool()
|
|
239
|
+
tool.execute({"lang": args.lang if hasattr(args, 'lang') else 'Chinese', "root_dir": args.root_dir})
|
|
240
|
+
|
|
241
|
+
if __name__ == "__main__":
|
|
242
|
+
sys.exit(main())
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from typing import Any, Tuple
|
|
2
|
+
import subprocess
|
|
3
|
+
from jarvis.jarvis_utils.embedding import (
|
|
4
|
+
get_context_token_count,
|
|
5
|
+
load_tokenizer
|
|
6
|
+
)
|
|
7
|
+
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
|
8
|
+
|
|
9
|
+
def init_models() -> Tuple[Any, Any, Any, Any]:
|
|
10
|
+
"""
|
|
11
|
+
初始化所需的模型和分词器。
|
|
12
|
+
|
|
13
|
+
返回:
|
|
14
|
+
Tuple[Any, Any, Any, Any]: (embedding_model, rerank_model, rerank_tokenizer, tokenizer)
|
|
15
|
+
"""
|
|
16
|
+
try:
|
|
17
|
+
|
|
18
|
+
# 加载GPT2分词器
|
|
19
|
+
PrettyOutput.print("正在加载GPT2分词器...", OutputType.INFO)
|
|
20
|
+
tokenizer = load_tokenizer()
|
|
21
|
+
|
|
22
|
+
# 测试token计算
|
|
23
|
+
test_text = "这是一个测试文本,用于验证token计算功能。"
|
|
24
|
+
token_count = get_context_token_count(test_text)
|
|
25
|
+
PrettyOutput.print(f"Token计算测试成功,测试文本token数: {token_count}", OutputType.SUCCESS)
|
|
26
|
+
|
|
27
|
+
return embedding_model, rerank_model, rerank_tokenizer, tokenizer
|
|
28
|
+
|
|
29
|
+
except Exception as e:
|
|
30
|
+
PrettyOutput.print(f"模型加载失败: {str(e)}", OutputType.ERROR)
|
|
31
|
+
raise
|
|
32
|
+
|
|
33
|
+
def install_playwright():
|
|
34
|
+
"""安装Playwright及其依赖。"""
|
|
35
|
+
try:
|
|
36
|
+
PrettyOutput.print("正在安装Playwright...", OutputType.INFO)
|
|
37
|
+
subprocess.run(["playwright", "install", "chromium"], check=True)
|
|
38
|
+
PrettyOutput.print("Playwright安装成功", OutputType.SUCCESS)
|
|
39
|
+
except subprocess.CalledProcessError as e:
|
|
40
|
+
PrettyOutput.print(f"Playwright安装失败: {str(e)}", OutputType.ERROR)
|
|
41
|
+
raise
|
|
42
|
+
except Exception as e:
|
|
43
|
+
PrettyOutput.print(f"安装过程中发生错误: {str(e)}", OutputType.ERROR)
|
|
44
|
+
raise
|
|
45
|
+
|
|
46
|
+
def main():
|
|
47
|
+
"""主函数,初始化所有必要的组件。"""
|
|
48
|
+
try:
|
|
49
|
+
# 初始化模型
|
|
50
|
+
init_models()
|
|
51
|
+
|
|
52
|
+
# 安装Playwright
|
|
53
|
+
install_playwright()
|
|
54
|
+
|
|
55
|
+
PrettyOutput.print("所有组件初始化完成", OutputType.SUCCESS)
|
|
56
|
+
|
|
57
|
+
except Exception as e:
|
|
58
|
+
PrettyOutput.print(f"初始化失败: {str(e)}", OutputType.ERROR)
|
|
59
|
+
raise
|
|
60
|
+
|
|
61
|
+
if __name__ == "__main__":
|
|
62
|
+
main()
|
jarvis/jarvis_platform/base.py
CHANGED
|
@@ -31,6 +31,10 @@ class BasePlatform(ABC):
|
|
|
31
31
|
def chat(self, message: str) -> str:
|
|
32
32
|
"""Execute conversation"""
|
|
33
33
|
raise NotImplementedError("chat is not implemented")
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def upload_files(self, file_list: List[str]) -> bool:
|
|
37
|
+
raise NotImplementedError("upload_files is not implemented")
|
|
34
38
|
|
|
35
39
|
def chat_until_success(self, message: str) -> str:
|
|
36
40
|
def _chat():
|