Commit Graph
87 Commits
Author SHA1 Message Date
kimandClaude Sonnet 4.6 edf2c39472 Release 2.9.4: PPTX wizard figure analysis + skill model trigger fix
- pptx-wizard: add "🔍 이미지 분석" button in Step 2 image panel
  * calls /api/pptx/analyze-image per figure via mistral vision
  * shows per-image progress (1/10, 2/10...)
  * "제외" caption → dimmed card + filtered from outline prompt
  * captions shown below each thumbnail in the grid
- server: POST /api/pptx/analyze-image endpoint
  * resolves /api/files/ path to workspace file, thumbnails if >300KB
  * calls orchestration.secondary vision model (mistral-large-3:675b-cloud)
  * caches results in project/.image-captions.json (skips on re-analysis)
- pptx-wizard: generateOutline() includes captions in imgList
  * "제외" images filtered out before sending to LLM
  * format: "/api/files/... (figure_p2_1) — 카플란-마이어 생존곡선 3그룹"
- skills-manager: fix getModelOverrideForUser() trigger filtering
  * was returning skill model for ALL messages regardless of trigger keywords
  * now only overrides when message matches skill triggers (same logic as buildPromptContext)
  * presenter model (mistral) now only applies for 발표/pptx/슬라이드 keywords

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 14:58:22 +09:00
kimandClaude Sonnet 4.6 69734e2e58 Release 2.9.3: switch primary to gpt-oss:120b-cloud with mistral vision fallback
- config: primary model → gpt-oss:120b-cloud (faster general chat, 2.72s median)
- server-v2: fix vision regex to exclude gpt-oss (gpt(?!-oss) negative lookahead)
  * gpt-oss was incorrectly matching /gpt/ → image data sent to non-vision model
  * applied at all 3 _supportsVision check sites (lines 5204, 6362, 7832)
- server-v2: vision fallback routing — when primary lacks vision support and user
  message contains images, automatically route to orchestration.secondary
  (mistral-large-3:675b-cloud, 4.27s avg, fastest vision cloud model)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 14:38:15 +09:00
kimandClaude Sonnet 4.6 70fc406b2a Release 2.9.2: trigger-based skill injection + vision support for all adapters
- skills-manager: conditional skill injection via triggers frontmatter field
  (skills only sent to model when message matches trigger keywords)
- skills: added triggers to all skill SKILL.md files; cleaned up headers/disclaimers
- anthropic-adapter: toAnthropicContent() converts OpenAI image_url → Anthropic image blocks
- multi-agent: vision flag in SecondaryProfile; secondarySupportsVision() checks config
- config: secondary set to mistral-large-3:675b-cloud with vision:true

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 14:28:40 +09:00
kimandClaude Sonnet 4.6 d9df800524 Release 2.9.1: PPTX wizard project persistence + PDF column extraction
- PDF: PyMuPDF 2-column aware extraction (left col → right col, drop cap merge,
  header/footer/footnote removal), reference stripping, 200k char limit
- Wizard: chunked parallel translation (15k chars/chunk, ~4x faster)
- Wizard: save UPL_ (upload) papers to papers.json (were silently skipped)
- Wizard: restore UPL_ papers from manifest with _isUpload/_localPdf fields
- Wizard: project-papers endpoint correctly resolves UPL_ ko.txt in project dir
- Wizard: images loaded on manifest restore (renderImgGrid unconditional)
- Wizard: outline.json auto-save after generation and slide edits
- Wizard: outline.json fallback load when no PPTX exists
- Wizard: loadProjList() refresh after savePapersToProject()
- Code editor: default font size 14→12px

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 23:29:54 +09:00
kimandClaude Opus 4.8 6963ccb9a0 Release 2.9.0: open code editor in a standalone browser tab
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>
2026-05-30 21:07:22 +09:00
kimandClaude Opus 4.8 949a910ad6 Release 2.8.2: render title-slide photo background in PPTX
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>
2026-05-30 20:42:25 +09:00
kimandClaude Opus 4.8 957a13f98c Release 2.8.1: pptx-wizard slide editor + fixes
- 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>
2026-05-30 20:14:01 +09:00
kimandClaude Sonnet 4.6 22bfc3ac27 Separate skills state completely per user
- 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>
2026-05-28 17:33:29 +09:00
kimandClaude Sonnet 4.6 2d3e33b6b3 Centralize all path management via src/config/paths.ts
- Add getPaths() with workspace, scripts, ppt skin/template paths
- Export getWorkspacePath(args?) helper — removes duplicate local functions
  and stale process.cwd()/workspace fallbacks from sqlite, pdf, excel,
  image, pubmed, email, audio-transcribe (7 files)
