diff --git a/nanoclaude/services/backend_registry.py b/nanoclaude/services/backend_registry.py index b1b4a98..8f332ab 100644 --- a/nanoclaude/services/backend_registry.py +++ b/nanoclaude/services/backend_registry.py @@ -35,13 +35,22 @@ JSON 형식: - direct/route/clarify: {"action": "...", "response": "...", "prompt": "..."} - tools: {"action": "tools", "tool": "calendar|email|document", "operation": "...", "params": {...}} -규칙: -- JSON 외 텍스트는 절대 출력하지 마라 +중요 규칙: +- 반드시 순수 JSON만 출력. 백틱, 코드블록, 설명 텍스트 금지 - 날짜는 YYYY-MM-DD, 시간은 HH:MM - pending_draft가 있다고 [대화 이력]에 표시되어 있을 때만 create_confirmed 사용 -- 오늘 날짜 정보가 [현재 시간]에 있으니 참고하라 +- [현재 시간]의 날짜를 참고하여 "오늘", "내일", "이번주" 등을 YYYY-MM-DD로 변환하라 -���의 이름은 '이드'. 상냥하고 친근하게 대화한다. +판단 예시: +- "오늘 일정" → tools: calendar.today() +- "이번주 일정" → tools: calendar.search(이번주 월~일) +- "내일 3시 회의" → tools: calendar.create_draft(...) +- "최근 메일" → tools: email.search("", 7) +- "문서 찾아줘" → tools: document.search(...) +- "안녕" → direct +- "양자역학 설명해줘" → route + +너의 이름은 '이드'. 상냥하고 친근하게 대화한다. 대화 이력이 있으면 맥락을 고려하라.\ """ diff --git a/nanoclaude/services/worker.py b/nanoclaude/services/worker.py index b7113d5..d73e986 100644 --- a/nanoclaude/services/worker.py +++ b/nanoclaude/services/worker.py @@ -70,20 +70,21 @@ async def _stream_with_cancel(adapter, message: str, job: Job, collected: list[s def _parse_classification(raw: str) -> dict: """EXAONE JSON 응답 파싱. 실패 시 direct fallback.""" raw = raw.strip() - # JSON 블록 추출 (```json ... ``` 감싸는 경우 대응) - if "```" in raw: - start = raw.find("{") - end = raw.rfind("}") + 1 - if start >= 0 and end > start: - raw = raw[start:end] - try: - result = json.loads(raw) - if "action" in result: - return result - except json.JSONDecodeError: - pass + # 어떤 형태든 첫 번째 { ~ 마지막 } 추출 + start = raw.find("{") + end = raw.rfind("}") + if start >= 0 and end > start: + json_str = raw[start:end + 1] + try: + result = json.loads(json_str) + if "action" in result: + return result + except json.JSONDecodeError: + pass # JSON 파싱 실패 → direct로 취급 (raw 텍스트가 직접 응답) - return {"action": "direct", "response": raw, "prompt": ""} + # 마크다운/코드블록 잔재 제거 + cleaned = raw.replace("```json", "").replace("```", "").replace("`json", "").replace("`", "").strip() + return {"action": "direct", "response": cleaned, "prompt": ""} async def _send_callback(job: Job, text: str) -> None: