- All skill toggles are now per-user (except multi-agent-orchestrator
which remains global). Admin toggle without a target username defaults
to their own per-user state instead of the global file.
- GET /api/skills defaults to the requesting user's own state (previously
returned global state when no ?username= param was given).
- Add SkillsManager.initUserSkillsState(): creates per-user
skills_state.json from global defaults if missing — called on user
creation and on every login as a safety net for existing accounts.
- Create initial per-user skills_state.json for cherry and jasmine.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New skill:
- .smallclaw/skills/meteorologist/SKILL.md — 기상 전문가 스킬 (Windy iframe 규칙 포함)
New weather tools (src/tools/weather.ts):
- weather_airpollution: OpenWeather 대기질 (AQI, PM2.5/PM10/O3/NO2)
- weather_openmeteo: Open-Meteo 시간별 예보 (ECMWF/GFS, 키 불필요)
- weather_kma: 기상청 공식 API (초단기실황·단기예보)
- weather_airkorea: 에어코리아 실시간 대기질
- weather_nasa_power: NASA POWER 기후 데이터 (MERRA-2, 키 불필요)
- weather_era5: ERA5 재분석 과거 데이터 (Open-Meteo Historical, 키 불필요)
- weather_cds: Copernicus CDS 정식 API (ERA5·CMIP6 SSP 시나리오)
- weather_cmip6: CMIP6 기후 모델 (Open-Meteo Climate API, 키 불필요)
Scripts:
- scripts/era5_cds_fetch.py — CDS/CMIP6 Python 헬퍼 (ZIP→NetCDF 처리 포함)
web-ui:
- Windy URL → iframe 자동 렌더링 (standalone URL + 마크다운 링크 모두 감지)
- windyToEmbedUrl: windy.com comma 형식 URL 파싱 개선
server-v2.ts:
- BROWSER RULE: "열어줘" 제거 → 오용 방지
- weather context: 9개 도구 선택 기준 추가
- JSON schema 8개 추가
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
These skills only added prompt instructions — no gateway tools or
unique capabilities. The system prompt already covers their domains.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Remove blanket regex that stripped ALL image markdown from AI responses,
which was breaking dental-dict images. The [IMAGE COMPLETE] prompt reminder
already tells the model not to duplicate image_edit/image_read results.
- Remove coder skill (SKILL.md)
- Remove dental-dict skill (now handled by MCP server description alone)
- Remove broken external URL for 볼튼분석 (Open-i link dead)
- investor skill enabled in skills_state
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Fix settings save bug: primaryModel captured before _modelSettingsLoaded guard → wiped model roles when models tab not opened
- Fix server: filter empty-string roles before saving to prevent role wipe
- Add Voice and Session settings tabs to UI
- Add OpenWeather API key field to Credentials tab
- Add GET/POST endpoints: /api/settings/voice, /api/settings/session, /api/settings/openweather
- Fix Mistral parallel tool calls: model embeds tool calls as text instead of tool_calls array; parseEmbeddedToolCalls() detects and converts
- Add Anthropic provider adapter (anthropic-adapter.ts)
- Weather tool vault key resolution fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
사이드바에 💻 코드 탭 추가:
- Monaco Editor (vs-dark/light 테마 자동 연동)
- 파일 탭 관리 (새 파일, 전환, 닫기), Ctrl+S 저장
- 오른쪽 AI 채팅 패널 (Coder 세션, SSE 스트리밍)
- "선택 코드 → AI 전송" 버튼
- "▶ 실행" → 하단 터미널 패널로 명령 전송
- 에디터/AI 패널 수직 드래그 리사이즈
- 스킬 탭 이모지 버그 수정 (조건 반전, 커스텀 이모지 표시 안 되던 문제)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
풀스택 시니어 엔지니어 어시스턴트:
- 도구: python_eval, bash_eval, file_read/write, web_search
- 코드 실행 후 결과 검증 원칙
- 공식 문서 우선 참조 사이트 (MDN, PyPI, React, FastAPI 등)
- 코드 리뷰 체크리스트 (보안→정확성→성능→가독성)
- Python/JS/백엔드/DB/DevOps 언어별 핵심 포인트
- skills_state.json에 coder: true 등록
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- investor skill: TradingView 실시간 주가 차트 렌더링 지원
- ```tradingview SYMBOL|INTERVAL``` 블록 → 차트 위젯 자동 생성
- JSON 형식 출력 시 HTML 언이스케이프 후 파싱 (symbol/interval 추출)
- renderTVChart(): tv.js 동적 로드, 다크/라이트 테마 연동, RSI·MACD 기본 포함
- musician skill: MIDI 다운로드 사이트 4개 추가 (freemidi, bitmidi, piano-midi, midiworld)
- MIDI 탭 닫기 버그: window.open에 noopener,noreferrer 추가
- beforeunload/pagehide 시 midiRouter.stop() 호출
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- music-renderer: saveMidiFile export (JSON, no LilyPond), getRenderFile prefers original.midi, fix self-copy bug
- server-v2: POST /api/music/midi now saves to workspace/music/<name>/ and returns JSON immediately; new SSE endpoint /api/music/midi-score for on-demand LilyPond
- index.html: buildMidiPickerWidget with color-coded buttons (green/purple/amber), MIDI download moved inside player tab, score panel default closed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- web-ui/midi-editor.html: full piano roll MIDI editor (new tab)
- all tracks simultaneously, color-coded per channel
- note add/delete/move/resize, multi-select, copy/paste
- velocity lane, track panel (mute/solo/instrument), undo/redo
- GM reset + bank select on playback, MIDI output device select
- export to .mid, open via ?url= param or file picker
- web-ui/index.html: add ✏ 편집 button to MIDI widget (opens editor)
- GM SysEx reset + bank select before note playback
- 200ms note delay for synth init time
- getRenderFile: prefer original.midi over LilyPond output.midi
- src/gateway/music-renderer.ts: getRenderFile returns original.midi first
- LilyPond SVG render overwrites output.midi (no Program Changes)
- original.midi preserved from upload, served via /api/music/file/:id/midi
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- session.ts: Replace fixed maxMessages limit with token-based trimHistory;
resolveNumCtx() now queries Ollama API for actual model context length (cached).
maxMessages raised to 2000 as safety ceiling only.
- session.ts: Boot sessions (boot-*) never saved to disk — ephemeral by design.
- session.ts: New sessions not written to disk until first message is added.
- session.ts: Add cleanupEmptySessions() called at startup to auto-remove empty files.
- session.ts: migrateGlobalSessionsToUser() deletes global original after copying to user dir.
- server-v2.ts: Call cleanupEmptySessions() at startup.
- server-v2.ts: User creation API accepts optional telegramId for immediate channel mapping.
- config.json: Remove explicit maxMessages (now uses dynamic token-based default).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace piper TTS with edge-tts (Microsoft neural Korean voice)
- piper ko_KR-kss-medium uses pygoruut phoneme type unsupported by C++ binary,
causing Chinese-sounding output; edge-tts solves this via online neural TTS
- Added src/tools/edge_tts_synth.py Python helper script
- Server TTS endpoint now dispatches by provider (edge_tts vs piper)
- Config updated: voice.tts.provider = "edge_tts", voice = "ko-KR-SunHiNeural"
- Add TTS toggle switch to web UI (chat input bar)
- Toggles visibility of all 🔊 buttons and stops active playback
- State persisted in localStorage (default: on)
- Mic input now auto-submits after speech recognition completes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- STT: Replace MediaRecorder+Whisper with browser Web Speech API (ko-KR)
Whisper base model hallucinated English for Korean speech; Chrome's
built-in Google STT is far more accurate for Korean
- TTS: Skip ffmpeg OGG conversion, return WAV directly from Piper
Avoids OGG/Opus codec compatibility issues in browsers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- POST /api/voice/stt: Whisper-cpp transcription of webm/ogg audio
- POST /api/voice/tts: Piper Korean TTS returning ogg audio
- Web UI: 🎤 mic button in chat input; click to start/stop recording
MediaRecorder → /api/voice/stt → auto-fills chat input
- Web UI: 🔊 TTS button on each AI message; click to play/stop
- config.json: add absolute model/binary paths for whisper-cli and piper
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Luckysheet modal: 8-direction resize handles (edge + corner), title bar drag-to-move
- First drag/resize converts from flex-centered to absolute positioning
- Minimize/close reset to centered state on reopen
- New xlsx-viewer.html: standalone Luckysheet page for opening xlsx in separate window
- Added "↗ 새 창" button on xlsx cards to open viewer in a resizable popup window
- Viewer shares session cookies so auth works transparently
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Skills:
- Add accountant (CPA) and investor (CFA) skills with site: hints
- Add site: hints to lawyer, psychiatrist, musician skills
- Allow multiple skills active simultaneously (remove exclusive mode)
Tools:
- Add excel_read / excel_write tools (openpyxl-based)
- Fix python_eval packages: retry with --break-system-packages on PEP 668 failure
- Fix email_read: spaces→underscores in filenames, return /api/files/ links,
remove absolute savedPaths from data, send SSE 'files' event for attachments
Server:
- FILE_OP v2: fall through to primary when secondary model unavailable
- Add PUT /api/files/{*filePath} endpoint for xlsx editor save
UI:
- xlsx viewer: Luckysheet modal (lazy CDN load, ~3MB on first use)
with edit mode, 💾 save button, Nanum Gothic font
- Email attachment preview: SSE 'files' event appends file links to final reply
- ✏️ 편집 button (blue) for xlsx cards
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
스캔 PDF에서 텍스트 추출 실패 시 자동으로 OCR 실행.
PyMuPDF로 300DPI 이미지 렌더링 후 tesseract kor+eng 적용.
ocr: true 파라미터로 강제 OCR 가능. method 필드로 추출 방법 표시.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
사용자가 업로드한 PDF는 이미 갖고 있으므로 저장 버튼 불필요.
renderMarkdown/renderLinkButton에 hideDownload 옵션 추가,
유저 메시지 렌더링 시 적용. 미리보기 버튼은 유지.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
스캔 악보 PDF 처리 절차 추가:
pdf_read 시도 → 실패 시 pdf_extract_images로 페이지 추출 → image_read로 시각 분석.
도구 목록에 pdf_extract_images, image_read 추가.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Settings that were silently lost on reinstall:
- Track .smallclaw/heartbeat/config.json (active hours 8-22, interval 30m)
- Track .smallclaw/skills_state.json (multi-agent-orchestrator enabled)
- Fix gitignore: heartbeat/ → heartbeat/runs/ (only ignore run logs, not config)
- Fix gitignore: remove skills_state.json from ignored list
Vault (contains channel tokens, passwords) cannot go in git — instead:
- Add scripts/backup-vault.sh: backs up vault+credentials to ~/.smallclaw-backup/
keeping last 5 snapshots. Run manually or via cron (0 3 * * *).
- Run initial backup now → ~/.smallclaw-backup/vault_20260518_232441
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When no explicit output path is given and source is JPEG/WebP, output
defaults to PNG (lossless). This avoids cumulative quality loss on
repeated edits (brightness → contrast → filter → ...).
Exception: 'convert' operation keeps the original format so explicit
format-change requests still work. Explicit output path always honored.
Also fix quality default mismatch: TS params was 85, Python was 92.
Now both are 92 for when JPEG/WebP output is explicitly requested.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add per-user session/workspace paths to .gitignore so runtime data
(sessions, uploads, memory, attachments, pubmed) is no longer tracked
- Narrow ollama_web_search description to prevent it being chosen over
web_search for news/info queries — it's now explicitly a fallback only
- Add scripts/install-image-deps.sh to install Pillow/torch/rembg deps
- Remove stray root files (1, pdf-pptx.txt, eng.traineddata)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Korean search keywords to WEB category (뉴스, 검색해, etc.) so
Korean news queries trigger web_search instead of ollama_web_search
- Show ✓ SearXNG in startup banner when searxng_url is configured
- Update dental dict databases scripts and DB
- Clean up stale sessions and workspace runtime files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
image_edit:
- speech_bubble operation with Korean font, rounded rect, tail
- sketch quality: CLAHE pre-processing for better line contrast
- output filename with timestamp to prevent overwrites
- anime/painting stylize timeout 30s→600s (AnimeGANv2 model download)
- remove_bg PNG output fix
server-v2.ts:
- resolveToolImageContent: embed edited image as base64 in tool results
so vision models can see the output (3 execution paths covered)
- _activeModelName: fix vision support detection for Ollama-hosted models
(kimi/gemini run via Ollama — provider='ollama' was masking vision capability)
- Synthetic tool call ID generation to prevent Gemini function_response empty name error
- image_edit path hint format changed to English to prevent Gemini hallucination
- userRequestedImageEdit: expanded keyword list (풍선, 달아, 붙여 등)
- image_read OCR failure returns success:true with visual description hint
- TOOL_BLOCKS photo: image_edit workflow documentation updated
web-ui/index.html:
- renderFileDownloads: skip download buttons for image file extensions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reorganize .smallclaw/databases/ around a single entry point with
subcommands (add-terms / add-images / verify / reassign / stats),
absorb pmc_reassign.py into reassign, and route every image source
through inline vision-model verification before commit.
Layout
config.py paths, endpoints, API-key locations (no more
hard-coded absolute paths in source files)
manage.py argparse dispatcher
workflow_terms.py seed-JSON import (JSONC supported, dedupes on
korean/english)
workflow_images.py renamed from dental_image_workflow.py; main()
converted to run(verify=True, ...)
workflow_verify.py validate_image() / verify_db() + verify_updates()
gate used by every add-images source
seeds/ recovered seed_all.json, seed_periodontics.json
scratch/ ad-hoc work area replacing the /tmp habit
(only README.md is tracked)
docs/howto.md moved + expanded
docs/archive_image_rounds/ one-off round scripts + their results
docs/archive_validation/ model-comparison + validation history
Verification
- VERIFY_MODEL defaults to qwen3.5:397b-cloud (50-image test on
procedure-heavy sample: 9.8s/img avg, zero timeouts, Kimi-level
rigor — see archive_validation/).
- Prompt strengthened: in-image text/captions are not valid grounds
for "적합"; technique terms require visible procedure steps, not
generic device/anatomy photos.
- All 9 add-images sources gated through verify_updates() before
commit; --no-verify escape hatch for bulk runs.
.gitignore: API key files, dental_images/, __pycache__/, scratch/*
(README.md kept).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>