Commit Graph

61 Commits

Author SHA1 Message Date
Hyungi Ahn e7a86c81da feat(nanoclaude): ask-first routing + 서고 안내 통일 + document 로그
- document 진입 시 기본 ask (근거 중심 답변)
- 명시적 목록 요청만 search_full (목록/리스트/제목만 등)
- 안내 문구 "서고를 확인하는 중입니다..." 통일
- document 호출 전후 라우팅/지연 로그 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:59:22 +09:00
Hyungi Ahn 26e011d4a8 fix(nanoclaude): remove shadowed logging import in lifespan
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:26:36 +09:00
Hyungi Ahn 39e48c3b3b ops(nanoclaude): startup self-check for Document Server env vars
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:47:30 +09:00
Hyungi Ahn 7dbf37a63f feat(nanoclaude): 도메인 키워드 자동 라우팅 + 서고 확인 안내 문구
- _pre_route: 산업안전/ASME/법령 등 도메인 키워드로 "문서 찾아줘" 없이도
  자동으로 document tool 라우팅 (도메인 진입 시 ask +1 보너스)
- EXAONE classifier: document.ask/search_full 도구 + 예시 추가
- worker: document tool 호출 전 "서고를 확인하는 중입니다" 안내 문구 전송

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:06:14 +09:00
Hyungi Ahn 637df9df2e fix(compose): nanoclaude build context를 루트로 변경
Dockerfile이 nanoclaude/와 infra/ 둘 다 COPY하므로
build context가 프로젝트 루트여야 함.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:01:28 +09:00
Hyungi Ahn 36f9fad0af feat(nanoclaude): document.ask + search_full 통합
- document_tool.py: ask() (/api/search/ask 35초 timeout, citation 포맷,
  refused 시 검색 결과 fallback) + search_full() (rerank+analyze 포함)
- registry.py: ALLOWED_OPS에 ask, search_full 추가
- worker.py: 질문/탐색 점수 기반 분기 (ask 강신호 2개 이상),
  document.ask 전용 35초 timeout, render_mode="final" 시 EXAONE 스킵

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:59:27 +09:00
Hyungi Ahn 378866a99c fix(infra): agent alert-on-change — debounce + stable key + MacBook 제외
- 상태 파일로 이전 이슈 추적 (~/Library/Application Support/infra-agent/)
- stable issue key (docker:gpu:container:status 형태)
- 2회 연속 실패 시 알림, 2회 연속 성공 시 복구 알림
- 동일 이슈 지속 시 무음 (alert storm 방지)
- MacBook Pro를 EXPECTED_TAILSCALE_HOSTS에서 제거 (잠자기는 정상)
- state file atomic write + 손상 시 graceful fallback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 06:53:24 +09:00
Hyungi Ahn 03e3df058f feat(infra): docker_restart 쓰기 도구 추가
보호 컨테이너(home-caddy, home-fail2ban, nanoclaude) 재시작 차단.
MCP 11개 도구 + NanoClaude wrapper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:06:40 +09:00
Hyungi Ahn d47c04317c feat(infra): Phase 1.5 진단 도구 3개 + trace 정리
scheduler_status, queue_status, run_verify 추가.
MCP 10개 도구 + NanoClaude wrapper + pre-route 키워드.
worker.py trace print 제거.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:27:19 +09:00
Hyungi Ahn 476cebcf88 fix(nanoclaude): 도구 결과 포맷 프롬프트 개선
날짜 hallucination 방지 + 가독성 개선.
데이터에 없는 날짜/숫자 금지, 요약 한 줄 + 짧은 목록 형식.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:14:56 +09:00
Hyungi Ahn ff3c6f5903 fix(nanoclaude): infra status — exited 컨테이너가 있어도 데이터 반환
ok=False(일부 컨테이너 exited)와 error_type(SSH 실패)를 구분.
컨테이너 목록은 항상 반환되도록 수정.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:04:19 +09:00
Hyungi Ahn 2268e47067 fix(nanoclaude): docker CLI static binary 설치
docker.io 패키지가 slim 이미지에서 안 됨.
Docker static binary 직접 다운로드로 교체.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:02:35 +09:00
Hyungi Ahn 9141942974 fix(nanoclaude): docker CLI + socket 마운트로 로컬 docker 접근
INFRA_LOCAL_HOST=gpu에서 run_local("docker ps")가 동작하려면
컨테이너 안에 docker CLI + socket 필요.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:00:53 +09:00
Hyungi Ahn a632607aa8 fix(nanoclaude): PYTHONUNBUFFERED + pre-route trace prints
worker 로그 stdout 미출력 해결 + pre-route 분기 추적용 trace.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:55:43 +09:00
Hyungi Ahn 1ea66530af fix(nanoclaude): infra pre-route 키워드 추가
docker/컨테이너/디스크/헬스체크/tailscale/모델 키워드를
infra 도구로 직접 라우팅. EXAONE classifier 의존 없이 확실한 매칭.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:45:40 +09:00
Hyungi Ahn 1abec083e7 feat(nanoclaude): 배포 준비 — Dockerfile + self-SSH 로컬 분기
- Dockerfile: infra/ 복사, openssh-client, healthcheck 추가
- requirements.txt: asyncssh, python-dotenv 추가
- core/ssh.py: INFRA_LOCAL_HOST 환경변수로 self-SSH 대신 로컬 실행

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:31:41 +09:00
Hyungi Ahn c7e44646fd feat(nanoclaude): Phase 3 infra intent — 시놀로지 Chat에서 서버 관리
EXAONE classifier에 infra 도구 5개 추가 (status, health, disk, network, models).
infra_tool.py가 infra.core/ 호출 → NanoClaude 반환 형식으로 변환.
"GPU 상태 알려줘" → tools: infra.status("gpu") → 구조화된 결과.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:24:02 +09:00
Hyungi Ahn 82ce83b8b7 feat(infra): Phase 2.1 Gemma 4 알림 자연어 설명
이상 감지 시 Gemma 4(MLX localhost:8801)로 원인 분석 + 권장 조치 생성.
Gemma 실패해도 rule 결과만으로 알림 전송 (graceful degradation).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:21:02 +09:00
Hyungi Ahn ac8787c153 feat(infra): Phase 2 monitoring agent — rule-first + 시놀로지 Chat 알림
5분 cron용 agent. docker/disk/health/network 4개 체크.
asyncssh 로그 억제, 작은 파티션(< 1G) 무시.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:16:01 +09:00
Hyungi Ahn b1f9e87d6a feat(infra): MCP 인프라 서버 통합 — 7개 도구 + core/ 분리
mcp-infra-server를 gpu-services/infra/로 통합.
core/ 순수 로직은 Agent/NanoClaude에서도 직접 import 가능.
도구: docker_status, docker_logs, service_health, disk_usage,
tailscale_status, ollama_models, mlx_models.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:11:54 +09:00
Hyungi Ahn 6b36063010 feat: Conversation sqlite 영구화 — 재시작에도 컨텍스트 유지
- db/database.py: conversation_messages 테이블 + save/load/cleanup 헬퍼
- conversation.py: write-through (memory + DB) + lazy load on first access
  - 메모리 캐시 1시간 TTL, DB 7일 보관
  - add/get/format_for_prompt가 async로 변경
