Commit Graph
25 Commits
Author SHA1 Message Date
kimandClaude Sonnet 5 57cf65fd7e feat: 채팅·작업실 라이브 카메라 — 메시지마다 현재 화면 자동 첨부
- camera.js: getUserMedia 미리보기 패널, 전송 시 프레임(768px JPEG)을 /api/upload/image로 올려
  기존 이미지 첨부 경로(![📷…](/api/files/…) → resolveImageContent)로 모델에 전달. 음성 통화 STT도
  같은 전송 경로라 그대로 동작
- 메인 채팅: 📷 버튼+패널, sendChat에서 프레임 자동 첨부
- 작업실: 🎥 버튼+패널, 전송 훅·썸네일 표시·팝업에서 카메라 화면을 프로젝트 사진으로 저장
- handle-chat: 과거 턴의 카메라 프레임은 텍스트로 접어 비전 입력이 턴마다 누적되지 않게 함

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 20:37:16 +09:00
kimandClaude Sonnet 5 7ec72e776a refactor: "로봇 프로젝트" 단일 대시보드를 여러 프로젝트를 오가는 "작업실"로 일반화
로봇 프로젝트 하나만 다루던 대시보드/도구를 로봇 외 다른 메이커 프로젝트
(3D프린팅, 밀링 등)도 같은 틀로 관리할 수 있게 재설계. 사용자가 이름을
"작업실"로 정함.

- workshop-storage.ts(구 robot-storage.ts): 단일 문서 대신
  {projects:[], activeProjectId} 구조. 기존 실사용 중이던
  robot-project.json이 있으면 빈 시드로 덮어쓰지 않고 그 실제 데이터를
  그대로 첫 프로젝트("로봇 프로젝트")로 마이그레이션
- routes-workshop.ts(구 routes-robot.ts): GET/PUT /api/workshop/data
- workshop-project.ts(구 robot-project.ts) 채팅도구: project_name 파라미터
  추가(생략시 활성 프로젝트 대상), list_projects/create_project/
  set_active_project 액션 신설
- workshop-app.html(구 robot-app.html): 헤더에 프로젝트 선택 드롭다운 +
  새 프로젝트/삭제 버튼 추가. 장비(K2/밀링) 탭은 프로젝트와 무관하게
  전역 유지
- 세션 접두사 rb_→ws_(tool-scope.ts의 isWorkshopAppSession), 도구명
  robot_project→workshop_project
- 마이그레이션+새 프로젝트 생성/전환/삭제+채팅 연동까지 브라우저로 실제
  확인함

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 19:04:49 +09:00
kimandClaude Sonnet 5 9641f689b8 feat: 로봇 프로젝트 관리 대시보드(robot-app) 추가
메카넘휠 이동로봇 프로젝트(파이5+RPLidar, 추후 팔 추가)의 부품리스트/
단계별 작업/예산을 관리하는 웹앱. doctor-app의 GET/PUT 단일문서 패턴을
재사용하되 케이스 목록 없이 단일 프로젝트 문서로 단순화했고, 첫 로드시
project_robot_dog.md 메모 기준 실제 진행상황을 기본 시드로 반환한다.

- src/gateway/routes/routes-robot.ts: GET/PUT /api/robot/project,
  사용자별 workspace/.smallclaw/robot-project.json에 원자적 저장
- web-ui/html/robot-app.html: 부품/작업/메모 3탭, 실시간 예산 요약,
  디바운스 자동저장
- index.html 🏠 홈 드롭다운에 🤖 로봇 링크 추가

