jarvis-ai-assistant 0.4.1__py3-none-any.whl → 0.4.2__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 +64 -72
- jarvis/jarvis_agent/run_loop.py +18 -0
- jarvis/jarvis_data/config_schema.json +5 -0
- jarvis/jarvis_multi_agent/__init__.py +24 -11
- jarvis/jarvis_tools/registry.py +6 -0
- jarvis/jarvis_tools/sub_agent.py +9 -0
- jarvis/jarvis_utils/config.py +16 -11
- jarvis/jarvis_utils/input.py +77 -6
- {jarvis_ai_assistant-0.4.1.dist-info → jarvis_ai_assistant-0.4.2.dist-info}/METADATA +1 -1
- {jarvis_ai_assistant-0.4.1.dist-info → jarvis_ai_assistant-0.4.2.dist-info}/RECORD +15 -16
- jarvis/jarvis_agent/config.py +0 -100
- {jarvis_ai_assistant-0.4.1.dist-info → jarvis_ai_assistant-0.4.2.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.4.1.dist-info → jarvis_ai_assistant-0.4.2.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.4.1.dist-info → jarvis_ai_assistant-0.4.2.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.4.1.dist-info → jarvis_ai_assistant-0.4.2.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
jarvis/jarvis_agent/__init__.py
CHANGED
|
@@ -9,6 +9,7 @@ from pathlib import Path
|
|
|
9
9
|
from enum import Enum
|
|
10
10
|
from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
|
|
11
11
|
|
|
12
|
+
|
|
12
13
|
# 第三方库导入
|
|
13
14
|
from rich.align import Align
|
|
14
15
|
from rich.console import Console
|
|
@@ -35,7 +36,6 @@ from jarvis.jarvis_agent.edit_file_handler import EditFileHandler
|
|
|
35
36
|
from jarvis.jarvis_agent.rewrite_file_handler import RewriteFileHandler
|
|
36
37
|
from jarvis.jarvis_agent.prompt_manager import PromptManager
|
|
37
38
|
from jarvis.jarvis_agent.event_bus import EventBus
|
|
38
|
-
from jarvis.jarvis_agent.config import AgentConfig
|
|
39
39
|
from jarvis.jarvis_agent.run_loop import AgentRunLoop
|
|
40
40
|
from jarvis.jarvis_agent.events import (
|
|
41
41
|
BEFORE_SUMMARY,
|
|
@@ -67,7 +67,6 @@ from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
|
67
67
|
# jarvis_utils 相关
|
|
68
68
|
from jarvis.jarvis_utils.config import (
|
|
69
69
|
get_data_dir,
|
|
70
|
-
get_max_token_count,
|
|
71
70
|
get_normal_model_name,
|
|
72
71
|
get_normal_platform_name,
|
|
73
72
|
is_execute_tool_confirm,
|
|
@@ -76,7 +75,8 @@ from jarvis.jarvis_utils.config import (
|
|
|
76
75
|
is_use_methodology,
|
|
77
76
|
get_tool_filter_threshold,
|
|
78
77
|
get_after_tool_call_cb_dirs,
|
|
79
|
-
|
|
78
|
+
|
|
79
|
+
|
|
80
80
|
)
|
|
81
81
|
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
82
82
|
from jarvis.jarvis_utils.globals import (
|
|
@@ -282,6 +282,7 @@ class Agent:
|
|
|
282
282
|
use_tools: Optional[List[str]] = None,
|
|
283
283
|
execute_tool_confirm: Optional[bool] = None,
|
|
284
284
|
need_summary: bool = True,
|
|
285
|
+
auto_summary_rounds: Optional[int] = None,
|
|
285
286
|
multiline_inputer: Optional[Callable[[str], str]] = None,
|
|
286
287
|
use_methodology: Optional[bool] = None,
|
|
287
288
|
use_analysis: Optional[bool] = None,
|
|
@@ -289,6 +290,7 @@ class Agent:
|
|
|
289
290
|
files: Optional[List[str]] = None,
|
|
290
291
|
confirm_callback: Optional[Callable[[str, bool], bool]] = None,
|
|
291
292
|
non_interactive: Optional[bool] = None,
|
|
293
|
+
in_multi_agent: Optional[bool] = None,
|
|
292
294
|
**kwargs,
|
|
293
295
|
):
|
|
294
296
|
"""初始化Jarvis Agent实例
|
|
@@ -309,20 +311,36 @@ class Agent:
|
|
|
309
311
|
confirm_callback: 用户确认回调函数,签名为 (tip: str, default: bool) -> bool;默认使用CLI的user_confirm
|
|
310
312
|
non_interactive: 是否以非交互模式运行(优先级最高,覆盖环境变量与配置)
|
|
311
313
|
"""
|
|
312
|
-
#
|
|
313
|
-
|
|
314
|
+
# 基础属性初始化(仅根据入参设置原始值;实际生效的默认回退在 _init_config 中统一解析)
|
|
315
|
+
# 标识与描述
|
|
314
316
|
self.name = make_agent_name(name)
|
|
315
317
|
self.description = description
|
|
316
318
|
self.system_prompt = system_prompt
|
|
317
|
-
|
|
318
|
-
self.auto_complete = auto_complete
|
|
319
|
+
# 行为控制开关(原始入参值)
|
|
320
|
+
self.auto_complete = bool(auto_complete)
|
|
321
|
+
self.need_summary = bool(need_summary)
|
|
322
|
+
# 自动摘要轮次:None 表示使用配置文件中的默认值,由 AgentRunLoop 决定最终取值
|
|
323
|
+
self.auto_summary_rounds = auto_summary_rounds
|
|
324
|
+
self.use_methodology = use_methodology
|
|
325
|
+
self.use_analysis = use_analysis
|
|
326
|
+
self.execute_tool_confirm = execute_tool_confirm
|
|
327
|
+
self.summary_prompt = summary_prompt
|
|
328
|
+
self.force_save_memory = force_save_memory
|
|
329
|
+
# 资源与环境
|
|
330
|
+
self.model_group = model_group
|
|
331
|
+
self.files = files or []
|
|
332
|
+
self.use_tools = use_tools
|
|
333
|
+
self.non_interactive = non_interactive
|
|
334
|
+
# 多智能体运行标志:用于控制非交互模式下的自动完成行为
|
|
335
|
+
self.in_multi_agent = bool(in_multi_agent)
|
|
336
|
+
# 运行时状态
|
|
319
337
|
self.first = True
|
|
320
338
|
self.run_input_handlers_next_turn = False
|
|
321
339
|
self.user_data: Dict[str, Any] = {}
|
|
322
340
|
|
|
323
341
|
|
|
324
342
|
# 用户确认回调:默认使用 CLI 的 user_confirm,可由外部注入以支持 TUI/GUI
|
|
325
|
-
self.
|
|
343
|
+
self.confirm_callback: Callable[[str, bool], bool] = (
|
|
326
344
|
confirm_callback or user_confirm # type: ignore[assignment]
|
|
327
345
|
)
|
|
328
346
|
|
|
@@ -337,9 +355,9 @@ class Agent:
|
|
|
337
355
|
use_tools or [],
|
|
338
356
|
)
|
|
339
357
|
# 初始化用户交互封装,保持向后兼容
|
|
340
|
-
self.user_interaction = UserInteractionHandler(self.multiline_inputer, self.
|
|
358
|
+
self.user_interaction = UserInteractionHandler(self.multiline_inputer, self.confirm_callback)
|
|
341
359
|
# 将确认函数指向封装后的 confirm,保持既有调用不变
|
|
342
|
-
self.
|
|
360
|
+
self.confirm_callback = self.user_interaction.confirm # type: ignore[assignment]
|
|
343
361
|
# 非交互模式参数支持:允许通过构造参数显式控制,便于其他Agent调用时设置
|
|
344
362
|
try:
|
|
345
363
|
# 优先使用构造参数,其次回退到环境变量
|
|
@@ -351,24 +369,43 @@ class Agent:
|
|
|
351
369
|
# 如果构造参数显式提供,则同步到环境变量与全局配置,供下游组件读取
|
|
352
370
|
if non_interactive is not None:
|
|
353
371
|
os.environ["JARVIS_NON_INTERACTIVE"] = "true" if self.non_interactive else "false"
|
|
354
|
-
|
|
355
|
-
set_config("JARVIS_NON_INTERACTIVE", self.non_interactive)
|
|
356
|
-
except Exception:
|
|
357
|
-
# 配置同步失败不影响主流程
|
|
358
|
-
pass
|
|
372
|
+
|
|
359
373
|
except Exception:
|
|
360
374
|
# 防御式回退
|
|
361
375
|
self.non_interactive = False
|
|
362
376
|
|
|
363
|
-
#
|
|
364
|
-
|
|
365
|
-
use_methodology
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
377
|
+
# 初始化配置(直接解析,不再依赖 _init_config)
|
|
378
|
+
try:
|
|
379
|
+
resolved_use_methodology = bool(use_methodology if use_methodology is not None else is_use_methodology())
|
|
380
|
+
except Exception:
|
|
381
|
+
resolved_use_methodology = bool(use_methodology) if use_methodology is not None else True
|
|
382
|
+
|
|
383
|
+
try:
|
|
384
|
+
resolved_use_analysis = bool(use_analysis if use_analysis is not None else is_use_analysis())
|
|
385
|
+
except Exception:
|
|
386
|
+
resolved_use_analysis = bool(use_analysis) if use_analysis is not None else True
|
|
387
|
+
|
|
388
|
+
try:
|
|
389
|
+
resolved_execute_tool_confirm = bool(execute_tool_confirm if execute_tool_confirm is not None else is_execute_tool_confirm())
|
|
390
|
+
except Exception:
|
|
391
|
+
resolved_execute_tool_confirm = bool(execute_tool_confirm) if execute_tool_confirm is not None else False
|
|
392
|
+
|
|
393
|
+
try:
|
|
394
|
+
resolved_force_save_memory = bool(force_save_memory if force_save_memory is not None else is_force_save_memory())
|
|
395
|
+
except Exception:
|
|
396
|
+
resolved_force_save_memory = bool(force_save_memory) if force_save_memory is not None else False
|
|
397
|
+
|
|
398
|
+
self.use_methodology = resolved_use_methodology
|
|
399
|
+
self.use_analysis = resolved_use_analysis
|
|
400
|
+
self.execute_tool_confirm = resolved_execute_tool_confirm
|
|
401
|
+
self.summary_prompt = (summary_prompt or DEFAULT_SUMMARY_PROMPT)
|
|
402
|
+
self.force_save_memory = resolved_force_save_memory
|
|
403
|
+
# 多智能体模式下,默认不自动完成(即使是非交互),仅在明确传入 auto_complete=True 时开启
|
|
404
|
+
if self.in_multi_agent:
|
|
405
|
+
self.auto_complete = bool(self.auto_complete)
|
|
406
|
+
else:
|
|
407
|
+
# 非交互模式下默认自动完成;否则保持传入的 auto_complete 值
|
|
408
|
+
self.auto_complete = bool(self.auto_complete or (self.non_interactive or False))
|
|
372
409
|
|
|
373
410
|
# 初始化事件总线需先于管理器,以便管理器在构造中安全订阅事件
|
|
374
411
|
self.event_bus = EventBus()
|
|
@@ -432,46 +469,6 @@ class Agent:
|
|
|
432
469
|
]
|
|
433
470
|
self.multiline_inputer = multiline_inputer or get_multiline_input
|
|
434
471
|
|
|
435
|
-
def _init_config(
|
|
436
|
-
self,
|
|
437
|
-
use_methodology: Optional[bool],
|
|
438
|
-
use_analysis: Optional[bool],
|
|
439
|
-
execute_tool_confirm: Optional[bool],
|
|
440
|
-
summary_prompt: Optional[str],
|
|
441
|
-
model_group: Optional[str],
|
|
442
|
-
force_save_memory: Optional[bool],
|
|
443
|
-
):
|
|
444
|
-
"""初始化配置选项"""
|
|
445
|
-
# 使用集中配置解析,保持与原逻辑一致
|
|
446
|
-
cfg = AgentConfig(
|
|
447
|
-
system_prompt=self.system_prompt,
|
|
448
|
-
name=self.name,
|
|
449
|
-
description=self.description,
|
|
450
|
-
model_group=model_group,
|
|
451
|
-
auto_complete=self.auto_complete,
|
|
452
|
-
need_summary=self.need_summary,
|
|
453
|
-
summary_prompt=summary_prompt,
|
|
454
|
-
execute_tool_confirm=execute_tool_confirm,
|
|
455
|
-
use_methodology=use_methodology,
|
|
456
|
-
use_analysis=use_analysis,
|
|
457
|
-
force_save_memory=force_save_memory,
|
|
458
|
-
files=self.files,
|
|
459
|
-
max_token_count=None,
|
|
460
|
-
).resolve_defaults()
|
|
461
|
-
|
|
462
|
-
# 将解析结果回填到 Agent 实例属性,保持向后兼容
|
|
463
|
-
self.use_methodology = bool(cfg.use_methodology)
|
|
464
|
-
self.use_analysis = bool(cfg.use_analysis)
|
|
465
|
-
self.execute_tool_confirm = bool(cfg.execute_tool_confirm)
|
|
466
|
-
self.summary_prompt = cfg.summary_prompt or DEFAULT_SUMMARY_PROMPT
|
|
467
|
-
self.max_token_count = int(cfg.max_token_count or get_max_token_count(model_group))
|
|
468
|
-
self.force_save_memory = bool(cfg.force_save_memory)
|
|
469
|
-
# 非交互模式下自动完成标志需要同步到 Agent 实例,避免循环
|
|
470
|
-
self.auto_complete = bool(cfg.auto_complete)
|
|
471
|
-
|
|
472
|
-
# 聚合配置到 AgentConfig,作为后续单一事实来源(保持兼容,不改变既有属性使用)
|
|
473
|
-
self.config = cfg
|
|
474
|
-
|
|
475
472
|
def _setup_system_prompt(self):
|
|
476
473
|
"""设置系统提示词"""
|
|
477
474
|
try:
|
|
@@ -731,14 +728,9 @@ class Agent:
|
|
|
731
728
|
return message
|
|
732
729
|
|
|
733
730
|
def _manage_conversation_length(self, message: str) -> str:
|
|
734
|
-
"""
|
|
731
|
+
"""管理对话长度计数;摘要触发由轮次在 AgentRunLoop 中统一处理。"""
|
|
735
732
|
self.session.conversation_length += get_context_token_count(message)
|
|
736
733
|
|
|
737
|
-
if self.session.conversation_length > self.max_token_count:
|
|
738
|
-
summary = self._summarize_and_clear_history()
|
|
739
|
-
if summary:
|
|
740
|
-
message = join_prompts([summary, message])
|
|
741
|
-
self.session.conversation_length = get_context_token_count(message)
|
|
742
734
|
|
|
743
735
|
return message
|
|
744
736
|
|
|
@@ -1095,7 +1087,7 @@ class Agent:
|
|
|
1095
1087
|
return self._complete_task(auto_completed=False)
|
|
1096
1088
|
|
|
1097
1089
|
if any(handler.can_handle(current_response) for handler in self.output_handler):
|
|
1098
|
-
if self.
|
|
1090
|
+
if self.confirm_callback("检测到有工具调用,是否继续处理工具调用?", True):
|
|
1099
1091
|
self.session.prompt = join_prompts([
|
|
1100
1092
|
f"被用户中断,用户补充信息为:{user_input}",
|
|
1101
1093
|
"用户同意继续工具调用。"
|
|
@@ -1322,7 +1314,7 @@ class Agent:
|
|
|
1322
1314
|
f"并且存在3个以上标签重叠的记忆。\n"
|
|
1323
1315
|
f"是否立即整理记忆库以优化性能和相关性?"
|
|
1324
1316
|
)
|
|
1325
|
-
if self.
|
|
1317
|
+
if self.confirm_callback(prompt, True):
|
|
1326
1318
|
PrettyOutput.print(
|
|
1327
1319
|
f"正在开始整理 '{scope_name}' ({memory_type}) 记忆库...",
|
|
1328
1320
|
OutputType.INFO,
|
jarvis/jarvis_agent/run_loop.py
CHANGED
|
@@ -14,6 +14,7 @@ from typing import Any, TYPE_CHECKING
|
|
|
14
14
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
15
15
|
from jarvis.jarvis_agent.events import BEFORE_TOOL_CALL, AFTER_TOOL_CALL
|
|
16
16
|
from jarvis.jarvis_agent.utils import join_prompts, is_auto_complete, normalize_next_action
|
|
17
|
+
from jarvis.jarvis_utils.config import get_auto_summary_rounds
|
|
17
18
|
|
|
18
19
|
if TYPE_CHECKING:
|
|
19
20
|
# 仅用于类型标注,避免运行时循环依赖
|
|
@@ -25,6 +26,12 @@ class AgentRunLoop:
|
|
|
25
26
|
self.agent = agent
|
|
26
27
|
self.conversation_rounds = 0
|
|
27
28
|
self.tool_reminder_rounds = int(os.environ.get("JARVIS_TOOL_REMINDER_ROUNDS", 20))
|
|
29
|
+
# 基于轮次的自动总结阈值:优先使用 Agent 入参,否则回落到全局配置(默认20轮)
|
|
30
|
+
self.auto_summary_rounds = (
|
|
31
|
+
self.agent.auto_summary_rounds
|
|
32
|
+
if getattr(self.agent, "auto_summary_rounds", None) is not None
|
|
33
|
+
else get_auto_summary_rounds()
|
|
34
|
+
)
|
|
28
35
|
|
|
29
36
|
def run(self) -> Any:
|
|
30
37
|
"""主运行循环(委派到传入的 agent 实例的方法与属性)"""
|
|
@@ -37,6 +44,17 @@ class AgentRunLoop:
|
|
|
37
44
|
self.agent.session.addon_prompt = join_prompts(
|
|
38
45
|
[self.agent.session.addon_prompt, self.agent.get_tool_usage_prompt()]
|
|
39
46
|
)
|
|
47
|
+
# 基于轮次的自动总结判断:达到阈值后执行一次总结与历史清理
|
|
48
|
+
if self.conversation_rounds >= self.auto_summary_rounds:
|
|
49
|
+
summary_text = self.agent._summarize_and_clear_history()
|
|
50
|
+
if summary_text:
|
|
51
|
+
# 将摘要作为下一轮的附加提示加入,从而维持上下文连续性
|
|
52
|
+
self.agent.session.addon_prompt = join_prompts(
|
|
53
|
+
[self.agent.session.addon_prompt, summary_text]
|
|
54
|
+
)
|
|
55
|
+
# 重置轮次计数与对话长度计数器,开始新一轮周期
|
|
56
|
+
self.conversation_rounds = 0
|
|
57
|
+
self.agent.session.conversation_length = 0
|
|
40
58
|
|
|
41
59
|
ag = self.agent
|
|
42
60
|
|
|
@@ -193,6 +193,11 @@
|
|
|
193
193
|
"description": "脚本执行的超时时间(秒),仅在非交互模式下生效。",
|
|
194
194
|
"default": 300
|
|
195
195
|
},
|
|
196
|
+
"JARVIS_AUTO_SUMMARY_ROUNDS": {
|
|
197
|
+
"type": "number",
|
|
198
|
+
"description": "基于对话轮次的自动总结阈值(达到该轮次后自动总结并清理历史)",
|
|
199
|
+
"default": 20
|
|
200
|
+
},
|
|
196
201
|
"JARVIS_CONFIRM_BEFORE_APPLY_PATCH": {
|
|
197
202
|
"type": "boolean",
|
|
198
203
|
"description": "应用补丁前是否需要确认",
|
|
@@ -287,6 +287,11 @@ content: |2
|
|
|
287
287
|
return None
|
|
288
288
|
|
|
289
289
|
config = self.agents_config_map[name].copy()
|
|
290
|
+
# 标记为多智能体运行,避免在非交互模式下自动开启 auto_complete
|
|
291
|
+
config.setdefault("in_multi_agent", True)
|
|
292
|
+
# 非主智能体统一禁用自动补全,防止多智能体并行时误触发自动交互
|
|
293
|
+
if name != self.main_agent_name:
|
|
294
|
+
config["auto_complete"] = False
|
|
290
295
|
|
|
291
296
|
# Prepend common system prompt if configured
|
|
292
297
|
common_sp = getattr(self, "common_system_prompt", "")
|
|
@@ -328,9 +333,14 @@ content: |2
|
|
|
328
333
|
break
|
|
329
334
|
|
|
330
335
|
# Generate a brief summary via direct model call to avoid run-loop recursion
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
336
|
+
# 如果在配置中显式设置了 summary_on_send=False,则不生成摘要
|
|
337
|
+
sender_config = self.agents_config_map.get(last_agent_name, {}) if hasattr(self, "agents_config_map") else {}
|
|
338
|
+
summary_on_send = sender_config.get("summary_on_send", True)
|
|
339
|
+
summary_text = ""
|
|
340
|
+
if summary_on_send:
|
|
341
|
+
try:
|
|
342
|
+
# 参照 Agent.generate_summary 的实现思路:基于当前 session.prompt 追加请求提示,直接调用底层模型
|
|
343
|
+
multi_agent_summary_prompt = """
|
|
334
344
|
请基于当前会话,为即将发送给其他智能体的协作交接写一段摘要,包含:
|
|
335
345
|
- 已完成的主要工作与产出
|
|
336
346
|
- 关键决策及其理由
|
|
@@ -341,12 +351,12 @@ content: |2
|
|
|
341
351
|
- 仅输出纯文本,不包含任何指令或工具调用
|
|
342
352
|
- 使用简洁的要点式表述
|
|
343
353
|
""".strip()
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
354
|
+
summary_any: Any = agent.model.chat_until_success( # type: ignore[attr-defined]
|
|
355
|
+
f"{agent.session.prompt}\n{multi_agent_summary_prompt}"
|
|
356
|
+
)
|
|
357
|
+
summary_text = summary_any.strip() if isinstance(summary_any, str) else ""
|
|
358
|
+
except Exception:
|
|
359
|
+
summary_text = ""
|
|
350
360
|
prompt = f"""
|
|
351
361
|
Please handle this message:
|
|
352
362
|
from: {last_agent_name}
|
|
@@ -373,6 +383,9 @@ content: {msg['content']}
|
|
|
373
383
|
f"{last_agent_name} 正在向 {to_agent_name} 发送消息...", OutputType.INFO
|
|
374
384
|
)
|
|
375
385
|
|
|
386
|
+
# Keep a reference to the sender before switching to the receiver
|
|
387
|
+
sender_agent = agent
|
|
388
|
+
|
|
376
389
|
agent = self._get_agent(to_agent_name)
|
|
377
390
|
if not agent:
|
|
378
391
|
return f"智能体 {to_agent_name} 未找到"
|
|
@@ -380,9 +393,9 @@ content: {msg['content']}
|
|
|
380
393
|
# Check if the sending agent should be cleared
|
|
381
394
|
sender_config = self.agents_config_map.get(last_agent_name, {})
|
|
382
395
|
if sender_config.get("clear_after_send_message"):
|
|
383
|
-
if
|
|
396
|
+
if sender_agent:
|
|
384
397
|
PrettyOutput.print(f"清除智能体 {last_agent_name} 在发送消息后的历史记录...", OutputType.INFO)
|
|
385
|
-
|
|
398
|
+
sender_agent.clear_history()
|
|
386
399
|
|
|
387
400
|
last_agent_name = agent.name
|
|
388
401
|
msg = agent.run(prompt)
|
jarvis/jarvis_tools/registry.py
CHANGED
|
@@ -633,6 +633,12 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
|
633
633
|
异常:
|
|
634
634
|
Exception: 如果工具调用缺少必要字段
|
|
635
635
|
"""
|
|
636
|
+
# 如果</TOOL_CALL>出现在响应的末尾,但是前面没有换行符,自动插入一个换行符进行修复
|
|
637
|
+
if content.rstrip().endswith(ct("TOOL_CALL")):
|
|
638
|
+
pos = content.rfind(ct("TOOL_CALL"))
|
|
639
|
+
if pos > 0 and content[pos - 1] not in ("\n", "\r"):
|
|
640
|
+
content = content[:pos] + "\n" + content[pos:]
|
|
641
|
+
|
|
636
642
|
# 将内容拆分为行
|
|
637
643
|
pattern = rf'(?ms){re.escape(ot("TOOL_CALL"))}(.*?)^{re.escape(ct("TOOL_CALL"))}'
|
|
638
644
|
data = re.findall(pattern, content)
|
jarvis/jarvis_tools/sub_agent.py
CHANGED
|
@@ -51,6 +51,10 @@ class SubAgentTool:
|
|
|
51
51
|
"type": "string",
|
|
52
52
|
"description": "覆盖子Agent的总结提示词(必填)",
|
|
53
53
|
},
|
|
54
|
+
"non_interactive": {
|
|
55
|
+
"type": "boolean",
|
|
56
|
+
"description": "是否启用无交互模式(可选,默认继承父Agent或系统默认)",
|
|
57
|
+
},
|
|
54
58
|
},
|
|
55
59
|
"required": [
|
|
56
60
|
"task",
|
|
@@ -131,6 +135,11 @@ class SubAgentTool:
|
|
|
131
135
|
# 安全兜底:无法从父Agent获取配置则保持为None,使用系统默认
|
|
132
136
|
pass
|
|
133
137
|
|
|
138
|
+
# 可选参数:允许显式覆盖无交互模式
|
|
139
|
+
explicit_non_interactive = args.get("non_interactive", None)
|
|
140
|
+
if explicit_non_interactive is not None:
|
|
141
|
+
parent_non_interactive = bool(explicit_non_interactive)
|
|
142
|
+
|
|
134
143
|
agent = Agent(
|
|
135
144
|
system_prompt=system_prompt,
|
|
136
145
|
name=agent_name,
|
jarvis/jarvis_utils/config.py
CHANGED
|
@@ -76,17 +76,6 @@ def get_replace_map() -> dict:
|
|
|
76
76
|
return {**BUILTIN_REPLACE_MAP, **file_map}
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
def get_max_token_count(model_group_override: Optional[str] = None) -> int:
|
|
80
|
-
"""
|
|
81
|
-
获取模型允许的最大token数量。
|
|
82
|
-
|
|
83
|
-
返回:
|
|
84
|
-
int: 模型能处理的最大token数量,为最大输入token数量的30倍。
|
|
85
|
-
"""
|
|
86
|
-
max_input_tokens = get_max_input_token_count(model_group_override)
|
|
87
|
-
return max_input_tokens * 30
|
|
88
|
-
|
|
89
|
-
|
|
90
79
|
def get_max_input_token_count(model_group_override: Optional[str] = None) -> int:
|
|
91
80
|
"""
|
|
92
81
|
获取模型允许的最大输入token数量。
|
|
@@ -712,6 +701,22 @@ def get_tool_filter_threshold() -> int:
|
|
|
712
701
|
return int(GLOBAL_CONFIG_DATA.get("JARVIS_TOOL_FILTER_THRESHOLD", 30))
|
|
713
702
|
|
|
714
703
|
|
|
704
|
+
def get_auto_summary_rounds() -> int:
|
|
705
|
+
"""
|
|
706
|
+
获取基于对话轮次的自动总结阈值。
|
|
707
|
+
|
|
708
|
+
返回:
|
|
709
|
+
int: 轮次阈值,默认20
|
|
710
|
+
"""
|
|
711
|
+
try:
|
|
712
|
+
return int(GLOBAL_CONFIG_DATA.get("JARVIS_AUTO_SUMMARY_ROUNDS", 20))
|
|
713
|
+
except Exception:
|
|
714
|
+
return 20
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
|
|
715
720
|
def get_script_execution_timeout() -> int:
|
|
716
721
|
"""
|
|
717
722
|
获取脚本执行的超时时间(秒)。
|
jarvis/jarvis_utils/input.py
CHANGED
|
@@ -363,11 +363,50 @@ class FileCompleter(Completer):
|
|
|
363
363
|
return tag
|
|
364
364
|
|
|
365
365
|
|
|
366
|
-
|
|
367
|
-
|
|
366
|
+
# ---------------------
|
|
367
|
+
# 公共判定辅助函数(按当前Agent优先)
|
|
368
|
+
# ---------------------
|
|
369
|
+
def _get_current_agent_for_input():
|
|
370
|
+
try:
|
|
371
|
+
import jarvis.jarvis_utils.globals as g
|
|
372
|
+
current_name = getattr(g, "current_agent_name", "")
|
|
373
|
+
if current_name:
|
|
374
|
+
return g.get_agent(current_name)
|
|
375
|
+
except Exception:
|
|
376
|
+
pass
|
|
377
|
+
return None
|
|
378
|
+
|
|
379
|
+
def _is_non_interactive_for_current_agent() -> bool:
|
|
368
380
|
try:
|
|
369
381
|
from jarvis.jarvis_utils.config import is_non_interactive
|
|
370
|
-
|
|
382
|
+
ag = _get_current_agent_for_input()
|
|
383
|
+
try:
|
|
384
|
+
return bool(getattr(ag, "non_interactive", False)) if ag else bool(is_non_interactive())
|
|
385
|
+
except Exception:
|
|
386
|
+
return bool(is_non_interactive())
|
|
387
|
+
except Exception:
|
|
388
|
+
return False
|
|
389
|
+
|
|
390
|
+
def _is_auto_complete_for_current_agent() -> bool:
|
|
391
|
+
try:
|
|
392
|
+
from jarvis.jarvis_utils.config import GLOBAL_CONFIG_DATA
|
|
393
|
+
ag = _get_current_agent_for_input()
|
|
394
|
+
if ag is not None and hasattr(ag, "auto_complete"):
|
|
395
|
+
try:
|
|
396
|
+
return bool(getattr(ag, "auto_complete", False))
|
|
397
|
+
except Exception:
|
|
398
|
+
pass
|
|
399
|
+
env_v = os.getenv("JARVIS_AUTO_COMPLETE")
|
|
400
|
+
if env_v is not None:
|
|
401
|
+
return str(env_v).strip().lower() in ("1", "true", "yes", "on")
|
|
402
|
+
return bool(GLOBAL_CONFIG_DATA.get("JARVIS_AUTO_COMPLETE", False))
|
|
403
|
+
except Exception:
|
|
404
|
+
return False
|
|
405
|
+
|
|
406
|
+
def user_confirm(tip: str, default: bool = True) -> bool:
|
|
407
|
+
"""提示用户确认是/否问题(按当前Agent优先判断非交互)"""
|
|
408
|
+
try:
|
|
409
|
+
if _is_non_interactive_for_current_agent():
|
|
371
410
|
return default
|
|
372
411
|
suffix = "[Y/n]" if default else "[y/N]"
|
|
373
412
|
ret = get_single_line_input(f"{tip} {suffix}: ")
|
|
@@ -666,9 +705,41 @@ def get_multiline_input(tip: str, print_on_empty: bool = True) -> str:
|
|
|
666
705
|
preset: Optional[str] = None
|
|
667
706
|
preset_cursor: Optional[int] = None
|
|
668
707
|
while True:
|
|
669
|
-
from jarvis.jarvis_utils.config import is_non_interactive
|
|
670
|
-
|
|
671
|
-
|
|
708
|
+
from jarvis.jarvis_utils.config import is_non_interactive, GLOBAL_CONFIG_DATA
|
|
709
|
+
# 基于“当前Agent”精确判断非交互与自动完成,避免多Agent相互干扰
|
|
710
|
+
if _is_non_interactive_for_current_agent():
|
|
711
|
+
# 在多Agent系统中,无论是否启用自动完成,均提示可用智能体并建议使用 SEND_MESSAGE 转移控制权
|
|
712
|
+
hint = ""
|
|
713
|
+
try:
|
|
714
|
+
ag = _get_current_agent_for_input()
|
|
715
|
+
ohs = getattr(ag, "output_handler", [])
|
|
716
|
+
available_agents: List[str] = []
|
|
717
|
+
for oh in (ohs or []):
|
|
718
|
+
cfgs = getattr(oh, "agents_config", None)
|
|
719
|
+
if isinstance(cfgs, list):
|
|
720
|
+
for c in cfgs:
|
|
721
|
+
try:
|
|
722
|
+
name = c.get("name")
|
|
723
|
+
except Exception:
|
|
724
|
+
name = None
|
|
725
|
+
if isinstance(name, str) and name.strip():
|
|
726
|
+
available_agents.append(name.strip())
|
|
727
|
+
if available_agents:
|
|
728
|
+
# 去重但保留顺序
|
|
729
|
+
seen = set()
|
|
730
|
+
ordered = []
|
|
731
|
+
for n in available_agents:
|
|
732
|
+
if n not in seen:
|
|
733
|
+
seen.add(n)
|
|
734
|
+
ordered.append(n)
|
|
735
|
+
hint = "\n当前可用智能体: " + ", ".join(ordered) + f"\n如需将任务交给其他智能体,请使用 {ot('SEND_MESSAGE')} 块。"
|
|
736
|
+
except Exception:
|
|
737
|
+
hint = ""
|
|
738
|
+
if _is_auto_complete_for_current_agent():
|
|
739
|
+
base_msg = "我无法与你交互,所有的事情你都自我决策,如果无法决策,就完成任务。输出" + ot("!!!COMPLETE!!!")
|
|
740
|
+
return base_msg + hint
|
|
741
|
+
else:
|
|
742
|
+
return "我无法与你交互,所有的事情你都自我决策" + hint
|
|
672
743
|
user_input = _get_multiline_input_internal(
|
|
673
744
|
tip, preset=preset, preset_cursor=preset_cursor
|
|
674
745
|
)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
jarvis/__init__.py,sha256=
|
|
2
|
-
jarvis/jarvis_agent/__init__.py,sha256=
|
|
1
|
+
jarvis/__init__.py,sha256=NIbT8I8sAw3cCWWXtArSe6_eWeB17Gf7WmiF9nyxdKs,73
|
|
2
|
+
jarvis/jarvis_agent/__init__.py,sha256=OOoHubIIQ3A9xB7jHFRpJKDtAk0or8Y7TmUkdq00l4Q,51386
|
|
3
3
|
jarvis/jarvis_agent/agent_manager.py,sha256=Q0S-mYTPt8Xd7RKGoLWoWU_RP_wEXFWxCjve8_t2f2A,3807
|
|
4
4
|
jarvis/jarvis_agent/builtin_input_handler.py,sha256=wS-FqpT3pIXwHn1dfL3SpXonUKWgVThbQueUIeyRc2U,2917
|
|
5
|
-
jarvis/jarvis_agent/config.py,sha256=f_VmSfdEtl4a32y-fVxhcZYkni4RznBAUKjv6kET1LU,3517
|
|
6
5
|
jarvis/jarvis_agent/config_editor.py,sha256=hlb9EYxKWcR_qdW2O89CgNDdciR9Isi743JU_1gD8j4,1927
|
|
7
6
|
jarvis/jarvis_agent/edit_file_handler.py,sha256=8j7SRSWTw468fTuR-ueNKFK_0pR1GwDxTvsGGmm3zlA,24714
|
|
8
7
|
jarvis/jarvis_agent/event_bus.py,sha256=pRdfk7d0OG18K6yNfWlCvAh_dW5p9sBtT2Yc3jGmzgo,1519
|
|
@@ -19,7 +18,7 @@ jarvis/jarvis_agent/prompt_manager.py,sha256=_1qLBSA3yn4nT_N3X2npTpW40Cp-pMeyvnz
|
|
|
19
18
|
jarvis/jarvis_agent/prompts.py,sha256=CvbPYx_klEz6OQrxVReZAnC2uQNo53rWkkucmh30uKg,9531
|
|
20
19
|
jarvis/jarvis_agent/protocols.py,sha256=YFJaC9MHi7JfLzmvlyotJDjiCO4Z07XJXy1gKhVdUy4,956
|
|
21
20
|
jarvis/jarvis_agent/rewrite_file_handler.py,sha256=FVSrfrC115_cGvdPW9RIn3A-gQAhok7GyyBfnOFdpXs,5276
|
|
22
|
-
jarvis/jarvis_agent/run_loop.py,sha256=
|
|
21
|
+
jarvis/jarvis_agent/run_loop.py,sha256=iGfa28J2K6I07k6p66O3WJFSk9z4uOarqe6CLqALIsk,6167
|
|
23
22
|
jarvis/jarvis_agent/session_manager.py,sha256=5wVcaZGwJ9cEKTQglSbqyxUDJ2fI5KxYN8C8L16UWLw,3024
|
|
24
23
|
jarvis/jarvis_agent/share_manager.py,sha256=MF2RlomcgPxF8nVUk28DP6IRddZ_tot5l_YRvy0qXSQ,8726
|
|
25
24
|
jarvis/jarvis_agent/shell_input_handler.py,sha256=wiAPjB-9uTkcLszbO5dlOUwIfaeR39RgRcZhahIGqoA,2018
|
|
@@ -57,7 +56,7 @@ jarvis/jarvis_code_analysis/checklists/shell.py,sha256=aRFYhQQvTgbYd-uY5pc8UHIUA
|
|
|
57
56
|
jarvis/jarvis_code_analysis/checklists/sql.py,sha256=vR0T6qC7b4dURjJVAd7kSVxyvZEQXPG1Jqc2sNTGp5c,2355
|
|
58
57
|
jarvis/jarvis_code_analysis/checklists/swift.py,sha256=TPx4I6Gupvs6tSerRKmTSKEPQpOLEbH2Y7LXg1uBgxc,2566
|
|
59
58
|
jarvis/jarvis_code_analysis/checklists/web.py,sha256=25gGD7pDadZQybNFvALYxWvK0VRjGQb1NVJQElwjyk0,3943
|
|
60
|
-
jarvis/jarvis_data/config_schema.json,sha256=
|
|
59
|
+
jarvis/jarvis_data/config_schema.json,sha256=VlPqakEXx7k2wm5Uv-ZlbKeIPbHNc98r1pHFtXEBBBY,14884
|
|
61
60
|
jarvis/jarvis_data/tiktoken/9b5ad71b2ce5302211f9c61530b329a4922fc6a4,sha256=Ijkht27pm96ZW3_3OFE-7xAPtR0YyTWXoRO8_-hlsqc,1681126
|
|
62
61
|
jarvis/jarvis_git_squash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
63
62
|
jarvis/jarvis_git_squash/main.py,sha256=BRbsEQVXwseVFKliVqV8_JPh1om6QT6dLTHw0jQ7OE0,2474
|
|
@@ -69,7 +68,7 @@ jarvis/jarvis_mcp/streamable_mcp_client.py,sha256=BenOeZGNHdUOJT5Z3cc5MhS6aOeKQg
|
|
|
69
68
|
jarvis/jarvis_memory_organizer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
70
69
|
jarvis/jarvis_memory_organizer/memory_organizer.py,sha256=CMFL46vvtpcTI6oS3CAlYteR6xAlwCkvVJmMT22uDRw,26295
|
|
71
70
|
jarvis/jarvis_methodology/main.py,sha256=uiNzk5b5O6xdvRhsOuD7ubxdd2tPcDsFFnvmes8uH8I,11370
|
|
72
|
-
jarvis/jarvis_multi_agent/__init__.py,sha256=
|
|
71
|
+
jarvis/jarvis_multi_agent/__init__.py,sha256=frH5ufVMasKFz_jbVsBk2wH5nq4D0sfDcmfBWQ-DLoA,16726
|
|
73
72
|
jarvis/jarvis_multi_agent/main.py,sha256=vqLzHesgQkpScVvbgOSyi6X7XoEDQYq3dJ9gZfGiPZw,3351
|
|
74
73
|
jarvis/jarvis_platform/__init__.py,sha256=WLQHSiE87PPket2M50_hHzjdMIgPIBx2VF8JfB_NNRk,105
|
|
75
74
|
jarvis/jarvis_platform/ai8.py,sha256=g8JkqPGs9SEbqstNMCc5rCHO0QcPHX9LNvb7HMWwB-Q,11471
|
|
@@ -109,11 +108,11 @@ jarvis/jarvis_tools/generate_new_tool.py,sha256=tJz0YtfDwyH9y00VEWw3Btqr9JCNhvtI
|
|
|
109
108
|
jarvis/jarvis_tools/methodology.py,sha256=_K4GIDUodGEma3SvNRo7Qs5rliijgNespVLyAPN35JU,5233
|
|
110
109
|
jarvis/jarvis_tools/read_code.py,sha256=F1RuO0c69t0h7CvrUGqrTyNcOCcUrFQPACc61O_YSso,6382
|
|
111
110
|
jarvis/jarvis_tools/read_webpage.py,sha256=dfyXJ9vaX-ZRbua1P5ZlaU_SlSzKkeNw-1kI_3-gxFE,5433
|
|
112
|
-
jarvis/jarvis_tools/registry.py,sha256=
|
|
111
|
+
jarvis/jarvis_tools/registry.py,sha256=9gIhiyh7jAAnLeGBIDyUUHwOeDtgOx3UUWk6kRN1sJg,33670
|
|
113
112
|
jarvis/jarvis_tools/retrieve_memory.py,sha256=hhhGSr7jebPHICY9oEKICyI8mfqsRtKjh58qZNZApKc,8624
|
|
114
113
|
jarvis/jarvis_tools/save_memory.py,sha256=RQtNxcpU53FFv_EBjH0i0oyQ7jWubm-trD1BHuqaGjI,6985
|
|
115
114
|
jarvis/jarvis_tools/search_web.py,sha256=Hi8WBxcRH02qjOF1qcJP2qSqs3kVOKGFAARfh548Ii4,6370
|
|
116
|
-
jarvis/jarvis_tools/sub_agent.py,sha256=
|
|
115
|
+
jarvis/jarvis_tools/sub_agent.py,sha256=Fn2RZ7jLD4cZCWt0HnpSLkdIbeqeZq-1h97Nfg2RAqE,8485
|
|
117
116
|
jarvis/jarvis_tools/sub_code_agent.py,sha256=KpwTCU89kq_RGNpfyA1C0bTl-f0dTvsCyDKplU-hrds,9600
|
|
118
117
|
jarvis/jarvis_tools/virtual_tty.py,sha256=L7-J00ARQvIa25T45Hhqg2eCBl6W2LFgqDlWMWf-7dk,25275
|
|
119
118
|
jarvis/jarvis_tools/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -121,21 +120,21 @@ jarvis/jarvis_tools/cli/main.py,sha256=WL2GNV7WqYl7G1-btRGvCkzDCMk4fPfNvzCrnUFVP
|
|
|
121
120
|
jarvis/jarvis_utils/__init__.py,sha256=67h0ldisGlh3oK4DAeNEL2Bl_VsI3tSmfclasyVlueM,850
|
|
122
121
|
jarvis/jarvis_utils/builtin_replace_map.py,sha256=z8iAqsbZUiGFaozxG1xSu128op8udqHOeEw-GxNt4bU,1708
|
|
123
122
|
jarvis/jarvis_utils/clipboard.py,sha256=D3wzQeqg_yiH7Axs4d6MRxyNa9XxdnenH-ND2uj2WVQ,2967
|
|
124
|
-
jarvis/jarvis_utils/config.py,sha256=
|
|
123
|
+
jarvis/jarvis_utils/config.py,sha256=jOVCrlD597U6FTu8j-lyO93Mpoyqv3Do7Seja_XrRfE,22580
|
|
125
124
|
jarvis/jarvis_utils/embedding.py,sha256=x6mrkL7Bc3qgfuBDsjc4fg4nKG8ofGxVLVVydbsb8PY,2838
|
|
126
125
|
jarvis/jarvis_utils/file_processors.py,sha256=XiM248SHS7lLgQDCbORVFWqinbVDUawYxWDOsLXDxP8,3043
|
|
127
126
|
jarvis/jarvis_utils/fzf.py,sha256=vCs0Uh5dUqGbWzXn2JCtLLCOYE2B39ZNdNveR9PK4DA,1681
|
|
128
127
|
jarvis/jarvis_utils/git_utils.py,sha256=zxjdxbFb_X6aYo-w1fbMx3d2n1ScbmmaAYlE3wGaaSg,24071
|
|
129
128
|
jarvis/jarvis_utils/globals.py,sha256=7Xvf9HY6jYJL4vSD1F1WCoxHkHCAyltJUYt4V9gGVU4,8865
|
|
130
129
|
jarvis/jarvis_utils/http.py,sha256=eRhV3-GYuWmQ0ogq9di9WMlQkFcVb1zGCrySnOgT1x0,4392
|
|
131
|
-
jarvis/jarvis_utils/input.py,sha256=
|
|
130
|
+
jarvis/jarvis_utils/input.py,sha256=4VXpUZoAocW1mldlZd4bmXI8a_CmcQj7IPLBNgNLGSI,40045
|
|
132
131
|
jarvis/jarvis_utils/methodology.py,sha256=z_renvRGgHiC-XTQPuN6rvrJ_ffHlwxK_b1BU_jmNAQ,12800
|
|
133
132
|
jarvis/jarvis_utils/output.py,sha256=y2fVcao_2ZowFl0IxUrJZCi8T6ZM0z-iPzpk8T8eLxc,13623
|
|
134
133
|
jarvis/jarvis_utils/tag.py,sha256=f211opbbbTcSyzCDwuIK_oCnKhXPNK-RknYyGzY1yD0,431
|
|
135
134
|
jarvis/jarvis_utils/utils.py,sha256=uMtfaStxDtp2i9AFIxwtPKgSxLwQxw8Z2rXsX-ZGlis,72728
|
|
136
|
-
jarvis_ai_assistant-0.4.
|
|
137
|
-
jarvis_ai_assistant-0.4.
|
|
138
|
-
jarvis_ai_assistant-0.4.
|
|
139
|
-
jarvis_ai_assistant-0.4.
|
|
140
|
-
jarvis_ai_assistant-0.4.
|
|
141
|
-
jarvis_ai_assistant-0.4.
|
|
135
|
+
jarvis_ai_assistant-0.4.2.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
|
136
|
+
jarvis_ai_assistant-0.4.2.dist-info/METADATA,sha256=etNq0w20riwTP8aha2pt_wXBdC6SZHhrjTVeV5K4K38,18751
|
|
137
|
+
jarvis_ai_assistant-0.4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
138
|
+
jarvis_ai_assistant-0.4.2.dist-info/entry_points.txt,sha256=4GcWKFxRJD-QU14gw_3ZaW4KuEVxOcZK9i270rwPdjA,1395
|
|
139
|
+
jarvis_ai_assistant-0.4.2.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
|
140
|
+
jarvis_ai_assistant-0.4.2.dist-info/RECORD,,
|
jarvis/jarvis_agent/config.py
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
AgentConfig: 聚合 Agent 的初始化配置并提供默认值解析。
|
|
4
|
-
|
|
5
|
-
目标(阶段一,最小变更):
|
|
6
|
-
- 提供独立的配置承载类,封装 __init__ 中的配置项
|
|
7
|
-
- 支持从全局配置与上下文推导默认值
|
|
8
|
-
- 暂不强制替换 Agent 的现有参数与流程,后续逐步接入
|
|
9
|
-
"""
|
|
10
|
-
from dataclasses import dataclass, field
|
|
11
|
-
from typing import List, Optional
|
|
12
|
-
|
|
13
|
-
from jarvis.jarvis_agent.prompts import DEFAULT_SUMMARY_PROMPT
|
|
14
|
-
from jarvis.jarvis_utils.config import (
|
|
15
|
-
get_max_token_count,
|
|
16
|
-
is_execute_tool_confirm,
|
|
17
|
-
is_force_save_memory,
|
|
18
|
-
is_use_analysis,
|
|
19
|
-
is_use_methodology,
|
|
20
|
-
is_non_interactive,
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@dataclass
|
|
25
|
-
class AgentConfig:
|
|
26
|
-
# 核心身份与系统参数
|
|
27
|
-
system_prompt: str
|
|
28
|
-
name: str = "Jarvis"
|
|
29
|
-
description: str = ""
|
|
30
|
-
model_group: Optional[str] = None
|
|
31
|
-
|
|
32
|
-
# 运行行为
|
|
33
|
-
auto_complete: bool = False
|
|
34
|
-
non_interactive: bool = False
|
|
35
|
-
need_summary: bool = True
|
|
36
|
-
|
|
37
|
-
# 可选配置(None 表示使用默认策略解析)
|
|
38
|
-
summary_prompt: Optional[str] = None
|
|
39
|
-
execute_tool_confirm: Optional[bool] = None
|
|
40
|
-
use_methodology: Optional[bool] = None
|
|
41
|
-
use_analysis: Optional[bool] = None
|
|
42
|
-
force_save_memory: Optional[bool] = None
|
|
43
|
-
files: Optional[List[str]] = field(default_factory=list)
|
|
44
|
-
max_token_count: Optional[int] = None
|
|
45
|
-
|
|
46
|
-
def resolve_defaults(self) -> "AgentConfig":
|
|
47
|
-
"""
|
|
48
|
-
解析并填充默认值,返回新的 AgentConfig 实例,不修改原对象。
|
|
49
|
-
策略与 Agent._init_config 中的逻辑保持一致,确保兼容。
|
|
50
|
-
"""
|
|
51
|
-
# 复制当前实例的浅拷贝数据
|
|
52
|
-
cfg = AgentConfig(
|
|
53
|
-
system_prompt=self.system_prompt,
|
|
54
|
-
name=self.name,
|
|
55
|
-
description=self.description,
|
|
56
|
-
model_group=self.model_group,
|
|
57
|
-
auto_complete=self.auto_complete,
|
|
58
|
-
non_interactive=self.non_interactive,
|
|
59
|
-
need_summary=self.need_summary,
|
|
60
|
-
summary_prompt=self.summary_prompt,
|
|
61
|
-
execute_tool_confirm=self.execute_tool_confirm,
|
|
62
|
-
use_methodology=self.use_methodology,
|
|
63
|
-
use_analysis=self.use_analysis,
|
|
64
|
-
force_save_memory=self.force_save_memory,
|
|
65
|
-
files=list(self.files or []),
|
|
66
|
-
max_token_count=self.max_token_count,
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
# use_methodology: 若存在上传文件则禁用;否则按照外部传入或全局默认
|
|
70
|
-
if cfg.files:
|
|
71
|
-
cfg.use_methodology = False
|
|
72
|
-
elif cfg.use_methodology is None:
|
|
73
|
-
cfg.use_methodology = is_use_methodology()
|
|
74
|
-
|
|
75
|
-
# use_analysis
|
|
76
|
-
if cfg.use_analysis is None:
|
|
77
|
-
cfg.use_analysis = is_use_analysis()
|
|
78
|
-
|
|
79
|
-
# execute_tool_confirm
|
|
80
|
-
if cfg.execute_tool_confirm is None:
|
|
81
|
-
cfg.execute_tool_confirm = is_execute_tool_confirm()
|
|
82
|
-
|
|
83
|
-
# summary_prompt
|
|
84
|
-
# Treat None or whitespace-only string as unset, fallback to default
|
|
85
|
-
if cfg.summary_prompt is None or (isinstance(cfg.summary_prompt, str) and cfg.summary_prompt.strip() == ""):
|
|
86
|
-
cfg.summary_prompt = DEFAULT_SUMMARY_PROMPT
|
|
87
|
-
|
|
88
|
-
# max_token_count
|
|
89
|
-
if cfg.max_token_count is None:
|
|
90
|
-
cfg.max_token_count = get_max_token_count(cfg.model_group)
|
|
91
|
-
|
|
92
|
-
# force_save_memory
|
|
93
|
-
if cfg.force_save_memory is None:
|
|
94
|
-
cfg.force_save_memory = is_force_save_memory()
|
|
95
|
-
|
|
96
|
-
# 非交互模式下默认开启自动完成
|
|
97
|
-
if is_non_interactive():
|
|
98
|
-
cfg.auto_complete = True
|
|
99
|
-
|
|
100
|
-
return cfg
|
|
File without changes
|
{jarvis_ai_assistant-0.4.1.dist-info → jarvis_ai_assistant-0.4.2.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{jarvis_ai_assistant-0.4.1.dist-info → jarvis_ai_assistant-0.4.2.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|