jarvis-ai-assistant 0.3.15__py3-none-any.whl → 0.3.17__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 CHANGED
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Jarvis AI Assistant"""
3
3
 
4
- __version__ = "0.3.15"
4
+ __version__ = "0.3.17"
@@ -10,10 +10,357 @@ from jarvis.jarvis_agent.config_editor import ConfigEditor
10
10
  from jarvis.jarvis_agent.methodology_share_manager import MethodologyShareManager
11
11
  from jarvis.jarvis_agent.tool_share_manager import ToolShareManager
12
12
  from jarvis.jarvis_utils.utils import init_env
13
+ from jarvis.jarvis_utils.config import (
14
+ is_enable_git_repo_jca_switch,
15
+ is_enable_builtin_config_selector,
16
+ get_agent_definition_dirs,
17
+ get_multi_agent_dirs,
18
+ get_roles_dirs,
19
+ )
20
+ import jarvis.jarvis_utils.utils as jutils
21
+ from jarvis.jarvis_utils.input import user_confirm, get_single_line_input
22
+ import os
23
+ import sys
24
+ import subprocess
25
+ from pathlib import Path
26
+ import yaml # type: ignore
27
+ from rich.table import Table
28
+ from rich.console import Console
13
29
 
14
30
  app = typer.Typer(help="Jarvis AI 助手")
15
31
 
16
32
 
33
+ def print_commands_overview() -> None:
34
+ """打印命令与快捷方式总览表。"""
35
+ try:
36
+ cmd_table = Table(show_header=True, header_style="bold magenta")
37
+ cmd_table.add_column("命令", style="bold")
38
+ cmd_table.add_column("快捷方式", style="cyan")
39
+ cmd_table.add_column("功能描述", style="white")
40
+
41
+ cmd_table.add_row("jarvis", "jvs", "通用AI代理,适用于多种任务")
42
+ cmd_table.add_row("jarvis-agent", "ja", "AI代理基础功能,处理会话和任务")
43
+ cmd_table.add_row(
44
+ "jarvis-code-agent",
45
+ "jca",
46
+ "专注于代码分析、修改和生成的代码代理",
47
+ )
48
+ cmd_table.add_row("jarvis-code-review", "jcr", "智能代码审查工具")
49
+ cmd_table.add_row(
50
+ "jarvis-git-commit",
51
+ "jgc",
52
+ "自动化分析代码变更并生成规范的Git提交信息",
53
+ )
54
+ cmd_table.add_row("jarvis-git-squash", "jgs", "Git提交历史整理工具")
55
+ cmd_table.add_row(
56
+ "jarvis-platform-manager",
57
+ "jpm",
58
+ "管理和测试不同的大语言模型平台",
59
+ )
60
+ cmd_table.add_row("jarvis-multi-agent", "jma", "多智能体协作系统")
61
+ cmd_table.add_row("jarvis-tool", "jt", "工具管理与调用系统")
62
+ cmd_table.add_row("jarvis-methodology", "jm", "方法论知识库管理")
63
+ cmd_table.add_row(
64
+ "jarvis-rag",
65
+ "jrg",
66
+ "构建和查询本地化的RAG知识库",
67
+ )
68
+ cmd_table.add_row("jarvis-smart-shell", "jss", "实验性的智能Shell功能")
69
+ cmd_table.add_row(
70
+ "jarvis-stats",
71
+ "jst",
72
+ "通用统计模块,支持记录和可视化任意指标数据",
73
+ )
74
+ cmd_table.add_row(
75
+ "jarvis-memory-organizer",
76
+ "jmo",
77
+ "记忆管理工具,支持整理、合并、导入导出记忆",
78
+ )
79
+
80
+ Console().print(cmd_table)
81
+ except Exception:
82
+ # 静默忽略渲染异常,避免影响主流程
83
+ pass
84
+
85
+ def handle_edit_option(edit: bool, config_file: Optional[str]) -> bool:
86
+ """处理配置文件编辑选项,返回是否已处理并需提前结束。"""
87
+ if edit:
88
+ ConfigEditor.edit_config(config_file)
89
+ return True
90
+ return False
91
+
92
+
93
+ def handle_share_methodology_option(
94
+ share_methodology: bool, config_file: Optional[str]
95
+ ) -> bool:
96
+ """处理方法论分享选项,返回是否已处理并需提前结束。"""
97
+ if share_methodology:
98
+ init_env("", config_file=config_file) # 初始化配置但不显示欢迎信息
99
+ methodology_manager = MethodologyShareManager()
100
+ methodology_manager.run()
101
+ return True
102
+ return False
103
+
104
+
105
+ def handle_share_tool_option(share_tool: bool, config_file: Optional[str]) -> bool:
106
+ """处理工具分享选项,返回是否已处理并需提前结束。"""
107
+ if share_tool:
108
+ init_env("", config_file=config_file) # 初始化配置但不显示欢迎信息
109
+ tool_manager = ToolShareManager()
110
+ tool_manager.run()
111
+ return True
112
+ return False
113
+
114
+
115
+ def preload_config_for_flags(config_file: Optional[str]) -> None:
116
+ """预加载配置(仅用于读取功能开关),不会显示欢迎信息或影响后续 init_env。"""
117
+ try:
118
+ jutils.g_config_file = config_file
119
+ jutils.load_config()
120
+ except Exception:
121
+ # 静默忽略配置加载异常
122
+ pass
123
+
124
+
125
+ def try_switch_to_jca_if_git_repo(
126
+ llm_type: str,
127
+ model_group: Optional[str],
128
+ tool_group: Optional[str],
129
+ config_file: Optional[str],
130
+ restore_session: bool,
131
+ task: Optional[str],
132
+ ) -> None:
133
+ """在初始化环境前检测Git仓库,并可选择自动切换到代码开发模式(jca)。"""
134
+ if is_enable_git_repo_jca_switch():
135
+ try:
136
+ res = subprocess.run(
137
+ ["git", "rev-parse", "--show-toplevel"],
138
+ capture_output=True,
139
+ text=True,
140
+ )
141
+ if res.returncode == 0:
142
+ git_root = res.stdout.strip()
143
+ if git_root and os.path.isdir(git_root):
144
+ PrettyOutput.print(
145
+ f"检测到当前位于 Git 仓库: {git_root}", OutputType.INFO
146
+ )
147
+ if user_confirm(
148
+ "检测到Git仓库,是否切换到代码开发模式(jca)?", default=False
149
+ ):
150
+ # 构建并切换到 jarvis-code-agent 命令,传递兼容参数
151
+ args = ["jarvis-code-agent"]
152
+ if llm_type:
153
+ args += ["-t", llm_type]
154
+ if model_group:
155
+ args += ["-g", model_group]
156
+ if tool_group:
157
+ args += ["-G", tool_group]
158
+ if config_file:
159
+ args += ["-f", config_file]
160
+ if restore_session:
161
+ args += ["--restore-session"]
162
+ if task:
163
+ args += ["-r", task]
164
+ PrettyOutput.print(
165
+ "正在切换到 'jca'(jarvis-code-agent)以进入代码开发模式...",
166
+ OutputType.INFO,
167
+ )
168
+ os.execvp(args[0], args)
169
+ except Exception:
170
+ # 静默忽略检测异常,不影响主流程
171
+ pass
172
+
173
+
174
+ def handle_builtin_config_selector(
175
+ llm_type: str,
176
+ model_group: Optional[str],
177
+ tool_group: Optional[str],
178
+ config_file: Optional[str],
179
+ task: Optional[str],
180
+ ) -> None:
181
+ """在进入默认通用代理前,列出内置配置供选择(agent/multi_agent/roles)。"""
182
+ if is_enable_builtin_config_selector():
183
+ try:
184
+ # 优先使用项目内置目录,若不存在则回退到指定的绝对路径
185
+ builtin_root = Path(__file__).resolve().parents[3] / "builtin"
186
+ if not builtin_root.exists():
187
+ builtin_root = Path("/home/skyfire/code/Jarvis/builtin")
188
+
189
+ categories = [
190
+ ("agent", "jarvis-agent", "*.yaml"),
191
+ ("multi_agent", "jarvis-multi-agent", "*.yaml"),
192
+ ("roles", "jarvis-platform-manager", "*.yaml"),
193
+ ]
194
+
195
+ options = []
196
+ for cat, cmd, pattern in categories:
197
+ # 构建待扫描目录列表:优先使用配置中的目录,其次回退到内置目录
198
+ search_dirs = []
199
+ try:
200
+ if cat == "agent":
201
+ search_dirs.extend(
202
+ [Path(p) for p in get_agent_definition_dirs() if p]
203
+ )
204
+ elif cat == "multi_agent":
205
+ search_dirs.extend(
206
+ [Path(p) for p in get_multi_agent_dirs() if p]
207
+ )
208
+ elif cat == "roles":
209
+ search_dirs.extend([Path(p) for p in get_roles_dirs() if p])
210
+ except Exception:
211
+ # 忽略配置读取异常
212
+ pass
213
+
214
+ # 追加内置目录
215
+ search_dirs.append(builtin_root / cat)
216
+
217
+ # 去重并保留顺序
218
+ unique_dirs = []
219
+ seen = set()
220
+ for d in search_dirs:
221
+ try:
222
+ key = str(Path(d).resolve())
223
+ except Exception:
224
+ key = str(d)
225
+ if key not in seen:
226
+ seen.add(key)
227
+ unique_dirs.append(Path(d))
228
+
229
+ # 每日自动更新配置目录(如目录为Git仓库则执行git pull,每日仅一次)
230
+ try:
231
+ jutils.daily_check_git_updates([str(p) for p in unique_dirs], cat)
232
+ except Exception:
233
+ # 忽略更新过程中的所有异常,避免影响主流程
234
+ pass
235
+
236
+ for dir_path in unique_dirs:
237
+ if not dir_path.exists():
238
+ continue
239
+ for fpath in sorted(dir_path.glob(pattern)):
240
+ # 解析YAML以获取可读名称/描述(失败时静默降级为文件名)
241
+ name = fpath.stem
242
+ desc = ""
243
+ try:
244
+ with open(
245
+ fpath, "r", encoding="utf-8", errors="ignore"
246
+ ) as fh:
247
+ data = yaml.safe_load(fh) or {}
248
+ if isinstance(data, dict):
249
+ name = data.get("name") or data.get("title") or name
250
+ desc = data.get("description") or data.get("desc") or ""
251
+ if cat == "roles" and isinstance(
252
+ data.get("roles"), list
253
+ ):
254
+ if not desc:
255
+ desc = f"{len(data['roles'])} 个角色"
256
+ except Exception:
257
+ # 忽略解析错误,使用默认显示
258
+ pass
259
+
260
+ # 为 roles 构建详细信息(每个角色的名称与描述)
261
+ details = ""
262
+ if cat == "roles":
263
+ roles = (data or {}).get("roles", [])
264
+ if isinstance(roles, list):
265
+ lines = []
266
+ for role in roles:
267
+ if isinstance(role, dict):
268
+ rname = str(role.get("name", "") or "")
269
+ rdesc = str(role.get("description", "") or "")
270
+ lines.append(
271
+ f"{rname} - {rdesc}" if rdesc else rname
272
+ )
273
+ details = "\n".join([ln for ln in lines if ln])
274
+ # 如果没有角色详情,退回到统计信息
275
+ if not details and isinstance(
276
+ (data or {}).get("roles"), list
277
+ ):
278
+ details = f"{len(data['roles'])} 个角色"
279
+
280
+ options.append(
281
+ {
282
+ "category": cat,
283
+ "cmd": cmd,
284
+ "file": str(fpath),
285
+ "name": str(name),
286
+ "desc": str(desc),
287
+ "details": str(details),
288
+ }
289
+ )
290
+
291
+ if options:
292
+ PrettyOutput.section("可用的内置配置", OutputType.SUCCESS)
293
+ # 使用 rich Table 呈现
294
+ table = Table(show_header=True, header_style="bold magenta")
295
+ table.add_column("No.", style="cyan", no_wrap=True)
296
+ table.add_column("类型", style="green", no_wrap=True)
297
+ table.add_column("名称", style="bold")
298
+ table.add_column("文件", style="dim")
299
+ table.add_column("描述", style="white")
300
+
301
+ for idx, opt in enumerate(options, 1):
302
+ category = opt.get("category", "")
303
+ name = opt.get("name", "")
304
+ file_path = opt.get("file", "")
305
+ # 描述列显示配置描述;若为 roles 则显示角色列表
306
+ if category == "roles":
307
+ desc_display = opt.get("details", "")
308
+ else:
309
+ desc_display = opt.get("desc", "")
310
+ table.add_row(str(idx), category, name, file_path, desc_display)
311
+
312
+ Console().print(table)
313
+
314
+ choice = get_single_line_input(
315
+ "选择要启动的配置编号,直接回车使用默认通用代理(jvs): ", default=""
316
+ )
317
+
318
+ if choice.strip():
319
+ try:
320
+ index = int(choice.strip())
321
+ if 1 <= index <= len(options):
322
+ sel = options[index - 1]
323
+ args = []
324
+
325
+ if sel["category"] == "agent":
326
+ # jarvis-agent 支持 -f/--config(全局配置)与 -c/--agent-definition
327
+ args = [sel["cmd"], "-c", sel["file"]]
328
+ if llm_type:
329
+ args += ["--llm-type", llm_type]
330
+ if model_group:
331
+ args += ["-g", model_group]
332
+ if config_file:
333
+ args += ["-f", config_file]
334
+ if task:
335
+ args += ["--task", task]
336
+
337
+ elif sel["category"] == "multi_agent":
338
+ # jarvis-multi-agent 需要 -c/--config,用户输入通过 -i/--input 传递
339
+ args = [sel["cmd"], "-c", sel["file"]]
340
+ if task:
341
+ args += ["-i", task]
342
+
343
+ elif sel["category"] == "roles":
344
+ # jarvis-platform-manager role 子命令,支持 -c/-t/-g
345
+ args = [sel["cmd"], "role", "-c", sel["file"]]
346
+ if llm_type:
347
+ args += ["-t", llm_type]
348
+ if model_group:
349
+ args += ["-g", model_group]
350
+
351
+ if args:
352
+ PrettyOutput.print(
353
+ f"正在启动: {' '.join(args)}", OutputType.INFO
354
+ )
355
+ os.execvp(args[0], args)
356
+ except Exception:
357
+ # 任何异常都不影响默认流程
358
+ pass
359
+ except Exception:
360
+ # 静默忽略内置配置扫描错误,不影响主流程
361
+ pass
362
+
363
+
17
364
  @app.callback(invoke_without_command=True)
18
365
  def run_cli(
19
366
  ctx: typer.Context,
@@ -23,14 +370,18 @@ def run_cli(
23
370
  "--llm-type",
24
371
  help="使用的LLM类型,可选值:'normal'(普通)或 'thinking'(思考模式)",
25
372
  ),
26
- task: Optional[str] = typer.Option(None, "-T", "--task", help="从命令行直接输入任务内容"),
373
+ task: Optional[str] = typer.Option(
374
+ None, "-T", "--task", help="从命令行直接输入任务内容"
375
+ ),
27
376
  model_group: Optional[str] = typer.Option(
28
377
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
29
378
  ),
30
379
  tool_group: Optional[str] = typer.Option(
31
380
  None, "-G", "--tool-group", help="使用的工具组,覆盖配置文件中的设置"
32
381
  ),
33
- config_file: Optional[str] = typer.Option(None, "-f", "--config", help="自定义配置文件路径"),
382
+ config_file: Optional[str] = typer.Option(
383
+ None, "-f", "--config", help="自定义配置文件路径"
384
+ ),
34
385
  restore_session: bool = typer.Option(
35
386
  False,
36
387
  "--restore-session",
@@ -40,33 +391,44 @@ def run_cli(
40
391
  share_methodology: bool = typer.Option(
41
392
  False, "--share-methodology", help="分享本地方法论到中心方法论仓库"
42
393
  ),
43
- share_tool: bool = typer.Option(False, "--share-tool", help="分享本地工具到中心工具仓库"),
394
+ share_tool: bool = typer.Option(
395
+ False, "--share-tool", help="分享本地工具到中心工具仓库"
396
+ ),
44
397
  ) -> None:
45
398
  """Jarvis AI assistant command-line interface."""
46
399
  if ctx.invoked_subcommand is not None:
47
400
  return
48
401
 
402
+ # 使用 rich 输出命令与快捷方式总览
403
+ print_commands_overview()
404
+
49
405
  # 处理配置文件编辑
50
- if edit:
51
- ConfigEditor.edit_config(config_file)
406
+ if handle_edit_option(edit, config_file):
52
407
  return
53
408
 
54
409
  # 处理方法论分享
55
- if share_methodology:
56
- init_env("", config_file=config_file) # 初始化配置但不显示欢迎信息
57
- methodology_manager = MethodologyShareManager()
58
- methodology_manager.run()
410
+ if handle_share_methodology_option(share_methodology, config_file):
59
411
  return
60
412
 
61
413
  # 处理工具分享
62
- if share_tool:
63
- init_env("", config_file=config_file) # 初始化配置但不显示欢迎信息
64
- tool_manager = ToolShareManager()
65
- tool_manager.run()
414
+ if handle_share_tool_option(share_tool, config_file):
66
415
  return
67
416
 
417
+ # 预加载配置(仅用于读取功能开关),不会显示欢迎信息或影响后续 init_env
418
+ preload_config_for_flags(config_file)
419
+
420
+ # 在初始化环境前检测Git仓库,并可选择自动切换到代码开发模式(jca)
421
+ try_switch_to_jca_if_git_repo(
422
+ llm_type, model_group, tool_group, config_file, restore_session, task
423
+ )
424
+
425
+ # 在进入默认通用代理前,列出内置配置供选择(agent/multi_agent/roles)
426
+ handle_builtin_config_selector(llm_type, model_group, tool_group, config_file, task)
427
+
68
428
  # 初始化环境
69
- init_env("欢迎使用 Jarvis AI 助手,您的智能助理已准备就绪!", config_file=config_file)
429
+ init_env(
430
+ "欢迎使用 Jarvis AI 助手,您的智能助理已准备就绪!", config_file=config_file
431
+ )
70
432
 
71
433
  # 运行主流程
72
434
  try:
@@ -3,7 +3,7 @@ import os
3
3
  from typing import Optional
4
4
 
5
5
  import typer
6
- import yaml
6
+ import yaml # type: ignore[import-untyped]
7
7
 
8
8
  from jarvis.jarvis_agent import Agent
9
9
  from jarvis.jarvis_utils.input import get_multiline_input
@@ -45,20 +45,22 @@ def cli(
45
45
  agent_definition: Optional[str] = typer.Option(
46
46
  None, "-c", "--agent-definition", help="代理定义文件路径"
47
47
  ),
48
- task: Optional[str] = typer.Option(
49
- None, "-t", "--task", help="初始任务内容"
50
- ),
48
+ task: Optional[str] = typer.Option(None, "-T", "--task", help="初始任务内容"),
51
49
  llm_type: str = typer.Option(
52
50
  "normal",
53
- "-t", "--llm-type",
51
+ "-t",
52
+ "--llm-type",
54
53
  help="使用的LLM类型,覆盖配置文件中的设置",
55
54
  ),
56
55
  model_group: Optional[str] = typer.Option(
57
56
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
58
- ),):
57
+ ),
58
+ ):
59
59
  """Main entry point for Jarvis agent"""
60
60
  # Initialize environment
61
- init_env("欢迎使用 Jarvis AI 助手,您的智能助理已准备就绪!", config_file=config_file)
61
+ init_env(
62
+ "欢迎使用 Jarvis AI 助手,您的智能助理已准备就绪!", config_file=config_file
63
+ )
62
64
 
63
65
  # Load configuration
64
66
  config = load_config(agent_definition) if agent_definition else {}
@@ -77,21 +79,27 @@ def cli(
77
79
  if task:
78
80
  PrettyOutput.print(f"执行初始任务: {task}", OutputType.INFO)
79
81
  agent.run(task)
80
- raise typer.Exit(code=0)
82
+ return
81
83
 
82
84
  try:
83
85
  user_input = get_multiline_input("请输入你的任务(输入空行退出):")
84
86
  if not user_input:
85
- raise typer.Exit(code=0)
87
+ return
86
88
  agent.set_addon_prompt(
87
89
  "如果有必要,请先指定出行动计划,然后根据计划一步步执行,如果任务过于复杂,可以拆分子Agent进行执行,拆的子Agent需要掌握所有必要的任务信息,否则无法执行"
88
90
  )
89
91
  agent.run(user_input)
92
+ except KeyboardInterrupt:
93
+ # 用户主动取消输入,正常退出
94
+ return
95
+ except typer.Exit:
96
+ # 来自输入流程的正常退出
97
+ return
90
98
  except Exception as e:
91
99
  PrettyOutput.print(f"错误: {str(e)}", OutputType.ERROR)
92
100
 
93
101
  except typer.Exit:
94
- raise
102
+ return
95
103
  except Exception as e:
96
104
  PrettyOutput.print(f"初始化错误: {str(e)}", OutputType.ERROR)
97
105
  raise typer.Exit(code=1)
@@ -67,10 +67,18 @@ class SessionManager:
67
67
  return True
68
68
  return False
69
69
 
70
- def clear_history(self):
70
+ def clear_history(self) -> None:
71
71
  """