장비연동/전용챗봇/외부데이터연동/CAD플러그인은 다음 단계로 보류.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 13:46:37 +09:00
kimandClaude Sonnet 5 d65e8d958d feat: K2/밀링 앱을 NPM 서브도메인(HTTPS)으로 전환, 홈 드롭다운 재추가
print.applecherry.net(K2 콤보 Fluidd) · mill.applecherry.net(CNC 밀링
OctoPrint)로 NPM 프록시+Let's Encrypt 설정 완료. 앱들이 이제 HTTPS라
mixed content 경고 없이 홈 드롭다운에 다시 노출.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PppKcQmeTJDQCpfcgKietu
2026-09-19 16:39:30 +09:00
kimandClaude Sonnet 5 f13b40712c feat: 복원된 옛 홈페이지(애플체리, XpressEngine) 앱 추가
트루나스 Plex/applecherry에 있던 옛 XpressEngine(XE 1.11.6) 사이트를
PHP7.4+MariaDB 도커 앱으로 복원하고 home.applecherry.net(NPM+Let's
Encrypt)으로 서빙. 홈클로 홈 드롭다운에 iframe 래퍼 앱으로 추가.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PppKcQmeTJDQCpfcgKietu
2026-09-19 11:24:36 +09:00
kimandClaude Sonnet 5 a8149c136a feat: 프린터실 카메라 웹코덱(WebRTC/MSE) 전환 + K2 콤보 카메라 프록시, 옛 3D프린터 앱 제거
- go2rtc가 CORS/Origin 체크로 브라우저 직접접속을 막던 문제 해결: 클라이언트
  스크립트를 벤더링해 같은 오리진으로 서빙하고, WS는 게이트웨이 프록시
  (attachGo2rtcWsProxy)가 Origin을 다시 써서 우회. CCTV 앱의 프린터실 카메라
  라이브뷰가 MJPEG 대신 WebRTC/MSE를 쓰도록 전환(대역폭 절감).
- go2rtc mjpeg 트랜스코더가 멈추는 경우를 감지해 자동 재기동하는
  /api/nvr/mjpeg-health 엔드포인트 추가.
- 신규 3D프린터(K2 콤보, Klipper 스탠드얼론)의 내장 WebRTC 카메라 시그널링을
  프록시하는 /api/k2/webrtc-signal 추가 — 홈클로가 HTTPS로 서빙되는데 카메라가
  평문 HTTP만 지원해 브라우저 mixed-content 차단을 우회하기 위함.
- 옛 3D프린터(단종된 Anet A8 Plus, OctoPrint) 앱과 홈 드롭다운 링크 제거.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PppKcQmeTJDQCpfcgKietu
2026-09-18 22:40:10 +09:00
kimandClaude Sonnet 5 e3f038617d feat: CNC 밀링 앱 추가, 3D프린터/밀링 서버 IP를 새 옥토서버(.3)로 갱신
- web-ui/html/milling-app.html 신규: OctoPrint 밀링 인스턴스(:5001) iframe 임베드
- 홈 드롭다운에 "⚙️ CNC 밀링" 버튼 추가
- printer-app.html: 미니PC(192.168.0.106) → HP 프로데스크 "옥토서버"(192.168.0.3)로 IP 갱신

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PppKcQmeTJDQCpfcgKietu
2026-09-13 20:27:59 +09:00
kimandClaude Sonnet 5 8eb1a6c160 feat: 3D프린터 앱(OctoPrint) 홈 드롭다운에 추가
작업실 미니PC(192.168.0.106)에 설치한 OctoPrint를 iframe으로 임베드.
홈 CCTV/HA 옆에 🖨️ 3D프린터 항목 추가.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E5kyXurhNSboRcY3dAGceY
2026-09-12 00:13:15 +09:00
kimandClaude Sonnet 5 c22377778e feat: 유저별 로고·브랜드명 커스터마이징 — .smallclaw/users/<user>/logo.png, brand_name.txt
헤더/환영화면/채팅 아바타·라벨을 로그인 유저별로 스왑. 파일 없으면 기본 HomeClaw 유지.
애플·자스민 계정에 기본 로고(이모지 아이콘) 적용.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E5kyXurhNSboRcY3dAGceY
2026-09-11 16:13:38 +09:00
kimandClaude Opus 5 6df49c11a5 feat: 지서버 모델을 드롭다운으로 선택 (muse-glimmer / gemma4:26b)
지서버에 muse-glimmer와 gemma4:26b를 둘 다 두고 골라 쓰기 위해 되살린다.
86063d3에 있었으나 그 커밋이 통째로 되돌려졌던 UI 부분이다. 되돌린 사유였던
에러는 서버 로그상 8시간 앞선 별건(config.json 손상 + 지서버 엔드포인트 .99)으로
확인됐다.

