jarvis-ai-assistant 0.3.19__py3-none-any.whl → 0.3.21__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +33 -5
- jarvis/jarvis_agent/config_editor.py +5 -1
- jarvis/jarvis_agent/edit_file_handler.py +15 -9
- jarvis/jarvis_agent/jarvis.py +99 -3
- jarvis/jarvis_agent/memory_manager.py +3 -3
- jarvis/jarvis_agent/share_manager.py +3 -1
- jarvis/jarvis_agent/shell_input_handler.py +17 -2
- jarvis/jarvis_agent/task_analyzer.py +0 -1
- jarvis/jarvis_agent/task_manager.py +15 -5
- jarvis/jarvis_agent/tool_executor.py +2 -2
- jarvis/jarvis_code_agent/code_agent.py +39 -16
- jarvis/jarvis_git_utils/git_commiter.py +3 -6
- jarvis/jarvis_mcp/sse_mcp_client.py +9 -3
- jarvis/jarvis_mcp/streamable_mcp_client.py +15 -5
- jarvis/jarvis_memory_organizer/memory_organizer.py +1 -1
- jarvis/jarvis_methodology/main.py +4 -4
- jarvis/jarvis_multi_agent/__init__.py +3 -3
- jarvis/jarvis_platform/ai8.py +0 -4
- jarvis/jarvis_platform/base.py +12 -7
- jarvis/jarvis_platform/kimi.py +18 -6
- jarvis/jarvis_platform/tongyi.py +18 -5
- jarvis/jarvis_platform/yuanbao.py +10 -3
- jarvis/jarvis_platform_manager/main.py +21 -7
- jarvis/jarvis_platform_manager/service.py +4 -3
- jarvis/jarvis_rag/cli.py +61 -22
- jarvis/jarvis_rag/embedding_manager.py +10 -3
- jarvis/jarvis_rag/llm_interface.py +4 -1
- jarvis/jarvis_rag/query_rewriter.py +3 -1
- jarvis/jarvis_rag/rag_pipeline.py +11 -3
- jarvis/jarvis_rag/retriever.py +151 -2
- jarvis/jarvis_smart_shell/main.py +60 -19
- jarvis/jarvis_stats/cli.py +12 -9
- jarvis/jarvis_stats/stats.py +17 -11
- jarvis/jarvis_stats/storage.py +23 -6
- jarvis/jarvis_tools/cli/main.py +63 -29
- jarvis/jarvis_tools/edit_file.py +3 -4
- jarvis/jarvis_tools/file_analyzer.py +0 -1
- jarvis/jarvis_tools/generate_new_tool.py +3 -3
- jarvis/jarvis_tools/read_code.py +0 -1
- jarvis/jarvis_tools/read_webpage.py +14 -4
- jarvis/jarvis_tools/registry.py +0 -3
- jarvis/jarvis_tools/retrieve_memory.py +0 -1
- jarvis/jarvis_tools/save_memory.py +0 -1
- jarvis/jarvis_tools/search_web.py +0 -2
- jarvis/jarvis_tools/sub_agent.py +197 -0
- jarvis/jarvis_tools/sub_code_agent.py +194 -0
- jarvis/jarvis_tools/virtual_tty.py +21 -13
- jarvis/jarvis_utils/clipboard.py +1 -1
- jarvis/jarvis_utils/config.py +35 -5
- jarvis/jarvis_utils/input.py +528 -41
- jarvis/jarvis_utils/methodology.py +3 -1
- jarvis/jarvis_utils/output.py +218 -129
- jarvis/jarvis_utils/utils.py +480 -170
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/METADATA +10 -2
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/RECORD +60 -58
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.3.19.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/top_level.txt +0 -0
@@ -208,7 +208,9 @@ def load_methodology(
|
|
208
208
|
if not methodologies:
|
209
209
|
PrettyOutput.print("没有找到方法论文件", OutputType.WARNING)
|
210
210
|
return ""
|
211
|
-
PrettyOutput.print(
|
211
|
+
PrettyOutput.print(
|
212
|
+
f"加载方法论文件完成 (共 {len(methodologies)} 个)", OutputType.SUCCESS
|
213
|
+
)
|
212
214
|
|
213
215
|
if platform_name:
|
214
216
|
platform = PlatformRegistry().create_platform(platform_name)
|
jarvis/jarvis_utils/output.py
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
"""
|
11
11
|
from datetime import datetime
|
12
12
|
from enum import Enum
|
13
|
-
from typing import Dict, Optional, Tuple, Any
|
13
|
+
from typing import Dict, Optional, Tuple, Any, List
|
14
14
|
|
15
15
|
from pygments.lexers import guess_lexer
|
16
16
|
from pygments.util import ClassNotFound
|
@@ -20,8 +20,10 @@ from rich.style import Style as RichStyle
|
|
20
20
|
from rich.syntax import Syntax
|
21
21
|
from rich.text import Text
|
22
22
|
|
23
|
-
from jarvis.jarvis_utils.config import get_pretty_output
|
23
|
+
from jarvis.jarvis_utils.config import get_pretty_output, is_print_error_traceback
|
24
24
|
from jarvis.jarvis_utils.globals import console, get_agent_list
|
25
|
+
from dataclasses import dataclass
|
26
|
+
from abc import ABC, abstractmethod
|
25
27
|
|
26
28
|
|
27
29
|
class OutputType(Enum):
|
@@ -57,124 +59,60 @@ class OutputType(Enum):
|
|
57
59
|
TOOL = "TOOL"
|
58
60
|
|
59
61
|
|
60
|
-
|
62
|
+
@dataclass
|
63
|
+
class OutputEvent:
|
61
64
|
"""
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
-
|
66
|
-
-
|
67
|
-
-
|
68
|
-
-
|
65
|
+
输出事件的通用结构,供不同输出后端(Sink)消费。
|
66
|
+
- text: 文本内容
|
67
|
+
- output_type: 输出类型
|
68
|
+
- timestamp: 是否显示时间戳
|
69
|
+
- lang: 语法高亮语言(可选,不提供则自动检测)
|
70
|
+
- traceback: 是否显示异常堆栈
|
71
|
+
- section: 若为章节标题输出,填入标题文本;否则为None
|
72
|
+
- context: 额外上下文(预留给TUI/日志等)
|
69
73
|
"""
|
70
74
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
OutputType.PLANNING: "📋",
|
79
|
-
OutputType.PROGRESS: "⏳",
|
80
|
-
OutputType.SUCCESS: "✅",
|
81
|
-
OutputType.WARNING: "⚠️",
|
82
|
-
OutputType.DEBUG: "🔍",
|
83
|
-
OutputType.USER: "👤",
|
84
|
-
OutputType.TOOL: "🔧",
|
85
|
-
}
|
86
|
-
# 语法高亮的语言映射
|
87
|
-
_lang_map = {
|
88
|
-
"Python": "python",
|
89
|
-
"JavaScript": "javascript",
|
90
|
-
"TypeScript": "typescript",
|
91
|
-
"Java": "java",
|
92
|
-
"C++": "cpp",
|
93
|
-
"C#": "csharp",
|
94
|
-
"Ruby": "ruby",
|
95
|
-
"PHP": "php",
|
96
|
-
"Go": "go",
|
97
|
-
"Rust": "rust",
|
98
|
-
"Bash": "bash",
|
99
|
-
"HTML": "html",
|
100
|
-
"CSS": "css",
|
101
|
-
"SQL": "sql",
|
102
|
-
"R": "r",
|
103
|
-
"Kotlin": "kotlin",
|
104
|
-
"Swift": "swift",
|
105
|
-
"Scala": "scala",
|
106
|
-
"Perl": "perl",
|
107
|
-
"Lua": "lua",
|
108
|
-
"YAML": "yaml",
|
109
|
-
"JSON": "json",
|
110
|
-
"XML": "xml",
|
111
|
-
"Markdown": "markdown",
|
112
|
-
"Text": "text",
|
113
|
-
"Shell": "bash",
|
114
|
-
"Dockerfile": "dockerfile",
|
115
|
-
"Makefile": "makefile",
|
116
|
-
"INI": "ini",
|
117
|
-
"TOML": "toml",
|
118
|
-
}
|
75
|
+
text: str
|
76
|
+
output_type: OutputType
|
77
|
+
timestamp: bool = True
|
78
|
+
lang: Optional[str] = None
|
79
|
+
traceback: bool = False
|
80
|
+
section: Optional[str] = None
|
81
|
+
context: Optional[Dict[str, Any]] = None
|
119
82
|
|
120
|
-
@staticmethod
|
121
|
-
def _detect_language(text: str, default_lang: str = "markdown") -> str:
|
122
|
-
"""
|
123
|
-
检测给定文本的编程语言。
|
124
83
|
|
125
|
-
|
126
|
-
|
127
|
-
default_lang: 如果检测失败,默认返回的语言
|
84
|
+
class OutputSink(ABC):
|
85
|
+
"""输出后端抽象接口,不同前端(控制台/TUI/SSE/日志)实现该接口以消费输出事件。"""
|
128
86
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
try:
|
133
|
-
lexer = guess_lexer(text)
|
134
|
-
detected_lang = lexer.name # type: ignore[attr-defined]
|
135
|
-
return PrettyOutput._lang_map.get(detected_lang, default_lang)
|
136
|
-
except (ClassNotFound, Exception):
|
137
|
-
return default_lang
|
87
|
+
@abstractmethod
|
88
|
+
def emit(self, event: OutputEvent) -> None: # pragma: no cover - 抽象方法
|
89
|
+
raise NotImplementedError
|
138
90
|
|
139
|
-
@staticmethod
|
140
|
-
def _format(output_type: OutputType, timestamp: bool = True) -> str:
|
141
|
-
"""
|
142
|
-
使用时间戳和图标格式化输出头。
|
143
91
|
|
144
|
-
|
145
|
-
|
146
|
-
|
92
|
+
class ConsoleOutputSink(OutputSink):
|
93
|
+
"""
|
94
|
+
默认控制台输出实现,保持与原 PrettyOutput 行为一致。
|
95
|
+
"""
|
147
96
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
return formatted
|
97
|
+
def emit(self, event: OutputEvent) -> None:
|
98
|
+
# 章节输出
|
99
|
+
if event.section is not None:
|
100
|
+
text = Text(event.section, style=event.output_type.value, justify="center")
|
101
|
+
panel = Panel(text, border_style=event.output_type.value)
|
102
|
+
if get_pretty_output():
|
103
|
+
console.print(panel)
|
104
|
+
else:
|
105
|
+
console.print(text)
|
106
|
+
return
|
159
107
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
traceback: bool = False,
|
167
|
-
):
|
168
|
-
"""
|
169
|
-
使用样式和语法高亮打印格式化输出。
|
108
|
+
# 普通内容输出
|
109
|
+
lang = (
|
110
|
+
event.lang
|
111
|
+
if event.lang is not None
|
112
|
+
else PrettyOutput._detect_language(event.text, default_lang="markdown")
|
113
|
+
)
|
170
114
|
|
171
|
-
|
172
|
-
text: 要打印的文本内容
|
173
|
-
output_type: 输出类型(影响样式)
|
174
|
-
timestamp: 是否显示时间戳
|
175
|
-
lang: 语法高亮的语言
|
176
|
-
traceback: 是否显示错误的回溯信息
|
177
|
-
"""
|
115
|
+
# 与原实现保持一致的样式定义
|
178
116
|
styles: Dict[OutputType, Dict[str, Any]] = {
|
179
117
|
OutputType.SYSTEM: dict(bgcolor="#1e2b3c"),
|
180
118
|
OutputType.CODE: dict(bgcolor="#1c2b1c"),
|
@@ -255,25 +193,20 @@ class PrettyOutput:
|
|
255
193
|
),
|
256
194
|
}
|
257
195
|
|
258
|
-
lang = (
|
259
|
-
lang
|
260
|
-
if lang is not None
|
261
|
-
else PrettyOutput._detect_language(text, default_lang="markdown")
|
262
|
-
)
|
263
196
|
header = Text(
|
264
|
-
PrettyOutput._format(output_type, timestamp),
|
265
|
-
style=header_styles[output_type],
|
197
|
+
PrettyOutput._format(event.output_type, event.timestamp),
|
198
|
+
style=header_styles[event.output_type],
|
266
199
|
)
|
267
200
|
content = Syntax(
|
268
|
-
text,
|
201
|
+
event.text,
|
269
202
|
lang,
|
270
203
|
theme="monokai",
|
271
204
|
word_wrap=True,
|
272
|
-
background_color=styles[output_type]["bgcolor"],
|
205
|
+
background_color=styles[event.output_type]["bgcolor"],
|
273
206
|
)
|
274
207
|
panel = Panel(
|
275
208
|
content,
|
276
|
-
border_style=header_styles[output_type],
|
209
|
+
border_style=header_styles[event.output_type],
|
277
210
|
padding=(0, 0),
|
278
211
|
highlight=True,
|
279
212
|
)
|
@@ -281,27 +214,183 @@ class PrettyOutput:
|
|
281
214
|
console.print(panel)
|
282
215
|
else:
|
283
216
|
console.print(content)
|
284
|
-
if traceback or
|
217
|
+
if event.traceback or (
|
218
|
+
event.output_type == OutputType.ERROR and is_print_error_traceback()
|
219
|
+
):
|
285
220
|
try:
|
286
221
|
console.print_exception()
|
287
222
|
except Exception as e:
|
288
223
|
console.print(f"Error: {e}")
|
289
224
|
|
225
|
+
|
226
|
+
# 模块级输出分发器(默认注册控制台后端)
|
227
|
+
_output_sinks: List[OutputSink] = [ConsoleOutputSink()]
|
228
|
+
|
229
|
+
|
230
|
+
def emit_output(event: OutputEvent) -> None:
|
231
|
+
"""向所有已注册的输出后端广播事件。"""
|
232
|
+
for sink in list(_output_sinks):
|
233
|
+
try:
|
234
|
+
sink.emit(event)
|
235
|
+
except Exception as e:
|
236
|
+
# 后端故障不影响其他后端
|
237
|
+
console.print(f"[输出后端错误] {sink.__class__.__name__}: {e}")
|
238
|
+
|
239
|
+
|
240
|
+
class PrettyOutput:
|
241
|
+
"""
|
242
|
+
使用rich库格式化和显示富文本输出的类。
|
243
|
+
|
244
|
+
提供以下方法:
|
245
|
+
- 使用适当的样式格式化不同类型的输出
|
246
|
+
- 代码块的语法高亮
|
247
|
+
- 结构化内容的面板显示
|
248
|
+
- 渐进显示的流式输出
|
249
|
+
"""
|
250
|
+
|
251
|
+
# 不同输出类型的图标
|
252
|
+
_ICONS = {
|
253
|
+
OutputType.SYSTEM: "🤖",
|
254
|
+
OutputType.CODE: "📝",
|
255
|
+
OutputType.RESULT: "✨",
|
256
|
+
OutputType.ERROR: "❌",
|
257
|
+
OutputType.INFO: "ℹ️",
|
258
|
+
OutputType.PLANNING: "📋",
|
259
|
+
OutputType.PROGRESS: "⏳",
|
260
|
+
OutputType.SUCCESS: "✅",
|
261
|
+
OutputType.WARNING: "⚠️",
|
262
|
+
OutputType.DEBUG: "🔍",
|
263
|
+
OutputType.USER: "👤",
|
264
|
+
OutputType.TOOL: "🔧",
|
265
|
+
}
|
266
|
+
# 语法高亮的语言映射
|
267
|
+
_lang_map = {
|
268
|
+
"Python": "python",
|
269
|
+
"JavaScript": "javascript",
|
270
|
+
"TypeScript": "typescript",
|
271
|
+
"Java": "java",
|
272
|
+
"C++": "cpp",
|
273
|
+
"C#": "csharp",
|
274
|
+
"Ruby": "ruby",
|
275
|
+
"PHP": "php",
|
276
|
+
"Go": "go",
|
277
|
+
"Rust": "rust",
|
278
|
+
"Bash": "bash",
|
279
|
+
"HTML": "html",
|
280
|
+
"CSS": "css",
|
281
|
+
"SQL": "sql",
|
282
|
+
"R": "r",
|
283
|
+
"Kotlin": "kotlin",
|
284
|
+
"Swift": "swift",
|
285
|
+
"Scala": "scala",
|
286
|
+
"Perl": "perl",
|
287
|
+
"Lua": "lua",
|
288
|
+
"YAML": "yaml",
|
289
|
+
"JSON": "json",
|
290
|
+
"XML": "xml",
|
291
|
+
"Markdown": "markdown",
|
292
|
+
"Text": "text",
|
293
|
+
"Shell": "bash",
|
294
|
+
"Dockerfile": "dockerfile",
|
295
|
+
"Makefile": "makefile",
|
296
|
+
"INI": "ini",
|
297
|
+
"TOML": "toml",
|
298
|
+
}
|
299
|
+
|
290
300
|
@staticmethod
|
291
|
-
def
|
301
|
+
def _detect_language(text: str, default_lang: str = "markdown") -> str:
|
292
302
|
"""
|
293
|
-
|
303
|
+
检测给定文本的编程语言。
|
294
304
|
|
295
305
|
参数:
|
296
|
-
|
297
|
-
|
306
|
+
text: 要分析的文本
|
307
|
+
default_lang: 如果检测失败,默认返回的语言
|
308
|
+
|
309
|
+
返回:
|
310
|
+
str: 检测到的语言名称
|
298
311
|
"""
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
312
|
+
try:
|
313
|
+
lexer = guess_lexer(text)
|
314
|
+
detected_lang = lexer.name # type: ignore[attr-defined]
|
315
|
+
return PrettyOutput._lang_map.get(detected_lang, default_lang)
|
316
|
+
except (ClassNotFound, Exception):
|
317
|
+
return default_lang
|
318
|
+
|
319
|
+
@staticmethod
|
320
|
+
def _format(output_type: OutputType, timestamp: bool = True) -> str:
|
321
|
+
"""
|
322
|
+
使用时间戳和图标格式化输出头。
|
323
|
+
|
324
|
+
参数:
|
325
|
+
output_type: 输出类型
|
326
|
+
timestamp: 是否包含时间戳
|
327
|
+
|
328
|
+
返回:
|
329
|
+
Text: 格式化后的rich Text对象
|
330
|
+
"""
|
331
|
+
icon = PrettyOutput._ICONS.get(output_type, "")
|
332
|
+
formatted = f"{icon} "
|
333
|
+
if timestamp:
|
334
|
+
formatted += f"[{datetime.now().strftime('%H:%M:%S')}][{output_type.value}]"
|
335
|
+
agent_info = get_agent_list()
|
336
|
+
if agent_info:
|
337
|
+
formatted += f"[{agent_info}]"
|
338
|
+
return formatted
|
339
|
+
|
340
|
+
@staticmethod
|
341
|
+
def print(
|
342
|
+
text: str,
|
343
|
+
output_type: OutputType,
|
344
|
+
timestamp: bool = True,
|
345
|
+
lang: Optional[str] = None,
|
346
|
+
traceback: bool = False,
|
347
|
+
):
|
348
|
+
"""
|
349
|
+
使用样式和语法高亮打印格式化输出(已抽象为事件 + Sink 机制)。
|
350
|
+
保持对现有调用方的向后兼容,同时为TUI/日志等前端预留扩展点。
|
351
|
+
"""
|
352
|
+
event = OutputEvent(
|
353
|
+
text=text,
|
354
|
+
output_type=output_type,
|
355
|
+
timestamp=timestamp,
|
356
|
+
lang=lang,
|
357
|
+
traceback=traceback,
|
358
|
+
)
|
359
|
+
emit_output(event)
|
360
|
+
|
361
|
+
@staticmethod
|
362
|
+
def section(title: str, output_type: OutputType = OutputType.INFO):
|
363
|
+
"""
|
364
|
+
在样式化面板中打印章节标题(通过事件 + Sink 机制分发)。
|
365
|
+
"""
|
366
|
+
event = OutputEvent(
|
367
|
+
text="",
|
368
|
+
output_type=output_type,
|
369
|
+
section=title,
|
370
|
+
)
|
371
|
+
emit_output(event)
|
372
|
+
|
373
|
+
@staticmethod
|
374
|
+
# Sink管理(为外部注册自定义后端预留)
|
375
|
+
@staticmethod
|
376
|
+
def add_sink(sink: OutputSink) -> None:
|
377
|
+
"""注册一个新的输出后端。"""
|
378
|
+
_output_sinks.append(sink)
|
379
|
+
|
380
|
+
@staticmethod
|
381
|
+
def clear_sinks(keep_default: bool = True) -> None:
|
382
|
+
"""清空已注册的输出后端;可选择保留默认控制台后端。"""
|
383
|
+
if keep_default:
|
384
|
+
globals()["_output_sinks"] = [
|
385
|
+
s for s in _output_sinks if isinstance(s, ConsoleOutputSink)
|
386
|
+
]
|
303
387
|
else:
|
304
|
-
|
388
|
+
_output_sinks.clear()
|
389
|
+
|
390
|
+
@staticmethod
|
391
|
+
def get_sinks() -> List[OutputSink]:
|
392
|
+
"""获取当前已注册的输出后端列表(副本)。"""
|
393
|
+
return list(_output_sinks)
|
305
394
|
|
306
395
|
@staticmethod
|
307
396
|
def print_gradient_text(
|