Commit Graph
419 Commits
Author SHA1 Message Date
kim 6271b65f84 v4.3.15: browser/desktop advisor closures → gateway/chat/browser-desktop-advisor.ts 분리 보관
- handle-chat.ts에서 maybeRunBrowserAdvisorPass(430줄) + maybeRunDesktopAdvisorPass(140줄)
  + 헬퍼 4개를 별도 파일로 이동 (handle-chat.ts 3,900→3,400줄, 500줄 감소)
- 메인 루프의 가변 상태는 그대로 두고, getter/setter 기반 advisorCtx 뷰 객체를 통해
  새 파일과 공유 → 메인 루프 변수명/조건식은 모두 유지
- 현재 배포에선 dormantBrowserTools / Linux desktop 제한으로 여전히 도달 불가능한
  코드이나, 향후 브라우저/데스크톱 자동화 복구 시 이 파일만 다시 연결하면 됨
- 빌드 성공 + 재시작 후 일반 채팅/code_ai 채팅 모두 정상 동작 확인
2026-07-25 19:04:50 +09:00
kim cf15061e39 v4.3.14: 죽은 코드 5개 정리 (readDailyMemoryContext, readMemoryCategories, renderTaskCandidatesForHuman, latestTaskForSession, buildBlockedTaskStatusMessage)
정의만 있고 호출부 없는 함수들. readDailyMemoryContext/readMemoryCategories는
Chroma 벡터 메모리(2026-07-24 도입, buildPersonalityContext의 [RECALLED_FACTS])가
관련성 기반 회상으로 대체하면서 이미 실질적으로 무용해진 상태였음.
2026-07-25 18:34:48 +09:00
kim 394d990fba v4.3.13: handleTaskControlAction → gateway/tasks/handle-task-control.ts 분리 (5,021→4,668줄)
3자 순환 의존성(executeTool→handleTaskControlAction→handleChat→executeTool) 발견:
- inferTaskChannelFromSession/findBlockedTaskForSession/parseTaskIdFromText는 실제로는
  handleChat에 의존하지 않는 순수 쿼리 헬퍼임을 확인하고 팩토리 밖으로 빼서 일반 export로
  전환 → handle-chat.ts가 deps 주입 없이 직접 import하도록 변경 (HandleChatDeps 2개 필드 제거)
- handleTaskControlAction 자체만 진짜 순환: launchBackgroundTaskRunner가 handleChat을 필요로
  하는데 handleChat이 executeTool을, executeTool이 handleTaskControlAction을 필요로 함
  → lazy binding으로 해결: executeTool 인스턴스화 이전에 hoisted wrapper 함수
  (let _handleTaskControlActionImpl + function handleTaskControlAction)를 선언해 dep로 넘기고,
  handleChat 생성 후 실제 구현을 대입

실제 백그라운드 태스크 생성→조회→삭제 왕복으로 순환 경로 전체 검증 완료.
2026-07-25 18:31:45 +09:00
kim dc546ab5e2 v4.3.12: buildPersonalityContext → gateway/chat/personality-context.ts 분리 (5,455→5,021줄)
detectToolCategories/TOOL_BLOCKS/readMemorySnippets 등 관련 헬퍼 클러스터를
createPersonalityContext(resolvePromptPath) 팩토리로 통째 이동. 외부 의존은
resolvePromptPath 하나뿐이라 순환 의존성 없이 분리 가능했음.
2026-07-25 18:23:50 +09:00
kimandClaude Sonnet 5 5ed28240f3 v4.3.11: handleChat()+handleCodeChat()을 gateway/chat/handle-chat.ts로 분리 (server.ts -3712줄)
오늘 분석에서 찾은 3대 핵심 엔진 함수(buildTools/executeTool/handleChat,
합쳐서 원래 6043줄=51%) 중 가장 크고 마지막 조각. handleChat 바로 앞에
정의된 형제 함수 handleCodeChat(코드 에디터 /api/chat 전용 경로)이 정확히
같은 의존성 집합을 공유하는 걸 확인하고 함께 이동 — 둘 다 buildTools/
executeTool/normalizeToolArgs/logToolCall/ToolResult를 그대로 씀.

app/config/server로 잡혔던 "외부 심볼 참조"는 buildTools 때와 동일하게
전부 도구 설명/주석 안 우연한 단어 오탐으로 확인. 실제 dep는 34개
(밖에서도 쓰이는 telegramChannel/skillsManager/broadcastWS/codeAiLocalSessions/
buildTools/executeTool 등 + handleChat 전용이지만 재귀적 의존성 파악 부담을
피하기 위해 dep로 남긴 로컬 헬퍼 30개), createHandleChat(deps) 팩토리로 주입.
MAX_TOOL_ROUNDS/ExecutionMode/SubagentProfile+TOOL_PROFILES(죽은 코드)는
server.ts에서 정리.

server.ts: 9167 → 5455줄. handle-chat.ts는 3903줄.

검증: 빌드 1차 시도에서 에러 4종류(HandleChatResult 미export, getModelForRole/
fs/path 미import)만 발생 — 나머지 30여개 dep는 전부 정확히 맞았음. 재시작 후
실제 채팅으로 (1) 일반 텍스트 (2) 도구 호출 (3) handleCodeChat 코드에디터 경로
(4) web_search (5) 백그라운드 태스크(BackgroundTaskRunner 경유 handleChat) —
5개 시나리오 전부 실제 왕복 검증. 백그라운드 태스크가 needs_assistance로 끝난
건 handleChat 문제가 아니라 이 환경의 오케스트레이션 disabled 설정 때문임을
daily memory 로그("1+1은 2입니다" 3회 정상 응답 확인)로 교차검증 후 확인.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 18:06:31 +09:00
kimandClaude Sonnet 5 0d2372d0df v4.3.10: executeTool()을 gateway/chat/execute-tool.ts로 분리 (server.ts -1417줄)
executeTool 전용으로만 쓰이던 헬퍼(SAFE_COMMANDS, buildUrlOpenCommand,
buildBrowserLaunchCommand, hasUriScheme, quoteShellArg, BLOCKED_PATTERNS,
lastFilenameUsed, normalizeScheduleJobAction, summarizeCronJob,
normalizeDeliveryChannel, ToolResult 타입)도 함께 이동 — 전부 executeTool
밖에서 전혀 참조되지 않는 것을 grep으로 확인 후 판단. 죽은 코드였던
isLinux(정의만 있고 미사용)도 이 김에 삭제.

밖에서도 쓰이는 10개(isPathInsideDir/cronScheduler/resolvePromptPath/
webSearch/webFetch/imageSearch/IMAGE_TYPES/codeAiLocalSessions/
handleTaskControlAction/broadcastWS)는 createExecuteTool(deps) 팩토리로 주입,
호출부 시그니처는 그대로 유지.