설정에서 지서버 모델은 자유입력 텍스트 박스라 모델명을 손으로 정확히 적어야 했다.
정작 refreshProviderModels는 ollama_local일 때도 목록을 가져오고 있었는데, 그
결과를 항상 ollama 패널의 select에 써넣어서 — 지서버를 고르면 그 패널이 숨겨지므로 —
가져온 목록이 화면에 한 번도 안 보이고 버려지고 있었다.

- 지서버 모델 필드를 select로 바꾸고 "모델 새로고침" 버튼 추가
- refreshProviderModels가 provider별로 맞는 select와 상태줄을 쓰도록 수정
- lm_studio/llama_cpp의 모델 필드는 아직 input이라 SELECT일 때만 option을 채운다
  (input에 <option>을 넣으면 사용자가 입력한 값이 날아간다)

onProviderChange는 ollama_local만 자동 새로고침에서 빼둔다 — 드롭다운을 고른 것만으로
WOL 패킷을 쏘고 45초를 기다리면 안 되기 때문이다. 그래서 새로고침 없이 저장하면
select가 placeholder(값 "")뿐이라 설정된 모델명이 빈 값으로 덮어써진다.
seedModelSelect로 저장된 모델을 항상 실제 option으로 심어 막는다(빈 select에
.value를 넣으면 조용히 무시된다는 점도 이유).

app.js 쪽 호출은 typeof 가드로 감쌌다. seedModelSelect는 settings-provider.js에
있으므로, 브라우저가 그 파일의 캐시본을 든 채 새 app.js만 받으면 ReferenceError로
설정 로딩이 통째로 죽는다 — 지난번 "에러가 너무 나네"의 가장 유력한 경로다.

검증(실제 index.html 패널 마크업 + 실제 함수를 그대로 불러오고 네트워크 경계만 스텁):
새로고침 전 저장값이 실제 option으로 심어지고 저장 payload가 그 값을 읽는지,
새로고침 후 저장 모델이 목록 맨 앞에 오는지, 다른 패널 select를 안 건드리는지,
사용자가 고른 값이 저장 payload에 실리는지 — 전부 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 09:27:06 +09:00
kim 3b5c93df8e Revert "feat: 지서버 모델을 드롭다운으로 선택 + think:false가 조용히 뒤집히지 않게"
This reverts commit 86063d3ef5.
2026-08-12 23:08:27 +09:00
kimandClaude Opus 5 86063d3ef5 feat: 지서버 모델을 드롭다운으로 선택 + think:false가 조용히 뒤집히지 않게
지서버(ollama_local)에 muse-glimmer를 추가로 올려두고 gemma4:26b와 골라 쓰려 했으나
설정 화면에서 지서버 모델은 자유입력 텍스트 박스라 모델명을 손으로 정확히 적어야 했다.
정작 refreshProviderModels는 ollama_local일 때도 목록을 가져오고 있었는데, 그 결과를
항상 ollama 패널의 select에 써넣어서 — 지서버를 고르면 그 패널이 숨겨지므로 —
가져온 목록이 화면에 한 번도 안 보이고 버려지고 있었다.

- 지서버 모델 필드를 select로 바꾸고 "모델 새로고침" 버튼 추가
- refreshProviderModels가 provider별로 맞는 select와 상태줄을 쓰도록 수정
- lm_studio/llama_cpp의 모델 필드는 아직 input이라, SELECT일 때만 option을 채운다
  (input에 <option>을 넣으면 사용자가 입력한 값이 날아간다)

여기서 새로 생기는 함정 하나를 같이 막았다. onProviderChange는 ollama_local만
자동 새로고침에서 빼두는데, 드롭다운을 고른 것만으로 WOL 패킷을 쏘고 45초를 기다리면
안 되기 때문이다. 그러면 새로고침 없이 저장할 때 select가 placeholder(값 "")뿐이라
설정된 모델명이 빈 값으로 덮어써진다. seedModelSelect로 저장된 모델을 항상 실제
option으로 심어둬서 막았다(빈 select에 .value를 넣으면 조용히 무시된다는 점도 이유).

