refactor(agent): MCP 기반 에이전트 아키텍처 재설계 — unified.md 분류기 제거, Gemini CLI + MCP 자율 도구 호출로 전환
This commit is contained in:
@@ -14,12 +14,14 @@ from pathlib import Path
|
||||
logger = logging.getLogger("variet.gemini")
|
||||
|
||||
ROLE_PROMPTS_DIR = Path(__file__).parent.parent / "prompts"
|
||||
PROJECT_ROOT = Path(__file__).parent.parent
|
||||
GEMINI_MODEL = "gemini-3-flash-preview"
|
||||
|
||||
# 역할별 thinkingBudget (토큰 단위)
|
||||
# 512=가벼운 분류/요약, 4096=계획/검수, 8192=구현/비평
|
||||
ROLE_THINKING: dict[str, int] = {
|
||||
"unified": 512,
|
||||
"agent": 4096,
|
||||
"summarizer": 512,
|
||||
"planner": 4096,
|
||||
"coder": 8192,
|
||||
@@ -57,28 +59,50 @@ class GeminiCaller:
|
||||
"--approval-mode", "yolo"]
|
||||
return ["gemini", "--model", GEMINI_MODEL, "--approval-mode", "yolo"]
|
||||
|
||||
# MCP 서버 설정 (홈 레벨에 등록)
|
||||
_MCP_SERVERS = {
|
||||
"anime": {
|
||||
"command": str(Path(sys.executable)),
|
||||
"args": [str(PROJECT_ROOT / "mcp_servers" / "anime_server.py")],
|
||||
"cwd": str(PROJECT_ROOT),
|
||||
"trust": True,
|
||||
},
|
||||
"infra": {
|
||||
"command": str(Path(sys.executable)),
|
||||
"args": [str(PROJECT_ROOT / "mcp_servers" / "infra_server.py")],
|
||||
"cwd": str(PROJECT_ROOT),
|
||||
"trust": True,
|
||||
},
|
||||
}
|
||||
|
||||
def _set_thinking_budget(self, role: str):
|
||||
"""역할별 thinkingBudget을 settings.json에 반영."""
|
||||
"""역할별 thinkingBudget + MCP 서버 설정을 settings.json에 반영."""
|
||||
budget = ROLE_THINKING.get(role, DEFAULT_THINKING)
|
||||
try:
|
||||
if _SETTINGS_PATH.exists():
|
||||
settings = json.loads(_SETTINGS_PATH.read_text(encoding="utf-8"))
|
||||
else:
|
||||
_SETTINGS_PATH.parent.mkdir(parents=True, exist_ok=True)
|
||||
settings = {}
|
||||
|
||||
# modelConfigs.default.thinkingConfig.thinkingBudget 설정
|
||||
# thinkingBudget
|
||||
configs = settings.setdefault("modelConfigs", {})
|
||||
default = configs.setdefault("default", {})
|
||||
thinking = default.setdefault("thinkingConfig", {})
|
||||
thinking["thinkingBudget"] = budget
|
||||
|
||||
# MCP 서버 (홈 레벨에 등록 — cwd와 무관하게 항상 사용 가능)
|
||||
mcp_servers = settings.setdefault("mcpServers", {})
|
||||
for name, config in self._MCP_SERVERS.items():
|
||||
mcp_servers[name] = config
|
||||
|
||||
_SETTINGS_PATH.write_text(
|
||||
json.dumps(settings, indent=2, ensure_ascii=False),
|
||||
encoding="utf-8",
|
||||
)
|
||||
logger.debug(f"thinkingBudget={budget} for role={role}")
|
||||
except Exception as e:
|
||||
logger.warning(f"thinkingBudget 설정 실패 (role={role}): {e}")
|
||||
logger.warning(f"settings.json 업데이트 실패 (role={role}): {e}")
|
||||
|
||||
def _clean_output(self, raw: str) -> str:
|
||||
"""Gemini 출력에서 노이즈 라인 제거."""
|
||||
@@ -190,16 +214,30 @@ class GeminiCaller:
|
||||
else:
|
||||
system_prompt = f"You are a {role}. Respond in Korean."
|
||||
|
||||
# 역할에 따라 다른 지시
|
||||
if role == "agent":
|
||||
# 범용 에이전트: 도구 사용 여부를 자율 판단
|
||||
footer = (
|
||||
f"프로젝트 루트: {cwd}\n"
|
||||
f"모든 응답은 한국어로 작성하세요.\n"
|
||||
f"파일 작업이 필요하면 직접 수행하고, 대화만 필요하면 바로 답변하세요."
|
||||
)
|
||||
else:
|
||||
# coder 등 파일 작업 전용 역할
|
||||
footer = (
|
||||
f"프로젝트 루트: {cwd}\n"
|
||||
f"파일을 직접 생성/수정하세요. 코드블록으로 출력하지 말고, 실제 파일로 저장하세요.\n"
|
||||
f"작업 완료 후 변경한 파일 목록을 간단히 출력하세요.\n"
|
||||
f"모든 응답, 주석, 문서는 반드시 한국어로 작성하세요."
|
||||
)
|
||||
|
||||
full_input = (
|
||||
f"=== SYSTEM INSTRUCTIONS ===\n"
|
||||
f"{system_prompt}\n\n"
|
||||
f"=== TASK ===\n"
|
||||
f"{context}\n\n"
|
||||
f"=== IMPORTANT ===\n"
|
||||
f"프로젝트 루트: {cwd}\n"
|
||||
f"파일을 직접 생성/수정하세요. 코드블록으로 출력하지 말고, 실제 파일로 저장하세요.\n"
|
||||
f"작업 완료 후 변경한 파일 목록을 간단히 출력하세요.\n"
|
||||
f"모든 응답, 주석, 문서는 반드시 한국어로 작성하세요."
|
||||
f"{footer}"
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user