72
72
  Clears conversation history but keeps the system prompt by resetting the model state.
73
73
  """
74
74
  self.prompt = ""
75
75
  self.model.reset()
76
76
  self.conversation_length = 0
77
+
78
+ def clear(self) -> None:
79
+ """
80
+ Clears the session state, resetting prompt and conversation length while
81
+ preserving user_data. This method is an alias of clear_history for backward
82
+ compatibility with existing tests and callers.
83
+ """
84
+ self.clear_history()
@@ -3,8 +3,10 @@
3
3
  import os
4
4
  from typing import Dict
5
5
 
6
- import yaml
6
+ import yaml # type: ignore
7
7
  from prompt_toolkit import prompt
8
+ from rich.table import Table
9
+ from rich.console import Console
8
10
 
9
11
  from jarvis.jarvis_agent import (
10
12
  OutputType,
@@ -68,16 +70,19 @@ class TaskManager:
68
70
  return ""
69
71
 
70
72
  task_names = list(tasks.keys())
71
- task_list = ["可用任务:"]
73
+ # 使用 rich.Table 展示预定义任务
74
+ table = Table(show_header=True, header_style="bold magenta")
75
+ table.add_column("No.", style="cyan", no_wrap=True)
76
+ table.add_column("任务名", style="bold")
72
77
  for i, name in enumerate(task_names, 1):
73
- task_list.append(f"[{i}] {name}")
74
- task_list.append("[0] 跳过预定义任务")
75
- PrettyOutput.print("\n".join(task_list), OutputType.INFO)
78
+ table.add_row(str(i), name)
79
+ Console().print(table)
80
+ PrettyOutput.print("[0] 跳过预定义任务", OutputType.INFO)
76
81
 
77
82
  while True:
78
83
  try:
79
84
  choice_str = prompt(
80
- "\n请选择一个任务编号(0 跳过预定义任务):"
85
+ "\n请选择一个任务编号(0 或者直接回车跳过预定义任务):"
81
86
  ).strip()
82
87
  if not choice_str:
83
88
  return ""
@@ -52,8 +52,10 @@ class CodeAgent:
52
52
  model_group: Optional[str] = None,
53
53
  need_summary: bool = True,
54
54
  append_tools: Optional[str] = None,
55
+ tool_group: Optional[str] = None,
55
56
  ):
56
57
  self.root_dir = os.getcwd()
58
+ self.tool_group = tool_group
57
59
 
58
60
  # 检测 git username 和 email 是否已设置
59
61
  self._check_git_config()
@@ -239,10 +241,7 @@ class CodeAgent:
239
241
  if has_uncommitted_changes():
240
242
  print("⏳ 发现未提交修改,正在处理...")
241
243
  git_commiter = GitCommitTool()
242
- git_commiter.execute({
243
- "prefix": prefix,
244
- "suffix": suffix
245
- })
244
+ git_commiter.execute({"prefix": prefix, "suffix": suffix})
246
245
  print("✅ 未提交修改已处理完成")
247
246
  else:
248
247
  print("✅ 没有未提交的修改")
@@ -496,10 +495,7 @@ class CodeAgent:
496
495
  check=True,
497
496
  )
498
497
  git_commiter = GitCommitTool()
499
- git_commiter.execute({
500
- "prefix": prefix,
501
- "suffix": suffix
502
- })
498
+ git_commiter.execute({"prefix": prefix, "suffix": suffix})
503
499
 
504
500
  # 在用户接受commit后,根据配置决定是否保存记忆
505
501
  if self.agent.force_save_memory:
@@ -670,6 +666,12 @@ def cli(
670
666
  model_group: Optional[str] = typer.Option(
671
667
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
672
668
  ),
669
+ tool_group: Optional[str] = typer.Option(
670
+ None, "-G", "--tool-group", help="使用的工具组,覆盖配置文件中的设置"
671
+ ),
672
+ config_file: Optional[str] = typer.Option(
673
+ None, "-f", "--config", help="配置文件路径"
674
+ ),
673
675
  requirement: Optional[str] = typer.Option(
674
676
  None, "-r", "--requirement", help="要处理的需求描述"
675
677
  ),
@@ -693,7 +695,10 @@ def cli(
693
695
  ),
694
696
  ) -> None:
695
697
  """Jarvis主入口点。"""
696
- init_env("欢迎使用 Jarvis-CodeAgent,您的代码工程助手已准备就绪!")
698
+ init_env(
699
+ "欢迎使用 Jarvis-CodeAgent,您的代码工程助手已准备就绪!",
700
+ config_file=config_file,
701
+ )
697
702
 
698
703
  try:
699
704
  subprocess.run(
@@ -737,6 +742,7 @@ def cli(
737
742
  model_group=model_group,
738
743
  need_summary=False,
739
744
  append_tools=append_tools,
745
+ tool_group=tool_group,
740
746
  )
741
747
 
742
748
  # 尝试恢复会话
@@ -235,6 +235,30 @@
235
235
  },
236
236
  "default": []
237
237
  },
238
+ "JARVIS_AGENT_DEFINITION_DIRS": {
239
+ "type": "array",
240
+ "description": "agent 定义加载目录",
241
+ "items": {
242
+ "type": "string"
243
+ },
244
+ "default": []
245
+ },
246
+ "JARVIS_MULTI_AGENT_DIRS": {
247
+ "type": "array",
248
+ "description": "multi_agent 加载目录",
249
+ "items": {
250
+ "type": "string"
251
+ },
252
+ "default": []
253
+ },
254
+ "JARVIS_ROLES_DIRS": {
255
+ "type": "array",
256
+ "description": "roles 加载目录",
257
+ "items": {
258
+ "type": "string"
259
+ },
260
+ "default": []
261
+ },
238
262
  "JARVIS_CENTRAL_METHODOLOGY_REPO": {
239
263
  "type": "string",
240
264
  "description": "中心方法论Git仓库地址,该仓库会自动添加到方法论加载路径中",
@@ -260,6 +284,16 @@
260
284
  "description": "是否强制保存记忆",
261
285
  "default": true
262
286
  },
287
+ "JARVIS_ENABLE_GIT_JCA_SWITCH": {
288
+ "type": "boolean",
289
+ "description": "在初始化环境前检测Git仓库并提示可切换到代码开发模式(jca)",
290
+ "default": false
291
+ },
292
+ "JARVIS_ENABLE_STARTUP_CONFIG_SELECTOR": {
293
+ "type": "boolean",
294
+ "description": "在进入默认通用代理前,列出可用配置(agent/multi_agent/roles)供选择",
295
+ "default": false
296
+ },
263
297
  "JARVIS_TOOL_GROUP": {
264
298
  "type": "string",
265
299
  "description": "选择一个预定义的工具配置组",
@@ -2,7 +2,7 @@
2
2
  from typing import Optional
3
3
 
4
4
  import typer
5
- import yaml
5
+ import yaml # type: ignore[import-untyped]
6
6
 
7
7
  from jarvis.jarvis_multi_agent import MultiAgent
8
8
  from jarvis.jarvis_utils.input import get_multiline_input
@@ -15,7 +15,9 @@ app = typer.Typer(help="多智能体系统启动器")
15
15
  @app.command()
16
16
  def cli(
17
17
  config: str = typer.Option(..., "--config", "-c", help="YAML配置文件路径"),
18
- user_input: Optional[str] = typer.Option(None, "--input", "-i", help="用户输入(可选)"),
18
+ user_input: Optional[str] = typer.Option(
19
+ None, "--input", "-i", help="用户输入(可选)"
20
+ ),
19
21
  ):
20
22
  """从YAML配置文件初始化并运行多智能体系统"""
21
23
  init_env("欢迎使用 Jarvis-MultiAgent,您的多智能体系统已准备就绪!")
@@ -39,11 +41,13 @@ def cli(
39
41
  else get_multiline_input("请输入内容(输入空行结束):")
40
42
  )
41
43
  if not final_input:
42
- raise typer.Exit(code=0)
44
+ return
43
45
  multi_agent.run(final_input)
44
46
 
47
+ except KeyboardInterrupt:
48
+ return
45
49
  except typer.Exit:
46
- raise
50
+ return
47
51
  except (ValueError, RuntimeError, yaml.YAMLError) as e:
48
52
  PrettyOutput.print(f"错误: {str(e)}", OutputType.ERROR)
49
53
  raise typer.Exit(code=1)
@@ -6,7 +6,14 @@ from typing import Any, Callable, Dict
6
6
  class Tool:
7
7
  """工具类,用于封装工具的基本信息和执行方法"""
8
8
 
9
- def __init__(self, name: str, description: str, parameters: Dict, func: Callable):
9
+ def __init__(
10
+ self,
11
+ name: str,
12
+ description: str,
13
+ parameters: Dict,
14
+ func: Callable,
15
+ protocol_version: str = "1.0",
16
+ ):
10
17
  """