- weather.ts: replace __dirname-relative scripts path with getPaths().scripts
- Move ppt/ to .smallclaw/skills/presenter/ppt/; update server-v2.ts,
  pptx.ts, pptx_gen.py (argparse --skin-dir/--template-dir)
- Fix PPT skin thumbnail serving: res.sendFile → fs.createReadStream
  (bypasses send module dotfiles restriction for .smallclaw/ paths)
- Fix workspace default: .smallclaw/workspace (was project root workspace/)
- Fix subagent paths to use SMALLCLAW_DATA_DIR env var
- Fix Monaco marked module load failure: restore define.amd on
  DOMContentLoaded after deferred UMD libs (tone, magenta) have loaded
- Add AudioContext resume on first user click (Chrome autoplay policy)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:55:14 +09:00
kimandClaude Sonnet 4.6 5608b83850 Refactor project layout and fix workspace/subagent paths
- Remove global workspace (workspace/) — all data migrated to .smallclaw/
- Move ppt/ skins & templates to .smallclaw/skills/presenter/ppt/
- Add .smallclaw/templates/ for user bootstrap files
- Move dental_images to .smallclaw/databases/, update 1,485 DB entries
- Fix subagent store paths to use SMALLCLAW_DATA_DIR instead of workspace.path
- Per-user Telegram bots: MultiUserTelegramManager, vault-stored tokens
- Fix Telegram token persistence (vault fallback, strip from config.json)
- Fix session migration: delete global originals even when skipping
- Delete unused root images, MD docs, tests/, smallclawworkspace/ artifacts
- Add meteorologist skill, counselor skill, presenter skill scaffold
- Strip workspace.path from config.json (was causing path confusion)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 15:21:21 +09:00
kimandClaude Sonnet 4.6 d7eb0abc6d Add meteorologist skill with 9 weather/climate tools
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>
2026-05-26 14:22:49 +09:00
kimandClaude Opus 4.7 ed25f457df Update skills_state: lawyer/investor disabled
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 20:22:29 +09:00
kimandClaude Opus 4.7 8b0f47eba0 Restore musician and accountant skills
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 20:13:53 +09:00
kimandClaude Opus 4.7 2485cea650 Restore psychiatrist skill — has unique value (crisis protocol, DSM-5 guidance)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 15:30:14 +09:00
kimandClaude Opus 4.7 0020109a69 Remove skills with no unique tools (musician, accountant, psychiatrist)
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>
2026-05-24 15:14:46 +09:00
kimandClaude Opus 4.7 7a9826f20a Fix dental-dict images, remove coder skill and image stripping regex
- 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>
2026-05-24 15:07:58 +09:00
kimandClaude Opus 4.7 347bab27b3 v2.9.1 — Config centralization, settings route extraction, web-ui split
- tools/*.ts: Replace fs.readFileSync config reads with getConfig() + resolveSecret()
  (pubmed, legal, scholar, weather, email, web, files — 7 files)
- tools: Remove direct getVault() calls in email.ts and weather.ts, use resolveSecret()
- gateway: Extract 21 /api/settings/* routes from server-v2.ts into routes/settings.ts
  (server-v2.ts reduced by ~375 lines)
- types: Add missing config fields (legal, semantic_scholar, openweather, weather, email, search.pubmed_api_key)
- web-ui: Split index.html (13,879 lines) into index.html (1,934) + styles.css (2,530) + app.js (9,416)
- web-ui: Allow static assets to bypass auth middleware
- Remove empty index2.html template stub

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:26:23 +09:00
kimandClaude Sonnet 4.6 8aee152f2f v2.9.0 — Settings overhaul, Mistral parallel tool fix, Anthropic provider
- 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>
2026-05-23 18:52:40 +09:00
kimandClaude Sonnet 4.6 eaf6678a21 v2.8.0 — Code editor tab + context panel improvements
- Add 💻 코드 nav button; code mode shows aside + right-panel
- Code mode left sidebar: 파일/모델/설정 tabs (file tree, model selector, Monaco settings)
- Monaco editor settings restored from localStorage on init
- Server log panel: collapsible (▾ toggle), height fixed to 50% of aside
- Context panel compact layout: reduced padding/margins/min-heights throughout so all sections (시스템통계/에이전트컨텍스트/빠른작업/프로세스로그) fit without scrolling
- POST /api/code/save, GET /api/code/files, GET /api/code/file, DELETE /api/code/file endpoints
- Coder AI: glm-5.1:cloud default, auto-open generated code in Monaco tabs
- Code folder browser with fixed-position dropdown (escape overflow clip)
- Code editor terminal panel with PTY/xterm.js (Ctrl+` shortcut)
- Remove canvas panel; restore chat terminal infrastructure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 12:20:16 +09:00
kimandClaude Sonnet 4.6 7ebf8cf86f Add VS Code-style code editor tab with AI chat panel
사이드바에 💻 코드 탭 추가:
- Monaco Editor (vs-dark/light 테마 자동 연동)
- 파일 탭 관리 (새 파일, 전환, 닫기), Ctrl+S 저장
- 오른쪽 AI 채팅 패널 (Coder 세션, SSE 스트리밍)
- "선택 코드 → AI 전송" 버튼
- "▶ 실행" → 하단 터미널 패널로 명령 전송
- 에디터/AI 패널 수직 드래그 리사이즈
- 스킬 탭 이모지 버그 수정 (조건 반전, 커스텀 이모지 표시 안 되던 문제)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 00:20:30 +09:00
kimandClaude Sonnet 4.6 7dac40381e Add Coder skill (fullstack dev expert)
풀스택 시니어 엔지니어 어시스턴트:
- 도구: 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>
2026-05-22 00:06:42 +09:00
kimandClaude Sonnet 4.6 9fca14e8db Add chat inline terminal panel (xterm.js + PTY)
채팅 입력창 옆 ⌨ 버튼으로 슬라이드업 터미널 패널 토글.
- 상단 드래그 핸들로 높이 조절 (120px~70vh)
- + 버튼으로 bash 탭 추가, × 로 탭 닫기
- 기존 xterm.js / PTY WebSocket 인프라 재사용

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 23:44:14 +09:00
kimandClaude Sonnet 4.6 6df1bcf5b3 Add TradingView chart widget + MIDI/tab close fixes
- 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>
2026-05-21 23:26:28 +09:00
kimandClaude Sonnet 4.6 00d508cc77 MIDI upload flow: save to workspace, action picker (재생/편집/악보)
- 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>
2026-05-21 17:29:49 +09:00
kimandClaude Sonnet 4.6 1bfadd6060 Add MIDI editor + fix external synth instrument mapping
- 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>
2026-05-21 13:54:15 +09:00
kimandClaude Sonnet 4.6 bc9fb4043b Improve session management: token-based history, boot session cleanup, telegram user mapping
- 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>
2026-05-20 11:03:53 +09:00
kimandClaude Sonnet 4.6 15650e5798 Switch TTS to edge-tts (ko-KR-SunHiNeural), add TTS toggle + mic auto-send
- 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>
2026-05-19 21:06:10 +09:00
kimandClaude Sonnet 4.6 cd48a8ebe0 Fix voice: Web Speech API for STT, WAV for TTS
- 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>
2026-05-19 18:15:41 +09:00
kimandClaude Sonnet 4.6 de18ddc9f6 Add Level 1 push-to-talk voice chat (STT + TTS)
- 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>
2026-05-19 18:03:55 +09:00
kimandClaude Sonnet 4.6 8d5ff0d785 Add Excel modal resize/drag and pop-out new-window viewer
- 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>
2026-05-19 17:18:46 +09:00
kimandClaude Sonnet 4.6 0095381c41 Update config: set cloud models for primary and orchestration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 16:41:12 +09:00
kimandClaude Sonnet 4.6 2be3edc314 Add accountant/investor skills, Excel editor, email attachment fixes
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>
2026-05-19 16:38:42 +09:00
kimandClaude Sonnet 4.6 bac5604d5e Add Tesseract OCR fallback to pdf_read
스캔 PDF에서 텍스트 추출 실패 시 자동으로 OCR 실행.
PyMuPDF로 300DPI 이미지 렌더링 후 tesseract kor+eng 적용.
ocr: true 파라미터로 강제 OCR 가능. method 필드로 추출 방법 표시.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 13:04:52 +09:00
kimandClaude Sonnet 4.6 8135477d12 Make skills exclusive: enabling one disables all others
toggle/setEnabled 시 다른 스킬 자동 비활성화.
현재 상태: musician만 활성화.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:48:33 +09:00
kimandClaude Sonnet 4.6 297d4ac166 Strengthen Korean language rule in musician skill
영어 곡 분석 시에도 한국어로만 답변하도록 규칙 강화.
영어 답변 절대 금지 명시.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:46:33 +09:00
kimandClaude Sonnet 4.6 e2c6395a9a Hide PDF download button in user messages
사용자가 업로드한 PDF는 이미 갖고 있으므로 저장 버튼 불필요.
renderMarkdown/renderLinkButton에 hideDownload 옵션 추가,
유저 메시지 렌더링 시 적용. 미리보기 버튼은 유지.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:27:39 +09:00
kimandClaude Sonnet 4.6 d1423c9a3b Add image PDF sheet music analysis workflow to musician skill
스캔 악보 PDF 처리 절차 추가:
pdf_read 시도 → 실패 시 pdf_extract_images로 페이지 추출 → image_read로 시각 분석.
도구 목록에 pdf_extract_images, image_read 추가.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:23:48 +09:00
kimandClaude Sonnet 4.6 2e97f6f47c Show active skill names in console log instead of session ID
[v2] ASSISTANT [papa@musician] 형식으로 변경.
스킬 없으면 세션ID 앞 8자리 표시.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:19:30 +09:00
kimandClaude Sonnet 4.6 7f053156b8 Fix musician skill: add Korean language instruction
음악 용어가 영어 위주라 영어로 응답하던 문제 수정.
한국어 우선 + 영어 병기 규칙 명시.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:06:51 +09:00
kimandClaude Sonnet 4.6 7a5c1e81d8 Add musician skill
범장르 음악 어시스턴트: 작곡·편곡·이론 분석·악기 코칭·음악사.
클래식·재즈·팝·국악 포함, python_eval로 조옮김·코드 계산 지원.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 11:56:30 +09:00
kimandClaude Sonnet 4.6 81ae83a8fc Track skills directory in git
.gitignore에서 .smallclaw/skills/ 제외 해제.
lawyer, psychiatrist, multi-agent-orchestrator SKILL.md 추가.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 11:51:14 +09:00
kimandClaude Sonnet 4.6 d93cac545a Add legal research tools and lawyer/psychiatrist skills
- src/tools/legal.ts: korean_law_search (law.go.kr API, 법령+판례),
  korean_law_fetch (전문 조회), us_case_search (CourtListener)
- registry.ts: legal tools 등록, web profile에 포함
- config.json: law.go.kr API 키 추가 (legal.law_go_kr_api_key)
- skills_state.json: lawyer, psychiatrist 스킬 활성화

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 11:49:33 +09:00
kimandClaude Sonnet 4.6 ac678db97b Track heartbeat/skills settings, add vault backup script
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>
2026-05-18 23:24:54 +09:00
kimandClaude Sonnet 4.6 4f536861bb Save edited images as PNG by default to prevent JPEG compression buildup
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>
2026-05-18 23:09:01 +09:00
kimandClaude Sonnet 4.6 0777409479 Add saturation/blur/filter/vignette/auto_enhance ops, raise JPEG quality
New image_edit operations (pure Pillow, no new deps):
- saturation: color saturation control (value: 0=gray, 1=original, 2=vivid)
- blur: gaussian blur (radius param)
- auto_enhance: one-click auto levels + mild saturation boost
- filter: photo presets — warm, cool, vintage, sepia, fade, dramatic, bw_film
- vignette: edge darkening for portrait look (strength param)

Also raise default JPEG/WebP quality 85 → 92 to reduce compression
artifacts on repeated edits, and update TOOL_BLOCK + schema to include
all new operations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 23:03:28 +09:00
kimandClaude Sonnet 4.6 38fbb03f90 Tighten gitignore, clarify ollama_web_search, add image deps installer
- 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>
2026-05-18 22:23:03 +09:00
kimandClaude Sonnet 4.6 569f563cca Fix Korean web search detection and SearXNG banner, update dental dict
- 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>
2026-05-18 22:18:20 +09:00
kimandClaude Sonnet 4.6 fd79dfea6f Add SearXNG settings.yml to repo (.smallclaw/searxng/)
Copy of /home/kim/searxng/settings.yml for version control.
Disables failing engines (brave, karmasearch, startpage, qwant, yahoo, reuters, wikinews)
and enables working news engines (naver news, hackernews, mojeek news).

Deploy: cp .smallclaw/searxng/settings.yml ~/searxng/ && docker restart searxng

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:05:07 +09:00
kimandClaude Sonnet 4.6 3f9857a639 Track .smallclaw/config.json and add SearXNG search config
- Remove .smallclaw/config.json from .gitignore
- Add search config: preferred_provider=searxng, searxng_url=http://localhost:8888

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:04:32 +09:00
kimandClaude Sonnet 4.6 245606252e v2.7.1 — image edit improvements, search config, bug fixes
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>
2026-05-18 22:03:32 +09:00
kimandClaude Opus 4.7 34932ac50a Refactor per-user channel registration and improve PDF/PPTX workflows
- Generalize per-user channel registration (telegram/discord/whatsapp)
  via vault instead of config.json userMap
- Add API endpoints for self-service channel binding
- Migrate Telegram channel to use vault-based username resolution
- Improve PDF figure extraction filters (OpenCV)
- Fix PPTX image embedding and font sizing
- Reorder search providers: searxng → ddg priority

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 22:37:56 +09:00
kim e7fd3de974 v2.7.0 2026-05-15 12:13:35 +09:00
kimandClaude Opus 4.7 1b0ac0f605 v2.7.0
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 12:12:36 +09:00
kimandClaude Opus 4.7 e11ddd7f3e Refactor dental dictionary into manage.py CLI
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>
2026-05-15 11:58:53 +09:00
kim ff6627bc25 v2.6.3 2026-05-10 16:32:18 +09:00
kim 930f52ca48 v2.6.2 2026-05-10 12:02:23 +09:00
kim c26f9b431b v2.6.2 2026-05-10 12:00:01 +09:00
kim 82bda7409e v.2.6.1 2026-05-09 11:35:33 +09:00
kim a77ee3bdc9 v2.6.0 2026-05-06 22:45:28 +09:00
kim dac32dbcee v.2.5.1 2026-05-05 19:51:22 +09:00
kim 13f832f693 v.2.5.0 2026-05-05 17:46:17 +09:00
kim 233b67b9a3 v2.4.1 2026-05-05 00:51:37 +09:00
kim 9714d4b50c v2.4.0 2026-05-04 17:58:17 +09:00
kim fc88bda24b v2.3.8 2026-05-04 00:41:10 +09:00
kim a7cdb06e60 v2.3.7 2026-05-03 23:27:21 +09:00
kim 999dddec9e v2.3.6 2026-05-03 20:39:16 +09:00
kim b37525434c v2.3.5 2026-05-03 19:41:35 +09:00
kim cb131e8047 v2.3.3 2026-05-03 18:56:13 +09:00
kim f92e5ef782 v2.3.2 2026-05-03 17:36:47 +09:00
kim 83eb31f121 v2.3.1 2026-05-02 23:15:25 +09:00
kim ec53a112b4 v.2.3.0 2026-05-01 23:23:11 +09:00
kimandClaude Sonnet 4.6 e8c825992f fix: remove duplicate bare URL/path appended to PPTX tool result
Python stdout already includes the correct markdown download link.
Appending extra bare URL and absolute path caused the model to generate
two download links in its response. Keep only Python's stdout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 18:04:32 +09:00
kimandClaude Sonnet 4.6 07f2ae7e2d fix: correct file link hint — PPTX uses project folder path not uploads/
The v2.2.3 hint "ALWAYS use /api/files/uploads/filename" was too broad,
causing the model to format PPTX download links as uploads/file.pptx
instead of the correct project_folder/file.pptx path returned by the tool.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 17:57:36 +09:00
kimandClaude Sonnet 4.6 d4fedeccd5 fix: use system Chromium on unsupported OS (Ubuntu 26.04+)
Playwright's bundled browser install fails on Ubuntu 26.04 with
"Playwright does not support chromium on ubuntu26.04-x64".

Fall back to system Chromium (/usr/bin/chromium-browser etc.) via
executablePath when launching headless, bypassing the platform check.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 17:45:45 +09:00
kimandClaude Sonnet 4.6 8da045eb72 v2.2.3
- Mobile menu: full-screen overlay on bottom nav tap (slide-up animation + close button)
- Sidebar: server log panel with auto-scroll and real-time polling
- Admin: context viewer tab (session usage per user)
- Chat export: Markdown / TXT / JSON
- Online users display in system stats (admin-only)
- Fix: workspace priority (session > global) for multi-user file isolation
- Fix: upload filenames now preserve Unicode/Korean characters
- Fix: log ring buffer wrap-around bug (logTotalCount monotonic counter)
- Security: /api/logs requires auth; online_users restricted to admin
- WebSocket: ping/pong keepalive every 30s

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 17:20:24 +09:00
kim 6675779566 v2.2.2 2026-05-01 01:09:04 +09:00
kim fbaacc2e60 v2.2.1 2026-05-01 00:48:36 +09:00
kim 7177f684b7 v2.2 2026-04-30 18:04:21 +09:00
kim 7b34afbd38 v2.0 2026-04-30 12:41:49 +09:00
kim c348c9cbed v2.1 2026-04-29 23:16:01 +09:00
kim d89d7213f6 v2.0 2026-04-29 22:23:08 +09:00
kim 10eb7405bc v1.0.6 2026-04-29 19:39:03 +09:00
kim 1106553b81 v1.0.5 2026-04-29 18:03:48 +09:00
kim 4324985508 v1.0.4 2026-04-29 17:34:36 +09:00
kim ee10549c5a v1.0.2 2026-04-29 17:26:46 +09:00
kim 5fc7cdb6be v1.0.1 2026-04-29 15:39:52 +09:00
kim 3e8974a8eb v1.0 2026-04-29 11:45:59 +09:00