- worker.py: 모든 conversation_store 호출에 await 추가
- main.py lifespan에 startup cleanup 호출 (7일 이상 정리)

서버 재시작 후 "방금 그거 더 자세히" 같은 후속 질문이 컨텍스트 유지

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:02:38 +09:00
Hyungi Ahn 26ccdb0f5e fix: Gemma route 시 대화 이력 전달 — 컨텍스트 단절 해결
reasoner_messages에 conversation_store의 최근 10개 메시지 포함.
"더 자세히 설명해줘" 같은 후속 질문이 이전 컨텍스트를 잇도록.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 08:29:05 +09:00
Hyungi Ahn 04027758ec fix: route 시 원본 메시지를 Gemma에 전달 — EXAONE이 답변까지 미리 작성하는 문제
EXAONE classifier가 route prompt 필드에 답변을 미리 작성해서
Gemma가 그것을 사용자 입력으로 받아 메타 응답을 하는 문제.
원본 job.message를 그대로 Gemma에 전달하도록 변경.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 08:26:39 +09:00
Hyungi Ahn cc792eddbb feat: MLX /status API 통합 — GPU 무접촉 부하 측정
- model_adapter.status_check(): GET /status, 미지원 백엔드는 None
- backend_registry.get_load_status(): /status API 1순위, hybrid fallback
  - active_jobs >=4 매우 바쁨, >=2 바쁨, =1 보통, =0 여유
  - source: status_api | hybrid 표시
- worker._build_system_status(): source별 분기, active_jobs/total_requests 표시
- hybrid 경로의 self-job 제외 (active > 1)
- health loop에서 status도 같이 캐시 (지원 백엔드만)

