jarvis-ai-assistant 0.1.212__py3-none-any.whl → 0.1.213__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_platform/ai8.py +104 -111
- jarvis/jarvis_platform/oyi.py +118 -125
- jarvis/jarvis_utils/input.py +5 -5
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.213.dist-info}/METADATA +2 -2
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.213.dist-info}/RECORD +10 -10
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.213.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.213.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.213.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.213.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
jarvis/jarvis_platform/ai8.py
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
import os
|
2
|
-
from typing import
|
2
|
+
from typing import Generator, List, Tuple
|
3
3
|
from jarvis.jarvis_platform.base import BasePlatform
|
4
|
-
import requests
|
5
4
|
import json
|
6
|
-
import base64
|
7
5
|
|
6
|
+
from jarvis.jarvis_utils import http
|
8
7
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
8
|
+
from jarvis.jarvis_utils.utils import while_success
|
9
|
+
|
9
10
|
|
10
11
|
class AI8Model(BasePlatform):
|
11
12
|
"""AI8 model implementation"""
|
@@ -16,7 +17,7 @@ class AI8Model(BasePlatform):
|
|
16
17
|
def get_model_list(self) -> List[Tuple[str, str]]:
|
17
18
|
"""获取模型列表"""
|
18
19
|
self.get_available_models()
|
19
|
-
return [(name,info[
|
20
|
+
return [(name, info["desc"]) for name, info in self.models.items()]
|
20
21
|
|
21
22
|
def __init__(self):
|
22
23
|
"""Initialize model"""
|
@@ -30,24 +31,23 @@ class AI8Model(BasePlatform):
|
|
30
31
|
PrettyOutput.print("未设置 AI8_API_KEY", OutputType.WARNING)
|
31
32
|
|
32
33
|
self.headers = {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
34
|
+
"Authorization": self.token,
|
35
|
+
"Content-Type": "application/json",
|
36
|
+
"Accept": "application/json, text/plain, */*",
|
37
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
38
|
+
"X-APP-VERSION": "2.3.0",
|
39
|
+
"Origin": self.BASE_URL,
|
40
|
+
"Referer": f"{self.BASE_URL}/chat?_userMenuKey=chat",
|
41
|
+
"Sec-Fetch-Site": "same-origin",
|
42
|
+
"Sec-Fetch-Mode": "cors",
|
43
|
+
"Sec-Fetch-Dest": "empty",
|
43
44
|
}
|
44
45
|
|
45
46
|
self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-chat"
|
46
47
|
if self.model_name not in self.get_available_models():
|
47
|
-
PrettyOutput.print(
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
PrettyOutput.print(
|
49
|
+
f"警告: 选择的模型 {self.model_name} 不在可用列表中", OutputType.WARNING
|
50
|
+
)
|
51
51
|
|
52
52
|
def set_model_name(self, model_name: str):
|
53
53
|
"""Set model name"""
|
@@ -58,24 +58,22 @@ class AI8Model(BasePlatform):
|
|
58
58
|
"""Create a new conversation"""
|
59
59
|
try:
|
60
60
|
|
61
|
-
|
62
61
|
# 1. 创建会话
|
63
|
-
response =
|
64
|
-
|
65
|
-
|
66
|
-
|
62
|
+
response = while_success(
|
63
|
+
lambda: http.post(
|
64
|
+
f"{self.BASE_URL}/api/chat/session", headers=self.headers, json={}
|
65
|
+
),
|
66
|
+
sleep_time=5,
|
67
67
|
)
|
68
68
|
|
69
|
-
if response.status_code != 200:
|
70
|
-
PrettyOutput.print(f"创建会话失败: {response.status_code}", OutputType.WARNING)
|
71
|
-
return False
|
72
|
-
|
73
69
|
data = response.json()
|
74
|
-
if data[
|
75
|
-
PrettyOutput.print(
|
70
|
+
if data["code"] != 0:
|
71
|
+
PrettyOutput.print(
|
72
|
+
f"创建会话失败: {data.get('msg', '未知错误')}", OutputType.WARNING
|
73
|
+
)
|
76
74
|
return False
|
77
75
|
|
78
|
-
self.conversation = data[
|
76
|
+
self.conversation = data["data"]
|
79
77
|
|
80
78
|
# 2. 更新会话设置
|
81
79
|
session_data = {
|
@@ -85,25 +83,27 @@ class AI8Model(BasePlatform):
|
|
85
83
|
"prompt": self.system_prompt,
|
86
84
|
"plugins": [],
|
87
85
|
"localPlugins": None,
|
88
|
-
"useAppId": 0
|
86
|
+
"useAppId": 0,
|
89
87
|
}
|
90
88
|
|
91
|
-
response =
|
92
|
-
|
93
|
-
|
94
|
-
|
89
|
+
response = while_success(
|
90
|
+
lambda: http.put(
|
91
|
+
f"{self.BASE_URL}/api/chat/session/{self.conversation['id']}", # type: ignore
|
92
|
+
headers=self.headers,
|
93
|
+
json=session_data,
|
94
|
+
),
|
95
|
+
sleep_time=5,
|
95
96
|
)
|
96
97
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
return True
|
102
|
-
else:
|
103
|
-
PrettyOutput.print(f"更新会话设置失败: {data.get('msg', '未知错误')}", OutputType.WARNING)
|
104
|
-
return False
|
98
|
+
data = response.json()
|
99
|
+
if data["code"] == 0:
|
100
|
+
self.conversation = data["data"]
|
101
|
+
return True
|
105
102
|
else:
|
106
|
-
PrettyOutput.print(
|
103
|
+
PrettyOutput.print(
|
104
|
+
f"更新会话设置失败: {data.get('msg', '未知错误')}",
|
105
|
+
OutputType.WARNING,
|
106
|
+
)
|
107
107
|
return False
|
108
108
|
|
109
109
|
except Exception as e:
|
@@ -123,41 +123,40 @@ class AI8Model(BasePlatform):
|
|
123
123
|
if not self.create_conversation():
|
124
124
|
raise Exception("Failed to create conversation")
|
125
125
|
|
126
|
-
|
127
|
-
|
128
126
|
payload = {
|
129
127
|
"text": message,
|
130
|
-
"sessionId": self.conversation[
|
131
|
-
"files": []
|
128
|
+
"sessionId": self.conversation["id"] if self.conversation else None,
|
129
|
+
"files": [],
|
132
130
|
}
|
133
131
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
132
|
+
# 使用stream_post进行流式请求
|
133
|
+
response_stream = while_success(
|
134
|
+
lambda: http.stream_post(
|
135
|
+
f"{self.BASE_URL}/api/chat/completions",
|
136
|
+
headers=self.headers,
|
137
|
+
json=payload,
|
138
|
+
),
|
139
|
+
sleep_time=5,
|
140
140
|
)
|
141
141
|
|
142
|
-
if response.status_code != 200:
|
143
|
-
error_msg = f"Failed to chat: {response.status_code} {response.text}"
|
144
|
-
PrettyOutput.print(error_msg, OutputType.WARNING)
|
145
|
-
raise Exception(error_msg)
|
146
|
-
|
147
142
|
# 处理流式响应
|
148
|
-
for
|
149
|
-
if
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
143
|
+
for chunk in response_stream:
|
144
|
+
if chunk:
|
145
|
+
try:
|
146
|
+
line = chunk.decode("utf-8")
|
147
|
+
if line.startswith("data: "):
|
148
|
+
try:
|
149
|
+
data = json.loads(line[6:])
|
150
|
+
if data.get("type") == "string":
|
151
|
+
chunk_data = data.get("data", "")
|
152
|
+
if chunk_data:
|
153
|
+
yield chunk_data
|
154
|
+
|
155
|
+
except json.JSONDecodeError:
|
156
|
+
continue
|
157
|
+
|
158
|
+
except UnicodeDecodeError:
|
159
|
+
continue
|
161
160
|
|
162
161
|
return None
|
163
162
|
|
@@ -169,30 +168,26 @@ class AI8Model(BasePlatform):
|
|
169
168
|
"""Return model name"""
|
170
169
|
return self.model_name
|
171
170
|
|
172
|
-
|
173
171
|
def delete_chat(self) -> bool:
|
174
172
|
"""Delete current chat session"""
|
175
173
|
try:
|
176
174
|
if not self.conversation:
|
177
175
|
return True
|
178
176
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
177
|
+
response = while_success(
|
178
|
+
lambda: http.delete(
|
179
|
+
f"{self.BASE_URL}/api/chat/session/{self.conversation['id']}", # type: ignore
|
180
|
+
headers=self.headers,
|
181
|
+
),
|
182
|
+
sleep_time=5,
|
183
183
|
)
|
184
184
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
return True
|
190
|
-
else:
|
191
|
-
error_msg = f"删除会话失败: {data.get('msg', '未知错误')}"
|
192
|
-
PrettyOutput.print(error_msg, OutputType.WARNING)
|
193
|
-
return False
|
185
|
+
data = response.json()
|
186
|
+
if data["code"] == 0:
|
187
|
+
self.conversation = None
|
188
|
+
return True
|
194
189
|
else:
|
195
|
-
error_msg = f"
|
190
|
+
error_msg = f"删除会话失败: {data.get('msg', '未知错误')}"
|
196
191
|
PrettyOutput.print(error_msg, OutputType.WARNING)
|
197
192
|
return False
|
198
193
|
|
@@ -210,25 +205,23 @@ class AI8Model(BasePlatform):
|
|
210
205
|
if self.models:
|
211
206
|
return list(self.models.keys())
|
212
207
|
|
213
|
-
response =
|
214
|
-
|
215
|
-
|
208
|
+
response = while_success(
|
209
|
+
lambda: http.get(
|
210
|
+
f"{self.BASE_URL}/api/chat/tmpl", headers=self.headers
|
211
|
+
),
|
212
|
+
sleep_time=5,
|
216
213
|
)
|
217
214
|
|
218
|
-
if response.status_code != 200:
|
219
|
-
PrettyOutput.print(f"获取模型列表失败: {response.status_code}", OutputType.WARNING)
|
220
|
-
return []
|
221
|
-
|
222
215
|
data = response.json()
|
223
|
-
if data[
|
224
|
-
PrettyOutput.print(
|
216
|
+
if data["code"] != 0:
|
217
|
+
PrettyOutput.print(
|
218
|
+
f"获取模型列表失败: {data.get('msg', '未知错误')}",
|
219
|
+
OutputType.WARNING,
|
220
|
+
)
|
225
221
|
return []
|
226
222
|
|
227
223
|
# 保存模型信息
|
228
|
-
self.models = {
|
229
|
-
model['value']: model
|
230
|
-
for model in data['data']['models']
|
231
|
-
}
|
224
|
+
self.models = {model["value"]: model for model in data["data"]["models"]}
|
232
225
|
|
233
226
|
for model in self.models.values():
|
234
227
|
# 添加标签
|
@@ -236,23 +229,23 @@ class AI8Model(BasePlatform):
|
|
236
229
|
|
237
230
|
# 添加特性标记
|
238
231
|
features = []
|
239
|
-
if model[
|
232
|
+
if model["attr"].get("multimodal"):
|
240
233
|
features.append("Multimodal")
|
241
|
-
if model[
|
234
|
+
if model["attr"].get("plugin"):
|
242
235
|
features.append("Plugin support")
|
243
|
-
if model[
|
236
|
+
if model["attr"].get("onlyImg"):
|
244
237
|
features.append("Image support")
|
245
|
-
if model[
|
246
|
-
features.append(model[
|
247
|
-
if model[
|
248
|
-
features.append(model[
|
238
|
+
if model["attr"].get("tag"):
|
239
|
+
features.append(model["attr"]["tag"])
|
240
|
+
if model["attr"].get("integral"):
|
241
|
+
features.append(model["attr"]["integral"])
|
249
242
|
# 添加备注
|
250
|
-
if model[
|
243
|
+
if model["attr"].get("note"):
|
251
244
|
model_str += f" - {model['attr']['note']}"
|
252
245
|
if features:
|
253
246
|
model_str += f" [{'|'.join(features)}]"
|
254
247
|
|
255
|
-
model[
|
248
|
+
model["desc"] = model_str
|
256
249
|
|
257
250
|
return list(self.models.keys())
|
258
251
|
|
@@ -262,9 +255,9 @@ class AI8Model(BasePlatform):
|
|
262
255
|
|
263
256
|
def support_upload_files(self) -> bool:
|
264
257
|
return False
|
265
|
-
|
258
|
+
|
266
259
|
def support_web(self) -> bool:
|
267
260
|
return False
|
268
|
-
|
261
|
+
|
269
262
|
def upload_files(self, file_list: List[str]) -> bool:
|
270
263
|
return False
|
jarvis/jarvis_platform/oyi.py
CHANGED
@@ -2,10 +2,12 @@ import mimetypes
|
|
2
2
|
import os
|
3
3
|
from typing import Dict, Generator, List, Tuple
|
4
4
|
from jarvis.jarvis_platform.base import BasePlatform
|
5
|
-
import requests
|
6
5
|
import json
|
7
6
|
|
7
|
+
from jarvis.jarvis_utils import http
|
8
8
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
9
|
+
from jarvis.jarvis_utils.utils import while_success
|
10
|
+
|
9
11
|
|
10
12
|
class OyiModel(BasePlatform):
|
11
13
|
"""Oyi model implementation"""
|
@@ -16,7 +18,7 @@ class OyiModel(BasePlatform):
|
|
16
18
|
def get_model_list(self) -> List[Tuple[str, str]]:
|
17
19
|
"""Get model list"""
|
18
20
|
self.get_available_models()
|
19
|
-
return [(name,info[
|
21
|
+
return [(name, info["desc"]) for name, info in self.models.items()]
|
20
22
|
|
21
23
|
def __init__(self):
|
22
24
|
"""Initialize model"""
|
@@ -33,23 +35,23 @@ class OyiModel(BasePlatform):
|
|
33
35
|
|
34
36
|
self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-chat"
|
35
37
|
if self.model_name not in [m.split()[0] for m in self.get_available_models()]:
|
36
|
-
PrettyOutput.print(
|
37
|
-
|
38
|
+
PrettyOutput.print(
|
39
|
+
f"警告: 选择的模型 {self.model_name} 不在可用列表中", OutputType.WARNING
|
40
|
+
)
|
38
41
|
|
39
42
|
def set_model_name(self, model_name: str):
|
40
43
|
"""Set model name"""
|
41
44
|
|
42
45
|
self.model_name = model_name
|
43
46
|
|
44
|
-
|
45
47
|
def create_conversation(self) -> bool:
|
46
48
|
"""Create a new conversation"""
|
47
49
|
try:
|
48
50
|
headers = {
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
"Authorization": f"Bearer {self.token}",
|
52
|
+
"Content-Type": "application/json",
|
53
|
+
"Accept": "application/json",
|
54
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
53
55
|
}
|
54
56
|
|
55
57
|
payload = {
|
@@ -58,35 +60,36 @@ class OyiModel(BasePlatform):
|
|
58
60
|
"title": "New conversation",
|
59
61
|
"isLock": False,
|
60
62
|
"systemMessage": "",
|
61
|
-
"params": json.dumps(
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
63
|
+
"params": json.dumps(
|
64
|
+
{
|
65
|
+
"model": self.model_name,
|
66
|
+
"is_webSearch": True,
|
67
|
+
"message": [],
|
68
|
+
"systemMessage": None,
|
69
|
+
"requestMsgCount": 65536,
|
70
|
+
"temperature": 0.8,
|
71
|
+
"speechVoice": "Alloy",
|
72
|
+
"max_tokens": 8192,
|
73
|
+
"chatPluginIds": [],
|
74
|
+
}
|
75
|
+
),
|
72
76
|
}
|
73
77
|
|
74
|
-
response =
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
+
response = while_success(
|
79
|
+
lambda: http.post(
|
80
|
+
f"{self.BASE_URL}/chatapi/chat/save", headers=headers, json=payload
|
81
|
+
),
|
82
|
+
sleep_time=5,
|
78
83
|
)
|
79
84
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
return True
|
85
|
-
else:
|
86
|
-
PrettyOutput.print(f"创建会话失败: {data['message']}", OutputType.WARNING)
|
87
|
-
return False
|
85
|
+
data = response.json()
|
86
|
+
if data["code"] == 200 and data["type"] == "success":
|
87
|
+
self.conversation = data
|
88
|
+
return True
|
88
89
|
else:
|
89
|
-
PrettyOutput.print(
|
90
|
+
PrettyOutput.print(
|
91
|
+
f"创建会话失败: {data['message']}", OutputType.WARNING
|
92
|
+
)
|
90
93
|
return False
|
91
94
|
|
92
95
|
except Exception as e:
|
@@ -114,19 +117,21 @@ class OyiModel(BasePlatform):
|
|
114
117
|
|
115
118
|
# 1. 发送消息
|
116
119
|
headers = {
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
120
|
+
"Authorization": f"Bearer {self.token}",
|
121
|
+
"Content-Type": "application/json",
|
122
|
+
"Accept": "application/json, text/plain, */*",
|
123
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
124
|
+
"Origin": "https://ai.rcouyi.com",
|
125
|
+
"Referer": "https://ai.rcouyi.com/",
|
123
126
|
}
|
124
127
|
|
125
128
|
payload = {
|
126
|
-
"topicId":
|
129
|
+
"topicId": (
|
130
|
+
self.conversation["result"]["id"] if self.conversation else None
|
131
|
+
),
|
127
132
|
"messages": self.messages,
|
128
133
|
"content": message,
|
129
|
-
"contentFiles": []
|
134
|
+
"contentFiles": [],
|
130
135
|
}
|
131
136
|
|
132
137
|
# 如果有上传的文件,添加到请求中
|
@@ -138,52 +143,47 @@ class OyiModel(BasePlatform):
|
|
138
143
|
self.messages.append({"role": "user", "content": message})
|
139
144
|
|
140
145
|
# 发送消息
|
141
|
-
response =
|
142
|
-
|
143
|
-
|
144
|
-
|
146
|
+
response = while_success(
|
147
|
+
lambda: http.post(
|
148
|
+
f"{self.BASE_URL}/chatapi/chat/message",
|
149
|
+
headers=headers,
|
150
|
+
json=payload,
|
151
|
+
),
|
152
|
+
sleep_time=5,
|
145
153
|
)
|
146
154
|
|
147
|
-
if response.status_code != 200:
|
148
|
-
error_msg = f"聊天请求失败: {response.status_code}"
|
149
|
-
PrettyOutput.print(error_msg, OutputType.WARNING)
|
150
|
-
raise Exception(error_msg)
|
151
|
-
|
152
155
|
data = response.json()
|
153
|
-
if data[
|
156
|
+
if data["code"] != 200 or data["type"] != "success":
|
154
157
|
error_msg = f"聊天失败: {data.get('message', '未知错误')}"
|
155
158
|
PrettyOutput.print(error_msg, OutputType.WARNING)
|
156
159
|
raise Exception(error_msg)
|
157
160
|
|
158
|
-
message_id = data[
|
161
|
+
message_id = data["result"][-1]
|
159
162
|
|
160
163
|
# 获取响应内容
|
161
|
-
response =
|
162
|
-
|
163
|
-
|
164
|
-
|
164
|
+
response = while_success(
|
165
|
+
lambda: http.stream_post(
|
166
|
+
f"{self.BASE_URL}/chatapi/chat/message/{message_id}",
|
167
|
+
headers=headers,
|
168
|
+
),
|
169
|
+
sleep_time=5,
|
165
170
|
)
|
166
171
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
return None
|
183
|
-
else:
|
184
|
-
error_msg = f"获取响应失败: {response.status_code}"
|
185
|
-
PrettyOutput.print(error_msg, OutputType.WARNING)
|
186
|
-
raise Exception(error_msg)
|
172
|
+
full_response = ""
|
173
|
+
bin = b""
|
174
|
+
for chunk in response:
|
175
|
+
if chunk:
|
176
|
+
bin += chunk
|
177
|
+
try:
|
178
|
+
text = bin.decode("utf-8")
|
179
|
+
except UnicodeDecodeError:
|
180
|
+
continue
|
181
|
+
full_response += text
|
182
|
+
bin = b""
|
183
|
+
yield text
|
184
|
+
|
185
|
+
self.messages.append({"role": "assistant", "content": full_response})
|
186
|
+
return None
|
187
187
|
except Exception as e:
|
188
188
|
PrettyOutput.print(f"聊天失败: {str(e)}", OutputType.ERROR)
|
189
189
|
raise e
|
@@ -192,7 +192,6 @@ class OyiModel(BasePlatform):
|
|
192
192
|
"""Return model name"""
|
193
193
|
return self.model_name
|
194
194
|
|
195
|
-
|
196
195
|
def delete_chat(self) -> bool:
|
197
196
|
"""Delete current chat session"""
|
198
197
|
try:
|
@@ -200,37 +199,34 @@ class OyiModel(BasePlatform):
|
|
200
199
|
return True
|
201
200
|
|
202
201
|
headers = {
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
202
|
+
"Authorization": f"Bearer {self.token}",
|
203
|
+
"Content-Type": "application/json",
|
204
|
+
"Accept": "application/json, text/plain, */*",
|
205
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
206
|
+
"Origin": "https://ai.rcouyi.com",
|
207
|
+
"Referer": "https://ai.rcouyi.com/",
|
209
208
|
}
|
210
209
|
|
211
|
-
response =
|
212
|
-
|
213
|
-
|
214
|
-
|
210
|
+
response = while_success(
|
211
|
+
lambda: http.post(
|
212
|
+
f"{self.BASE_URL}/chatapi/chat/{self.conversation['result']['id']}", # type: ignore
|
213
|
+
headers=headers,
|
214
|
+
json={},
|
215
|
+
),
|
216
|
+
sleep_time=5,
|
215
217
|
)
|
216
218
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
return True
|
224
|
-
else:
|
225
|
-
error_msg = f"删除会话失败: {data.get('message', '未知错误')}"
|
226
|
-
PrettyOutput.print(error_msg, OutputType.WARNING)
|
227
|
-
return False
|
219
|
+
data = response.json()
|
220
|
+
if data["code"] == 200 and data["type"] == "success":
|
221
|
+
self.messages = []
|
222
|
+
self.conversation = None
|
223
|
+
self.first_chat = True
|
224
|
+
return True
|
228
225
|
else:
|
229
|
-
error_msg = f"
|
226
|
+
error_msg = f"删除会话失败: {data.get('message', '未知错误')}"
|
230
227
|
PrettyOutput.print(error_msg, OutputType.WARNING)
|
231
228
|
return False
|
232
229
|
|
233
|
-
|
234
230
|
except Exception as e:
|
235
231
|
PrettyOutput.print(f"删除会话失败: {str(e)}", OutputType.ERROR)
|
236
232
|
return False
|
@@ -246,55 +242,53 @@ class OyiModel(BasePlatform):
|
|
246
242
|
return list(self.models.keys())
|
247
243
|
|
248
244
|
headers = {
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
245
|
+
"Content-Type": "application/json",
|
246
|
+
"Accept": "application/json, text/plain, */*",
|
247
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
248
|
+
"Origin": "https://ai.rcouyi.com",
|
249
|
+
"Referer": "https://ai.rcouyi.com/",
|
254
250
|
}
|
255
251
|
|
256
|
-
response =
|
257
|
-
|
258
|
-
|
252
|
+
response = while_success(
|
253
|
+
lambda: http.get(
|
254
|
+
"https://ai.rcouyi.com/config/system.json", headers=headers
|
255
|
+
),
|
256
|
+
sleep_time=5,
|
259
257
|
)
|
260
258
|
|
261
|
-
if response.status_code != 200:
|
262
|
-
PrettyOutput.print(f"获取模型列表失败: {response.status_code}", OutputType.WARNING)
|
263
|
-
return []
|
264
|
-
|
265
259
|
data = response.json()
|
266
260
|
|
267
261
|
# 保存模型信息
|
268
262
|
self.models = {
|
269
|
-
model[
|
270
|
-
for model in data.get(
|
271
|
-
if model.get(
|
263
|
+
model["value"]: model
|
264
|
+
for model in data.get("model", [])
|
265
|
+
if model.get("enable", False) # 只保存启用的模型
|
272
266
|
}
|
273
267
|
|
274
268
|
# 格式化显示
|
275
269
|
models = []
|
276
270
|
for model in self.models.values():
|
277
271
|
# 基本信息
|
278
|
-
model_name = model[
|
279
|
-
model_str = model[
|
272
|
+
model_name = model["value"]
|
273
|
+
model_str = model["label"]
|
280
274
|
|
281
275
|
# 添加后缀标签
|
282
|
-
suffix = model.get(
|
276
|
+
suffix = model.get("suffix", [])
|
283
277
|
if suffix:
|
284
278
|
# 处理新格式的suffix (字典列表)
|
285
279
|
if suffix and isinstance(suffix[0], dict):
|
286
|
-
suffix_str =
|
280
|
+
suffix_str = ", ".join(s.get("tag", "") for s in suffix)
|
287
281
|
# 处理旧格式的suffix (字符串列表)
|
288
282
|
else:
|
289
|
-
suffix_str =
|
283
|
+
suffix_str = ", ".join(str(s) for s in suffix)
|
290
284
|
model_str += f" ({suffix_str})"
|
291
285
|
|
292
286
|
# 添加描述或提示
|
293
|
-
info = model.get(
|
287
|
+
info = model.get("tooltip") or model.get("description", "")
|
294
288
|
if info:
|
295
289
|
model_str += f" - {info}"
|
296
290
|
|
297
|
-
model[
|
291
|
+
model["desc"] = model_str
|
298
292
|
models.append(model_name)
|
299
293
|
|
300
294
|
return sorted(models)
|
@@ -305,10 +299,9 @@ class OyiModel(BasePlatform):
|
|
305
299
|
|
306
300
|
def support_upload_files(self) -> bool:
|
307
301
|
return False
|
308
|
-
|
309
|
-
|
302
|
+
|
310
303
|
def support_web(self) -> bool:
|
311
304
|
return False
|
312
|
-
|
305
|
+
|
313
306
|
def upload_files(self, file_list: List[str]) -> bool:
|
314
307
|
return False
|
jarvis/jarvis_utils/input.py
CHANGED
@@ -38,7 +38,7 @@ def get_single_line_input(tip: str) -> str:
|
|
38
38
|
返回:
|
39
39
|
str: 用户的输入
|
40
40
|
"""
|
41
|
-
session = PromptSession(history=None)
|
41
|
+
session: PromptSession = PromptSession(history=None)
|
42
42
|
style = PromptStyle.from_dict(
|
43
43
|
{
|
44
44
|
"prompt": "ansicyan",
|
@@ -190,7 +190,7 @@ def get_multiline_input(tip: str) -> str:
|
|
190
190
|
"""
|
191
191
|
# 显示输入说明
|
192
192
|
PrettyOutput.section(
|
193
|
-
"用户输入 - 使用 @ 触发文件补全,Tab 选择补全项,Ctrl+J 提交,Ctrl+
|
193
|
+
"用户输入 - 使用 @ 触发文件补全,Tab 选择补全项,Ctrl+J 提交,Ctrl+O 复制最后一条消息,按 Ctrl+C 取消输入",
|
194
194
|
OutputType.USER,
|
195
195
|
)
|
196
196
|
print(f"{Fore.GREEN}{tip}{ColoramaStyle.RESET_ALL}")
|
@@ -212,9 +212,9 @@ def get_multiline_input(tip: str) -> str:
|
|
212
212
|
"""处理Ctrl+J以提交输入。"""
|
213
213
|
event.current_buffer.validate_and_handle()
|
214
214
|
|
215
|
-
@bindings.add("c-
|
215
|
+
@bindings.add("c-o")
|
216
216
|
def _(event):
|
217
|
-
"""处理Ctrl+
|
217
|
+
"""处理Ctrl+O以复制最后一条消息到剪贴板。"""
|
218
218
|
from jarvis.jarvis_utils.globals import get_last_message
|
219
219
|
import subprocess
|
220
220
|
|
@@ -246,7 +246,7 @@ def get_multiline_input(tip: str) -> str:
|
|
246
246
|
# 获取数据目录路径
|
247
247
|
history_dir = get_data_dir()
|
248
248
|
# 初始化带历史记录的会话
|
249
|
-
session = PromptSession(
|
249
|
+
session: PromptSession = PromptSession(
|
250
250
|
history=FileHistory(os.path.join(history_dir, "multiline_input_history")),
|
251
251
|
completer=FileCompleter(),
|
252
252
|
key_bindings=bindings,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: jarvis-ai-assistant
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.213
|
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
|
@@ -54,8 +54,8 @@ Requires-Dist: pillow==10.2.0
|
|
54
54
|
Requires-Dist: openai==1.78.1
|
55
55
|
Requires-Dist: tabulate==0.9.0
|
56
56
|
Requires-Dist: pyte==0.8.2
|
57
|
-
Requires-Dist: pyyaml>=6.0.2
|
58
57
|
Requires-Dist: httpx>=0.28.1
|
58
|
+
Requires-Dist: pyyaml>=5.3.1
|
59
59
|
Provides-Extra: dev
|
60
60
|
Requires-Dist: pytest; extra == "dev"
|
61
61
|
Requires-Dist: black; extra == "dev"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
jarvis/__init__.py,sha256
|
1
|
+
jarvis/__init__.py,sha256=-plSw2QooYexMaRlKIRHSdkQww5y9LDlUdoQ1gxFf2I,75
|
2
2
|
jarvis/jarvis_agent/__init__.py,sha256=QbI5vkourPJZ2OR63RBZAtFptTYrZz_si8bIkc9EB2o,31709
|
3
3
|
jarvis/jarvis_agent/builtin_input_handler.py,sha256=1V7kV5Zhw2HE3Xgjs1R-43RZ2huq3Kg-32NCdNnyZmA,2216
|
4
4
|
jarvis/jarvis_agent/edit_file_handler.py,sha256=bIciBghx5maDz09x0XNTxdNsyrBbTND95GupVdJIVVg,16762
|
@@ -45,12 +45,12 @@ jarvis/jarvis_methodology/main.py,sha256=-PqsWvtpUJkkhiGgV-1JegEnEZBmv8SHnNMNNm_
|
|
45
45
|
jarvis/jarvis_multi_agent/__init__.py,sha256=sDd3sK88dS7_qAz2ywIAaEWdQ4iRVCiuBu2rQQmrKbU,4512
|
46
46
|
jarvis/jarvis_multi_agent/main.py,sha256=h7VUSwoPrES0XTK8z5kt3XLX1mmcm8UEuFEHQOUWPH4,1696
|
47
47
|
jarvis/jarvis_platform/__init__.py,sha256=WLQHSiE87PPket2M50_hHzjdMIgPIBx2VF8JfB_NNRk,105
|
48
|
-
jarvis/jarvis_platform/ai8.py,sha256=
|
48
|
+
jarvis/jarvis_platform/ai8.py,sha256=UWbe6kveQvOO8wMM9mh5YWyB0zapUEeFiYVPBMnhBAE,8845
|
49
49
|
jarvis/jarvis_platform/base.py,sha256=CBFk1Kq7qzOwafOj22bacXChWvCnap3D4IacZCWC_Ss,7882
|
50
50
|
jarvis/jarvis_platform/human.py,sha256=_WQtC5w6QJnHh-3KuW8T49C-HucXiHsBEVw-m51ykj4,3196
|
51
51
|
jarvis/jarvis_platform/kimi.py,sha256=w0-OJ6xkOGPApcc2Jvc30BMjabwrnzcndmsJJsWOWJg,13419
|
52
52
|
jarvis/jarvis_platform/openai.py,sha256=uEjBikfFj7kp5wondLvOx4WdkmTX0aqF6kixxAufcHg,4806
|
53
|
-
jarvis/jarvis_platform/oyi.py,sha256=
|
53
|
+
jarvis/jarvis_platform/oyi.py,sha256=U6klSMESC69H9xTo44PXD1ZvdnMa5d7qE3jcPmPBspY,10662
|
54
54
|
jarvis/jarvis_platform/registry.py,sha256=Sz4ADAaxuufpAQG0KSQZuL1yALzH-aF3FDapkNn5foE,8107
|
55
55
|
jarvis/jarvis_platform/tongyi.py,sha256=juvzMjZ2mbNzSWzem8snmFuE28YVOjjE_YdHCZa9Qnw,20698
|
56
56
|
jarvis/jarvis_platform/yuanbao.py,sha256=ZsKXWifESXGfvB9eOot1I6TnhlmgXwnaft3e2UXgSXk,21045
|
@@ -83,14 +83,14 @@ jarvis/jarvis_utils/file_processors.py,sha256=XiM248SHS7lLgQDCbORVFWqinbVDUawYxW
|
|
83
83
|
jarvis/jarvis_utils/git_utils.py,sha256=7AZblSD4b76vXxaDFkmZOy5rNkwvkwQQxGUy3NAusDQ,21641
|
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=D0fQ6sRHjBaMm8s1L8HccC09Qlt_JD_SB_EHPCoztyA,8907
|
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
90
|
jarvis/jarvis_utils/utils.py,sha256=BoRwLcixdf7mU3Tawe95ygGhQpkMffrFYLYhPwIvw8A,14498
|
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.
|
91
|
+
jarvis_ai_assistant-0.1.213.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
92
|
+
jarvis_ai_assistant-0.1.213.dist-info/METADATA,sha256=ihUbPrOcnHuEjAtbY2-IA3Tj_ZOM3Hj_YDT5wJcsH6M,19564
|
93
|
+
jarvis_ai_assistant-0.1.213.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
94
|
+
jarvis_ai_assistant-0.1.213.dist-info/entry_points.txt,sha256=SF46ViTZcQVZEfbqzJDKKVc9TrN1x-P1mQ6wup7u2HY,875
|
95
|
+
jarvis_ai_assistant-0.1.213.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
96
|
+
jarvis_ai_assistant-0.1.213.dist-info/RECORD,,
|
File without changes
|
{jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.213.dist-info}/entry_points.txt
RENAMED
File without changes
|
{jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.213.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
{jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.213.dist-info}/top_level.txt
RENAMED
File without changes
|