jarvis-ai-assistant 0.2.1__py3-none-any.whl → 0.2.3__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/jarvis.py +61 -59
- jarvis/jarvis_agent/main.py +42 -40
- jarvis/jarvis_agent/prompts.py +26 -4
- jarvis/jarvis_code_agent/code_agent.py +35 -31
- jarvis/jarvis_code_analysis/code_review.py +73 -39
- jarvis/jarvis_data/config_schema.json +67 -12
- jarvis/jarvis_git_squash/main.py +16 -12
- jarvis/jarvis_git_utils/git_commiter.py +25 -20
- jarvis/jarvis_methodology/main.py +34 -49
- jarvis/jarvis_multi_agent/main.py +28 -23
- jarvis/jarvis_platform/ai8.py +31 -22
- jarvis/jarvis_platform/kimi.py +31 -61
- jarvis/jarvis_platform/tongyi.py +71 -85
- jarvis/jarvis_platform/yuanbao.py +44 -50
- jarvis/jarvis_platform_manager/main.py +55 -90
- jarvis/jarvis_rag/cli.py +79 -23
- jarvis/jarvis_rag/query_rewriter.py +61 -12
- jarvis/jarvis_rag/rag_pipeline.py +143 -34
- jarvis/jarvis_rag/retriever.py +5 -5
- jarvis/jarvis_smart_shell/main.py +58 -87
- jarvis/jarvis_tools/cli/main.py +120 -153
- jarvis/jarvis_tools/generate_new_tool.py +22 -1
- jarvis/jarvis_tools/registry.py +1 -7
- jarvis/jarvis_tools/search_web.py +12 -10
- jarvis/jarvis_utils/config.py +92 -11
- jarvis/jarvis_utils/globals.py +29 -8
- jarvis/jarvis_utils/http.py +58 -79
- jarvis/jarvis_utils/input.py +114 -121
- jarvis/jarvis_utils/output.py +1 -1
- jarvis/jarvis_utils/utils.py +3 -0
- jarvis_ai_assistant-0.2.3.dist-info/METADATA +301 -0
- {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.3.dist-info}/RECORD +37 -40
- {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.3.dist-info}/entry_points.txt +0 -2
- jarvis/jarvis_git_details/__init__.py +0 -0
- jarvis/jarvis_git_details/main.py +0 -265
- jarvis/jarvis_platform/oyi.py +0 -357
- jarvis_ai_assistant-0.2.1.dist-info/METADATA +0 -845
- {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.3.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.3.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.3.dist-info}/top_level.txt +0 -0
jarvis/jarvis_utils/config.py
CHANGED
@@ -115,22 +115,26 @@ def get_shell_name() -> str:
|
|
115
115
|
return os.path.basename(shell_path).lower()
|
116
116
|
|
117
117
|
|
118
|
-
def _get_resolved_model_config(
|
118
|
+
def _get_resolved_model_config(
|
119
|
+
model_group_override: Optional[str] = None,
|
120
|
+
) -> Dict[str, Any]:
|
119
121
|
"""
|
120
122
|
解析并合并模型配置,处理模型组。
|
121
123
|
|
122
124
|
优先级顺序:
|
123
125
|
1. 单独的环境变量 (JARVIS_PLATFORM, JARVIS_MODEL, etc.)
|
124
|
-
2.
|
126
|
+
2. JARVIS_LLM_GROUP 中定义的组配置
|
125
127
|
3. 代码中的默认值
|
126
128
|
|
127
129
|
返回:
|
128
130
|
Dict[str, Any]: 解析后的模型配置字典
|
129
131
|
"""
|
130
132
|
group_config = {}
|
131
|
-
model_group_name = model_group_override or GLOBAL_CONFIG_DATA.get(
|
133
|
+
model_group_name = model_group_override or GLOBAL_CONFIG_DATA.get(
|
134
|
+
"JARVIS_LLM_GROUP"
|
135
|
+
)
|
132
136
|
# The format is a list of single-key dicts: [{'group_name': {...}}, ...]
|
133
|
-
model_groups = GLOBAL_CONFIG_DATA.get("
|
137
|
+
model_groups = GLOBAL_CONFIG_DATA.get("JARVIS_LLM_GROUPS", [])
|
134
138
|
|
135
139
|
if model_group_name and isinstance(model_groups, list):
|
136
140
|
for group_item in model_groups:
|
@@ -202,7 +206,9 @@ def get_thinking_model_name(model_group_override: Optional[str] = None) -> str:
|
|
202
206
|
"""
|
203
207
|
config = _get_resolved_model_config(model_group_override)
|
204
208
|
# Fallback to normal model if thinking model is not specified
|
205
|
-
return config.get(
|
209
|
+
return config.get(
|
210
|
+
"JARVIS_THINKING_MODEL", get_normal_model_name(model_group_override)
|
211
|
+
)
|
206
212
|
|
207
213
|
|
208
214
|
def is_execute_tool_confirm() -> bool:
|
@@ -334,14 +340,65 @@ def get_mcp_config() -> List[Dict[str, Any]]:
|
|
334
340
|
# ==============================================================================
|
335
341
|
|
336
342
|
|
337
|
-
|
343
|
+
DEFAULT_RAG_GROUPS = [
|
344
|
+
{
|
345
|
+
"text": {
|
346
|
+
"embedding_model": "BAAI/bge-m3",
|
347
|
+
"rerank_model": "BAAI/bge-reranker-v2-m3",
|
348
|
+
"use_bm25": True,
|
349
|
+
"use_rerank": True,
|
350
|
+
}
|
351
|
+
},
|
352
|
+
{
|
353
|
+
"code": {
|
354
|
+
"embedding_model": "Qodo/Qodo-Embed-1-7B",
|
355
|
+
"use_bm25": False,
|
356
|
+
"use_rerank": False,
|
357
|
+
}
|
358
|
+
},
|
359
|
+
]
|
360
|
+
|
361
|
+
|
362
|
+
def _get_resolved_rag_config(
|
363
|
+
rag_group_override: Optional[str] = None,
|
364
|
+
) -> Dict[str, Any]:
|
338
365
|
"""
|
339
|
-
|
366
|
+
解析并合并RAG配置,处理RAG组。
|
367
|
+
|
368
|
+
优先级顺序:
|
369
|
+
1. JARVIS_RAG 中的顶级设置 (embedding_model, etc.)
|
370
|
+
2. JARVIS_RAG_GROUP 中定义的组配置
|
371
|
+
3. 代码中的默认值
|
340
372
|
|
341
373
|
返回:
|
342
|
-
Dict[str, Any]: RAG配置字典
|
374
|
+
Dict[str, Any]: 解析后的RAG配置字典
|
343
375
|
"""
|
344
|
-
|
376
|
+
group_config = {}
|
377
|
+
rag_group_name = rag_group_override or GLOBAL_CONFIG_DATA.get("JARVIS_RAG_GROUP")
|
378
|
+
rag_groups = GLOBAL_CONFIG_DATA.get("JARVIS_RAG_GROUPS", DEFAULT_RAG_GROUPS)
|
379
|
+
|
380
|
+
if rag_group_name and isinstance(rag_groups, list):
|
381
|
+
for group_item in rag_groups:
|
382
|
+
if isinstance(group_item, dict) and rag_group_name in group_item:
|
383
|
+
group_config = group_item[rag_group_name]
|
384
|
+
break
|
385
|
+
|
386
|
+
# Start with group config
|
387
|
+
resolved_config = group_config.copy()
|
388
|
+
|
389
|
+
# Override with specific settings from the top-level JARVIS_RAG dict
|
390
|
+
top_level_rag_config = GLOBAL_CONFIG_DATA.get("JARVIS_RAG", {})
|
391
|
+
if isinstance(top_level_rag_config, dict):
|
392
|
+
for key in [
|
393
|
+
"embedding_model",
|
394
|
+
"rerank_model",
|
395
|
+
"use_bm25",
|
396
|
+
"use_rerank",
|
397
|
+
]:
|
398
|
+
if key in top_level_rag_config:
|
399
|
+
resolved_config[key] = top_level_rag_config[key]
|
400
|
+
|
401
|
+
return resolved_config
|
345
402
|
|
346
403
|
|
347
404
|
def get_rag_embedding_model() -> str:
|
@@ -351,7 +408,8 @@ def get_rag_embedding_model() -> str:
|
|
351
408
|
返回:
|
352
409
|
str: 嵌入模型的名称
|
353
410
|
"""
|
354
|
-
|
411
|
+
config = _get_resolved_rag_config()
|
412
|
+
return config.get("embedding_model", "BAAI/bge-m3")
|
355
413
|
|
356
414
|
|
357
415
|
def get_rag_rerank_model() -> str:
|
@@ -361,7 +419,8 @@ def get_rag_rerank_model() -> str:
|
|
361
419
|
返回:
|
362
420
|
str: rerank模型的名称
|
363
421
|
"""
|
364
|
-
|
422
|
+
config = _get_resolved_rag_config()
|
423
|
+
return config.get("rerank_model", "BAAI/bge-reranker-v2-m3")
|
365
424
|
|
366
425
|
|
367
426
|
def get_rag_embedding_cache_path() -> str:
|
@@ -382,3 +441,25 @@ def get_rag_vector_db_path() -> str:
|
|
382
441
|
str: 数据库路径
|
383
442
|
"""
|
384
443
|
return ".jarvis/rag/vectordb"
|
444
|
+
|
445
|
+
|
446
|
+
def get_rag_use_bm25() -> bool:
|
447
|
+
"""
|
448
|
+
获取RAG是否使用BM25。
|
449
|
+
|
450
|
+
返回:
|
451
|
+
bool: 如果使用BM25则返回True,默认为True
|
452
|
+
"""
|
453
|
+
config = _get_resolved_rag_config()
|
454
|
+
return config.get("use_bm25", True) is True
|
455
|
+
|
456
|
+
|
457
|
+
def get_rag_use_rerank() -> bool:
|
458
|
+
"""
|
459
|
+
获取RAG是否使用rerank。
|
460
|
+
|
461
|
+
返回:
|
462
|
+
bool: 如果使用rerank则返回True,默认为True
|
463
|
+
"""
|
464
|
+
config = _get_resolved_rag_config()
|
465
|
+
return config.get("use_rerank", True) is True
|
jarvis/jarvis_utils/globals.py
CHANGED
@@ -9,9 +9,11 @@
|
|
9
9
|
"""
|
10
10
|
import os
|
11
11
|
|
12
|
-
#
|
13
|
-
|
14
|
-
|
12
|
+
# 全局变量:保存消息历史
|
13
|
+
from typing import Any, Dict, Set, List
|
14
|
+
|
15
|
+
message_history: List[str] = []
|
16
|
+
MAX_HISTORY_SIZE = 50
|
15
17
|
|
16
18
|
import colorama
|
17
19
|
from rich.console import Console
|
@@ -169,13 +171,18 @@ def get_interrupt() -> int:
|
|
169
171
|
|
170
172
|
def set_last_message(message: str) -> None:
|
171
173
|
"""
|
172
|
-
|
174
|
+
将消息添加到历史记录中。
|
173
175
|
|
174
176
|
参数:
|
175
177
|
message: 要保存的消息
|
176
178
|
"""
|
177
|
-
global
|
178
|
-
|
179
|
+
global message_history
|
180
|
+
if message:
|
181
|
+
# 避免重复添加
|
182
|
+
if not message_history or message_history[-1] != message:
|
183
|
+
message_history.append(message)
|
184
|
+
if len(message_history) > MAX_HISTORY_SIZE:
|
185
|
+
message_history.pop(0)
|
179
186
|
|
180
187
|
|
181
188
|
def get_last_message() -> str:
|
@@ -183,6 +190,20 @@ def get_last_message() -> str:
|
|
183
190
|
获取最后一条消息。
|
184
191
|
|
185
192
|
返回:
|
186
|
-
str:
|
193
|
+
str: 最后一条消息,如果历史记录为空则返回空字符串
|
194
|
+
"""
|
195
|
+
global message_history
|
196
|
+
if message_history:
|
197
|
+
return message_history[-1]
|
198
|
+
return ""
|
199
|
+
|
200
|
+
|
201
|
+
def get_message_history() -> List[str]:
|
202
|
+
"""
|
203
|
+
获取完整的消息历史记录。
|
204
|
+
|
205
|
+
返回:
|
206
|
+
List[str]: 消息历史列表
|
187
207
|
"""
|
188
|
-
|
208
|
+
global message_history
|
209
|
+
return message_history
|
jarvis/jarvis_utils/http.py
CHANGED
@@ -1,140 +1,120 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
import
|
4
|
-
from typing import Any, Dict, Optional,
|
3
|
+
import requests
|
4
|
+
from typing import Any, Dict, Optional, Generator
|
5
5
|
|
6
6
|
|
7
|
-
def
|
7
|
+
def get_requests_session() -> requests.Session:
|
8
8
|
"""
|
9
|
-
获取一个配置好的
|
9
|
+
获取一个配置好的 requests.Session 对象
|
10
10
|
|
11
11
|
返回:
|
12
|
-
|
12
|
+
requests.Session 对象
|
13
13
|
"""
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
session = requests.Session()
|
15
|
+
session.headers.update(
|
16
|
+
{
|
17
17
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
|
18
|
-
}
|
18
|
+
}
|
19
19
|
)
|
20
|
-
return
|
20
|
+
return session
|
21
21
|
|
22
22
|
|
23
|
-
|
24
|
-
"""
|
25
|
-
获取一个配置好的 httpx.AsyncClient 对象
|
26
|
-
|
27
|
-
返回:
|
28
|
-
httpx.AsyncClient 对象
|
29
|
-
"""
|
30
|
-
client = httpx.AsyncClient(
|
31
|
-
timeout=httpx.Timeout(None), # 永不超时
|
32
|
-
headers={
|
33
|
-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
|
34
|
-
},
|
35
|
-
)
|
36
|
-
return client
|
37
|
-
|
38
|
-
|
39
|
-
# 增强版本的 HTTP 请求方法(使用 httpx 实现,带重试机制,解决连接中断问题)
|
23
|
+
# 增强版本的 HTTP 请求方法(使用 requests 实现)
|
40
24
|
def post(
|
41
25
|
url: str,
|
42
26
|
data: Optional[Any] = None,
|
43
27
|
json: Optional[Dict[str, Any]] = None,
|
44
28
|
**kwargs,
|
45
|
-
) ->
|
29
|
+
) -> requests.Response:
|
46
30
|
"""
|
47
|
-
发送增强版永不超时的 POST 请求,使用
|
31
|
+
发送增强版永不超时的 POST 请求,使用 requests 实现
|
48
32
|
|
49
33
|
参数:
|
50
34
|
url: 请求的 URL
|
51
35
|
data: (可选) 请求体数据 (表单数据或原始数据)
|
52
36
|
json: (可选) JSON 数据,会自动设置 Content-Type
|
53
|
-
**kwargs: 其他传递给
|
37
|
+
**kwargs: 其他传递给 requests.post 的参数
|
54
38
|
|
55
39
|
返回:
|
56
|
-
|
40
|
+
requests.Response 对象
|
57
41
|
|
58
42
|
注意:
|
59
|
-
此方法使用
|
43
|
+
此方法使用 requests 实现。要实现重试,请考虑使用 Session 和 HTTPAdapter。
|
44
|
+
永不超时通过 timeout=None 设置。
|
60
45
|
"""
|
61
|
-
|
62
|
-
|
63
|
-
response =
|
46
|
+
kwargs.setdefault("timeout", None)
|
47
|
+
with get_requests_session() as session:
|
48
|
+
response = session.post(url=url, data=data, json=json, **kwargs)
|
64
49
|
response.raise_for_status()
|
65
50
|
return response
|
66
|
-
finally:
|
67
|
-
client.close()
|
68
51
|
|
69
52
|
|
70
|
-
def get(url: str, **kwargs) ->
|
53
|
+
def get(url: str, **kwargs) -> requests.Response:
|
71
54
|
"""
|
72
|
-
发送增强版永不超时的 GET 请求,使用
|
55
|
+
发送增强版永不超时的 GET 请求,使用 requests 实现
|
73
56
|
|
74
57
|
参数:
|
75
58
|
url: 请求的 URL
|
76
|
-
**kwargs: 其他传递给
|
59
|
+
**kwargs: 其他传递给 requests.get 的参数
|
77
60
|
|
78
61
|
返回:
|
79
|
-
|
62
|
+
requests.Response 对象
|
80
63
|
|
81
64
|
注意:
|
82
|
-
此方法使用
|
65
|
+
此方法使用 requests 实现。
|
66
|
+
永不超时通过 timeout=None 设置。
|
83
67
|
"""
|
84
|
-
|
85
|
-
|
86
|
-
response =
|
68
|
+
kwargs.setdefault("timeout", None)
|
69
|
+
with get_requests_session() as session:
|
70
|
+
response = session.get(url=url, **kwargs)
|
87
71
|
response.raise_for_status()
|
88
72
|
return response
|
89
|
-
finally:
|
90
|
-
client.close()
|
91
73
|
|
92
74
|
|
93
|
-
def put(url: str, data: Optional[Any] = None, **kwargs) ->
|
75
|
+
def put(url: str, data: Optional[Any] = None, **kwargs) -> requests.Response:
|
94
76
|
"""
|
95
|
-
发送增强版永不超时的 PUT 请求,使用
|
77
|
+
发送增强版永不超时的 PUT 请求,使用 requests 实现
|
96
78
|
|
97
79
|
参数:
|
98
80
|
url: 请求的 URL
|
99
81
|
data: (可选) 请求体数据 (表单数据或原始数据)
|
100
|
-
**kwargs: 其他传递给
|
82
|
+
**kwargs: 其他传递给 requests.put 的参数
|
101
83
|
|
102
84
|
返回:
|
103
|
-
|
85
|
+
requests.Response 对象
|
104
86
|
|
105
87
|
注意:
|
106
|
-
此方法使用
|
88
|
+
此方法使用 requests 实现。
|
89
|
+
永不超时通过 timeout=None 设置。
|
107
90
|
"""
|
108
|
-
|
109
|
-
|
110
|
-
response =
|
91
|
+
kwargs.setdefault("timeout", None)
|
92
|
+
with get_requests_session() as session:
|
93
|
+
response = session.put(url=url, data=data, **kwargs)
|
111
94
|
response.raise_for_status()
|
112
95
|
return response
|
113
|
-
finally:
|
114
|
-
client.close()
|
115
96
|
|
116
97
|
|
117
|
-
def delete(url: str, **kwargs) ->
|
98
|
+
def delete(url: str, **kwargs) -> requests.Response:
|
118
99
|
"""
|
119
|
-
发送增强版永不超时的 DELETE 请求,使用
|
100
|
+
发送增强版永不超时的 DELETE 请求,使用 requests 实现
|
120
101
|
|
121
102
|
参数:
|
122
103
|
url: 请求的 URL
|
123
|
-
**kwargs: 其他传递给
|
104
|
+
**kwargs: 其他传递给 requests.delete 的参数
|
124
105
|
|
125
106
|
返回:
|
126
|
-
|
107
|
+
requests.Response 对象
|
127
108
|
|
128
109
|
注意:
|
129
|
-
此方法使用
|
110
|
+
此方法使用 requests 实现。
|
111
|
+
永不超时通过 timeout=None 设置。
|
130
112
|
"""
|
131
|
-
|
132
|
-
|
133
|
-
response =
|
113
|
+
kwargs.setdefault("timeout", None)
|
114
|
+
with get_requests_session() as session:
|
115
|
+
response = session.delete(url=url, **kwargs)
|
134
116
|
response.raise_for_status()
|
135
117
|
return response
|
136
|
-
finally:
|
137
|
-
client.close()
|
138
118
|
|
139
119
|
|
140
120
|
# 同步流式POST请求方法
|
@@ -143,27 +123,26 @@ def stream_post(
|
|
143
123
|
data: Optional[Any] = None,
|
144
124
|
json: Optional[Dict[str, Any]] = None,
|
145
125
|
**kwargs,
|
146
|
-
) -> Generator[
|
126
|
+
) -> Generator[str, None, None]:
|
147
127
|
"""
|
148
|
-
发送流式 POST 请求,使用
|
128
|
+
发送流式 POST 请求,使用 requests 实现,返回解码后的字符串行生成器
|
149
129
|
|
150
130
|
参数:
|
151
131
|
url: 请求的 URL
|
152
132
|
data: (可选) 请求体数据 (表单数据或原始数据)
|
153
133
|
json: (可选) JSON 数据,会自动设置 Content-Type
|
154
|
-
**kwargs: 其他传递给
|
134
|
+
**kwargs: 其他传递给 requests.post 的参数
|
155
135
|
|
156
136
|
返回:
|
157
|
-
Generator[
|
137
|
+
Generator[str, None, None]: 字符串行生成器
|
158
138
|
|
159
139
|
注意:
|
160
|
-
此方法使用
|
140
|
+
此方法使用 requests 实现流式请求,适用于处理大文件下载或流式响应
|
161
141
|
"""
|
162
|
-
|
163
|
-
|
164
|
-
with
|
142
|
+
kwargs.setdefault("timeout", None)
|
143
|
+
with get_requests_session() as session:
|
144
|
+
with session.post(url, data=data, json=json, stream=True, **kwargs) as response:
|
165
145
|
response.raise_for_status()
|
166
|
-
for
|
167
|
-
|
168
|
-
|
169
|
-
client.close()
|
146
|
+
for line in response.iter_lines(chunk_size=1):
|
147
|
+
if line:
|
148
|
+
yield line.decode("utf-8", errors="ignore")
|