Mac mini /opt/mlx-proxy.py에 active_jobs 카운터 + /status 엔드포인트 추가됨

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 08:06:44 +09:00
Hyungi Ahn 3eacbac964 fix: KST 시간대 적용 — UTC 서버 → 한국 표준시로 모델에 전달
- 분류기 input의 [현재 시간]을 KST로 명시
- reasoner system prompt에도 현재 KST 시간 주입
- GPU 서버가 UTC라 모델이 시간 개념을 이상하게 가졌던 문제 해결

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 07:50:14 +09:00
Hyungi Ahn 875a4f80d2 feat: Hybrid 부하 판단 — health latency baseline + 조건부 inference
- model_adapter: measure_inference_latency() (max_tokens=1, 최소 부하)
- backend_registry:
  - health latency baseline 학습 (초기 5회 max, 이후 EMA)
  - get_load_status(): inference 우선, health/queue 보조
  - cache 30s + cooldown 10s + asyncio.Lock으로 자기증폭 루프 방지
  - 조건: health > baseline*3 또는 사용자 명시 요청 시에만 ping
- worker:
  - "system_status" 액션 — 사용자 상태 조회 시 force_measure
  - _build_system_status() 응답 빌더 (health/baseline/ping/queue)
  - route busy 안내를 get_load_status 기반으로 변경

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 07:46:57 +09:00
Hyungi Ahn fcd29a82c3 fix: 시스템 상태 키워드 확장 — 대기/큐/바빠/느려 등 추가
"젬마4 대기건이 많지 않아?" 같은 후속 질문도 상태 조회로 라우팅

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 15:19:00 +09:00
Hyungi Ahn ee31f06601 feat: 시스템 상태에 큐 정보 + Gemma busy 안내
- 상태 조회: 처리 중/대기 건수 표시
- Gemma route 시 큐에 다른 작업 있으면 "조금 걸릴 수 있어" 안내

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 15:13:02 +09:00
Hyungi Ahn a057e9a358 fix: Synology Chat rate limit 대응 — 최소 1.5초 간격 + 재시도
"create post too fast" 에러로 응답이 누락되던 문제.
전송 간 최소 1.5초 간격 보장 + API success:false 시 2초 후 1회 재시도.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 15:05:16 +09:00
Hyungi Ahn 8eeec87857 debug: synology_sender에 전송 내용 로그 추가
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 15:00:13 +09:00
Hyungi Ahn 1e3f9d83eb feat: 시스템 상태 질문 사전 라우팅 — 추론 모델/서버 상태 조회
"추론 모델 일하고 있어?" → backend health 체크 후 직접 응답

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 14:56:07 +09:00
Hyungi Ahn 37c5616735 feat: 이메일 폴더 필터링 — 테크니컬코리아/Gmail/개인 지정 가능
"테크니컬코리아 메일만" → Technicalkorea 폴더만 검색
"구글 메일" → Gmail만, "개인 메일" → INBOX만
폴더 미지정 시 전체 검색 유지

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 14:49:54 +09:00
Hyungi Ahn 12ca8f19d9 fix: 이메일 멀티 폴더 조회 + Synology 무응답 방지
- email_tool: INBOX/Gmail/Technicalkorea 3개 폴더 순회
  - 폴더별 try/except isolation (하나 실패해도 나머지 조회)
  - UID → folder:uid 형식 (폴더간 충돌 방지)
  - 날짜 parsedate_to_datetime 정렬
  - 폴더 라벨 표시 (개인/Gmail/회사)