server.ts: 10584 → 9167줄. 빌드/재시작 후 실제 채팅으로 shell/coder_write_file/
web_search 3개 도구 실행 왕복 검증(생성 파일 확인 후 정리 완료), 기존
라우트 8개 재확인.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 17:46:46 +09:00
kimandClaude Sonnet 5 44de254ab4 v4.3.9: buildTools()를 gateway/chat/build-tools.ts로 분리 (server.ts -1201줄)
3개 핵심 엔진 함수(buildTools/executeTool/handleChat, 합쳐서 6043줄=51%) 중
가장 독립적인 것부터 분리 시작. 실제 참조하는 외부 심볼은
isOrchestrationSkillEnabled 단 하나뿐 — app/config/server는 텍스트 검색에서
도구 설명 문자열("node app.js" 등) 안 우연한 단어와 오탐이었음. 캐시(_toolsCache)
도 함수 스코프 안에서만 쓰여 통째로 이동. createBuildTools(dep) 팩토리 패턴으로
감싸 호출부 시그니처는 그대로 유지.

server.ts: 11785 → 10584줄. 빌드/재시작 후 실제 채팅 메시지로 coder_list_files
도구 호출 왕복까지 검증(HTTP 200 체크만으론 부족 — 실제 도구 실행까지 확인).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 17:32:50 +09:00
kimandClaude Sonnet 5 7dba6f8816 v4.3.8: fix — gateway 폴더 재구성 후 __dirname 기반 경로 6곳 깨짐 (치과사전 DB 500 등)
routes-*.ts를 routes/ 서브디렉토리로 옮기면서 import 경로는 스크립트로
재계산했지만, __dirname 기반 런타임 파일 경로(디렉토리 한 단계 더 깊어짐)는
놓쳤음. dental_dict.db·web-ui/schematics·scripts/pptx_preview.py·
edge_tts_synth.py(voice/writer/language 3곳) 전부 ../를 하나씩 추가.
실제 DB 통계(4809건)·검색 API로 재검증 완료.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 17:19:30 +09:00
kimandClaude Sonnet 5 f8fc787fe8 v4.3.7: 죽은 레거시 orchestrator.ts 삭제
export {} 뿐인 빈 껍데기, 아무 곳에서도 참조 안 됨(reactor.ts +
orchestration/multi-agent.ts로 대체된 지 오래). 빌드/재시작 확인 완료.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 17:12:54 +09:00
kimandClaude Sonnet 5 05976e3f05 v4.3.6: gateway 루트에 남아있던 나머지 20개 파일도 서브디렉토리로 분류
- memory/ (3): fact-store, memory-manager, memory-vector
- hooks/ (2): hooks, hook-loader
- infra/ (4): boot, gpu-detector, ollama-process-manager, mcp-manager
- guards/ (6): link-validator, visual-error-detection, context-injection,
  prompt-gates, retry-strategy, verification-flow
- internal-agent-task.ts(실제 express 라우터), music-renderer.ts(routes-music.ts
  전용 백엔드)는 routes/로 편입
- server.ts/session.ts/skills-manager.ts는 5곳 안팎에서 두루 참조되는 핵심
  모듈이라 루트 유지, orchestrator.ts(export {}뿐인 죽은 레거시 껍데기)도
  분류 대상이 아니라 별도 이슈로 루트에 남김
- 이번에도 import 경로 자동 재계산 스크립트 사용, 41곳 수정 후 빌드/재시작/
  20개 엔드포인트 재검증 완료

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 17:10:44 +09:00
kimandClaude Sonnet 5 db7260ac46 v4.3.5: gateway 폴더 구조 정리 — routes/channels/mocks/errors/tasks/automation 서브디렉토리 분리
- src/gateway/ 76개 .ts 파일 중 55개를 종류별 서브디렉토리로 이동
  (routes/ 35, channels/ 4, mocks/ 3, errors/ 5, tasks/ 8, automation/ 3)
- 루트엔 server.ts(server-v2.ts에서 개명) 포함 21개 핵심 인프라 파일만 유지
- gateway 내부 상대경로 import 101곳 + 외부 참조 5곳(cli/index.ts,
  tools/kakao.ts, tools/pptx.ts, tools/shell.ts, tools/task-control.ts)을
  스크립트로 재계산, 빌드/재시작/26개 엔드포인트 스모크테스트로 검증

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 17:02:54 +09:00
kimandClaude Sonnet 5 a1cfeb7710 v4.3.4: server-v2.ts 라우트 분리 3차 (chat-sessions/auth-openai/users/admin/channel-mappings/detective)
- 7개 라우트 클러스터 추가 추출 (12,785 → 11,785줄)
- detective는 2곳에 흩어진 사례(9761~)와 네트워크도구(11581~)를 하나로 통합,
  /pdf-editor 프록시가 쓰는 detectiveFilesDir/resolveDetectiveUploadPath는 export
- users는 CRUD/이메일계정/텔레그램봇 3곳을 통합, 생성→조회→삭제 전체 사이클 실제
  테스트로 검증(테스트 계정 정리 완료)
- 핵심 로그인/세션(/api/auth/status·setup·login·logout·change-password)과
  handleChat에 직결된 거대 POST /api/chat 루프는 위험도 높아 이번에도 제외
  (기존 /api/code/round 제외와 동일한 이유)
- 오늘 세 차례 분리 누적: 14,913 → 11,785줄 (-3,128줄, -21%)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 16:52:17 +09:00
kimandClaude Sonnet 5 4a74d79491 v4.3.3: server-v2.ts 라우트 분리 2차 (tasks/agents/channels/telegram/orchestration/schematics/canvas/ppt/misc)
- 9개 라우트 클러스터 추가 추출 (14,002 → 12,785줄)
- 오늘 두 차례 분리로 총 14,913 → 12,785줄 (-2,128줄, -14.3%)
- 남은 detective/auth/admin/user/chat 클러스터는 최대 4,700줄 범위에 걸쳐
  뒤섞여 있어 이 패턴으로는 분리 어려움 — 별도 전략 필요

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 16:25:04 +09:00
kimandClaude Sonnet 5 5d3d54e949 v4.3.2: server-v2.ts 라우트 분리(bg-tasks/kakao/schedules/skills/code) + 뉴스 다이제스트 정리
- 14,913줄 server-v2.ts에서 라우트 클러스터 5개를 routes-*.ts로 추출
  (기존 routes-arduino.ts 패턴 재사용, 14,002줄로 축소)
- 뉴스 multi-call 다이제스트: BM25 재정렬은 실측 벤치마크에서 원본보다 나빠
  되돌리고, 검증된 이득(URL 중복제거)만 발행일 최신순 정렬로 유지

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 16:05:00 +09:00
kimandClaude Sonnet 5 98725caff6 v4.3.1: 뉴스/소식 게이트 정리 + 미스트랄 tool_choice 강제
- news_search 스키마에 지역코드 안내 부족 버그 수정 (동유럽 country code 예시 추가)
- "소식"을 뉴스 동의어로 게이트에 추가, "무슨 좋은 소식 있어" 같은 개인 안부 관용구는
  PERSONAL_NEWS_IDIOM 예외로 오탐 방지