11
18
  初始化工具对象
12
19
 
@@ -15,11 +22,13 @@ class Tool:
15
22
  description (str): 工具描述
16
23
  parameters (Dict): 工具参数定义
17
24
  func (Callable): 工具执行函数
25
+ protocol_version (str): 工具协议版本,默认"1.0";支持"1.0"或"2.0"
18
26
  """
19
27
  self.name = name
20
28
  self.description = description
21
29
  self.parameters = parameters
22
30
  self.func = func
31
+ self.protocol_version = protocol_version
23
32
 
24
33
  def to_dict(self) -> Dict:
25
34
  """将工具对象转换为字典格式,主要用于序列化"""
@@ -7,7 +7,7 @@ import tempfile
7
7
  from pathlib import Path
8
8
  from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple
9
9
 
10
- import yaml
10
+ import yaml # type: ignore[import-untyped]
11
11
 
12
12
  from jarvis.jarvis_mcp import McpClient
13
13
  from jarvis.jarvis_mcp.sse_mcp_client import SSEMcpClient
@@ -32,6 +32,7 @@ tool_call_help = f"""
32
32
  {ot("TOOL_CALL")}
33
33
  want: 想要从执行结果中获取到的信息,如果工具输出内容过长,会根据此字段尝试提取有效信息