buildThinkCandidates: 명시적 think:false는 재시도 사다리를 오르지 않는다.
사다리는 glm-5.1:cloud처럼 think를 생략하면 생각만 하고 content를 안 내는 모델을
건지려고 만든 것인데, false는 성격이 다르다. "이 모델은 생각에 예산을 낭비한다"는
운영자의 결정이라, 빈 응답 한 번에 thinking을 도로 켜면 그 결정이 조용히 뒤집힌다.
08-12 muse-glimmer 실측: 생각비중 85%, 체감 3.1 tok/s → think:false로 20.9 tok/s(7배)에
답변은 오히려 길어지고 잘림도 사라짐(20문항 빈 답변 0건). 사다리가 이걸 되돌리면
의도한 7배가 말없이 느린 경로로 돌아간다. 이제 false는 모델 기본값까지만 물러선다
— 빈 응답이 막다른 길이 되지는 않게.

테스트용으로 모듈 레벨 export로 추출(346개 통과).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 23:02:08 +09:00
kimandClaude Opus 5 ce684a6cf3 feat: 설정 자격증명 탭에 키 발급 사이트 카드 추가
Vault에 저장된 키는 이름만 opaque 문자열로 남아 있고 어디서 발급받았는지가 UI
어디에도 없어, 갱신·재발급 때마다 해당 콘솔을 찾아 헤매야 했다. data.go.kr은
특히 하나의 키라도 서비스별로 활용신청이 따로 필요한데(에어코리아 측정소정보가
같은 키로 403 난 이유), 그 사실이 기록된 곳이 없었다.

- 서비스 19곳의 발급 페이지 링크. /api/credentials/status로 실제 저장 여부를 읽어
  ✓(저장됨)/·(미저장)로 표시하므로 하드코딩된 목록이 아니다.
- 공공데이터포털 항목에 "서비스별로 활용신청 필요"를 명시했다.
- 전 링크 https + target=_blank + rel=noopener noreferrer, 값은 escHtml 처리.
- Vault 조회에 실패해도 링크는 그대로 보이고 경고만 덧붙인다. 저장 여부를 잘못
  표시하는 것보다 모른다고 하는 편이 낫다.

브라우저에서 렌더 확인: 19개 중 17개 ✓, 미저장으로 표시된 Brave·OpenAI는
실제 Vault 내용과 일치. 콘솔 에러 없음.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 10:40:22 +09:00
kimandClaude Sonnet 5 b8c6a769be feat: 지서버용 별도 Ollama provider(ollama_local) 추가
기존 "ollama" provider(클로서버 localhost, 주로 *:cloud 모델용)는 그대로
두고, LAN의 다른 로컬 GPU 머신(지서버 등)을 가리키는 두 번째 독립 Ollama
provider "ollama_local"을 신설. OllamaAdapter가 id를 생성자 인자로 받게
바꿔서(기존 'ollama' 하드코딩 → 'ollama'|'ollama_local' 선택 가능) 두
인스턴스를 provider 캐시/설정에서 구분함. 설정화면에 "Ollama
(클로서버/클라우드)" / "Ollama (지서버/로컬)"로 라벨 분리, 엔드포인트·모델
입력 필드 추가.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 19:42:31 +09:00
kimandClaude Sonnet 5 b02fe0a184 feat: 상단 네비게이션 드롭다운으로 재구성
앱 버튼이 늘어나면서 상단 바가 너무 길어져, 창작/전문직/법률·탐정/홈으로
그룹화한 드롭다운 메뉴로 재구성.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 13:12:23 +09:00
kimandClaude Sonnet 5 b001cd9318 feat: OpenAI 모델 목록 조회 라우트 추가, LM Studio thinking 비활성화 스위치
프론트엔드가 예전부터 호출하던 POST /api/openai/models가 백엔드에 구현이
안 되어 있어 항상 404였던 버그 수정 - OpenAICompatAdapter로 실제 OpenAI
API에 모델 목록을 조회하도록 구현.