- 하드코딩 가드 9개 추가 정리: prompt-gates.ts로 통합(isNewsRequest 중복 제거,
  task-intent 6개, isHighStakesFile/requestedFullTemplate/
  shouldForceSessionScopeForTemporalClaim/userRequestedImageEdit 이동), 죽은
  코드 4개 삭제
- 브라우저 자동화 재시도 가드가 dormant된 browser_* 도구를 강제 호출하려던
  사각지대 수정 (도구 가용성 체크로 게이팅)
- tool_choice를 provider 체인 전체에 플러밍, 모델별 프로필에
  forceToolChoiceOnLiveData 플래그 추가 — 미스트랄이 뉴스/사실질의에서 도구
  호출 없이 답변을 지어내던 문제를 라운드 0부터 강제 도구호출로 차단
  (프롬프트 경고만으로는 불충분함을 실측 확인)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 11:54:40 +09:00
kimandClaude Sonnet 5 7bc1b1bb65 v4.3.0: Chroma 벡터 메모리 시스템 구축 + 하드코딩 게이트 정리
- USER.md/SOUL.md 문자캡 잘림 보완용 벡터 검색(Chroma, EmbeddingGemma) 신설
- 일별 대화로그 LLM 추출 파이프라인(user_facts/daily_extracts 컬렉션 분리)
- 검증-강제 게이트(isFactualInfoRequest 등)를 prompt-gates.ts로 분리, 개인 인프라
  별명(지서버/클로서버) 관련 불필요한 web_search 강제 호출 버그 수정
- Qwen3-Embedding-8B는 실측 결과 이미지생성 GPU와 자원 충돌 확인되어 폐기,
  EmbeddingGemma(경량+다국어)로 최종 선택

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 16:06:29 +09:00
kimandClaude Sonnet 5 df856877e8 v4.2.3: 작가앱 Google Books/알라딘 API 키 vault 매핑 누락분 추가
v4.2.1 이북 리더 커밋에서 빠뜨렸던 부분 — 이제 이 두 공급자 키를 평문으로
저장하면 다음 config 저장 때 자동으로 vault로 이전된다(기존 nvr.password 등과 동일 패턴).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 11:21:07 +09:00
kimandClaude Sonnet 5 174da1e5bd v4.2.2: 홈CCTV 앱에 독립 IP카메라 지원 추가(ONVIF PTZ) + 채널 이름/화질 고정
- 메인 NVR과 별개인 독립 IP카메라(예: Mercusys/Tapo) 등록 지원
  (nvr.extraCameras, id 1000+) — RTSP/화면 표시는 메인 NVR과 동일 그리드에 통합
- ONVIF(WS-Security) 기반 PTZ 제어 — 라이브 모달의 기존 PTZ 버튼이 독립 카메라에서도
  그대로 작동(백엔드에서 채널 id로 NVR/독립 카메라 라우팅)
- 카메라 자체에 상하반전 옵션이 없는 모델을 위한 ffmpeg 소프트웨어 180도 회전,
  반전 시 PTZ 팬/틸트 방향도 화면 기준으로 자동 보정
- 채널 이름/위치 라벨 커스텀 표시, 채널별 화질(메인/서브) 강제 고정
- 6분할 라이브로 확장(기존 5분할 하드코딩 제거)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 11:19:43 +09:00
kimandClaude Sonnet 5 0bab3f7924 v4.2.1: 작가 어시스턴트 앱에 이북 리더 추가 — 페이지 넘김 형태 + Gutenberg 검색/보관
- Project Gutenberg/Google Books/알라딘 검색 및 서재(EPUB) 보관
- 페이지 넘김 리더: 책 판형 비율 고정 페이지, 챕터 자동 새 페이지 시작,
  단어/문단 경계 유지, 브라우저 창 크기와 무관한 고정 페이지 분량(스케일만 조정)
- Gutenberg 원문의 강제 줄바꿈을 문단 단위로 재조판(reflowHardWrappedProse)
- 서재에서도 바로 읽기 지원(다운로드 시 원문 URL 함께 저장)
- TTS 낭독(현재 페이지 기준)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 22:56:35 +09:00
kimandClaude Sonnet 5 e0e9a97761 v4.2.0: 날씨 지오코딩 동명 도시 국가 구분 + PTY 워크스페이스 cwd 수정
- weather.ts: "Rome"처럼 국가 미명시 동명 도시 조회시 지오코딩 API의
  index 0을 그대로 믿지 않도록 개선. Open-Meteo 결과는 인구수 기준으로
  재정렬해 최적 후보를 고르고, OpenWeather 쪽은 country 미명시일 때
  Open-Meteo 좌표로 재조회해 이름 모호성 자체를 피함. 국가 파싱 로직
  (parseExplicitCountry)을 두 경로가 공유하도록 정리.
- server-v2.ts: PTY 셸 세션 생성시 cwd 기본값을 고정된 homeclaw 경로
  대신 사용자별 워크스페이스로 사용, 세션 시작 전 워크스페이스 보장.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 16:52:30 +09:00
kimandClaude Sonnet 5 c271c96bdb v4.1.23: NVR MJPEG 스트림 메모리 누수 수정 — OOM으로 RDP까지 끊기던 사고 대응
homeclaw 게이트웨이 node 프로세스가 34GB+까지 자라 커널 OOM killer에
강제종료되고, 그 여파로 systemd-oomd가 GNOME 세션(D-Bus 포함)까지 같이
죽여 원격데스크탑 연결이 끊기는 사고가 하루 4회 발생. 원인은 NVR 라이브
MJPEG 프레임 파서와 응답 스트림 두 곳의 무제한 버퍼 증식.

- nvr.ts: 손상 스트림에서 SOI만 오고 EOI가 안 오면 프레임 버퍼가 무한
  이어붙기하는 것을 20MB 캡으로 차단 (MAX_FRAME_BYTES)
- nvr.ts: res.write()가 false를 반환할 때(클라이언트가 못 따라옴) ffmpeg
  stdout을 pause()하고 'drain'에서 resume()하는 백프레셔 처리 추가 —
  프레임 캡만으로는 재발을 못 막았던 잔여 누수의 실제 원인
- .smallclaw/config.json, config.ts: nvr 설정 블록(host/rtspPort/경로
  템플릿/계정) 추가, password는 vault 경유
- nvr-app.html: 4분할→5분할 라이브, 녹화 목록 조회 탭 추가
- index.html: 홈CCTV 앱 런처 버튼 추가