34
34
  name: 工具名称
35
+
35
36
  arguments:
36
37
  param1: 值1
37
38
  param2: 值2
@@ -77,6 +78,7 @@ arguments:
77
78
  {ot("TOOL_CALL")}
78
79
  want: 当前的git状态,期望获取xxx的提交记录
79
80
  name: execute_script
81
+
80
82
  arguments:
81
83
  interpreter: bash
82
84
  script_content: |2
@@ -595,6 +597,9 @@ class ToolRegistry(OutputHandlerProtocol):
595
597
  description=tool_instance.description,
596
598
  parameters=tool_instance.parameters,
597
599
  func=tool_instance.execute,
600
+ protocol_version=getattr(
601
+ tool_instance, "protocol_version", "1.0"
602
+ ),
598
603
  )
599
604
  tool_found = True
600
605
  break
@@ -630,7 +635,7 @@ class ToolRegistry(OutputHandlerProtocol):
630
635
  content: 包含工具调用的内容
631
636
 
632
637
  返回:
633
- Tuple[Dict[str, Dict[str, Any]], str]:
638
+ Tuple[Dict[str, Dict[str, Any]], str]:
634
639
  - 第一个元素是提取的工具调用字典
635
640
  - 第二个元素是错误消息字符串(成功时为"")
636
641
 
@@ -708,6 +713,7 @@ class ToolRegistry(OutputHandlerProtocol):
708
713
  description: str,
709
714
  parameters: Any,
710
715
  func: Callable[..., Dict[str, Any]],
716
+ protocol_version: str = "1.0",
711
717
  ) -> None:
712
718
  """注册新工具
713
719
 
@@ -721,7 +727,7 @@ class ToolRegistry(OutputHandlerProtocol):
721
727
  PrettyOutput.print(
722
728
  f"警告: 工具 '{name}' 已存在,将被覆盖", OutputType.WARNING
723
729
  )
724
- self.tools[name] = Tool(name, description, parameters, func)
730
+ self.tools[name] = Tool(name, description, parameters, func, protocol_version)
725
731
 
726
732
  def get_tool(self, name: str) -> Optional[Tool]:
727
733
  """获取工具
@@ -742,12 +748,15 @@ class ToolRegistry(OutputHandlerProtocol):
742
748
  """
743
749
  return [tool.to_dict() for tool in self.tools.values()]
744
750
 
745
- def execute_tool(self, name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
751
+ def execute_tool(
752
+ self, name: str, arguments: Dict[str, Any], agent: Optional[Any] = None
753
+ ) -> Dict[str, Any]:
746
754
  """执行指定工具
747
755
 
748
756
  参数:
749
757
  name: 工具名称
750
758
  arguments: 工具参数
759
+ agent: 智能体实例(由系统内部传递,用于v2.0分离agent与参数)
751
760
 
752
761
  返回:
753
762
  Dict[str, Any]: 包含执行结果的字典,包含success、stdout和stderr字段
@@ -763,7 +772,23 @@ class ToolRegistry(OutputHandlerProtocol):
763
772
  # 更新工具调用统计
764
773
  self._update_tool_stats(name)
765
774
 
766
- return tool.execute(arguments)
775
+ # 根据工具实现声明的协议版本分发调用方式
776
+ try:
777
+ if getattr(tool, "protocol_version", "1.0") == "2.0":
778
+ # v2.0: agent与参数分离传递
779
+ return tool.func(arguments, agent) # type: ignore[misc]
780
+ else:
781
+ # v1.0: 兼容旧实现,将agent注入到arguments(如果提供)
782
+ args_to_call = arguments.copy() if isinstance(arguments, dict) else {}
783
+ if agent is not None:
784
+ args_to_call["agent"] = agent
785
+ return tool.execute(args_to_call)
786
+ except TypeError:
787
+ # 兼容处理:如果函数签名不匹配,回退到旧方式
788
+ args_to_call = arguments.copy() if isinstance(arguments, dict) else {}
789
+ if agent is not None:
790
+ args_to_call["agent"] = agent
791
+ return tool.execute(args_to_call)
767
792
 
768
793
  def _format_tool_output(self, stdout: str, stderr: str) -> str:
769
794
  """格式化工具输出为可读字符串
@@ -802,14 +827,14 @@ class ToolRegistry(OutputHandlerProtocol):
802
827
  def handle_tool_calls(self, tool_call: Dict[str, Any], agent: Any) -> str:
803
828
  try:
804
829
  name = tool_call["name"] # 确保name是str类型
805
- args = tool_call["arguments"] # args已经是Dict[str, Any]
830
+ args = tool_call["arguments"] # 原始参数(来自外部协议)
806
831
  want = tool_call["want"]
807
- args["agent"] = agent
808
832
 
809
833
  from jarvis.jarvis_agent import Agent
810
834
 
811
835
  agent_instance: Agent = agent
812
836
 
837
+ # 如果args是字符串,尝试解析为JSON
813
838
  if isinstance(args, str):
814
839
  try:
815
840
  args = json.loads(args)
@@ -819,8 +844,8 @@ class ToolRegistry(OutputHandlerProtocol):
819
844
  )
820
845
  return ""
821
846
 
822
- # 执行工具调用
823
- result = self.execute_tool(name, args) # 修正参数传递
847
+ # 执行工具调用(根据工具实现的协议版本,由系统在内部决定agent的传递方式)
848
+ result = self.execute_tool(name, args, agent)
824
849
 
825
850
  # 格式化输出
826
851
  output = self._format_tool_output(
@@ -853,8 +878,9 @@ class ToolRegistry(OutputHandlerProtocol):
853
878
  [output_file]
854
879
  )
855
880
  if upload_success:
856
- # 删除args的agent
857
- args.pop("agent", None)
881
+ # 删除args的agent键(保持协议v2.0的“参数与agent分离”在可视化中的一致性)
882
+ if isinstance(args, dict):
883
+ args.pop("agent", None)
858
884
  prompt = f"""
859
885
  以下是之前对话的关键信息总结:
860
886
 
@@ -309,6 +309,36 @@ def get_methodology_dirs() -> List[str]:
309
309
  return GLOBAL_CONFIG_DATA.get("JARVIS_METHODOLOGY_DIRS", [])
310
310
 
311
311
 
312
+ def get_agent_definition_dirs() -> List[str]:
313
+ """
314
+ 获取 agent 定义的加载目录。
315
+
316
+ 返回:
317
+ List[str]: agent 定义加载目录列表
318
+ """
319
+ return GLOBAL_CONFIG_DATA.get("JARVIS_AGENT_DEFINITION_DIRS", [])
320
+
321
+
322
+ def get_multi_agent_dirs() -> List[str]:
323
+ """
324
+ 获取 multi_agent 的加载目录。
325
+
326
+ 返回:
327
+ List[str]: multi_agent 加载目录列表
328
+ """
329
+ return GLOBAL_CONFIG_DATA.get("JARVIS_MULTI_AGENT_DIRS", [])
330
+
331
+
332
+ def get_roles_dirs() -> List[str]:
333
+ """
334
+ 获取 roles 的加载目录。
335
+
336
+ 返回:
337
+ List[str]: roles 加载目录列表
338
+ """
339
+ return GLOBAL_CONFIG_DATA.get("JARVIS_ROLES_DIRS", [])
340
+
341
+
312
342
  def get_central_methodology_repo() -> str:
313
343
  """
314
344
  获取中心方法论Git仓库地址。
@@ -576,3 +606,21 @@ def get_tool_dont_use_list() -> List[str]:
576
606
  """
577
607
  config = _get_resolved_tool_config()
578
608
  return config.get("dont_use", [])
609
+
610
+
611
+ def is_enable_git_repo_jca_switch() -> bool:
612
+ """
613
+ 是否启用:在初始化环境前检测Git仓库并提示可切换到代码开发模式(jca)
614
+ 默认关闭
615
+ """
616
+ return GLOBAL_CONFIG_DATA.get("JARVIS_ENABLE_GIT_JCA_SWITCH", False) is True
617
+
618
+
619
+ def is_enable_builtin_config_selector() -> bool:
620
+ """
621
+ 是否启用:在进入默认通用代理前,列出可用配置(agent/multi_agent/roles)供选择
622
+ 默认关闭
623
+ """
624
+ return (
625
+ GLOBAL_CONFIG_DATA.get("JARVIS_ENABLE_STARTUP_CONFIG_SELECTOR", False) is True
626
+ )
@@ -15,7 +15,7 @@ from colorama import Fore
15
15
  from colorama import Style as ColoramaStyle
16
16
  from fuzzywuzzy import process
17
17
  from prompt_toolkit import PromptSession
18
- from prompt_toolkit.application import Application
18
+ from prompt_toolkit.application import Application, run_in_terminal
19
19
  from prompt_toolkit.completion import CompleteEvent
