jarvis-ai-assistant 0.1.175__py3-none-any.whl → 0.1.177__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 +22 -35
- jarvis/jarvis_agent/jarvis.py +14 -12
- jarvis/jarvis_agent/main.py +6 -6
- jarvis/jarvis_code_agent/code_agent.py +10 -8
- jarvis/jarvis_code_analysis/code_review.py +1 -1
- jarvis/jarvis_dev/main.py +1 -1
- jarvis/jarvis_git_details/main.py +1 -1
- jarvis/jarvis_git_squash/main.py +1 -1
- jarvis/jarvis_git_utils/git_commiter.py +1 -1
- jarvis/jarvis_multi_agent/main.py +1 -1
- jarvis/jarvis_platform/base.py +53 -32
- jarvis/jarvis_platform/human.py +4 -3
- jarvis/jarvis_platform/kimi.py +22 -170
- jarvis/jarvis_platform/openai.py +8 -30
- jarvis/jarvis_platform/yuanbao.py +35 -83
- jarvis/jarvis_platform_manager/main.py +1 -1
- jarvis/jarvis_smart_shell/main.py +4 -2
- jarvis/jarvis_tools/ask_codebase.py +8 -2
- jarvis/jarvis_tools/cli/main.py +28 -1
- jarvis/jarvis_tools/edit_file.py +163 -103
- jarvis/jarvis_tools/read_code.py +0 -2
- jarvis/jarvis_tools/registry.py +30 -0
- jarvis/jarvis_utils/config.py +12 -3
- jarvis/jarvis_utils/embedding.py +1 -10
- jarvis/jarvis_utils/output.py +78 -41
- jarvis/jarvis_utils/utils.py +19 -1
- {jarvis_ai_assistant-0.1.175.dist-info → jarvis_ai_assistant-0.1.177.dist-info}/METADATA +5 -4
- {jarvis_ai_assistant-0.1.175.dist-info → jarvis_ai_assistant-0.1.177.dist-info}/RECORD +33 -34
- {jarvis_ai_assistant-0.1.175.dist-info → jarvis_ai_assistant-0.1.177.dist-info}/WHEEL +1 -1
- jarvis/jarvis_agent/file_input_handler.py +0 -108
- {jarvis_ai_assistant-0.1.175.dist-info → jarvis_ai_assistant-0.1.177.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.175.dist-info → jarvis_ai_assistant-0.1.177.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.175.dist-info → jarvis_ai_assistant-0.1.177.dist-info}/top_level.txt +0 -0
jarvis/jarvis_platform/kimi.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
from typing import Dict, List, Tuple
|
|
2
|
+
from typing import Dict, Generator, List, Tuple
|
|
3
3
|
import requests # type: ignore
|
|
4
4
|
import json
|
|
5
5
|
import os
|
|
@@ -241,7 +241,7 @@ class KimiModel(BasePlatform):
|
|
|
241
241
|
return True
|
|
242
242
|
|
|
243
243
|
|
|
244
|
-
def chat(self, message: str) -> str:
|
|
244
|
+
def chat(self, message: str) -> Generator[str, None, None]:
|
|
245
245
|
"""Send message and get response"""
|
|
246
246
|
if not self.chat_id:
|
|
247
247
|
if not self._create_chat():
|
|
@@ -279,177 +279,29 @@ class KimiModel(BasePlatform):
|
|
|
279
279
|
|
|
280
280
|
try:
|
|
281
281
|
response = while_success(lambda: requests.post(url, headers=headers, json=payload, stream=True), sleep_time=5)
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
border_style="magenta",
|
|
295
|
-
box=box.ROUNDED)
|
|
296
|
-
|
|
297
|
-
with Live(panel, refresh_per_second=3, transient=False) as live:
|
|
298
|
-
for line in response.iter_lines():
|
|
299
|
-
if not line:
|
|
300
|
-
continue
|
|
301
|
-
|
|
302
|
-
line = line.decode('utf-8')
|
|
303
|
-
if not line.startswith("data: "):
|
|
304
|
-
continue
|
|
305
|
-
|
|
306
|
-
try:
|
|
307
|
-
data = json.loads(line[6:])
|
|
308
|
-
event = data.get("event")
|
|
309
|
-
|
|
310
|
-
if event == "cmpl":
|
|
311
|
-
# 处理补全文本
|
|
312
|
-
text = data.get("text", "")
|
|
313
|
-
if text:
|
|
314
|
-
full_response += text
|
|
315
|
-
text_content.append(text)
|
|
316
|
-
panel.subtitle = "生成中..."
|
|
317
|
-
live.update(panel)
|
|
318
|
-
|
|
319
|
-
elif event == "search_plus":
|
|
320
|
-
# 收集搜索结果
|
|
321
|
-
msg = data.get("msg", {})
|
|
322
|
-
if msg.get("type") == "get_res":
|
|
323
|
-
search_results.append({
|
|
324
|
-
"date": msg.get("date", ""),
|
|
325
|
-
"site_name": msg.get("site_name", ""),
|
|
326
|
-
"snippet": msg.get("snippet", ""),
|
|
327
|
-
"title": msg.get("title", ""),
|
|
328
|
-
"type": msg.get("type", ""),
|
|
329
|
-
"url": msg.get("url", "")
|
|
330
|
-
})
|
|
331
|
-
panel.subtitle = f"搜索中: 找到 {len(search_results)} 个结果"
|
|
332
|
-
live.update(panel)
|
|
333
|
-
|
|
334
|
-
elif event == "ref_docs":
|
|
335
|
-
# 收集引用来源
|
|
336
|
-
ref_cards = data.get("ref_cards", [])
|
|
337
|
-
for card in ref_cards:
|
|
338
|
-
ref_sources.append({
|
|
339
|
-
"idx_s": card.get("idx_s", ""),
|
|
340
|
-
"idx_z": card.get("idx_z", ""),
|
|
341
|
-
"ref_id": card.get("ref_id", ""),
|
|
342
|
-
"url": card.get("url", ""),
|
|
343
|
-
"title": card.get("title", ""),
|
|
344
|
-
"abstract": card.get("abstract", ""),
|
|
345
|
-
"source": card.get("source_label", ""),
|
|
346
|
-
"rag_segments": card.get("rag_segments", []),
|
|
347
|
-
"origin": card.get("origin", {})
|
|
348
|
-
})
|
|
349
|
-
panel.subtitle = f"分析引用: 找到 {len(ref_sources)} 个来源"
|
|
350
|
-
live.update(panel)
|
|
351
|
-
|
|
352
|
-
except json.JSONDecodeError:
|
|
353
|
-
continue
|
|
354
|
-
|
|
355
|
-
# 显示对话完成状态
|
|
356
|
-
panel.subtitle = "[bold green]回答完成[/bold green]"
|
|
357
|
-
live.update(panel)
|
|
358
|
-
else:
|
|
359
|
-
# 如果禁止输出,则静默处理
|
|
360
|
-
for line in response.iter_lines():
|
|
361
|
-
if not line:
|
|
362
|
-
continue
|
|
363
|
-
|
|
364
|
-
line = line.decode('utf-8')
|
|
365
|
-
if not line.startswith("data: "):
|
|
366
|
-
continue
|
|
367
|
-
|
|
368
|
-
try:
|
|
369
|
-
data = json.loads(line[6:])
|
|
370
|
-
event = data.get("event")
|
|
371
|
-
|
|
372
|
-
if event == "cmpl":
|
|
373
|
-
# 处理补全文本
|
|
374
|
-
text = data.get("text", "")
|
|
375
|
-
if text:
|
|
376
|
-
full_response += text
|
|
377
|
-
|
|
378
|
-
elif event == "search_plus":
|
|
379
|
-
# 收集搜索结果
|
|
380
|
-
msg = data.get("msg", {})
|
|
381
|
-
if msg.get("type") == "get_res":
|
|
382
|
-
search_results.append({
|
|
383
|
-
"date": msg.get("date", ""),
|
|
384
|
-
"site_name": msg.get("site_name", ""),
|
|
385
|
-
"snippet": msg.get("snippet", ""),
|
|
386
|
-
"title": msg.get("title", ""),
|
|
387
|
-
"type": msg.get("type", ""),
|
|
388
|
-
"url": msg.get("url", "")
|
|
389
|
-
})
|
|
390
|
-
|
|
391
|
-
elif event == "ref_docs":
|
|
392
|
-
# 收集引用来源
|
|
393
|
-
ref_cards = data.get("ref_cards", [])
|
|
394
|
-
for card in ref_cards:
|
|
395
|
-
ref_sources.append({
|
|
396
|
-
"idx_s": card.get("idx_s", ""),
|
|
397
|
-
"idx_z": card.get("idx_z", ""),
|
|
398
|
-
"ref_id": card.get("ref_id", ""),
|
|
399
|
-
"url": card.get("url", ""),
|
|
400
|
-
"title": card.get("title", ""),
|
|
401
|
-
"abstract": card.get("abstract", ""),
|
|
402
|
-
"source": card.get("source_label", ""),
|
|
403
|
-
"rag_segments": card.get("rag_segments", []),
|
|
404
|
-
"origin": card.get("origin", {})
|
|
405
|
-
})
|
|
406
|
-
|
|
407
|
-
except json.JSONDecodeError:
|
|
408
|
-
continue
|
|
409
|
-
|
|
410
|
-
# 显示搜索结果摘要
|
|
411
|
-
if search_results and not self.suppress_output:
|
|
412
|
-
output = ["搜索结果:"]
|
|
413
|
-
for result in search_results:
|
|
414
|
-
output.append(f"- {result['title']}")
|
|
415
|
-
if result['date']:
|
|
416
|
-
output.append(f" 日期: {result['date']}")
|
|
417
|
-
output.append(f" 来源: {result['site_name']}")
|
|
418
|
-
if result['snippet']:
|
|
419
|
-
output.append(f" 摘要: {result['snippet']}")
|
|
420
|
-
output.append(f" 链接: {result['url']}")
|
|
421
|
-
output.append("")
|
|
422
|
-
PrettyOutput.print("\n".join(output), OutputType.PROGRESS)
|
|
423
|
-
|
|
424
|
-
# 显示引用来源
|
|
425
|
-
if ref_sources and not self.suppress_output:
|
|
426
|
-
output = ["引用来源:"]
|
|
427
|
-
for source in ref_sources:
|
|
428
|
-
output.append(f"- [{source['ref_id']}] {source['title']} ({source['source']})")
|
|
429
|
-
output.append(f" 链接: {source['url']}")
|
|
430
|
-
if source['abstract']:
|
|
431
|
-
output.append(f" 摘要: {source['abstract']}")
|
|
432
|
-
|
|
433
|
-
# 显示相关段落
|
|
434
|
-
if source['rag_segments']:
|
|
435
|
-
output.append(" 相关段落:")
|
|
436
|
-
for segment in source['rag_segments']:
|
|
437
|
-
text = segment.get('text', '').replace('\n', ' ').strip()
|
|
438
|
-
if text:
|
|
439
|
-
output.append(f" - {text}")
|
|
440
|
-
|
|
441
|
-
# 显示原文引用
|
|
442
|
-
origin = source['origin']
|
|
443
|
-
if origin:
|
|
444
|
-
text = origin.get('text', '')
|
|
445
|
-
if text:
|
|
446
|
-
output.append(f" 原文: {text}")
|
|
282
|
+
# 如果禁止输出,则静默处理
|
|
283
|
+
for line in response.iter_lines():
|
|
284
|
+
if not line:
|
|
285
|
+
continue
|
|
286
|
+
|
|
287
|
+
line = line.decode('utf-8')
|
|
288
|
+
if not line.startswith("data: "):
|
|
289
|
+
continue
|
|
290
|
+
|
|
291
|
+
try:
|
|
292
|
+
data = json.loads(line[6:])
|
|
293
|
+
event = data.get("event")
|
|
447
294
|
|
|
448
|
-
|
|
295
|
+
if event == "cmpl":
|
|
296
|
+
# 处理补全文本
|
|
297
|
+
text = data.get("text", "")
|
|
298
|
+
if text:
|
|
299
|
+
yield text
|
|
300
|
+
except json.JSONDecodeError:
|
|
301
|
+
continue
|
|
449
302
|
|
|
450
|
-
PrettyOutput.print("\n".join(output), OutputType.PROGRESS)
|
|
451
303
|
|
|
452
|
-
return
|
|
304
|
+
return None
|
|
453
305
|
|
|
454
306
|
except Exception as e:
|
|
455
307
|
raise Exception(f"Chat failed: {str(e)}")
|
jarvis/jarvis_platform/openai.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
from typing import Dict, List, Tuple
|
|
2
|
+
from typing import Dict, Generator, List, Tuple
|
|
3
3
|
import os
|
|
4
4
|
from openai import OpenAI
|
|
5
5
|
from rich.live import Live
|
|
@@ -73,7 +73,7 @@ class OpenAIModel(BasePlatform):
|
|
|
73
73
|
self.system_message = message
|
|
74
74
|
self.messages.append({"role": "system", "content": self.system_message})
|
|
75
75
|
|
|
76
|
-
def chat(self, message: str) -> str:
|
|
76
|
+
def chat(self, message: str) -> Generator[str, None, None]:
|
|
77
77
|
"""Execute conversation"""
|
|
78
78
|
try:
|
|
79
79
|
|
|
@@ -87,38 +87,16 @@ class OpenAIModel(BasePlatform):
|
|
|
87
87
|
) # type: ignore
|
|
88
88
|
|
|
89
89
|
full_response = ""
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
title=f"[bold blue]{self.model_name}[/bold blue]",
|
|
96
|
-
subtitle="生成中...",
|
|
97
|
-
border_style="cyan",
|
|
98
|
-
box=box.ROUNDED)
|
|
99
|
-
|
|
100
|
-
with Live(panel, refresh_per_second=3, transient=False) as live:
|
|
101
|
-
for chunk in response:
|
|
102
|
-
if chunk.choices and chunk.choices[0].delta.content:
|
|
103
|
-
text = chunk.choices[0].delta.content
|
|
104
|
-
full_response += text
|
|
105
|
-
text_content.append(text)
|
|
106
|
-
live.update(panel)
|
|
107
|
-
|
|
108
|
-
# 显示对话完成状态
|
|
109
|
-
panel.subtitle = "[bold green]对话完成[/bold green]"
|
|
110
|
-
live.update(panel)
|
|
111
|
-
else:
|
|
112
|
-
# 如果禁止输出,则静默处理
|
|
113
|
-
for chunk in response:
|
|
114
|
-
if chunk.choices and chunk.choices[0].delta.content:
|
|
115
|
-
text = chunk.choices[0].delta.content
|
|
116
|
-
full_response += text
|
|
90
|
+
for chunk in response:
|
|
91
|
+
if chunk.choices and chunk.choices[0].delta.content:
|
|
92
|
+
text = chunk.choices[0].delta.content
|
|
93
|
+
full_response += text
|
|
94
|
+
yield text
|
|
117
95
|
|
|
118
96
|
# Add assistant reply to history
|
|
119
97
|
self.messages.append({"role": "assistant", "content": full_response})
|
|
120
98
|
|
|
121
|
-
return
|
|
99
|
+
return None
|
|
122
100
|
|
|
123
101
|
except Exception as e:
|
|
124
102
|
PrettyOutput.print(f"对话失败:{str(e)}", OutputType.ERROR)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
from typing import Dict, List, Tuple
|
|
2
|
+
from typing import Dict, Generator, List, Tuple
|
|
3
3
|
import requests
|
|
4
4
|
import json
|
|
5
5
|
import os
|
|
@@ -294,7 +294,7 @@ class YuanbaoPlatform(BasePlatform):
|
|
|
294
294
|
with open(file_path, 'rb') as file:
|
|
295
295
|
file_content = file.read()
|
|
296
296
|
|
|
297
|
-
spinner.write(f"ℹ️
|
|
297
|
+
spinner.write(f"ℹ️ 上传文件大小: {len(file_content)}")
|
|
298
298
|
|
|
299
299
|
# Prepare headers for PUT request
|
|
300
300
|
host = f"{upload_info['bucketName']}.{upload_info.get('accelerateDomain', 'cos.accelerate.myqcloud.com')}"
|
|
@@ -386,7 +386,7 @@ class YuanbaoPlatform(BasePlatform):
|
|
|
386
386
|
PrettyOutput.print(f"生成签名时出错: {str(e)}", OutputType.ERROR)
|
|
387
387
|
raise e
|
|
388
388
|
|
|
389
|
-
def chat(self, message: str) -> str:
|
|
389
|
+
def chat(self, message: str) -> Generator[str, None, None]:
|
|
390
390
|
"""发送消息并获取响应,可选文件附件
|
|
391
391
|
|
|
392
392
|
参数:
|
|
@@ -452,86 +452,38 @@ class YuanbaoPlatform(BasePlatform):
|
|
|
452
452
|
error_msg += f", 响应: {response.text}"
|
|
453
453
|
raise Exception(error_msg)
|
|
454
454
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
# 处理思考中的消息
|
|
489
|
-
elif data.get("type") == "think":
|
|
490
|
-
think_content = data.get("content", "")
|
|
491
|
-
if think_content:
|
|
492
|
-
thinking_content = think_content
|
|
493
|
-
panel.subtitle = f"思考中: {thinking_content}"
|
|
494
|
-
live.update(panel)
|
|
495
|
-
|
|
496
|
-
except json.JSONDecodeError:
|
|
497
|
-
pass
|
|
498
|
-
|
|
499
|
-
# 检测结束标志
|
|
500
|
-
elif line_str == "data: [DONE]":
|
|
501
|
-
break
|
|
502
|
-
|
|
503
|
-
# 显示对话完成状态
|
|
504
|
-
panel.subtitle = "[bold green]对话完成[/bold green]"
|
|
505
|
-
live.update(panel)
|
|
506
|
-
else:
|
|
507
|
-
# 如果禁止输出,则静默处理
|
|
508
|
-
for line in response.iter_lines():
|
|
509
|
-
if not line:
|
|
510
|
-
continue
|
|
511
|
-
|
|
512
|
-
line_str = line.decode('utf-8')
|
|
513
|
-
|
|
514
|
-
# SSE格式的行通常以"data: "开头
|
|
515
|
-
if line_str.startswith("data: "):
|
|
516
|
-
try:
|
|
517
|
-
data_str = line_str[6:] # 移除"data: "前缀
|
|
518
|
-
data = json.loads(data_str)
|
|
519
|
-
|
|
520
|
-
# 处理文本类型的消息
|
|
521
|
-
if data.get("type") == "text":
|
|
522
|
-
is_text_block = True
|
|
523
|
-
msg = data.get("msg", "")
|
|
524
|
-
if msg:
|
|
525
|
-
full_response += msg
|
|
526
|
-
|
|
527
|
-
except json.JSONDecodeError:
|
|
528
|
-
pass
|
|
529
|
-
|
|
530
|
-
# 检测结束标志
|
|
531
|
-
elif line_str == "data: [DONE]":
|
|
532
|
-
break
|
|
533
|
-
|
|
534
|
-
return full_response
|
|
455
|
+
# 处理SSE流响应
|
|
456
|
+
for line in response.iter_lines():
|
|
457
|
+
if not line:
|
|
458
|
+
continue
|
|
459
|
+
|
|
460
|
+
line_str = line.decode('utf-8')
|
|
461
|
+
|
|
462
|
+
# SSE格式的行通常以"data: "开头
|
|
463
|
+
if line_str.startswith("data: "):
|
|
464
|
+
try:
|
|
465
|
+
data_str = line_str[6:] # 移除"data: "前缀
|
|
466
|
+
data = json.loads(data_str)
|
|
467
|
+
|
|
468
|
+
# 处理文本类型的消息
|
|
469
|
+
if data.get("type") == "text":
|
|
470
|
+
msg = data.get("msg", "")
|
|
471
|
+
if msg:
|
|
472
|
+
yield msg
|
|
473
|
+
|
|
474
|
+
# 处理思考中的消息
|
|
475
|
+
elif data.get("type") == "think":
|
|
476
|
+
think_content = data.get("content", "")
|
|
477
|
+
if think_content:
|
|
478
|
+
yield think_content
|
|
479
|
+
|
|
480
|
+
except json.JSONDecodeError:
|
|
481
|
+
pass
|
|
482
|
+
|
|
483
|
+
# 检测结束标志
|
|
484
|
+
elif line_str == "data: [DONE]":
|
|
485
|
+
return None
|
|
486
|
+
return None
|
|
535
487
|
|
|
536
488
|
except Exception as e:
|
|
537
489
|
raise Exception(f"对话失败: {str(e)}")
|
|
@@ -606,7 +606,7 @@ def main():
|
|
|
606
606
|
"""Main function"""
|
|
607
607
|
import argparse
|
|
608
608
|
|
|
609
|
-
init_env()
|
|
609
|
+
init_env("欢迎使用 Jarvis-PlatformManager,您的平台管理助手已准备就绪!")
|
|
610
610
|
|
|
611
611
|
parser = argparse.ArgumentParser(description='Jarvis AI 平台')
|
|
612
612
|
subparsers = parser.add_subparsers(dest='command', help='可用子命令')
|
|
@@ -5,6 +5,8 @@ import os
|
|
|
5
5
|
import sys
|
|
6
6
|
from typing import Optional
|
|
7
7
|
|
|
8
|
+
from sympy import false
|
|
9
|
+
|
|
8
10
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
9
11
|
from jarvis.jarvis_utils.config import get_shell_name
|
|
10
12
|
from jarvis.jarvis_utils.input import get_multiline_input
|
|
@@ -113,8 +115,8 @@ def process_request(request: str) -> Optional[str]:
|
|
|
113
115
|
return None
|
|
114
116
|
|
|
115
117
|
def main() -> int:
|
|
116
|
-
# 创建参数解析器
|
|
117
|
-
init_env()
|
|
118
|
+
# 创建参数解析器s
|
|
119
|
+
init_env("")
|
|
118
120
|
parser = argparse.ArgumentParser(
|
|
119
121
|
description="将自然语言要求转换为shell命令",
|
|
120
122
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
@@ -253,20 +253,26 @@ def main():
|
|
|
253
253
|
```
|
|
254
254
|
python -m jarvis.jarvis_tools.ask_codebase "登录功能在哪个文件实现?" --root_dir /path/to/codebase
|
|
255
255
|
```
|
|
256
|
+
如果没有提供问题参数,则会进入交互式多行输入模式
|
|
256
257
|
"""
|
|
257
258
|
import argparse
|
|
258
259
|
import sys
|
|
260
|
+
from jarvis.jarvis_utils.input import get_multiline_input
|
|
259
261
|
|
|
260
|
-
init_env()
|
|
262
|
+
init_env("欢迎使用 Jarvis-AskCodebase,您的智能代码库查询工具已准备就绪!")
|
|
261
263
|
|
|
262
264
|
# 创建命令行参数解析器
|
|
263
265
|
parser = argparse.ArgumentParser(description="智能代码库查询工具")
|
|
264
|
-
parser.add_argument("question", help="关于代码库的问题")
|
|
266
|
+
parser.add_argument("question", nargs="?", help="关于代码库的问题")
|
|
265
267
|
parser.add_argument("--root_dir", "-d", default=".", help="代码库根目录路径")
|
|
266
268
|
|
|
267
269
|
# 解析命令行参数
|
|
268
270
|
args = parser.parse_args()
|
|
269
271
|
|
|
272
|
+
# 如果没有提供问题参数,使用多行输入
|
|
273
|
+
if not args.question:
|
|
274
|
+
args.question = get_multiline_input("请输入关于代码库的问题:")
|
|
275
|
+
|
|
270
276
|
# 创建并执行工具
|
|
271
277
|
tool = AskCodebaseTool(auto_complete=False)
|
|
272
278
|
result = tool.execute({
|
jarvis/jarvis_tools/cli/main.py
CHANGED
|
@@ -29,7 +29,7 @@ def main() -> int:
|
|
|
29
29
|
import argparse
|
|
30
30
|
import json
|
|
31
31
|
|
|
32
|
-
init_env()
|
|
32
|
+
init_env("欢迎使用 Jarvis-Tools,您的工具系统已准备就绪!")
|
|
33
33
|
|
|
34
34
|
parser = argparse.ArgumentParser(description="Jarvis 工具系统命令行界面")
|
|
35
35
|
subparsers = parser.add_subparsers(dest="command", help="命令")
|
|
@@ -47,6 +47,10 @@ def main() -> int:
|
|
|
47
47
|
"--args-file", type=str, help="从文件加载工具参数 (JSON格式)"
|
|
48
48
|
)
|
|
49
49
|
|
|
50
|
+
# 统计子命令
|
|
51
|
+
stat_parser = subparsers.add_parser("stat", help="显示工具调用统计信息")
|
|
52
|
+
stat_parser.add_argument("--json", action="store_true", help="以JSON格式输出")
|
|
53
|
+
|
|
50
54
|
args = parser.parse_args()
|
|
51
55
|
|
|
52
56
|
# 初始化工具注册表
|
|
@@ -72,6 +76,29 @@ def main() -> int:
|
|
|
72
76
|
print(f" 参数:")
|
|
73
77
|
print(tool["parameters"]) # 显示详细参数信息
|
|
74
78
|
|
|
79
|
+
elif args.command == "stat":
|
|
80
|
+
from tabulate import tabulate
|
|
81
|
+
stats = registry._get_tool_stats()
|
|
82
|
+
tools = registry.get_all_tools()
|
|
83
|
+
|
|
84
|
+
# 构建统计表格数据
|
|
85
|
+
table_data = []
|
|
86
|
+
for tool in tools:
|
|
87
|
+
name = tool["name"]
|
|
88
|
+
count = stats.get(name, 0)
|
|
89
|
+
table_data.append([name, count])
|
|
90
|
+
|
|
91
|
+
# 按调用次数降序排序
|
|
92
|
+
table_data.sort(key=lambda x: x[1], reverse=True)
|
|
93
|
+
|
|
94
|
+
if args.json:
|
|
95
|
+
print(json.dumps(dict(table_data), indent=2))
|
|
96
|
+
else:
|
|
97
|
+
PrettyOutput.section("工具调用统计", OutputType.SYSTEM)
|
|
98
|
+
print(tabulate(table_data, headers=["工具名称", "调用次数"], tablefmt="grid"))
|
|
99
|
+
|
|
100
|
+
return 0
|
|
101
|
+
|
|
75
102
|
elif args.command == "call":
|
|
76
103
|
tool_name = args.tool_name
|
|
77
104
|
tool_obj = registry.get_tool(tool_name)
|