homeclaw.service에 MemoryMax=8G/MemoryHigh=6G cgroup 상한을 시스템 드롭인
으로 별도 적용(이 커밋에는 미포함, systemd 유닛 파일은 저장소 밖)해
재발해도 GNOME 세션까지는 안 죽도록 안전망도 걸어둠.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 16:38:39 +09:00
kimandClaude Sonnet 5 5064d2bb3a v4.1.22: 홈CCTV NVR 앱 추가 — RTSP 라이브영상(MJPEG)+PTZ 제어
- EseeCloud K8208-3WS NVR RTSP(포트80, /ch{N}_{S}.264)를 ffmpeg로
  MJPEG(multipart/x-mixed-replace) 변환, 4분할 자동재생+모달 확대
- PTZ 팬/틸트: NVR 웹UI와 동일한 /netsdk/Channel/PTZ + S.PtzControl
  포맷, 숫자 Cmd코드로 수정(기존 PTZControl 문자열 명령은 무반응이었음)
- ffmpeg NVDEC를 GPU1에 고정(GPU0은 이미지 스튜디오가 이미 점유)
- mid-stream 드롭(PTZ 이동 등) 자동 respawn으로 화면 끊김 복구
- 화면 전환시 서버에 명시적 stop 요청 + activeStreams를 abort()
  콜백으로 전환해 레이스컨디션으로 인한 ffmpeg 프로세스 배가 수정

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 01:07:18 +09:00
kimandClaude Sonnet 5 4dd970e506 v4.1.21: 설정 변경 — primary 모델 gemma4:31b-cloud로 전환 + 기타 조정
primary/manager/executor/verifier를 gemma4:31b-cloud로 전환 — 순수모델
비교(2026-07-18)에서 mistral-large-3/qwen3.5보다 실시간정보 환각이 훨씬
적고 프로덕션 파이프라인 검증에서도 문제 없었음.

orchestration.secondary 모델을 mistral-large-3→kimi-k2.6:cloud로 변경,
preflight.mode를 off→complex_only로, multi-agent에 subagent_mode:false
추가, search에 google_api_key vault 참조 추가(평문 없음, updateConfig
경유로 vault 마이그레이션됨).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 15:54:32 +09:00
kimandClaude Sonnet 5 66eb1dc88d v4.1.20: CherryClaw → HomeClaw 리브랜딩 + 로고 교체 + 습관성 🦞 이모지 제거
브랜드명 전체 변경: "CherryClaw"→"HomeClaw", localStorage 키 6종
(cherryclaw_theme 등)→homeclaw_*, alt="🍒"→alt="🏠". 15개 web-ui 파일 +
OpenAI OAuth 완료 페이지 전체 반영.

로고를 체리 아이콘에서 집 모양으로 교체 후, 사용자 피드백을 반영해 동화풍
성(castle) 실루엣으로 재작업 — 대리석/벽돌 텍스처의 회색 톤, 검은 윤곽선,
중앙 첨탑 우측에 작은 반짝임 별. FLUX.1로 생성 후 배경 제거해 투명 PNG로
저장. 파일명도 cherry_logo.png → homeclaw_logo.png로 통일(web-ui/, assets/
양쪽).

시스템 프롬프트("You are SmallClaw 🦞")와 IDENTITY.md(papa/cherry/jasmine
+ 템플릿 4곳)의 Name 필드에서 🦞를 빼고, 습관적으로 이모지를 붙이지 말라는
지시를 추가 — 모델이 응답 끝마다 무의식적으로 🦞를 붙이던 문제 해결.
텔레그램 봇 응답/self-update 알림/연동 테스트 메시지 등 하드코딩된 🦞도
전부 제거.