지서버(LM Studio)의 gemma-4-26b-a4b가 응답당 완성 토큰을 2.5배 더 많이
쓰는 것을 벤치마크로 확인(322 vs 132 토큰/응답, thinking 오버헤드로 추정) -
chat_template_kwargs.enable_thinking=false를 기본 적용하되, 복잡한 질문에서
품질이 떨어질 수 있어 설정 화면(모델 → LM Studio)에 체크박스로 켜고 끌 수
있게 구현. 기본값은 비활성화(현재 상태 유지).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 12:57:22 +09:00
kimandClaude Sonnet 5 6a61c3f4af 스튜디오 앱에 프롬프트 작성 도우미 채팅 + 생성 진행률 바 추가
이미지/동영상/사진편집/이모티콘세트 탭과 ComfyUI 탭 양쪽에 AI 프롬프트
도우미를 붙여, 한국어로 설명하면 SDXL/FLUX/LTX용 영어 프롬프트를 만들어줌.
생성 중에는 예상 소요시간 기준 진행률 바를 표시.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 12:27:39 +09:00
kimandClaude Sonnet 5 a80ad9e809 v4.3.19-6: Google 일일 사용량 표시 + 한도 도달시 자동 폴백
- google-usage.ts: Gemini 무료티어 RPD(하루 500회 추정치) 대비 요청 카운트를
  날짜별로 추적(.smallclaw/google-usage.json, 자정 자동 리셋)
- openai-compat-adapter.ts: google provider일 때 post() 호출마다 카운트
- factory.ts: getProvider()/getModelForRole() 둘 다 getEffectiveProviderConfig()
  경유하도록 통일 — 카운트가 480(여유분 20 적용) 넘으면 자동으로
  ollama+deepseek-v4-flash:cloud로 전환(429 맞고 반응하는 게 아니라 사전 차단).
  provider/model 선택이 별도 함수라 따로 고치면 불일치 날 수 있어서 공유
  헬퍼로 묶음
- 메인 채팅 사이드바 모델 pill에 "N/500" 뱃지 추가(Google일 때만 표시,
  70%↑ 노랑/90%↑ 빨강), 기존 10초 폴링(checkStatus)에 얹어서 실시간 반영
- 실사용 확인: 배포 직후 실제 채팅으로 카운트 0→1 증가 확인, 480 시뮬레이션
  으로 폴백 전환/복귀 양쪽 다 확인

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 17:37:03 +09:00
kimandClaude Sonnet 5 5f83803ed4 v4.3.19-4: Google(Gemini) LLM provider 추가
- LLMProvider.ts/factory.ts: 'google' ProviderID 추가, 기존 openai_compat
  어댑터를 Gemini의 OpenAI 호환 엔드포인트로 재사용(새 어댑터 클래스 없음).
  api_key는 resolveEnvKey가 아닌 getConfig().resolveSecret()로 해석 —
  vault: 참조를 실제로 못 푸는 기존 openai/anthropic 케이스의 버그를
  google 케이스에서는 피해감
- config.ts: llm.providers.google 기본값 추가(기본모델 gemini-3.6-flash),
  SECRET_FIELD_MAP에 api_key 자동 vault 이관 등록
- 설정 화면(index.html/settings-provider.js): LLM 제공자 드롭다운에
  Google 옵션 + API키/모델 선택 UI, anthropic 패턴 그대로 재사용
- openai-compat-adapter.ts: 기본 max_tokens 512→4000 — 사고형 모델
  (gemini-3.6-flash)이 내부 사고 토큰에 예산을 다 써서 빈 응답 반환하는
  버그 실측 후 수정(llama_cpp/lm_studio/openai/google 전부 공유하는 값)
- 5문항 벤치마크로 gemini-3.6-flash/3.5-flash-lite/3.1-flash-lite 비교,
  secondary 후보로 3.5-flash-lite 확정(정직함 동률 최상위+5배 빠름+저가)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 15:50:26 +09:00
