tests/ 디렉터리가 비어 있었고 package.json의 두 스크립트가 삭제된 파일을
가리킨 채 방치돼 있었음:
- test → tests/test-v2.ts (존재하지 않음)
- gateway → src/gateway/server-v2.ts (v4.3.5에서 삭제됨)
즉 npm test가 몇 달간 실행 자체가 불가능한 상태였고, 그 대가로 프롬프트 게이트
정규식을 고칠 때마다 node -e 임시 스크립트를 손으로 짜고 버리는 일이 반복됐음
(2026-07-29 하루에만 5회). 회귀 방지는 하나도 남지 않았음.
- Node 22 내장 러너(node:test) + tsx 사용, 테스트 프레임워크 의존성 없음
- tests/prompt-gates.test.ts (25) — 모델 동작을 강제/억제하는 정규식 게이트 전반
- tests/usage-log.test.ts (5) — Ollama 외 provider의 토큰 집계 단일 지점
- tests/README.md — 무엇을 왜 테스트하는지, 케이스 작성 규칙, 다음 확장 대상
- 전체 30개 통과, 0.6초
부수 성과 — 테스트가 실제 버그를 찾음:
케이스를 쓰면서 프로덕션 원문을 한 단어(GPU) 줄여 썼더니 실패했고, 그게 진짜
구멍이었음. "토큰 처리 속도 손실이 약 15%~25%"처럼 하드웨어 명사가 없는 처리량
날조는 SPEC_CONTEXT_KEYWORD에 걸리지 않아 그대로 통과하고 있었음 — 원문에
우연히 들어있던 "GPU" 덕에 잡히던 것. 토큰/대역폭/추론/처리속도를 키워드에
추가해 막고, 그 케이스를 테스트로 고정함(강수확률·할인율 오탐 없음 확인).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
파일별 다운로드(download 속성), 폴더 전체 zip 다운로드(archiver 신규
의존성 + /api/detective/files/download-folder 라우트) 추가. 사이드바에
법률 서식(대한법률구조공단)·법원 소송 서식(전자소송포털)·대법원 판례
검색(사법정보공개포털)·경찰청 링크 블록 신설.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- handle-chat.ts: excel/coder+shell/email/kakao/sqlite_query/image_edit/
image_read/run_command/news_search/pdf_*/schedule_job를 전용 앱 세션·
키워드·첨부 신호로 스코핑 (기존 weather/legal/pptx/dental/mind 패턴과
동일). 일반 대화 기준 도구 스키마 오버헤드 10,204→3,951 토큰(-61%)
- desktop_*(10개, Windows 전용) 완전 제외 — 이 리눅스 서버에서 전량
실패 확인(tool_audit.log), process.platform 체크라 윈도우 이전시 자동 복구
- 채팅 기본 num_predict 4096→6000 (사고형 모델 빈 응답 여유분)
- ollama-adapter.ts: 턴마다 prompt/completion 토큰을 token-usage.jsonl에
기록 (Ollama Cloud vs 종량제 API 비용 비교용)
- web-ui/js/ 25개 파일을 app/·code-editor/·voice/·music/·claude-app/
서브디렉토리로 재배치, 전체 참조 경로 갱신
- package.json build 스크립트에 dist 클린 단계 추가
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
오늘 분석에서 찾은 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>
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>
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>
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>
export {} 뿐인 빈 껍데기, 아무 곳에서도 참조 안 됨(reactor.ts +
orchestration/multi-agent.ts로 대체된 지 오래). 빌드/재시작 확인 완료.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- 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>
- 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>
- 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>
- 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>
- 메인 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>
- Project Gutenberg/Google Books/알라딘 검색 및 서재(EPUB) 보관
- 페이지 넘김 리더: 책 판형 비율 고정 페이지, 챕터 자동 새 페이지 시작,
단어/문단 경계 유지, 브라우저 창 크기와 무관한 고정 페이지 분량(스케일만 조정)
- Gutenberg 원문의 강제 줄바꿈을 문단 단위로 재조판(reflowHardWrappedProse)
- 서재에서도 바로 읽기 지원(다운로드 시 원문 URL 함께 저장)
- TTS 낭독(현재 페이지 기준)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- 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>
- 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>
- [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>
- 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>
- 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>
- 스튜디오 앱: 사진 편집(스타일 변환/이모티콘 세트) + 결과 뷰어 내 크롭/회전/필터/보정/텍스트 오버레이 편집 툴바 + 저장 플로우(중간 편집은 갤러리에 안 남기고 최종본만 저장+업로드 목록에 재사용 등록)
- 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>
- 이미지·동영상 생성 전용 앱(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>
- 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>
- 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>
- 진짜 원인: 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>
- 투자앱 시작 시 빈 차트 대신 XLK(기술주 섹터 ETF) TradingView 차트를 바로 띄우도록 변경
- 언어앱 플래시카드 타일 그리드 뷰에 🔊 발음 듣기 버튼 추가 (기존엔 로마자 발음
표시만 있고 TTS 버튼이 빠져있었음) — 단일 카드 뷰와 동일하게 카드 중앙 하단에 배치,
클릭 시 카드가 뒤집히지 않도록 stopPropagation 처리
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- 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>
- 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>
- 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>
- homeclaw 라이브 서비스를 /home/kim/homeclaw에서 /srv/homeclaw(480G 전용 파티션)로
컷오버, 하드코딩된 절대경로 전부 치환 (config, mcp-servers, routes, scripts, web-ui)
- Android 에뮬레이터 컨테이너 리소스를 32스레드 Xeon 기준으로 상향(3g/3cpu → 6g/10cpu)
- 코드 에디터에 USB 실기기 패널 추가: 기기 감지, APK 설치, Logcat, scrcpy 화면 미러링
(companion.py에 독립 프로세스로 scrcpy 스폰하는 로직 포함)
- 관리자 컨텍스트 뷰어에 차단된 IP 목록 탭 추가
- ollama primary 모델을 gemma4:31b-cloud로, 음성 TTS를 edge_tts로 전환
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
XTTS는 한영 혼용 발음이 깨지고(Zoom→쭘 등) 짧은 문장에서 rambling이 발생했음.
Qwen3-TTS로 교체해봤으나 realtime factor 0.3x로 통화에 쓰기엔 너무 느려서 폐기.
최종적으로 OmniVoice(k2-fsa)로 교체 — realtime factor 1.8~2.8x로 XTTS보다도
빠르고 한영 혼용 발음도 자연스러움.
voice-call.js에는 navigator.wakeLock 추가 — 폰 화면이 꺼지면 브라우저가
백그라운드 탭을 스로틀링해서 통화가 끊기는 문제를 방지.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Docker(budtmo/docker-android) + noVNC로 코드 에디터 하단 패널에 실제
조작 가능한 Android 에뮬레이터 화면을 띄운다. 세션 생명주기(생성/유휴
타임아웃/정리)는 기존 Arduino QEMU 라우트 패턴을 따르고, noVNC 화면은
Stirling-PDF 프록시와 같은 방식으로 게이트웨이를 통해 리버스 프록시한다.
- src/gateway/routes-android.ts: Docker 세션 관리 + noVNC HTTP/WS 프록시
- web-ui/android-emulator.html: 부팅 폴링 + noVNC 임베드 페이지
- code.js/code.html: "🤖 Android" 버튼, 기존 에뮬레이터 패널 재사용
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- USB CDC 경로 복원: #define Serial Serial1 우회 제거
- rp2040js/avr8js/codemirror/xterm/monaco-editor vendor화
- /vendor 정적 라우팅 추가 (Express 5 catch-all 우회)
- 부팅 완료 타임아웃 감지 (Serial 출력 없어도 8초 후 RAF 전환)
- 리셋 시 Simulator 재생성으로 주변 장치 상태 초기화
- 시리얼 패널의 내부 메시지를 console.log로 이동
- RP2040(Pico) 보드 감지·컴파일·에뮬레이션 지원 추가
- Serial → Serial1(UART0) 자동 리다이렉트 (#define 삽입)
- .uf2 파일 우선 추출, bootrom 자동 다운로드·캐싱
- ELF .text 추출: arm-none-eabi-objcopy 대신 Node.js 내장 파서
- HTTP 302 리다이렉트 자동 팔로우 (_httpsGetFollow)
- rp2040js 에뮬레이터: fast-path 초기화 루프, 피코 SVG 보드, GPIO25 LED
- 예외 처리: HardFault(#3)만 중지, 나머지 IRQ/SysTick 정상 통과
- UART onByte: TextDecoder stream 모드로 한글 UTF-8 정상 출력
- heartbeat 메시지 제거
- WiFi scan mock: WSCN 프로토콜로 C++ ↔ 브라우저 동기화, UI 편집 지원
- 에뮬레이터 팝업 → 코드 에디터 인라인 iframe 패널로 전환
- CDN 의존성 → /vendor/ 로컬 서빙 (xterm, Monaco)
- SSE 세션 idle timer (창 닫힘 후 5분 자동 종료)
- 업로드: 속도 자동 재시도(921600→460800→230400) + FlashMode fallback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- requestAnimationFrame → setTimeout(60ms): 패널 레이아웃 계산 후 xterm 초기화
- ptyReady 스냅샷 버그 수정: codeTermShells 대신 xtermInstances 참조
- 터미널 열릴 때 cls/clear 자동 실행 (Windows: cls, Linux: clear)
- companionPlatform 타이밍 버그 수정: clearCmd를 shell_ready 수신 후 평가
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 코드 에디터 저장: 서버 API → File System Access API로 전환
- codeSaveFileById에 저장 성공/실패/폴더미선택 피드백 메시지 추가
- 프로젝트 생성 형식: project-files JSON → @@FILE/@@ENDFILE 델리미터로 변경
- JSON 이스케이프 오류(Unterminated string) 근본 해결
- 계획 단계 시스템 프롬프트 강화: JSON 출력 절대 금지 명시
- 프로젝트 생성 세션 ID: 계획 세션 재사용 (서버가 history 파라미터 무시하므로)
- _projFileCreated async화: 파일 쓰기 완료 후 사이드바 리프레시
- 헤더/드롭다운 폴더명 표시 동적 업데이트 (workspace/code/ 하드코딩 제거)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The 💻 코드 sidebar tab now opens a dedicated code.html page in a new tab,
mirroring how the slide wizard opens pptx-wizard.html.
- Add web-ui/code.html: standalone code editor page reusing styles.css and
the same CodeMirror/xterm/Monaco head as the main app.
- Add web-ui/code.js: self-contained code-view logic — inlined shared helpers
(api/authHeaders/escHtml/getCookie) + the extracted code-editor block +
a bootstrap that inits Monaco and loads models/dir. It mirrors the code
block in app.js (kept duplicated so the main app stays untouched).
- index.html: tab-code now window.open('/code.html'). The in-page code mode
(top mode button) is unchanged, so chat→editor live streaming still works.
Verified with Playwright: Monaco initializes, editor/sidebar/toolbar/Coder AI
render, no JS errors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The slide editor draws a title slide's image as a full-bleed darkened
background, but pptx_gen.py's make_title_slide ignored image_path entirely
and only drew the skin background — so photo backgrounds showed in the
editor but vanished from the generated PPTX / preview.
- make_title_slide now renders image_path full-bleed (cover) with a dark
overlay and white title/subtitle, matching the editor preview.
- Add set_shape_fill_opacity() that injects OOXML <a:alpha>, since
python-pptx's fill.transparency is a silent no-op (the overlay was
rendering as fully opaque black). Apply it to the fullscreen bottom bar too.
- Pass project_dir/workspace_path/warnings into make_title_slide.
- Bump version to 2.8.2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Fix pptx-wizard slide editor modal opening off-screen (header clipped)
when a saved drag position is restored on a fresh page load: clear the
CSS centering transform and clamp coordinates into the viewport.
- Add pptx-wizard.html and python-runner.html web UIs.
- Bump version to 2.8.1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>