부수적으로 발견한 문서 버그도 수정: 웹훅 가이드와 curl 복사 버튼이
"x-cherryclaw-token" 헤더를 안내하고 있었는데, 서버가 실제로 검사하는
헤더는 X-Gateway-Token이었음 — 그대로 썼으면 401 에러가 났을 문제.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 15:48:22 +09:00
kimandClaude Sonnet 5 8f235a148d v4.1.19: news_search country 파라미터 6개 이상 입력시 에러 대신 앞 5개만 사용
NewsData.io는 country를 6개 이상 넘기면 하드 에러("Number of country
cannot exceeded 5")를 내는데, "소아시아 뉴스"처럼 자연스럽게 6개 이상의
국가코드로 매핑되는 요청에서 모델이 왕복을 한 번 날리게 되던 문제 —
5개 초과분은 조용히 잘라내도록 수정.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 13:08:01 +09:00
kimandClaude Sonnet 5 20ee4fc45e v4.1.18: 동영상 생성에 CogVideoX-2B 옵션 추가 + 스튜디오 UI 레이아웃 수정
video_generate에 model 파라미터 추가 — 기존 LTX-Video(빠름, 기본값)에
CogVideoX-2B(THUDM, 느리지만 화질 비교용)를 선택지로 추가. CogVideoX는
12GB VRAM 한계에 거의 딱 맞아(enable_model_cpu_offload에도 peak ~11GB)
해상도/프레임수 기본값 이상으로 올리면 여유가 없음.

스튜디오앱 동영상 탭에서 모델/프레임수/FPS 세 필드가 320px 폭 폼에
한 줄로 욱여넣어져 프레임수부터 우측 패널에 가려 안 보이던 레이아웃
버그 수정 — 모델 드롭다운을 단독 줄로 분리하고 프레임수/FPS는 그 아래
별도 행으로 이동.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 13:07:51 +09:00
kimandClaude Sonnet 5 16c3d0e4ae v4.1.17: tool_calls/응답 짝맞춤 버그 + 검색예산 유동화 + 시간일관성 프롬프트
검색예산 하드캡·image_edit 차단·FILE_OP v2 대체실행 등 도구호출을 가로채는
5곳이 messages 배열에 매칭되는 role:'tool' 응답을 안 넣고 continue만 해서,
Ollama가 다음 호출에서 "Not the same number of function calls and responses"로
거부하는 버그 수정.

검색예산은 소프트캡 5회 유지하되 새 토큰(도시명 등)이 포함된 진짜 새 주제
검색이면 하드캡 12회까지 자동 연장 — "유럽 주요 도시 최고온도"처럼 정당한
다건 검색이 캡에 걸려 차단되던 문제 해결.

시스템프롬프트에 TEMPORAL CONSISTENCY 문단 추가 — 시장개장/영업 여부 판단시
검색결과보다 주입된 현재날짜(요일 포함)를 우선 신뢰하도록 지시. mistral이
검색은 하면서도 요일을 반영 못해 주말에 "시장 열려있음" 같은 오답을 내던
잔여 문제 대응.

ollama-adapter.ts에 parseOrphanTrailingToolJson 추가 — 모델이 함수명을
빠뜨리고 원시 JSON(예: write_note 인자)을 답변 끝에 그대로 노출하는 케이스를,
알려진 도구 스키마와 매칭될 때만 실제 tool_call로 복구하거나(유일 매칭)
화면에서만 제거(모호한 매칭)하도록 처리.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 13:07:39 +09:00
kim a0a8807caf v4.1.16: 검색예산 하드캡 우회 구멍 수정 — 텍스트 흉내 tool call 복구가 tools:[] 무시
toolsDisabledForRestOfTurn(검색예산 2회 초과 시 그 턴 tools를 []로 비우는 안전장치)가
걸려도, "모델이 함수호출 대신 텍스트로 toolname{...}를 흉내낸 경우 복구"하는 로직이
이 상태를 확인하지 않고 원래 도구 목록으로 계속 텍스트를 재파싱해 tool call로
되살리고 있었음 — 실질적으로 tools:[] 캡을 완전히 무력화시키는 구멍이었음.

실측: "GPT-5.6 가격 비교" 질문 하나에 web_search가 37라운드 넘게 반복되다 결국
"못 찾았다"로 종료(로그로 재현·확인). toolsDisabledForRestOfTurn일 때 이 복구
로직을 스킵하도록 수정.
2026-07-17 00:48:29 +09:00
kim 449ecaea9d v4.1.15: 뉴스/검색 신뢰성 개선 — AUTO-RECOVER 무한재시도·해외뉴스 국가필터 버그 수정
AUTO-RECOVER의 근거도구 인식 정규식에 news_search가 빠져있어서, 뉴스 검색을
몇 번을 성공시켜도 "아직 도구 안 불렀다"고 오판해 강제 재호출을 반복 주입하던
버그 수정(server-v2.ts) — 실측상 "오늘 유럽 뉴스" 요청 하나에 13라운드 넘게
반복 호출되던 원인이었음, 모델 종류와 무관하게 재현됨.

news_search(NewsData.io)는 country+language 불일치, country+category=world
조합에서 country 필터를 조용히 무시하고 엉뚱한 나라 뉴스를 반환함을 확인 —
country 지정 시 language/category=world를 드롭하도록 수정하고, "유럽" 같은
대륙 코드가 없다는 점 + country는 콤마로 최대 5개까지 받는다는 점을 도구
설명에 명시(news.ts).

SearXNG 쿼리에 language/time_range 파라미터 추가로 오래된 결과 필터링
정교화(web.ts).
2026-07-17 00:11:51 +09:00
kim 636a06f17d v4.1.14: 언어앱 독일어 지원 추가 (언어 파라미터화)
우즈베크어 전용으로 하드코딩돼 있던 language-app을 lang 파라미터 기반으로
리팩터링하고 독일어 어휘 56개·레슨 8개를 추가. 진도/커스텀 카테고리도
언어별로 분리 저장(기존 우즈베크어 데이터는 자동 마이그레이션).

덤으로 퀴즈 시작 시 id 불일치로 showQuizQuestion()이 매번 죽던 버그도 수정.
2026-07-16 16:18:04 +09:00
kim f6f7f14541 v4.1.13: 언어앱 타일뷰 기본화 + 카테고리 추가 + 선생님 Q&A 패널
기본 보기를 타일 그리드로 전환하고 사용자가 카테고리를 직접 추가할 수 있게 함.
문법/단어/문화 질문에 답하는 "선생님" 채팅 패널 신설(/api/language/ask-teacher).
선생님 답변의 마크다운(표·볼드·목록·인용)이 그대로 노출되던 버그를 자체 렌더러로 수정.
2026-07-16 15:30:48 +09:00
kimandClaude Sonnet 5 edd7816048 v4.1.12: 보안 취약점 수정 — RCE, 경로탈출 2건, IDOR, XSS(스튜디오/언어 앱)
- [CRITICAL] image_edit/imagegen 도구의 숫자 파라미터(x,y,width,height,degrees,opacity,quality,seed,guidance_scale,num_frames,fps)가 검증 없이 Python 소스에 직접 문자열 삽입되어 원격 코드 실행 가능했음. toFiniteNumber()로 전 지점 강제 숫자 변환 — 실제 페이로드로 라이브 검증 완료
- [HIGH] imageStyleTransformTool과 /api/imagegen/save-result에 경로 탈출 방어(isPathInsideDir) 누락 — 다른 사용자 워크스페이스/임의 파일 접근 가능했음. 둘 다 수정 후 실제 ../ 페이로드로 차단 확인
- [HIGH] 언어 앱 진행상황 저장 API가 URL의 :userId를 그대로 신뢰해 다른 사용자 진행상황을 읽고 덮어쓸 수 있었음(IDOR). 세션 기반으로 수정, 실제 다른 사용자명으로 테스트해 본인 워크스페이스에만 저장됨을 확인
- [MEDIUM] 언어 앱 플래시카드·단어장 렌더링(LLM 생성 콘텐츠)이 이스케이프 없이 innerHTML에 삽입되던 XSS 경로 수정(escHtml 추가)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 15:04:20 +09:00
kimandClaude Sonnet 5 5b089ac297 v4.1.11: 뉴스 전용 도구 신설(NewsData.io) + 검색 루프/설정 버그 수정
- news_search 도구 신설(NewsData.io /latest API) — 과거 48시간 실시간 뉴스, 국가/언어/카테고리 필터, 실제 pubDate·출처 포함. 뉴스 요청엔 web_search보다 우선 사용하도록 시스템프롬프트·강제재시도 넛지 전부 갱신 — 위키피디아 연도페이지·날짜 오라벨링 문제가 구조적으로 해결됨
- 검색예산(5회) 차단 후에도 모델이 무시하고 계속 재시도하는 문제 수정 — "오늘 남미 주요 뉴스" 요청에서 실제 검색 6회 후 42라운드가 전부 헛되이 낭비된 사례 확인(TOOL[48]까지 감). 두 번째 차단부터는 해당 턴 나머지 동안 모델에게 tools를 빈 배열로 보내 물리적으로 더 이상 호출 못 하게 함
- OpenWeather 도시명 모호성 버그 수정 — "Rome, Italy"가 미국 조지아주 Rome으로 잘못 resolve되던 문제. 국가명→ISO코드 자동 정규화(40여개국) + 국가 불일치 시 에러로 재시도 유도
- SearXNG general 카테고리에 뉴스 아닌 위키피디아 엔진이 섞여있던 문제 수정 — 뉴스 쿼리는 categories=news로 daum_news/yahoo_news 등 뉴스 전용 엔진만 사용하도록 변경(사후 필터링 아닌 근본 차단)
- 설정 화면에서 모델 전환 시 models.fallback/profiles가 매번 사라지던 버그 수정 — /api/settings/model 저장 로직이 models 객체를 통째로 새로 만들어서 덮어쓰던 것을, 기존 값을 먼저 펼친 뒤 필요한 필드만 덮어쓰도록 변경
- news.newsdata_api_key를 SECRET_FIELD_MAP에 추가해 vault 자동 암호화 대상에 포함(평문 미저장)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 14:25:14 +09:00
kimandClaude Sonnet 5 a5fb92d477 v4.1.10: 웹검색/도구호출 신뢰성 대개선 — 모델별 프로필 시스템 도입
- AUTO-RECOVER 구조적 허점 수정: "라운드 0 & 도구 0회 호출"일 때만 발동하던 걸 "이 요청에 필요한 도구가 아직 안 불렸으면" 언제든 발동하도록 변경 — 엉뚱한 도구 하나만 불러도 안전장치가 통째로 무장해제되던 버그 수정
- 뉴스/날씨/스펙·가격·비교 등 팩트성 질문에 도구 호출 강제(isLiveDataRequest/isFactualInfoRequest) — 확신에 차서 지어내는 것(mistral-large-3에서 다발, 없는 "2026 파리 올림픽" 등)을 사전 넛지+사후 강제재시도로 이중 차단
- web_search/web_fetch 턴당 5회 하드캡 추가 — kimi-k2.6이 단순 뉴스요청에 최대 50회까지 검색하던 문제 차단
- 모델이 함수 호출 대신 텍스트로 tool call을 흉내내는 케이스(`web_search{...}`, 반복시 토큰 열화로 `웍웍웍_search`, 가비지 토큰 삽입 `web_search Räikk{...}`) 복구 로직을 브레이스 앞 텍스트에서 실제 도구명을 찾는 방식으로 일반화
- 뉴스 검색: 대화 이력 주제로 새는 것 방지, 국제뉴스는 영어 쿼리 사용, 위키/홈페이지뿐인 저품질 결과는 다음 provider(tavily 등)로 폴백, 기사 실제 게재일 라벨링(오늘 날짜로 잘못 표기 금지)
- email_send/kakao_send_message 실제 호출 없이 "보냈습니다"라고 답하면 강제 재시도
- browser_open: image_edit와 동일하게 명시 요청 없으면 코드 레벨 차단(기존엔 프롬프트 텍스트뿐)
- config.json models.profiles로 모델별 시스템프롬프트 추가지침 주입 가능(코드 재배포 없이 모델별 이상행동 교정)
- ollama-client 모델 fallback 재시도를 quota 초과 외 retired/deprecated 에러까지 확장, models.fallback 값 유지
- 각종 인텐트 판별 함수(브라우저/데스크톱/실행형 요청, 백그라운드 작업 재개/취소/상태질문)에 한국어 키워드 커버리지 추가
- shell 툴 스키마 예시와 PACKAGE INSTALL 프롬프트 규칙의 모순(pip install 예시 vs 금지 규칙) 제거

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 12:58:57 +09:00
kimandClaude Sonnet 5 2228aedbf7 v4.1.9: 스튜디오 이미지 편집·저장 플로우 + 음성엔진 정리 + GPU 게이지 분리
- 스튜디오 앱: 사진 편집(스타일 변환/이모티콘 세트) + 결과 뷰어 내 크롭/회전/필터/보정/텍스트 오버레이 편집 툴바 + 저장 플로우(중간 편집은 갤러리에 안 남기고 최종본만 저장+업로드 목록에 재사용 등록)
- image_style_transform: SDXL img2img + IP-Adapter-FaceID로 cartoon 스타일 추가 (watercolor/sketch는 identity drift로 재검토 후 제외)
- 음성엔진 provider 값 xtts_gpu → omnivoice_gpu로 리네이밍 (실제 로딩 모델과 이름 일치, XTTS는 이미 OmniVoice로 교체된 지 오래)
- 메인창 사이드바 GPU 게이지를 GPU0/GPU1로 분리 표시
- 단종된 gemini-3-flash-preview를 기본 모델값에서 전부 제거, kimi-k2.6:cloud로 교체
- vault 백업을 cron→systemd timer(Persistent=true)로 전환, /DATA 전체 동기화 스크립트 추가

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 18:16:20 +09:00
kimandClaude Sonnet 5 88bad1e7d9 v4.1.8: 이미지/동영상 생성 스튜디오 앱 + SDXL/FLUX 품질 개선
- 이미지·동영상 생성 전용 앱(studio-app.html) + API 라우트 추가, 갤러리 기능 포함
- SD1.5 → SDXL 교체 (프롬프트 반영력/해상도 개선), 한글 프롬프트 자동 영어 번역 추가
- image_generate에 quality="high" 옵션 추가 (FLUX.1-schnell 4비트 양자화, 게이트 없는 커뮤니티 미러 사용)
- video_generate에 guidance_scale 노출, 기본 steps 상향
- 생성기 서브프로세스가 결과 없이 죽는 경우의 크래시 방지 + 에러 로깅 강화
- 멀티 GPU 환경에서 시스템 통계 GPU 미터가 깨지던 nvidia-smi 파싱 버그 수정

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 02:38:58 +09:00
kim 2427aeeaba v4.1.7: SD1.5/LTX-Video 로컬 이미지·동영상 생성 툴 추가
image_generate(SD1.5), video_generate(LTX-Video)를 전용 venv+GPU1에서
구동하는 채팅 툴로 추가. image_edit과 구분되도록 시스템 프롬프트에
사용 규칙 명시.
2026-07-14 20:42:42 +09:00
kimandClaude Sonnet 5 2f690fd999 v4.1.6: SMILES 구조식 위젯 교과서식 개편 + 화학표기 규칙 추가 + 코드블록 렌더링 버그 수정
- SMILES 위젯을 버튼 클릭식 큰 위젯 → 자동렌더링 소형 인라인(교과서식)으로 전면 개편
- 링크/이미지/볼드 등 후속 정규식이 SMILES 입체화학 표기([C@@H](C) 등)를 마크다운 링크로
  오인해 구조식이 깨지던 버그 수정 (코드블록 결과물을 플레이스홀더로 보호 후 최종 복원)
- 구조 복잡도(중원자 수)에 따라 SMILES 캔버스 크기 동적 조절 (벤젠은 작게, 콜레스테롤 등은 크게)
- SMILES 위젯 테두리/배경/여백 제거로 더 가벼운 인라인 표시
- 코드블록(.md-code-block) 검은 배경 제거 + 고정폭 폰트 누락으로 ASCII 다이어그램이
  틀어지던 버그 수정 (font-family 미지정 → 본문 가변폭 폰트 상속이 원인)
- code.trim()이 전체 문자열 기준으로만 동작해 ASCII 아트 첫 줄의 들여쓰기만 사라지던
  버그 수정 (줄 단위가 아닌 blank 줄만 제거하도록 변경)
- 시스템 프롬프트에 CHEMISTRY NOTATION 규칙 추가 (ASCII 아트 금지, LaTeX/mhchem·SMILES 사용 유도)
- Ollama Cloud 일시적 오류(5xx/타임아웃) 발생 시 즉시 실패 대신 백오프 재시도 추가
- weather_map_screenshot 툴을 ToolRegistry에도 등록 (buildImageMarkdown export 추가)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 15:18:23 +09:00
kimandClaude Sonnet 5 c8b4e251bf v4.1.5: KaTeX 수식·화학식 렌더링 + SMILES 2D 구조식(결합선) 추가 + 코드블록 이스케이핑 버그 수정
- KaTeX self-host (vendor/katex) 추가, $...$/$$...$$ 자동 렌더링 + mhchem 확장으로
  \ce{C4H10} 같은 화학식·반응식 표기 지원 (renderKatexIn, renderChatMessages 후처리)
- SmilesDrawer self-host (vendor/smiles-drawer) 추가, ```smiles``` 코드블록으로 SMILES
  표기를 실제 결합선 있는 2D 구조식으로 렌더링. 라이브러리의 Drawer(canvas) 클래스가
  내부 svgWrapper null 참조로 깨지는 버그가 있어 SvgDrawer로 우회
- 진짜 원인 버그 수정: escHtml()가 백틱(`)/백슬래시/달러도 이스케이프하는데, 코드블록·
  인라인코드 정규식이 이스케이프 *이후*에 원본 백틱을 찾고 있어 애초에 매치가 안 됐음
  — tradingview 차트·네이버 주식차트·MIDI 위젯 등 기존 기능도 전부 이 버그로 작동 안
  하고 있었고, 이번에 같이 고쳐서 정상 작동 확인

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 12:35:33 +09:00
kimandClaude Sonnet 5 4526de2914 v4.1.4: 메인챗 무한 스피너 버그 수정 + SSE 스톨 자동복구
- 진짜 원인: partialContent가 try{} 블록 안에서 let 선언돼 catch{}에서 참조되던
  스코프 버그. fetch abort/에러 시 catch 블록 자체가 ReferenceError로 죽어서
  뒤따르는 정리 코드(isThinking=false 등)가 전혀 실행되지 않고 스피너가 영원히
  돌았음(직접 재현 확인). 선언을 try 밖으로 이동해 해결
- SSE 스톨 워치독 추가: 45초간 스트림에 아무 데이터도 없으면 자동 abort 후
  세션 히스토리를 재조회해 서버가 이미 완료·저장한 응답이 있으면 복구 표시,
  없으면 재시도 안내. 방금 보낸 사용자 메시지(fullMessage, 내용을 정확히 아는
  값)를 기준점 삼아 뒤에서부터 매칭 — AI 응답 내용 추측/비교보다 안정적
- 부수 개선: 이메일 첨부 SSE 파일 링크 푸시 로직 등 기존 코드는 변경 없음

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 11:31:52 +09:00
kimandClaude Sonnet 5 30db2a0a48 v4.1.3: 투자앱 시작화면 XLK 차트 자동표시 + 언어앱 타일뷰 발음 버튼 추가
- 투자앱 시작 시 빈 차트 대신 XLK(기술주 섹터 ETF) TradingView 차트를 바로 띄우도록 변경
- 언어앱 플래시카드 타일 그리드 뷰에 🔊 발음 듣기 버튼 추가 (기존엔 로마자 발음
  표시만 있고 TTS 버튼이 빠져있었음) — 단일 카드 뷰와 동일하게 카드 중앙 하단에 배치,
  클릭 시 카드가 뒤집히지 않도록 stopPropagation 처리

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 10:38:19 +09:00
kimandClaude Sonnet 5 1f112fd227 v4.1.2: 기상도(Windy) 캡처 화질 개선 + 지도 읽는 법·좌표·태풍 트리거 추가
- weather_map_screenshot 캡처 해상도 900x620→1280x880, PNG→JPEG(품질90)로 변경.
  300KB 넘으면 vision 파이프라인이 600x600으로 강제 축소하던 걸(server-v2.ts
  resolveToolImageContent) 파일 크기를 낮춰서 회피 — 지명·기온 숫자가 선명해짐
- 기상전문가 프롬프트에 lat/lon을 서울로 고정 복사하지 않고 실제 언급된 지역
  기준으로 치환하도록 명시 + 주요 도시 12곳 좌표표 추가
- 오버레이 9종(바람/강수/기온/구름/기압/대기질/레이더/적설/파고)별 색상 범례
  해석 가이드("지도 읽는 법") 추가 — 이미지는 받아도 읽는 법이 없어 해석이
  부실했던 문제
- "태풍" 계열 단어를 Windy 지도 트리거에 추가(기존엔 없어서 뜨는 게 랜덤했음)
  + 태풍 요청 시 좌표를 먼저 검색해 그 위치로 지도를 센터링하도록 지시

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-13 22:47:43 +09:00
kimandClaude Sonnet 5 c1d72a2a2d v4.1.1: weather_map_screenshot 연결 + 언어앱 카드생성 버그 수정 + 상담앱 심리검사 5종 추가
- weather_map_screenshot 툴이 코드(weather.ts)·레지스트리엔 있었지만 buildTools()
  스키마가 없어 모델이 호출 자체를 못 하던 걸 연결. 날씨앱(wt_ 세션) 전용으로 게이팅
- 언어앱 "AI 카드 생성"이 실제로는 0장을 반환하던 버그 수정 — config.json 모델이
  kimi-k2.6:cloud(추론모델)로 바뀌면서 num_predict가 너무 작아 생각(thinking)만 하다
  토큰을 다 쓰고 실제 답변을 못 내놓고 있었음. think:false + num_predict 상향으로 해결
  (generate-flashcards/generate-lesson/check-answer 3개 API 모두 동일 수정)
- 언어앱 플래시카드에 타일 그리드 뷰 추가 — 카테고리 카드 전체를 한번에 펼쳐보고
  개별 탭으로 뒤집어볼 수 있음
- 상담앱 심리검사를 7종 → 12종으로 확장: PCL-5(PTSD), MDQ(양극성), OCI-R(강박),
  ASRS-6(성인ADHD), SPIN(사회불안) 추가. PHQ-9 9번 문항(자살/자해 생각) 안전장치를
  안내문 한 줄에서 결과화면 상단 위기상담 배너로 강화

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-13 21:46:18 +09:00
kimandClaude Sonnet 5 b969c672b0 v4.1.0: 메인챗 툴/시스템프롬프트 오버헤드 66% 감소 + 실시간 컨텍스트 게이지
- 2개월 tool_audit.log 실사용 확인 후 미사용 에이전트 툴(start_task 등)과
  포트 9222 연결실패로 고장난 브라우저 툴을 메인챗에서 제외
- 날씨/법률/논문 툴을 스킬+키워드 조건부로 전환, dental/mind 전용 MCP DB
  24개를 해당 앱 세션(dental_/mn_)에만 스코핑, weather/lawyer 앱 세션은
  스킬·키워드와 무관하게 항상 포함되도록 별도 처리
- 위 변경으로 메인챗 고정 오버헤드 24,439 → 8,169 토큰(-66%) 실측 확인
- tool_overhead SSE 이벤트를 모델 호출 전에 전송해 세션 게이지가 중단된
  턴에서도 툴 스키마+시스템프롬프트 크기를 반영하도록 수정 (app.js)
- 부수 수정: heartbeat 세션을 lastMainSessionId 폴백에서 완전 격리(다른
  세션 기록 오염 방지), webSearch 빈 결과를 실패로 오판하던 버그 수정

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-13 01:09:27 +09:00
kimandClaude a11e554e88 feat: web_search·ollama_web_search 폴백 체인 통일 + ollama_web_search 설명 정정
searchForSynthesis가 executeWebSearch에 위임하도록 재작성 — 두 툴이 동일한
6-provider 체인(searxng→ollama_cloud→tavily→google→brave→ddg→ddg_html) +
빈결과가드(21367ea) + 이벤트 보강을 공유. 이전엔 ollama_web_search가
searxng→ollama_cloud→ddg→ddg_html만 거치고 tavily/google/brave를 스킵하는
분리된 체인이었음(API 키가 없어 잠복 상태로 남아 있던 구멍).

ollamaWebSearchTool 설명이 "Ollama 모델이 DuckDuckGo 웹 검색을 수행"이라
적혀 있던 것을 실제 동작에 맞게 정정 — 코드가 먼저 폴백 체인으로 검색하고
Ollama chat API(config의 ollama.endpoint+model)는 요약만 담당. 모델은 검색을
직접 수행하거나 검색 여부를 결정하지 않음(환각 방지). 모델명처럼 변하는 값은
하드코딩하지 않고 config 참조로만 기술.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-12 15:19:38 +09:00
kimandClaude Sonnet 5 20f0db935a fix: web_search 폴백 체인이 빈 결과를 성공으로 오판하던 버그 수정
executeWebSearch()가 provider 호출이 예외를 던지지 않으면 결과가
0건이어도 "성공"으로 간주하고 그 자리에서 반환해버려, 뒤에 있는
(더 잘 작동할 수도 있는) provider로 넘어가지 못했음. 오늘 시어엔진이
bing 타임아웃으로 0건을 반환했을 때 ollama_cloud가 멀쩡히 있었는데도
전혀 시도되지 않은 게 이 버그 때문이었음.

- SearchProviderAttempt에 'empty' 상태 추가 (성공했지만 결과 없음)
- 각 provider 호출 후 실제 결과 개수를 확인해서 0건이면 다음
  provider로 계속 진행하도록 수정
- 전부 empty/failed로 끝나면 하드 에러 대신 가장 처음 나온 "성공했지만
  빈 결과"를 우아하게 반환 (기존엔 여기까지 오면 무조건 에러)
- ddg를 candidates 맨 뒤로 재배치 — Instant Answer API는 구조적으로
  일반 검색을 지원 안 하고, HTML 스크래핑 폴백은 현재 이 서버 IP에서
  DuckDuckGo 봇탐지에 막혀있어 거의 항상 빈손임 (html.duckduckgo.com,
  lite.duckduckgo.com, duckduckgo.com 전부 확인함)
- 중복되던 6개의 거의 동일한 provider 분기를 runProvider() 디스패치
  헬퍼 하나로 통합

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 00:27:56 +09:00
kimandClaude Sonnet 5 e356573228 feat: 웹검색에 Ollama Cloud API 폴백 추가 + ollama_web_search 이중화
- searchOllama()를 예전 tool_calls 방식에서 "코드가 검색 먼저 실행 →
  모델은 결과만 요약" 방식으로 교체 (모델이 검색 스킵하고 환각 답변하던
  버그 수정)
- ollama.com/api/web_search 기반 새 provider(ollama_cloud) 추가,
  web_search 폴백 순서: searxng → ollama_cloud → ddg → tavily →
  google → brave
- web_search와 ollama_web_search가 searchForSynthesis() 공통 헬퍼로
  같은 폴백 체인을 공유하도록 통합 (기존엔 ollama_web_search가 DDG
  단일 의존이라 SearXNG 이중화 혜택을 못 받았음)
- search.ollama_api_key 설정 필드 추가 (config.json, types.ts,
  settings.ts REST 라우트). 실제 키 값은 vault:search.ollama_api_key
  참조로 저장 — 평문은 config.json에도 git 히스토리에도 남기지 않음
  (.smallclaw/vault/ AES-256-GCM 암호화 저장소, gitignore 대상)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 00:08:20 +09:00
kimandClaude Sonnet 5 cec930c69c fix: 음성통화 STT 잡음/겹침 목소리 환각 완화
no_speech_prob가 높은 세그먼트를 텍스트 조합에서 제외하고
hallucination_silence_threshold를 걸어, 배경 소음이나 다른 사람
목소리가 섞였을 때 엉뚱한 텍스트가 연속으로 나오는 문제를 완화.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11 02:04:20 +09:00
kimandClaude Sonnet 5 64f7e5ec3b fix: TTS 발음/타이밍 대규모 개선 (숫자, 단위, 방위, 줄바꿈 pause)
- 숫자를 완전한 한글 표기로 변환 (사이노-한국어 기본, 시각은 순우리말)
- °C/°F/%/m/s/mm/km 등 단위를 한글로 스펠아웃
- 괄호 앞뒤 pause 강화, 방위 약어(SSW 등) 한글 변환
- 마크다운 표/리스트를 줄바꿈 전에 분할 후 정제하도록 파이프라인 재설계
- 구조적 개행(리스트/표 셀) 유래 조각은 병합 금지, 대화체 문장만 병합
- 소수점(27.7) 오탐 문장경계 버그 수정
- num_step 16, speed 1.15로 튜닝 (품질 손실 없이 생성속도 개선)
- 대기열 위치 표시 (tts_queue 메시지)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 16:39:46 +09:00
kimandClaude Sonnet 5 adfa136597 fix: TTS 중첩클릭 에코 버그 + 음성엔진 한/영 발음 개선 + 생성속도 2배
- web-ui: 🔊 버튼 연타/중첩 클릭 시 이전 요청이 완료되면서 새 요청과 오디오가
  겹쳐 재생되던 버그 수정 (playTTSText/playTTSMsg를 _ttsPlay 공용 코어로 통합,
  AbortController + 활성 버튼 가드로 stale response의 재생을 원천 차단)
- voice.tts.provider를 edge_tts(ko-KR-SunHiNeural)에서 xtts_gpu로 전환 —
  실제로는 실시간 통화와 동일한 GPU 엔진(OmniVoice)을 타서 영어 섞인 문장의
  발음이 훨씬 자연스러워짐
- voice_engine.py: OmniVoice num_step 기본값을 32→16으로 낮춤. STT 왕복
  검증으로 실측: ~1.9배 빠른 생성(2.94s→1.55s), 품질 저하 없음(8은 문장이
  깨져서 폐기). 텍스트 버튼/실시간 통화 양쪽에 공통 적용됨

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 14:42:44 +09:00