kimandClaude Sonnet 5 f5ae095837 v4.3.19-3: 도구 스키마 컨텍스트 스코핑 + web-ui/js 서브디렉토리 정리
- 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>
2026-07-26 14:58:32 +09:00
kimandClaude Sonnet 5 0963231327 v4.3.19-2: 회계사 앱 스프레드시트 뷰어 수정 + helpers.js 5개 파일 분리
- coder_write_file이 xlsx/pptx/docx/pdf/zip 같은 바이너리 확장자로 파일을
  만들려 하면 차단 (텍스트 escape로 바이너리를 흉내내다 파일이 깨지던 문제)
- 레거시 HTML 리다이렉트(/xlsx-viewer.html 등)가 쿼리스트링을 버리던 버그 수정
- xlsx-viewer: "새 시트"가 존재하지 않는 __new__.xlsx를 fetch하다 404나던
  것을 빈 워크북 생성 후 저장 시 파일명 입력받는 흐름으로 교체
- xlsx-viewer: LuckyExcel 변환이 내놓는 손상된 숫자 서식("???.???")을
  Luckysheet SSF 파서가 못 읽고 죽던 문제에 sanitizer 적용
- 회계사 앱 업로드가 존재하지 않는 /api/upload를 호출하던 것을
  /api/upload/file로 수정
- web-ui/js/helpers.js(2240줄)를 helpers-core/markdown/voice/media/files.js
  5개로 분리 (기능 변경 없음, 함수 단위 1:1 이관 확인됨)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 21:30:05 +09:00
kimandClaude 4d0404ea0d v4.3.19-1: Helpers 섹션을 helpers.js로 분리 + escHtml 중복 제거
app.js 4728-6961(Helpers 섹션 전체)을 web-ui/js/helpers.js로 추출.
escHtml/_normalizeFileUrl/_renderLinkButton, renderMarkdown+embed 변환기,
TTS/voice(mic 포함), music/MIDI, smiles/tradingview, 파일 미리보기/업로드,
동적 로더(SheetJS/Luckysheet/PDF.js) 등 75개 함수 + midiRouter 객체.

모든 함수를 전역 function 선언으로 유지(모듈 래핑 안 함)해 inline onclick
문자열(downloadFile, openImageZoom, togglePdfEmbed, playTTSMsg, ...)이
그대로 동작. state vars(_xxxLoaded, stagedAttachments, _tts*, _appSendFn
등)도 함께 이동.

escHtml 중복(원래 3625, dead code — 5412 버전이 이김) 제거로 단일 정의.
escapeHtml(이메일 렌더링 전용, 다른 매핑)은 app.js에 유지.

index.html: voice-call → helpers → chat-sse → app 순서로 로드.
node --check 통과, 재시작 후 /js/helpers.js 200 확인.

다음(B2)에서 helpers.js를 5개 파일로 세분화 예정.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-25 20:07:32 +09:00
kimandClaude e2dc133934 v4.3.19: sendChat SSE 함수를 chat-sse.js로 분리
app.js 1411-2092의 async function sendChat을 web-ui/js/chat-sse.js로
추출. 범위 내 top-level 선언은 sendChat 하나뿝이라 외부 노출 대상은
sendChat 단일. 끝에 window.sendChat 할당 추가. app.js에서 제거 후
index.html에서 app.js 직전에 로드.

공유 상태(currentAbortController/isThinking)와 외부 헬퍼
(authHeaders/renderChatMessages/addProcessEntry 등)는 전역 그대로
참조. node --check 통과, 재시작 후 /js/chat-sse.js 200 확인.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-25 20:05:41 +09:00
kimandClaude 7b74b2315d v4.3.18-1: web-ui 로고 경로 상대→절대 /homeclaw_logo.png 수정
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-25 19:44:42 +09:00
kimandClaude 52b373f2d4 v4.3.18: web-ui 폴더 정리 - html/js/css 분리, server.ts 레거시 리다이렉트 추가
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-25 19:39:44 +09:00