20
20
  from prompt_toolkit.completion import (
21
21
  Completer,
@@ -40,6 +40,28 @@ from jarvis.jarvis_utils.tag import ot
40
40
  # Sentinel value to indicate that Ctrl+O was pressed
41
41
  CTRL_O_SENTINEL = "__CTRL_O_PRESSED__"
42
42
 
43
+ # Persistent hint marker for multiline input (shown only once across runs)
44
+ _MULTILINE_HINT_MARK_FILE = os.path.join(get_data_dir(), "multiline_enter_hint_shown")
45
+
46
+
47
+ def _multiline_hint_already_shown() -> bool:
48
+ """Check if the multiline Enter hint has been shown before (persisted)."""
49
+ try:
50
+ return os.path.exists(_MULTILINE_HINT_MARK_FILE)
51
+ except Exception:
52
+ return False
53
+
54
+
55
+ def _mark_multiline_hint_shown() -> None:
56
+ """Persist that the multiline Enter hint has been shown."""
57
+ try:
58
+ os.makedirs(os.path.dirname(_MULTILINE_HINT_MARK_FILE), exist_ok=True)
59
+ with open(_MULTILINE_HINT_MARK_FILE, "w", encoding="utf-8") as f:
60
+ f.write("1")
61
+ except Exception:
62
+ # Non-critical persistence failure; ignore to avoid breaking input flow
63
+ pass
64
+
43
65
 
44
66
  def get_single_line_input(tip: str, default: str = "") -> str:
45
67
  """
@@ -315,8 +337,32 @@ def _get_multiline_input_internal(tip: str) -> str:
315
337
  """
316
338
  bindings = KeyBindings()
317
339
 
340
+ # Show a one-time hint on the first Enter press in this invocation
341
+ first_enter_hint_shown = False
342
+
318
343
  @bindings.add("enter")
319
344
  def _(event):
345
+ nonlocal first_enter_hint_shown
346
+ if not first_enter_hint_shown and not _multiline_hint_already_shown():
347
+ first_enter_hint_shown = True
348
+
349
+ def _show_notice():
350
+ print(
351
+ f"{Fore.YELLOW}提示:当前支持多行输入。输入完成请使用 Ctrl+J 确认;Enter 仅用于换行。{ColoramaStyle.RESET_ALL}"
352
+ )
353
+ try:
354
+ input("按回车继续...")
355
+ except Exception:
356
+ pass
357
+ # Persist the hint so it won't be shown again in future runs
358
+ try:
359
+ _mark_multiline_hint_shown()
360
+ except Exception:
361
+ pass
362
+
363
+ run_in_terminal(_show_notice)
364
+ return
365
+
320
366
  if event.current_buffer.complete_state:
321
367
  completion = event.current_buffer.complete_state.current_completion
322
368
  if completion:
@@ -363,7 +409,7 @@ def get_multiline_input(tip: str) -> str:
363
409
  此函数处理控制流,允许在不破坏终端状态的情况下处理历史记录复制。
364
410
  """
365
411
  PrettyOutput.section(
366
- "用户输入 - 使用 @ 触发文件补全,Tab 选择补全项,Ctrl+J 提交,Ctrl+O 从历史记录中选择消息复制,按 Ctrl+C/D 取消输入",
412
+ "用户输入 - 使用 @ 触发文件补全,Tab 选择补全项,Ctrl+J 确认,Ctrl+O 从历史记录中选择消息复制,按 Ctrl+C/D 取消输入",
367
413
  OutputType.USER,
368
414
  )
369
415
 
@@ -372,7 +418,7 @@ def get_multiline_input(tip: str) -> str:
372
418
 
373
419
  if user_input == CTRL_O_SENTINEL:
374
420
  _show_history_and_copy()
375
- tip = "请继续输入(或按Ctrl+J提交):"
421
+ tip = "请继续输入(或按Ctrl+J确认):"
376
422
  continue
377
423
  else:
378
424
  if not user_input:
@@ -880,12 +880,154 @@ def _load_and_process_config(jarvis_dir: str, config_file: str) -> None:
880
880
  config_file: 配置文件路径
881
881
  """
882
882
  from jarvis.jarvis_utils.input import user_confirm as get_yes_no
883
+ from jarvis.jarvis_utils.input import get_single_line_input
883
884
 
884
885
  try:
885
886
  content, config_data = _load_config_file(config_file)
886
887
  _ensure_schema_declaration(jarvis_dir, config_file, content, config_data)
887
888
  set_global_env_data(config_data)
888
889
  _process_env_variables(config_data)
890
+
891
+ # 首次运行提示:为新功能开关询问用户(默认值见各配置的getter)
892
+ def _ask_and_set(_key, _tip, _default, _type="bool"):
893
+ try:
894
+ if _key in config_data:
895
+ return False
896
+ if _type == "bool":
897
+ val = get_yes_no(_tip, default=bool(_default))
898
+ config_data[_key] = bool(val)
899
+ else:
900
+ val = get_single_line_input(f"{_tip}", default=str(_default or ""))
901
+ config_data[_key] = val.strip()
902
+ return True
903
+ except Exception:
904
+ # 出现异常时按默认值设置,避免中断流程
905
+ config_data[_key] = (
906
+ bool(_default) if _type == "bool" else str(_default or "")
907
+ )
908
+ return True
909
+
910
+ changed = False
911
+ # 现有两个开关
912
+ changed = (
913
+ _ask_and_set(
914
+ "JARVIS_ENABLE_GIT_JCA_SWITCH",
915
+ "是否在检测到Git仓库时,提示并可自动切换到代码开发模式(jca)?",
916
+ False,
917
+ "bool",
918
+ )
919
+ or changed
920
+ )
921
+ changed = (
922
+ _ask_and_set(
923
+ "JARVIS_ENABLE_STARTUP_CONFIG_SELECTOR",
924
+ "在进入默认通用代理前,是否先列出可用配置(agent/multi_agent/roles)供选择?",
925
+ False,
926
+ "bool",
927
+ )
928
+ or changed
929
+ )
930
+
931
+ # 新增的配置项交互
932
+ changed = (
933
+ _ask_and_set(
934
+ "JARVIS_PRETTY_OUTPUT",
935
+ "是否启用更美观的终端输出(Pretty Output)?",
936
+ False,
937
+ "bool",
938
+ )
939
+ or changed
940
+ )
941
+ changed = (
942
+ _ask_and_set(
943
+ "JARVIS_PRINT_PROMPT",
944
+ "是否打印发送给模型的提示词(Prompt)?",
945
+ False,
946
+ "bool",
947
+ )
948
+ or changed
949
+ )
950
+ changed = (
951
+ _ask_and_set(
952
+ "JARVIS_ENABLE_STATIC_ANALYSIS",
953
+ "是否启用静态代码分析(Static Analysis)?",
954
+ True,
955
+ "bool",
956
+ )
957
+ or changed
958
+ )
959
+ changed = (
960
+ _ask_and_set(
961
+ "JARVIS_USE_METHODOLOGY",
962
+ "是否启用方法论系统(Methodology)?",
963
+ True,
964
+ "bool",
965
+ )
966
+ or changed
967
+ )
968
+ changed = (
969
+ _ask_and_set(
970
+ "JARVIS_USE_ANALYSIS",
971
+ "是否启用分析流程(Analysis)?",
972
+ True,
973
+ "bool",
974
+ )
975
+ or changed
976
+ )
977
+ changed = (
978
+ _ask_and_set(
979
+ "JARVIS_FORCE_SAVE_MEMORY",
980
+ "是否强制保存会话记忆?",
981
+ True,
982
+ "bool",
983
+ )
984
+ or changed
985
+ )
986
+ changed = (
987
+ _ask_and_set(
988
+ "JARVIS_CENTRAL_METHODOLOGY_REPO",
989
+ "请输入中心方法论仓库地址(可留空跳过):",
990
+ "",
991
+ "str",
992
+ )
993
+ or changed
994
+ )
995
+ changed = (
996
+ _ask_and_set(
997
+ "JARVIS_CENTRAL_TOOL_REPO",
998
+ "请输入中心工具仓库地址(可留空跳过):",
999
+ "",
1000
+ "str",
1001
+ )
1002
+ or changed
1003
+ )
1004
+
1005
+ if changed:
1006
+ # 保留schema声明,如无则自动补充
1007
+ header = ""
1008
+ try:
1009
+ with open(config_file, "r", encoding="utf-8") as rf:
1010
+ first_line = rf.readline()
1011
+ if first_line.startswith("# yaml-language-server: $schema="):
1012
+ header = first_line
1013
+ except Exception:
1014
+ header = ""
1015
+ yaml_str = yaml.dump(config_data, allow_unicode=True, sort_keys=False)
1016
+ if not header:
1017
+ schema_path = Path(
1018
+ os.path.relpath(
1019
+ Path(__file__).parent.parent
1020
+ / "jarvis_data"
1021
+ / "config_schema.json",
1022
+ start=jarvis_dir,
1023
+ )
1024
+ )
1025
+ header = f"# yaml-language-server: $schema={schema_path}\n"
1026
+ with open(config_file, "w", encoding="utf-8") as wf:
1027
+ wf.write(header)
1028
+ wf.write(yaml_str)
1029
+ # 更新全局配置
1030
+ set_global_env_data(config_data)
889
1031
  except Exception:
890
1032
  PrettyOutput.print("加载配置文件失败", OutputType.ERROR)
891
1033
  if get_yes_no("配置文件格式错误,是否删除并重新配置?"):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.3.15
3
+ Version: 0.3.17
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
@@ -1,27 +1,27 @@
1
- jarvis/__init__.py,sha256=pgHuAj3RKAHzddxR4-Pj5AIL9SywaQNWi0v2Ayu1tvQ,74
1
+ jarvis/__init__.py,sha256=B3aeVws2GyKWNL5gcAastwUvTv8_xzc1QrhuTZ8zGJs,74
2
2
  jarvis/jarvis_agent/__init__.py,sha256=CkFa66l5lM0-_zlzApwBxTYbrnbC4_NqdD4QuK3H1VQ,32614
3
3
  jarvis/jarvis_agent/agent_manager.py,sha256=YzpMiF0H2-eyk2kn2o24Bkj3bXsQx7Pv2vfD4gWepo0,2893
4
4
  jarvis/jarvis_agent/builtin_input_handler.py,sha256=wS-FqpT3pIXwHn1dfL3SpXonUKWgVThbQueUIeyRc2U,2917
5
5
  jarvis/jarvis_agent/config_editor.py,sha256=Ctk82sO6w2cNW0-_5L7Bomj-hgM4U7WwMc52fwhAJyg,1809
6
6
  jarvis/jarvis_agent/edit_file_handler.py,sha256=w-byNJ4TN_SlV3djjfFC7OksySOFGrM8ku49w662dzc,11854
7
7
  jarvis/jarvis_agent/file_methodology_manager.py,sha256=PwDUQwq7HVIyPInsN8fgWyMXLwi8heIXPrqfBZJhVHs,4260
8
- jarvis/jarvis_agent/jarvis.py,sha256=mE7sPQzuHtL9j8e_yDO91KfpbEqxrBrBG3px_WyWz50,3238
9
- jarvis/jarvis_agent/main.py,sha256=0xq-rjadcTedcB2HJSk2v0ihcm2-r2NXLj_Nq9xS9LY,3345
8
+ jarvis/jarvis_agent/jarvis.py,sha256=SrlAZdt6kad78dRbCbIdrus16PL1rE2QE9i54qItSmk,18789
9
+ jarvis/jarvis_agent/main.py,sha256=Hu5u0mq0owuzt965IqaGP6TtVGFXHE4E4Tg1TzCtGYE,3552
10
10
  jarvis/jarvis_agent/memory_manager.py,sha256=F7HTNzdN1_-cSygnz7zKSJRJvPLUOosqcXQeiW8zG4U,5266
11
11
  jarvis/jarvis_agent/methodology_share_manager.py,sha256=vwWNexluTXSI3qeNP3zJAemOjWW37o_1AlqDR1C8wCI,6910
12
12
  jarvis/jarvis_agent/output_handler.py,sha256=P7oWpXBGFfOsWq7cIhS_z9crkQ19ES7qU5pM92KKjAs,1172
13
13
  jarvis/jarvis_agent/prompt_builder.py,sha256=PH1fPDVa8z_RXkoXHJFNDf8PQjUoLNLYwkh2lC__p40,1705
14
14
  jarvis/jarvis_agent/prompts.py,sha256=X6cXa-n0xqBQ8LDTgLsD0kqziAh1s0cNp89i4mxcvHg,9444
15
15
  jarvis/jarvis_agent/protocols.py,sha256=JWnJDikFEuwvFUv7uzXu0ggJ4O9K2FkMnfVCwIJ5REw,873
16
- jarvis/jarvis_agent/session_manager.py,sha256=xPeQcQRBmAlc-CGAzVz4MTOKhZKb27rTS-5De3Oauwg,2713
16
+ jarvis/jarvis_agent/session_manager.py,sha256=5wVcaZGwJ9cEKTQglSbqyxUDJ2fI5KxYN8C8L16UWLw,3024
17
17
  jarvis/jarvis_agent/share_manager.py,sha256=wFcdULSog1mMxDyB94ofbqitFL8DCX8i1u6qVzSEuAk,8704
18
18
  jarvis/jarvis_agent/shell_input_handler.py,sha256=1IboqdxcJuoIqRpmDU10GugR9fWXUHyCEbVF4nIWbyo,1328
19
19
  jarvis/jarvis_agent/task_analyzer.py,sha256=-fQ9YBYFcc-Z1FSoDIPzRfAgkREFoIOXtU2TdBkB-e0,4656
20
- jarvis/jarvis_agent/task_manager.py,sha256=HJm4_SMpsFbQMUUsAZeHm7cZuhNbz28YW-DRLYgoarc,4422
20
+ jarvis/jarvis_agent/task_manager.py,sha256=IRfkjkeSjSo5rDKmzICdsJtJiVfTOf3Xc13qMVwl5ZM,4689
21
21
  jarvis/jarvis_agent/tool_executor.py,sha256=k73cKhZEZpljvui4ZxALlFEIE-iLzJ32Softsmiwzqk,1896
22
22
  jarvis/jarvis_agent/tool_share_manager.py,sha256=R5ONIQlDXX9pFq3clwHFhEW8BAJ3ECaR2DqWCEC9tzM,5205
23
23
  jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- jarvis/jarvis_code_agent/code_agent.py,sha256=Sw3I_IrUjHCSe2UbgmbSEZUk4uM4EOThabJtS7OmulU,30637
24
+ jarvis/jarvis_code_agent/code_agent.py,sha256=GhY79JRzyLeeNKxNJtgieO9UvqQl36S7W521ZyOwjMY,30967
25
25
  jarvis/jarvis_code_agent/lint.py,sha256=LZPsfyZPMo7Wm7LN4osZocuNJwZx1ojacO3MlF870x8,4009
26
26
  jarvis/jarvis_code_analysis/code_review.py,sha256=OLoMtXz7Kov6cVTdBoxq_OsX_j0rb7Rk3or5tKgiLpo,36023
27
27
  jarvis/jarvis_code_analysis/checklists/__init__.py,sha256=LIXAYa1sW3l7foP6kohLWnE98I_EQ0T7z5bYKHq6rJA,78
@@ -44,7 +44,7 @@ jarvis/jarvis_code_analysis/checklists/shell.py,sha256=aRFYhQQvTgbYd-uY5pc8UHIUA
44
44
  jarvis/jarvis_code_analysis/checklists/sql.py,sha256=vR0T6qC7b4dURjJVAd7kSVxyvZEQXPG1Jqc2sNTGp5c,2355
45
45
  jarvis/jarvis_code_analysis/checklists/swift.py,sha256=TPx4I6Gupvs6tSerRKmTSKEPQpOLEbH2Y7LXg1uBgxc,2566
46
46
  jarvis/jarvis_code_analysis/checklists/web.py,sha256=25gGD7pDadZQybNFvALYxWvK0VRjGQb1NVJQElwjyk0,3943
47
- jarvis/jarvis_data/config_schema.json,sha256=Mw8LveVXoyTaHEgn4d8HOuH-uUEbgjE0yuJJCnppEgo,11700
47
+ jarvis/jarvis_data/config_schema.json,sha256=MdVuj0zSFlo0X5mA-Oxtj0S5tx9GslFN9VInQQwrmbQ,12660
48
48
  jarvis/jarvis_data/tiktoken/9b5ad71b2ce5302211f9c61530b329a4922fc6a4,sha256=Ijkht27pm96ZW3_3OFE-7xAPtR0YyTWXoRO8_-hlsqc,1681126
49
49
  jarvis/jarvis_git_squash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
50
  jarvis/jarvis_git_squash/main.py,sha256=6PECdAbTbrsJBRLK1pXBh4hdJ_LADh-XXSic1xJi97E,2255
@@ -57,7 +57,7 @@ jarvis/jarvis_memory_organizer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
57
57
  jarvis/jarvis_memory_organizer/memory_organizer.py,sha256=4tf6Bs8u6Drj4repvuY3-XeH2Sb6ajVMFcW-rQEiGEY,26502
58
58
  jarvis/jarvis_methodology/main.py,sha256=6QF8hH3vB6rfxim0fPR34uVPf41zVpb4ZLqrFN2qONg,10983
59
59
  jarvis/jarvis_multi_agent/__init__.py,sha256=kCgtAX7VvliyEOQxIj2DvNjRAuh6bpNaOtDn60nzph4,6089
60
- jarvis/jarvis_multi_agent/main.py,sha256=Wbarez48QxXexlKEOcRsoMbcQEOP5rv_DzGkNk0SfpY,1779
60
+ jarvis/jarvis_multi_agent/main.py,sha256=b9IThFMeUZCYSlgT-VT8r7xeBdrEE_zNT11awEc8IdY,1853
61
61
  jarvis/jarvis_platform/__init__.py,sha256=WLQHSiE87PPket2M50_hHzjdMIgPIBx2VF8JfB_NNRk,105
62
62
  jarvis/jarvis_platform/ai8.py,sha256=W3947AGMpk3RRBfsfZmf222sEP0VIGoSU0vPkgiVnl0,11683
63
63
  jarvis/jarvis_platform/base.py,sha256=VyZhXgtGbUTrhXaDwA3kYUo03mfM-nNCYaTGgpY_TZQ,9365
@@ -88,7 +88,7 @@ jarvis/jarvis_stats/storage.py,sha256=MBQRxExIWdePXzY1EE8JAs1IEpMqamImpgjruqt_u9
88
88
  jarvis/jarvis_stats/visualizer.py,sha256=ZIBmGELzs6c7qM01tQql1HF6eFKn6HDGVQfKXRUUIY0,8529
89
89
  jarvis/jarvis_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
90
  jarvis/jarvis_tools/ask_user.py,sha256=M6DdLNryCE8y1JcdZHEifUgZkPUEPNKc-zDW5p0Mb1k,2029
91
- jarvis/jarvis_tools/base.py,sha256=kgDjh64HYr_ox_1FR7j52LsJ4B4W2wSqOejdtSBb2Fc,1413
91
+ jarvis/jarvis_tools/base.py,sha256=tFZkRlbV_a-pbjM-ci9AYmXVJm__FXuzVWKbQEyz4Ao,1639
92
92
  jarvis/jarvis_tools/clear_memory.py,sha256=HQMK70UJhhDgPPHozGaTpYizzQblUzYRwPbvD1z3z6o,8730
93
93
  jarvis/jarvis_tools/edit_file.py,sha256=hM345E9rxS-EkqCZpwwizL6fmPdTadtB798tEO5Ce3g,10417
94
94
  jarvis/jarvis_tools/execute_script.py,sha256=gMarE5yCCSPU6Dp6HlcL2KT-2xCzR-1p-oQNlYOJK58,6157
@@ -97,7 +97,7 @@ jarvis/jarvis_tools/generate_new_tool.py,sha256=uaWKlDMGjetvvwKTj0_AVTdmd14IktRb
97
97
  jarvis/jarvis_tools/methodology.py,sha256=_K4GIDUodGEma3SvNRo7Qs5rliijgNespVLyAPN35JU,5233
98
98
  jarvis/jarvis_tools/read_code.py,sha256=EnI-R-5HyIQYhMD391nZWXHIuHHBF-OJIRE0QpLcPX4,6417
99
99
  jarvis/jarvis_tools/read_webpage.py,sha256=NmDUboVZd4CGHBPRFK6dp3uqVhuGopW1bOi3TcaLDF4,2092
100
- jarvis/jarvis_tools/registry.py,sha256=nOcj_WKkEEiR2CJ84REchKSaWFGjnUFD3EVwxtfVF74,31165
100
+ jarvis/jarvis_tools/registry.py,sha256=IJ2ExlNqje2hA9MgiGnd0SCyy0zqAhxuZ76s_98FGwU,32668
101
101
  jarvis/jarvis_tools/retrieve_memory.py,sha256=0UBZm4wQTXLTj5WHXR9fjsiIDQh-Z2UINVu8cJ12YYg,9488
102
102
  jarvis/jarvis_tools/rewrite_file.py,sha256=eG_WKg6cVAXmuGwUqlWkcuyay5S8DOzEi8vZCmX3O8w,7255
103
103
  jarvis/jarvis_tools/save_memory.py,sha256=DjeFb38OtK9Y_RpWYHz8vL72JdauXZTlc_Y0FUQBtiM,7486
@@ -108,20 +108,20 @@ jarvis/jarvis_tools/cli/main.py,sha256=GsfZJ4OS4Hvxh0H2XiLkgbzm-ajBsb4c0LyjuIAAa
108
108
  jarvis/jarvis_utils/__init__.py,sha256=67h0ldisGlh3oK4DAeNEL2Bl_VsI3tSmfclasyVlueM,850
109
109
  jarvis/jarvis_utils/builtin_replace_map.py,sha256=4BurljGuiG_I93EBs7mlFlPm9wYC_4CmdTG5tQWpF6g,1712
110
110
  jarvis/jarvis_utils/clipboard.py,sha256=WgbQIQR2sh7_5ZzeX04eT3zXx_mxQbKyJOZXgGX_TcI,2907
111
- jarvis/jarvis_utils/config.py,sha256=HwMd5_JgdqubIo050BDG0kfQ_7ySzzZRPgiGEAWxT8s,16083
111
+ jarvis/jarvis_utils/config.py,sha256=dB6zivA66fPjoTmSXxvu5Y5R0MF-ERP9aUPA4fxkD64,17320
112
112
  jarvis/jarvis_utils/embedding.py,sha256=oEOEM2qf16DMYwPsQe6srET9BknyjOdY2ef0jsp3Or8,2714
113
113
  jarvis/jarvis_utils/file_processors.py,sha256=XiM248SHS7lLgQDCbORVFWqinbVDUawYxWDOsLXDxP8,3043
114
114
  jarvis/jarvis_utils/git_utils.py,sha256=AkczUiRcGcOnPfz2v3mdLwV1S41IopiAYD2tjeMTDrE,23586
115
115
  jarvis/jarvis_utils/globals.py,sha256=aTrOHcCgPAeZFLFIWMAMiJCYlmr4XhdFZf5gZ745hnE,8900
116
116
  jarvis/jarvis_utils/http.py,sha256=eRhV3-GYuWmQ0ogq9di9WMlQkFcVb1zGCrySnOgT1x0,4392
117
- jarvis/jarvis_utils/input.py,sha256=pl8SanShzaEJZybvNHTjnFdKC2VxDPS1IwONtbwe-7U,12765
117
+ jarvis/jarvis_utils/input.py,sha256=YO1jdK9HObkGO44XfXHNNN3HNneD_WrbANYkfJmrdJU,14489
118
118
  jarvis/jarvis_utils/methodology.py,sha256=IIMU17WVSunsWXsnXROd4G77LxgYs4xEC_xm_0CDkjw,12554
119
119
  jarvis/jarvis_utils/output.py,sha256=QRLlKObQKT0KuRSeZRqYb7NlTQvsd1oZXZ41WxeWEuU,10894
120
120
  jarvis/jarvis_utils/tag.py,sha256=f211opbbbTcSyzCDwuIK_oCnKhXPNK-RknYyGzY1yD0,431
121
- jarvis/jarvis_utils/utils.py,sha256=LiVui9RMsbfUdzbvBBwbGNC4uniGnLp3LFsk7LXGrQE,47370
122
- jarvis_ai_assistant-0.3.15.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
123
- jarvis_ai_assistant-0.3.15.dist-info/METADATA,sha256=oVWrBozetAj2ICvlfwVHLPfHqkVdLP2NgTUuWNJ7u14,18216
124
- jarvis_ai_assistant-0.3.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
125
- jarvis_ai_assistant-0.3.15.dist-info/entry_points.txt,sha256=4GcWKFxRJD-QU14gw_3ZaW4KuEVxOcZK9i270rwPdjA,1395
126
- jarvis_ai_assistant-0.3.15.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
127
- jarvis_ai_assistant-0.3.15.dist-info/RECORD,,
121
+ jarvis/jarvis_utils/utils.py,sha256=UMDOAQsIdlgobTN14ToKarLq3HeKUQrhUsSbfrFUPYo,52132
122
+ jarvis_ai_assistant-0.3.17.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
123
+ jarvis_ai_assistant-0.3.17.dist-info/METADATA,sha256=Vb3yaWH1VcDsh5G_4EAt4UzSZS1N_HZ22wdzyJN05x8,18216
124
+ jarvis_ai_assistant-0.3.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
125
+ jarvis_ai_assistant-0.3.17.dist-info/entry_points.txt,sha256=4GcWKFxRJD-QU14gw_3ZaW4KuEVxOcZK9i270rwPdjA,1395
126
+ jarvis_ai_assistant-0.3.17.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
127
+ jarvis_ai_assistant-0.3.17.dist-info/RECORD,,