- worker: response_sent 플래그 + finally 무응답 방지
  - 어떤 에러 경로에서든 Synology에 최소 1회 응답 보장

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 14:38:35 +09:00
Hyungi Ahn f73c46de3a fix: 캘린더 종료 시간(end_time) 지원 — 1시간 고정 제거
create_draft/create_confirmed에 end_time 파라미터 추가.
없으면 기본 1시간, 있으면 사용자 지정 종료 시간 사용.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 14:12:07 +09:00
Hyungi Ahn 131022eb12 fix: 도구 결과 포맷팅에 평문 프롬프트 사용 — JSON 출력 방지
분류기 system prompt가 JSON 강제라서 결과 포맷도 JSON으로 나옴.
도구 결과 정리 시 별도 평문 프롬프트를 messages로 직접 전달.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 14:02:33 +09:00
Hyungi Ahn 0b260eec5e fix: vobject 의존성 추가 + calendar 파싱 icalendar fallback
CalDAV 3.x에서 vobject 분리됨 → 이벤트 파싱 실패 원인.
vobject 설치 + icalendar fallback 파싱 추가.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 13:50:44 +09:00
Hyungi Ahn f72eef6e31 feat: 키워드 사전 라우팅 — EXAONE 분류기 한계 보완
EXAONE 7.8B가 복잡한 JSON 분류를 안정적으로 못함.
키워드 매칭으로 일정/메일/문서/확인 요청을 사전 감지하여
분류기를 건너뛰고 바로 도구로 라우팅.
날짜 계산(오늘/내일/이번주)도 코드에서 처리.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 13:46:07 +09:00
Hyungi Ahn e786307a07 fix: JSON 파싱 견고화 + 분류기 프롬프트 강화
- _parse_classification: 어떤 형태든 첫{~마지막} 추출, 백틱 잔재 제거
- 분류기: 판단 예시 추가 (일정→tools, 인사→direct 등), 백틱/코드블록 금지 명시

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 13:43:01 +09:00
Hyungi Ahn 6e24da56a4 feat: 이드 도구 확장 — 캘린더/메일/문서 연동 (read-only + 캘린더 생성 확인)
- tools/calendar_tool.py: CalDAV search/today/create_draft/create_confirmed
- tools/email_tool.py: IMAP search/read (전송 비활성화)
- tools/document_tool.py: Document Server search/read (read-only)
- tools/registry.py: 도구 디스패처 + WRITE_OPS 안전장치 + 에러 표준화
- 분류기: "tools" 액션 추가, 도구 목록/파라미터 스키마/규칙 명시
- Worker: tools 분기 + tool timeout 10초 + payload 2000자 제한
- conversation: pending_draft (TTL 5분) + create 확인 플로우
- 현재 시간을 분류기에 전달 (날짜 질문 대응)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 13:39:15 +09:00
Hyungi Ahn 40c5d3cf21 fix: Synology 응답에서 마크다운 제거 — **bold**, # header, - list → 순수 텍스트
상태 메시지(이모지)는 raw=True로 유지

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:57:50 +09:00
Hyungi Ahn a16ff2ea88 fix: max_tokens 추가 — Gemma 16000, EXAONE 4096
응답이 중간에 끊기는 문제 해결. ModelAdapter에 max_tokens
파라미터 추가, stream/complete 양쪽 payload에 반영.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:52:31 +09:00
Hyungi Ahn 74f8df48fc fix: Synology UX — "🤔 생각 중..." + route시 "📝 더 깊이 살펴볼게요..."
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:47:02 +09:00
Hyungi Ahn 53d3e8e056 fix: Synology 응답 길이 1500→4000자 (모닝 브리핑 대비)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:45:21 +09:00
Hyungi Ahn 21f6869898 feat: EXAONE 분류기 — direct/route/clarify 라우팅 + 대화 기억
- EXAONE: 분류기+프롬프트엔지니어+직접응답 (JSON 출력)
- 간단한 질문은 EXAONE이 직접 답변 (파이프라인 스킵)
- 복잡한 질문은 AI 최적화 프롬프트로 Gemma에 전달
- 모호한 질문은 사용자에게 추가 질문 (clarify)
- user별 최근 대화 기억 (최대 10개, 1시간 TTL)
- ModelAdapter: messages 직접 전달 옵션 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:40:39 +09:00
Hyungi Ahn 1ac4832bdc fix: 프롬프트 튜닝 v2 — 자기 인식 + rewrite 과잉 방지
- reasoner: EXAONE+Gemma4 파이프라인 자기 인식 추가
- rewriter: 간단한 질문/인사는 원문 그대로 통과, 복잡한 것만 재구성

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:36:43 +09:00
Hyungi Ahn 9b8059ca38 fix: 시스템 프롬프트 튜닝 — 상냥하고 간결한 대화 스타일
- reasoner: "이드" 페르소나, 간결+상냥, 불필요한 구조화 금지
- rewriter: 인사/잡담은 그대로 통과

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:33:39 +09:00
Hyungi Ahn 193c3249fc fix: python-multipart 추가 — form parsing 의존성
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:27:23 +09:00
Hyungi Ahn a44f6446cf feat: NanoClaude Phase 3 — Synology Chat 연동
- POST /webhook/synology: outgoing webhook 수신 + token 검증
- 파이프라인 완료 시 incoming webhook으로 응답 자동 전송
- "분석 중..." typing 메시지 선전송
- 응답 길이 1500자 제한 (Synology Chat 제한 대응)
- 에러/실패 시에도 사용자에게 알림 메시지 전송
- 중복 요청 방지 (30초 TTL dedup)
- Synology에서 rewrite 이벤트 숨김 (SSE에서만 노출)
- callback 구조로 확장 가능 (Slack, Discord 등)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:25:48 +09:00
Hyungi Ahn 9f0c527442 fix: health_check timeout 3→5초 — MLX cold start 대응
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:08:28 +09:00
Hyungi Ahn 2b4d182b24 fix: job_queue 모듈 import 방식 수정 — None 참조 해결
모듈 레벨 변수를 직접 import하면 init_queue() 이후에도
None 참조가 유지됨. 모듈 자체를 import하여 접근.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 12:06:48 +09:00