feat: batch wiki-fication of 00_Raw data
Applied double-save rule: Master Archive + Specialized Mapping for Skybound, Datacollector, and Frontend Mastery.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
# Datacollector - 인증 복구 후 자동 재개 상태 전환 수정
|
||||
|
||||
- 작성 시각: 2026-04-25 22:39:30 KST
|
||||
- 프로젝트: `/Volumes/Data/project/Antigravity/Datacollector`
|
||||
- 관련 파일: `src/components/AgentDashboard.tsx`, `src/lib/engine.ts`
|
||||
|
||||
## 상황
|
||||
|
||||
NotebookLM 인증 복구 로직을 강화했지만, 화면에서는 여전히 `CONTINUE MISSION` 버튼을 사용자가 눌러야 다음 큐가 이어지는 것처럼 보였다.
|
||||
|
||||
사용자 관찰:
|
||||
|
||||
- 작업은 일부 완료됨.
|
||||
- 큐에는 아직 작업이 많이 남아 있음.
|
||||
- 헤더 상태가 `IDLE`로 보임.
|
||||
- `CONTINUE MISSION` 버튼이 사용자의 수동 클릭을 기다림.
|
||||
|
||||
## 원인
|
||||
|
||||
프론트엔드 상태 전환에 빈틈이 있었다.
|
||||
|
||||
`AgentDashboard`의 `useEffect`는 `status !== 'running'`일 때 `KnowledgeEngine.stop()`을 호출한다. 그런데 기존 `stop()`은 내부 실행 플래그만 끄는 것이 아니라 항상 Zustand 상태까지 `idle`로 바꿨다.
|
||||
|
||||
그 결과 인증 오류 등으로 `paused` 상태를 유지해야 하는 경우에도 React effect를 지나면서 `paused -> idle`로 바뀌었다. 이렇게 되면 앱은 "복구 후 자동 재개 가능한 일시정지"가 아니라 "사용자가 다시 Continue를 눌러야 하는 대기 상태"처럼 동작했다.
|
||||
|
||||
## 조치
|
||||
|
||||
`src/lib/engine.ts`:
|
||||
|
||||
- `stop(updateStatus = true)` 형태로 변경했다.
|
||||
- 내부 엔진만 멈춰야 할 때는 UI 상태를 덮어쓰지 않도록 했다.
|
||||
|
||||
`src/components/AgentDashboard.tsx`:
|
||||
|
||||
- `status !== 'running'` effect에서는 `engine.stop(false)`를 호출하도록 변경했다.
|
||||
- `status === 'paused'`이고 큐가 남아 있으면 NotebookLM 연결 확인 후 자동으로 `running`으로 되돌리는 auto-resume effect를 추가했다.
|
||||
- 기존 버그로 이미 `idle`에 갇힌 화면도 구제하기 위해, 수동 정지나 작업 완료 로그가 없는 `idle + 남은 큐` 상태도 복구 가능한 멈춤으로 보고 자동 재개하도록 보강했다.
|
||||
- 중복 자동 재개를 막기 위해 `autoResumeRef` 잠금을 추가했다.
|
||||
|
||||
## 검증
|
||||
|
||||
다음 검증을 완료했다.
|
||||
|
||||
```bash
|
||||
npm run lint
|
||||
curl -sS -I http://127.0.0.1:3000
|
||||
curl -sS -X POST http://127.0.0.1:3002/api/check-connection
|
||||
```
|
||||
|
||||
결과:
|
||||
|
||||
- TypeScript 검사 통과
|
||||
- 프론트엔드 서버 응답 정상
|
||||
- NotebookLM 브리지 연결 확인 `success: true`
|
||||
|
||||
## 운영 메모
|
||||
|
||||
앞으로 인증 복구나 연결 복구로 인해 `paused` 상태가 되면 앱이 NotebookLM 연결을 확인하고 자동으로 다음 큐를 이어서 실행한다.
|
||||
|
||||
사용자가 직접 `STOP / PAUSE`를 누른 경우는 기존처럼 `idle`로 유지되므로, 수동 정지는 자동 재개 대상이 아니다.
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
# Datacollector Bridge Connection Refused Run Script Fix
|
||||
|
||||
Date: 2026-04-25 21:07:52 KST
|
||||
Project: Datacollector
|
||||
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
|
||||
|
||||
## Summary
|
||||
|
||||
사용자가 앱 실행 후 `POST http://127.0.0.1:3002/api/check-connection net::ERR_CONNECTION_REFUSED` 오류를 확인했다.
|
||||
이는 NotebookLM 인증 실패가 아니라 MCP Bridge 서버가 실행되지 않아 브라우저가 `3002` 포트에 연결하지 못한 상태였다.
|
||||
|
||||
## Root Cause
|
||||
|
||||
실행 경로가 여러 개였고 일부 경로는 프런트엔드 Vite 서버만 실행했다.
|
||||
|
||||
- `run_mac.command`: Bridge와 Vite를 함께 실행
|
||||
- `run_app.sh`: Vite만 실행
|
||||
- `npm run dev`: Vite만 실행
|
||||
|
||||
따라서 `run_app.sh` 또는 `npm run dev`로 앱을 켜면 UI는 열리지만 `/api/check-connection` 요청을 받을 Bridge 서버가 없어 `ERR_CONNECTION_REFUSED`가 발생했다.
|
||||
|
||||
## Changes Made
|
||||
|
||||
수정 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/run_app.sh`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/README.md`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/api.ts`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/engine.ts`
|
||||
|
||||
핵심 변경:
|
||||
|
||||
- `run_app.sh`가 Bridge 서버와 Vite 서버를 함께 실행하도록 변경
|
||||
- `run_app.sh` 시작 시 기존 `3000`, `3002` 포트 프로세스를 정리
|
||||
- 종료 시 Bridge 백그라운드 프로세스도 함께 종료하도록 trap 추가
|
||||
- README의 실행 안내를 `npm run dev` 단독에서 `./run_mac.command` 또는 `npm run start-full`로 변경
|
||||
- `src/lib/api.ts`에 `bridgeFetch()` 추가
|
||||
- Bridge 연결 실패 시 `Failed to fetch` 대신 “Bridge 서버가 실행되지 않았다”는 안내 메시지를 표시하도록 변경
|
||||
- `VITE_BRIDGE_URL`로 Bridge 주소를 override할 수 있게 함
|
||||
|
||||
## Verification
|
||||
|
||||
실행한 검증:
|
||||
|
||||
```bash
|
||||
node --check scripts/mcp_bridge.mjs
|
||||
npm run lint
|
||||
npm run build
|
||||
```
|
||||
|
||||
검증 결과:
|
||||
|
||||
- 브리지 문법 체크 통과
|
||||
- TypeScript 타입체크 통과
|
||||
- Vite 프로덕션 빌드 통과
|
||||
|
||||
## Operational Note
|
||||
|
||||
앞으로 앱은 아래 방식으로 실행해야 한다.
|
||||
|
||||
```bash
|
||||
./run_mac.command
|
||||
```
|
||||
|
||||
또는 수동으로 두 서버를 같이 실행한다.
|
||||
|
||||
```bash
|
||||
npm run start-full
|
||||
```
|
||||
|
||||
`npm run dev`만 실행하면 프런트엔드만 뜨므로 NotebookLM, Wiki save, 인증 복구 API가 동작하지 않는다.
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
# Datacollector Codebase Structure Review and Initial Risk Assessment
|
||||
|
||||
Date: 2026-04-25 20:38:01 KST
|
||||
Project: Datacollector
|
||||
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
|
||||
Knowledge Vault: `/Volumes/Data/project/Antigravity/Wiki/00_Raw`
|
||||
|
||||
## Summary
|
||||
|
||||
이 문서는 Datacollector 프로젝트의 첫 구조 파악 및 초기 코드 리뷰 결과를 정리한 기록이다.
|
||||
이번 검토의 목적은 이후 기능 개발 전에 현재 시스템의 책임 분리, 실행 흐름, 외부 의존성, 그리고 우선적으로 손봐야 할 위험 요소를 이해하는 데 있다.
|
||||
|
||||
현재 프로젝트는 단순한 프런트엔드 앱이 아니라, React 기반 UI와 Zustand 상태 저장소, 자율 실행 엔진, 그리고 NotebookLM MCP 및 로컬 LM을 연결하는 Express 브리지 서버가 결합된 자동화 연구 도구 형태로 구성되어 있다.
|
||||
|
||||
## High-Level Architecture
|
||||
|
||||
전체 흐름은 아래와 같다.
|
||||
|
||||
`React UI -> Zustand Store -> KnowledgeEngine -> Express Bridge -> NotebookLM MCP / Local LM / GitHub / Wiki Storage`
|
||||
|
||||
핵심 책임 분리는 다음과 같이 이해했다.
|
||||
|
||||
- `src/components/AgentDashboard.tsx`
|
||||
사용자 인터페이스, 미션 시작/중지/재개, 설정 입력, 로그 표시, 수동 커밋 등 상호작용 담당
|
||||
- `src/store/agentStore.ts`
|
||||
앱 전체 설정값과 실행 상태를 보관하는 단일 전역 상태 저장소
|
||||
- `src/lib/engine.ts`
|
||||
큐를 소비하며 연구, 합성, 링크 추출, 다음 토픽 확장을 반복하는 자율 엔진
|
||||
- `src/lib/gemini.ts`
|
||||
NotebookLM 미연결 시 사용하는 로컬 LM 프롬프트 생성 및 응답 파싱
|
||||
- `src/lib/github.ts`
|
||||
결과 Markdown을 GitHub 저장소의 `00_Raw/` 경로로 업로드
|
||||
- `scripts/mcp_bridge.mjs`
|
||||
NotebookLM MCP 서버와 통신하는 지속 프로세스형 브리지 서버
|
||||
|
||||
## Execution Flow
|
||||
|
||||
실행 흐름은 다음 순서로 이해했다.
|
||||
|
||||
1. 사용자가 `AgentDashboard`에서 주제를 입력하고 미션을 시작한다.
|
||||
2. 주제와 설정이 `agentStore`에 기록되고 상태가 `running`으로 바뀐다.
|
||||
3. `status` 변경을 감지한 UI가 `KnowledgeEngine` 싱글톤을 시작한다.
|
||||
4. `KnowledgeEngine`는 큐의 첫 항목을 읽고 현재 깊이와 루트 주제를 기준으로 처리 여부를 결정한다.
|
||||
5. NotebookLM 연결 상태가 좋으면 브리지 서버를 통해 리서치와 합성을 수행한다.
|
||||
6. NotebookLM이 없으면 로컬 LM 프록시(`/api/lm`)를 통해 대체 연구를 진행한다.
|
||||
7. 생성된 Markdown에서 위키 링크를 추출해 다음 큐를 구성한다.
|
||||
8. 결과는 pending commits, completed 목록, 로컬 위키 Raw 저장소 등에 반영된다.
|
||||
|
||||
## Current Structure Notes
|
||||
|
||||
이번 시점에서 구조적으로 눈에 띈 특징은 다음과 같다.
|
||||
|
||||
- 상태 관리가 거의 전부 Zustand store 하나에 집중되어 있어 흐름 추적은 쉽다.
|
||||
- 대신 엔진과 UI가 store를 매우 직접적으로 공유해서 결합도가 높다.
|
||||
- NotebookLM 경로와 Local LM 경로가 모두 존재해 fallback 전략은 분명하다.
|
||||
- 브리지 서버가 프런트엔드 백엔드이자 외부 도구 래퍼 역할까지 함께 맡고 있어 책임이 넓다.
|
||||
- 문서 저장 흐름이 GitHub 업로드와 로컬 위키 저장으로 이중화되어 있다.
|
||||
|
||||
## Review Findings
|
||||
|
||||
### 1. Sensitive secrets are persisted in browser storage
|
||||
|
||||
`githubToken`과 `notebookLmCookies`가 Zustand persist 설정에 포함되어 있어 브라우저 localStorage에 평문으로 저장된다.
|
||||
이 방식은 세션 쿠키나 GitHub 토큰 같은 민감 정보의 저장 위치로는 안전하지 않다.
|
||||
|
||||
관련 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/store/agentStore.ts`
|
||||
|
||||
영향:
|
||||
|
||||
- 같은 브라우저 프로필을 사용하는 다른 코드나 도구가 정보에 접근할 수 있다.
|
||||
- 장기적으로 토큰 유출 위험이 커진다.
|
||||
|
||||
### 2. Bridge server is exposed too broadly
|
||||
|
||||
브리지 서버는 `0.0.0.0:3002`로 열리고 CORS도 전부 허용한다.
|
||||
또한 `/api/lm`은 클라이언트가 전달한 임의의 URL로 요청을 프록시할 수 있다.
|
||||
|
||||
관련 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
|
||||
|
||||
영향:
|
||||
|
||||
- 로컬 개발용으로는 편하지만, 같은 네트워크 안에서 예상하지 않은 접근 통로가 될 수 있다.
|
||||
- 사실상 무인증 프록시처럼 동작할 여지가 있다.
|
||||
|
||||
### 3. Environment portability is weak
|
||||
|
||||
MCP 실행 파일 경로와 위키 저장 경로가 절대경로로 하드코딩되어 있다.
|
||||
|
||||
관련 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
|
||||
|
||||
영향:
|
||||
|
||||
- 다른 개발자 머신, 다른 사용자 계정, 다른 운영체제에서 그대로 실행하기 어렵다.
|
||||
- 배포보다는 특정 개인 작업 환경에 강하게 종속된다.
|
||||
|
||||
### 4. Manual handoff state is not fully cleared
|
||||
|
||||
`resolveManualNext`가 store에 함수 형태로 저장되는데, `clearState()`에서 정리되지 않는다.
|
||||
수동 합성 대기 중 reset 또는 새 미션 시작이 발생하면 상태 꼬임 가능성이 있다.
|
||||
|
||||
관련 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/store/agentStore.ts`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/engine.ts`
|
||||
|
||||
영향:
|
||||
|
||||
- 이전 미션의 대기 상태가 다음 미션에 잔존할 수 있다.
|
||||
- UI 버튼 상태와 실제 엔진 대기 상태가 어긋날 수 있다.
|
||||
|
||||
### 5. API endpoint usage is duplicated and hardcoded
|
||||
|
||||
프런트엔드에는 이미 Vite 프록시가 설정되어 있지만, UI와 엔진 코드 곳곳에서 `http://127.0.0.1:3002`를 직접 호출하고 있다.
|
||||
|
||||
관련 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/engine.ts`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/vite.config.ts`
|
||||
|
||||
영향:
|
||||
|
||||
- 포트 변경이나 배포 환경 변경 시 수정 지점이 늘어난다.
|
||||
- 런타임 경로 설정이 한 군데에서 관리되지 않는다.
|
||||
|
||||
## Validation Performed
|
||||
|
||||
이번 검토 중 아래 확인을 수행했다.
|
||||
|
||||
- 저장소 파일 구조 및 진입점 확인
|
||||
- UI, store, engine, bridge, GitHub, Local LM 계층 코드 확인
|
||||
- `npm run lint` 실행
|
||||
|
||||
검증 결과:
|
||||
|
||||
- TypeScript 타입체크는 현재 통과했다.
|
||||
|
||||
## Suggested Next Priorities
|
||||
|
||||
우선순위는 아래 순서가 적절하다.
|
||||
|
||||
1. 민감 정보 저장 방식을 localStorage 바깥으로 이동하거나 최소한 분리
|
||||
2. 브리지 서버 바인딩 범위와 CORS 정책 축소
|
||||
3. 절대경로를 환경변수 또는 설정 파일로 치환
|
||||
4. `resolveManualNext`를 포함한 미션 종료 정리 로직 강화
|
||||
5. API 베이스 URL을 단일 설정 지점으로 통합
|
||||
|
||||
## Working Agreement For Future Notes
|
||||
|
||||
사용자 요청에 따라, 앞으로 Datacollector 관련 조사/분석/리뷰 결과는 가능하면 이 지식 창고 경로에 계속 기록한다.
|
||||
|
||||
기본 원칙:
|
||||
|
||||
- 위치: `/Volumes/Data/project/Antigravity/Wiki/00_Raw`
|
||||
- 파일명: `YYYY-MM-DD-<Project>_<Topic>.md` 또는 기존 저장소 관례와 유사한 읽기 쉬운 영어 제목
|
||||
- 내용: 작업 목적, 파악한 구조, 핵심 발견사항, 다음 액션을 포함
|
||||
|
||||
## Source Files Reviewed
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/README.md`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/package.json`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/vite.config.ts`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/main.tsx`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/App.tsx`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/store/agentStore.ts`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/engine.ts`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/gemini.ts`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/github.ts`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_caller.py`
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
# Datacollector Local Wiki Save Only Output Mode
|
||||
|
||||
Date: 2026-04-25 20:50:41 KST
|
||||
Project: Datacollector
|
||||
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
|
||||
|
||||
## Summary
|
||||
|
||||
Datacollector의 생성 결과 저장 방식을 GitHub 업로드 중심에서 로컬 Wiki 저장 전용으로 정리했다.
|
||||
앞으로 앱에서 생성되는 연구 문서는 `/Volumes/Data/project/Antigravity/Wiki/00_Raw`에 저장되고, Git 업로드는 사용자가 나중에 별도로 한 번에 처리하는 운영 방식으로 둔다.
|
||||
|
||||
## Previous Behavior
|
||||
|
||||
기존 흐름은 결과 생성 후 두 경로가 동시에 존재했다.
|
||||
|
||||
- 로컬 Wiki Raw 폴더에 자동 저장
|
||||
- `pendingCommits`에 결과를 쌓고 UI의 `BATCH COMMIT` 버튼으로 GitHub 업로드 가능
|
||||
|
||||
이 방식은 앱 안에 GitHub 토큰과 저장소 설정을 유지해야 했고, 사용자가 의도하지 않아도 Git 업로드 기능이 계속 노출되는 구조였다.
|
||||
|
||||
## New Behavior
|
||||
|
||||
새 흐름은 다음과 같다.
|
||||
|
||||
1. 연구 결과 Markdown 생성
|
||||
2. `savedReports`에 프리뷰용 로컬 캐시 저장
|
||||
3. 브리지 서버의 `/api/wiki/save`를 통해 `/Volumes/Data/project/Antigravity/Wiki/00_Raw`에 Markdown 파일 저장
|
||||
4. GitHub 업로드 버튼이나 토큰 설정 없이 완료
|
||||
|
||||
GitHub 업로드는 앱이 수행하지 않는다.
|
||||
|
||||
## Changes Made
|
||||
|
||||
수정 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/store/agentStore.ts`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/engine.ts`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/.env.example`
|
||||
|
||||
삭제 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/github.ts`
|
||||
|
||||
핵심 변경:
|
||||
|
||||
- `githubToken`, `githubRepoUrl` 상태 제거
|
||||
- `pendingCommits` 제거
|
||||
- `addPendingCommit`, `clearPendingCommits` 제거
|
||||
- `savedReports`와 `addSavedReport` 추가
|
||||
- `BATCH COMMIT` 버튼 제거
|
||||
- 설정 모달의 GitHub Wiki Sync 섹션 제거
|
||||
- `.env.example`의 GitHub 설정 제거
|
||||
- 생성 결과는 기존 Wiki 저장 API를 통해 로컬 Raw 폴더에만 저장
|
||||
|
||||
## Verification
|
||||
|
||||
실행한 검증:
|
||||
|
||||
```bash
|
||||
npm run lint
|
||||
npm run build
|
||||
```
|
||||
|
||||
검증 결과:
|
||||
|
||||
- TypeScript 타입체크 통과
|
||||
- Vite 프로덕션 빌드 통과
|
||||
|
||||
## Notes
|
||||
|
||||
로컬 Wiki 저장은 기존 브리지 서버의 `/api/wiki/save` 라우트를 그대로 사용한다.
|
||||
저장 대상 경로는 현재 브리지 서버에 하드코딩된 `/Volumes/Data/project/Antigravity/Wiki/00_Raw`이다.
|
||||
추후 이 경로도 `.env` 설정으로 분리하면 다른 머신이나 폴더 구조에서도 더 쉽게 운영할 수 있다.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Datacollector Mac Windows Launcher Scripts
|
||||
|
||||
Date: 2026-04-25 21:09:42 KST
|
||||
Project: Datacollector
|
||||
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
|
||||
|
||||
## Summary
|
||||
|
||||
Datacollector 실행 시 Vite 프런트엔드만 뜨고 MCP Bridge 서버가 뜨지 않아 `ERR_CONNECTION_REFUSED`가 발생할 수 있었다.
|
||||
이를 막기 위해 맥용과 윈도우용 실행 파일을 명확히 정리했다.
|
||||
|
||||
## Main Launchers
|
||||
|
||||
- macOS: `/Volumes/Data/project/Antigravity/Datacollector/run_mac.command`
|
||||
- Windows: `/Volumes/Data/project/Antigravity/Datacollector/run_win.bat`
|
||||
|
||||
두 실행 파일 모두 아래를 수행한다.
|
||||
|
||||
1. 프로젝트 폴더로 이동
|
||||
2. `node_modules`가 없으면 `npm install`
|
||||
3. 기존 `3000`, `3002` 포트 프로세스 정리
|
||||
4. MCP Bridge 서버 실행
|
||||
5. Vite 앱 실행
|
||||
|
||||
## Compatibility Wrappers
|
||||
|
||||
기존 실행 파일과의 호환성을 위해 아래 파일은 메인 실행 파일로 위임하도록 단순화했다.
|
||||
|
||||
- `run_app.sh` -> `run_mac.command`
|
||||
- `run_app.bat` -> `run_win.bat`
|
||||
|
||||
## Verification
|
||||
|
||||
실행한 검증:
|
||||
|
||||
```bash
|
||||
bash -n run_mac.command
|
||||
bash -n run_app.sh
|
||||
npm run lint
|
||||
```
|
||||
|
||||
검증 결과:
|
||||
|
||||
- macOS shell script 문법 통과
|
||||
- TypeScript 타입체크 통과
|
||||
|
||||
## Operational Note
|
||||
|
||||
앞으로 맥에서는 `run_mac.command`, 윈도우에서는 `run_win.bat`만 실행하면 된다.
|
||||
`npm run dev` 단독 실행은 프런트엔드만 켜므로 NotebookLM, Wiki save, 인증 복구 API가 동작하지 않는다.
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
# Datacollector - NotebookLM 인증 브라우저 유지 및 오래된 .env 쿠키 우선순위 문제 해결
|
||||
|
||||
- 작성 시각: 2026-04-25 21:31:00 KST
|
||||
- 프로젝트: `/Volumes/Data/project/Antigravity/Datacollector`
|
||||
- 관련 파일: `scripts/mcp_bridge.mjs`, `auth_mac.command`, `auth_win.bat`, `.env.example`
|
||||
|
||||
## 상황
|
||||
|
||||
앱에서 `/api/check-connection` 호출이 500으로 실패했고, 화면에는 다음과 같은 메시지가 반복되었다.
|
||||
|
||||
- `Authentication expired`
|
||||
- `인증 자동 복구 실패. 브라우저 로그인이 필요한 상태일 수 있습니다.`
|
||||
- `MCP initialized: true, pending: 0`
|
||||
|
||||
사용자는 NotebookLM 인증 중 Chrome이 열렸다가 닫히는 점을 보고, 인증 브라우저를 유지해야 하는 것 아니냐고 질문했다.
|
||||
|
||||
## 확인한 내용
|
||||
|
||||
`notebooklm-mcp-auth` 소스 확인 결과, 기본 자동 실행 모드는 인증 후 자신이 띄운 Chrome 프로세스를 종료한다. 반면 `--no-auto-launch --port ... --user-data-dir ...` 모드는 이미 떠 있는 Chrome 디버깅 세션에 붙기 때문에 인증 브라우저를 유지할 수 있다.
|
||||
|
||||
브리지에서 Chrome을 유지하도록 바꾼 뒤 인증 CLI는 성공했다. 하지만 MCP 서버의 `notebook_list`는 여전히 `Authentication expired`를 반환했다.
|
||||
|
||||
추가 확인 결과, `.env`에 예전 `NOTEBOOKLM_COOKIES` 값이 남아 있었다. `scripts/mcp_bridge.mjs`가 `dotenv/config`를 로드한 뒤 MCP 서버를 자식 프로세스로 실행하면서 이 오래된 환경변수 쿠키가 `~/.notebooklm-mcp/auth.json`의 최신 인증 캐시보다 우선 적용되고 있었다.
|
||||
|
||||
즉 실제 핵심 원인은 다음 조합이었다.
|
||||
|
||||
- 인증 CLI는 최신 쿠키를 `~/.notebooklm-mcp/auth.json`에 정상 저장함.
|
||||
- 브리지는 `.env`의 오래된 `NOTEBOOKLM_COOKIES`를 MCP 자식 프로세스에 전달함.
|
||||
- MCP 서버는 캐시 파일보다 환경변수를 우선 사용함.
|
||||
- 결과적으로 새 인증 후에도 MCP는 계속 오래된 쿠키로 NotebookLM API를 호출함.
|
||||
|
||||
## 조치
|
||||
|
||||
`scripts/mcp_bridge.mjs`에서 기본적으로 MCP 자식 프로세스와 인증 CLI 자식 프로세스에 `NOTEBOOKLM_COOKIES`, `NOTEBOOKLM_CSRF_TOKEN`, `NOTEBOOKLM_SESSION_ID`를 넘기지 않도록 수정했다.
|
||||
|
||||
명시적으로 환경변수 인증을 사용해야 할 경우에는 `.env`에 아래 값을 둔다.
|
||||
|
||||
```env
|
||||
USE_NOTEBOOKLM_ENV_AUTH="true"
|
||||
```
|
||||
|
||||
기본값은 `false`이며, 이 경우 `notebooklm-mcp-auth`가 생성한 `~/.notebooklm-mcp/auth.json` 캐시를 우선 사용한다.
|
||||
|
||||
또한 `auth_mac.command`, `auth_win.bat`는 별도 Chrome 프로필과 디버깅 포트를 사용해 NotebookLM 인증 브라우저를 열어두는 방식으로 변경했다.
|
||||
|
||||
## 검증
|
||||
|
||||
다음 검증을 완료했다.
|
||||
|
||||
```bash
|
||||
node --check scripts/mcp_bridge.mjs
|
||||
npm run lint
|
||||
curl -sS -X POST http://127.0.0.1:3002/api/check-connection
|
||||
```
|
||||
|
||||
결과:
|
||||
|
||||
```json
|
||||
{"success":true,"count":0}
|
||||
```
|
||||
|
||||
직접 Python MCP 클라이언트로도 같은 인증 캐시를 사용해 `list_notebooks` 호출이 성공했고, 노트북 89개를 읽는 것을 확인했다.
|
||||
|
||||
## 운영 메모
|
||||
|
||||
앞으로는 `.env`에 오래된 `NOTEBOOKLM_COOKIES`가 남아 있어도 기본 브리지 실행에는 영향을 주지 않는다. 다만 혼란을 줄이려면 장기적으로 `.env`에서 `NOTEBOOKLM_COOKIES` 줄을 삭제하거나 주석 처리하는 것이 좋다.
|
||||
|
||||
NotebookLM 인증용 Chrome 창은 닫지 않는 것이 좋다. 인증이 풀렸을 때 브리지가 같은 디버깅 포트의 Chrome 세션에 붙어 자동 복구를 시도할 수 있다.
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
# Datacollector NotebookLM Automatic Auth Recovery
|
||||
|
||||
Date: 2026-04-25 20:47:05 KST
|
||||
Project: Datacollector
|
||||
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
|
||||
|
||||
## Summary
|
||||
|
||||
컴퓨터 포맷 이후 NotebookLM MCP 인증이 자주 실패하고, 20-30분마다 `auth_mac.command`를 수동 실행해야 하는 문제가 있었다.
|
||||
이번 작업에서는 인증 만료 시 브리지 서버가 자동으로 복구를 시도하도록 개선했다.
|
||||
|
||||
## Root Cause Hypothesis
|
||||
|
||||
기존 구조는 MCP 서버의 `refresh_auth` 도구 호출에만 의존했다.
|
||||
하지만 포맷 이후 로컬 토큰 저장 위치나 Chrome 세션 상태가 달라지면서 `refresh_auth`만으로 복구되지 않는 상황이 발생할 수 있다.
|
||||
|
||||
사용자가 직접 실행하던 파일은 다음 명령의 래퍼였다.
|
||||
|
||||
```bash
|
||||
/Users/g1nation_mac/.local/bin/notebooklm-mcp-auth
|
||||
```
|
||||
|
||||
따라서 자동 복구 흐름에도 이 CLI 인증 명령을 포함시키는 것이 가장 직접적인 개선 방향이다.
|
||||
|
||||
## Changes Made
|
||||
|
||||
수정 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/.env.example`
|
||||
|
||||
핵심 변경:
|
||||
|
||||
- 브리지 서버가 `.env`를 읽도록 `dotenv/config`를 추가했다.
|
||||
- `AUTH_PATH`, `AUTH_ARGS`, `AUTH_TIMEOUT_MS`, `AUTH_REFRESH_INTERVAL_MS` 설정을 추가했다.
|
||||
- MCP 인증 에러 발생 시 `refresh_auth`를 먼저 시도한다.
|
||||
- `refresh_auth` 실패 시 MCP 프로세스를 재시작하고 다시 갱신을 시도한다.
|
||||
- 그래도 실패하면 `notebooklm-mcp-auth` CLI를 브리지 서버가 직접 실행한다.
|
||||
- CLI 인증 후 MCP 프로세스를 재시작해 새 토큰을 읽게 만든다.
|
||||
- 장시간 실행 중에는 15분 간격으로 요청이 없는 시점에 인증 상태를 사전 갱신한다.
|
||||
- UI 안내 문구를 수동 재인증 중심에서 자동 복구 중심으로 수정했다.
|
||||
|
||||
## Runtime Behavior
|
||||
|
||||
새 인증 복구 순서:
|
||||
|
||||
1. NotebookLM MCP 요청 실패
|
||||
2. 에러 메시지가 인증 관련인지 판단
|
||||
3. `refresh_auth` 호출
|
||||
4. MCP 프로세스 재시작 후 `refresh_auth` 재시도
|
||||
5. `notebooklm-mcp-auth` CLI 자동 실행
|
||||
6. MCP 프로세스 재시작
|
||||
7. 원래 실패했던 NotebookLM 요청 재시도
|
||||
|
||||
주기적 갱신:
|
||||
|
||||
- 기본 간격: 15분
|
||||
- 설정값: `AUTH_REFRESH_INTERVAL_MS=900000`
|
||||
- 진행 중인 MCP 요청이 있을 때는 건드리지 않고 건너뛴다.
|
||||
|
||||
## Verification
|
||||
|
||||
실행한 검증:
|
||||
|
||||
```bash
|
||||
node --check scripts/mcp_bridge.mjs
|
||||
npm run lint
|
||||
npm run bridge
|
||||
curl -s http://127.0.0.1:3002/api/health
|
||||
```
|
||||
|
||||
검증 결과:
|
||||
|
||||
- `node --check` 통과
|
||||
- TypeScript 타입체크 통과
|
||||
- 브리지 서버 시작 성공
|
||||
- MCP 서버 초기화 성공
|
||||
- `/api/health`에서 `connected: true`, `version: 3.3.0`, `authPath` 확인
|
||||
|
||||
## Notes
|
||||
|
||||
완전히 백그라운드 인증이 가능한지는 Google/Chrome 세션 상태에 의존한다.
|
||||
브라우저 로그인이 만료되어 실제 사용자 로그인이 필요한 상태라면 자동 CLI 실행도 브라우저 로그인을 요구할 수 있다.
|
||||
다만 기존처럼 매번 사용자가 batch 파일을 직접 실행하는 흐름보다, 일반적인 토큰 만료와 MCP refresh 실패 상황은 브리지 서버가 먼저 복구하도록 개선되었다.
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
# Datacollector - NotebookLM 자동 재인증 검증 강화 및 동시 복구 잠금
|
||||
|
||||
- 작성 시각: 2026-04-25 22:17:33 KST
|
||||
- 프로젝트: `/Volumes/Data/project/Antigravity/Datacollector`
|
||||
- 관련 파일: `scripts/mcp_bridge.mjs`
|
||||
|
||||
## 상황
|
||||
|
||||
인증 브라우저 유지와 오래된 `.env` 쿠키 우선순위 문제를 해결한 뒤에도, 실제 작업 중 인증이 풀렸을 때 완전히 자동으로 재인증되지 않는 문제가 남아 있었다.
|
||||
|
||||
화면에서는 작업은 진행되지만 사용자가 기대한 "인증 만료 감지 -> 자동 재인증 -> 원래 작업 재시도" 흐름이 안정적으로 보장되지 않았다.
|
||||
|
||||
## 원인
|
||||
|
||||
브리지에는 자동 복구 로직이 있었지만 두 가지 빈틈이 있었다.
|
||||
|
||||
- `refresh_auth` 호출이 성공해도 실제 NotebookLM API 호출이 가능한지 검증하지 않았다.
|
||||
- `/api/re-auth`와 `/api/check-connection` 같은 요청이 동시에 들어오면 각각 MCP 재시작과 인증 복구를 시도해서 프로세스 재시작 경합이 생길 수 있었다.
|
||||
|
||||
추가로 인증 오류 판별 문자열에 `expired`, `RPC Error 16`, `csrf`, `만료` 같은 케이스가 충분히 포함되지 않아 일부 인증 만료 메시지가 일반 오류로 처리될 가능성이 있었다.
|
||||
|
||||
## 조치
|
||||
|
||||
`scripts/mcp_bridge.mjs`에서 다음을 수정했다.
|
||||
|
||||
- 재인증 성공 기준을 `refresh_auth` 성공이 아니라 실제 `notebook_list` 호출 성공으로 강화했다.
|
||||
- 인증 만료 감지 시 `refreshAuth({ allowExternalAuth: true })`를 통해 자동 CLI 인증 복구까지 이어지도록 정리했다.
|
||||
- 주기적 인증 점검도 필요 시 외부 인증 CLI 복구를 허용하도록 변경했다.
|
||||
- `_refreshAuthPromise` 잠금을 추가해 동시 재인증/재시작 요청이 서로 충돌하지 않게 했다.
|
||||
- 인증 오류 감지 키워드에 `expired`, `rpc error 16`, `csrf`, `unauthorized`, `forbidden`, `인증`, `만료`를 추가했다.
|
||||
|
||||
## 검증
|
||||
|
||||
다음 검증을 완료했다.
|
||||
|
||||
```bash
|
||||
node --check scripts/mcp_bridge.mjs
|
||||
npm run lint
|
||||
curl -sS -X POST http://127.0.0.1:3002/api/re-auth
|
||||
curl -sS -X POST http://127.0.0.1:3002/api/check-connection
|
||||
```
|
||||
|
||||
결과:
|
||||
|
||||
- `/api/re-auth`: `success: true`
|
||||
- `/api/check-connection`: `success: true`
|
||||
|
||||
또한 `/api/re-auth`와 `/api/check-connection`을 동시에 호출해도 둘 다 성공하는 것을 확인했다.
|
||||
|
||||
## 운영 메모
|
||||
|
||||
이제 인증이 풀린 상태에서 NotebookLM MCP 호출이 인증 오류를 반환하면 브리지가 다음 순서로 자동 복구한다.
|
||||
|
||||
1. MCP의 `refresh_auth` 실행
|
||||
2. 실제 `notebook_list` 호출로 인증 유효성 검증
|
||||
3. 실패 시 MCP 프로세스 재시작 후 재검증
|
||||
4. 그래도 실패하면 `notebooklm-mcp-auth` CLI 실행
|
||||
5. 인증 캐시 정리 후 MCP 재시작 및 실제 호출 검증
|
||||
|
||||
NotebookLM 브라우저 세션이 완전히 로그아웃된 상태라면 자동 CLI도 브라우저 로그인을 요구할 수 있다. 이 경우 사용자가 열린 NotebookLM Chrome 창에서 로그인만 해두면 이후 자동 복구가 다시 이어질 수 있다.
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
# Datacollector NotebookLM Connection Guard and MCP Restart Fix
|
||||
|
||||
Date: 2026-04-25 21:02:35 KST
|
||||
Project: Datacollector
|
||||
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
|
||||
|
||||
## Summary
|
||||
|
||||
실행 중 NotebookLM 연결 체크가 500 에러를 반환한 뒤에도 미션이 계속 시작되어 Local LM fallback으로 넘어가고, 결국 `Local LM returned an empty or invalid response` 에러가 발생했다.
|
||||
또한 브리지의 MCP 재시작 로직에서 자동 재시작과 수동 재시작이 겹쳐 여러 `notebooklm-mcp` 프로세스가 남는 문제가 확인되었다.
|
||||
|
||||
## Observed Errors
|
||||
|
||||
브라우저 콘솔:
|
||||
|
||||
```text
|
||||
:3000/favicon.ico 404 (Not Found)
|
||||
127.0.0.1:3002/api/check-connection 500 (Internal Server Error)
|
||||
```
|
||||
|
||||
앱 로그:
|
||||
|
||||
```text
|
||||
NotebookLM 연결 실패: 인증 자동 복구 실패...
|
||||
GENERAL MODE
|
||||
ENGINE ERROR Local LM returned an empty or invalid response.
|
||||
```
|
||||
|
||||
## Root Causes
|
||||
|
||||
1. `testNotebookLmConnection()`이 성공 여부를 반환하지 않았다.
|
||||
2. `handleStart`, `handleResume`, `handleGlobalResume`이 연결 실패 후에도 그대로 `running` 상태로 넘어갔다.
|
||||
3. `restart()`가 MCP 프로세스 종료 이벤트를 기다리지 않고 바로 새 프로세스를 띄울 수 있었다.
|
||||
4. `close` 이벤트의 자동 재시작이 수동 재시작과 겹쳐 MCP 하위 프로세스가 누적될 수 있었다.
|
||||
5. favicon 파일이 없어서 브라우저가 `/favicon.ico` 기본 요청을 404로 표시했다.
|
||||
|
||||
## Changes Made
|
||||
|
||||
수정 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/index.html`
|
||||
|
||||
추가 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/public/favicon.svg`
|
||||
|
||||
핵심 변경:
|
||||
|
||||
- `testNotebookLmConnection()`이 `Promise<boolean>`을 반환하도록 변경
|
||||
- NotebookLM 연결 실패 시 신규 미션 시작, 개별 재개, 전체 재개를 보류
|
||||
- 연결 실패 후 Local LM fallback으로 자동 진행되는 흐름 차단
|
||||
- MCP 프로세스를 종료할 때 `close` 이벤트를 기다리는 `_stopCurrentProcess()` 추가
|
||||
- 재시작 중 자동 재시작이 중복 실행되지 않도록 제어
|
||||
- 재시작 테스트 후 MCP 하위 프로세스가 하나만 남는지 확인
|
||||
- SVG favicon 추가 및 `index.html`에 명시
|
||||
|
||||
## Verification
|
||||
|
||||
실행한 검증:
|
||||
|
||||
```bash
|
||||
node --check scripts/mcp_bridge.mjs
|
||||
npm run lint
|
||||
npm run build
|
||||
npm run bridge
|
||||
curl -s http://127.0.0.1:3002/api/health
|
||||
curl -s -X POST http://127.0.0.1:3002/api/restart
|
||||
```
|
||||
|
||||
검증 결과:
|
||||
|
||||
- 브리지 문법 체크 통과
|
||||
- TypeScript 타입체크 통과
|
||||
- Vite 빌드 통과
|
||||
- 브리지 시작 성공
|
||||
- `/api/health` 응답 정상
|
||||
- `/api/restart` 후 `notebooklm-mcp` 프로세스가 하나만 남는 것 확인
|
||||
|
||||
## Operational Note
|
||||
|
||||
현재 실행 중이던 오래된 브리지와 누적된 MCP 하위 프로세스는 종료했다.
|
||||
앱은 다시 실행해야 새 브리지 로직이 적용된다.
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
# Datacollector NotebookLM Progress Visibility and Auth Diagnosis
|
||||
|
||||
Date: 2026-04-25 21:17:24 KST
|
||||
Project: Datacollector
|
||||
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
|
||||
|
||||
## Summary
|
||||
|
||||
사용자가 UI에서 `NotebookLM 연결 상태 점검 중...` 로그만 반복되고 실제 진행 상황을 알 수 없다고 보고했다.
|
||||
확인 결과 앱이 프로젝트 생성 단계까지 가지 못하고 있었으며, 원인은 NotebookLM 연결 확인 단계에서 MCP 인증이 만료 상태로 판단되기 때문이었다.
|
||||
|
||||
## Observed State
|
||||
|
||||
확인한 상태:
|
||||
|
||||
- Vite 서버 `3000` 실행 중
|
||||
- MCP Bridge 서버 `3002` 실행 중
|
||||
- `notebooklm-mcp` 프로세스 실행 중
|
||||
- `/api/health` 응답 가능
|
||||
- `/api/check-connection`은 NotebookLM 인증 만료 오류 반환
|
||||
|
||||
브리지 로그상 자동 인증 CLI는 Chrome을 열고 로그인 및 토큰 추출까지 수행했다.
|
||||
그러나 MCP 서버는 이후에도 `Authentication expired`로 판단하여 NotebookLM notebook list 호출에 실패했다.
|
||||
|
||||
## Changes Made
|
||||
|
||||
수정 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
|
||||
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
|
||||
|
||||
핵심 변경:
|
||||
|
||||
- MCP 초기화 타임아웃 추가: `MCP_INIT_TIMEOUT_MS`
|
||||
- NotebookLM 연결 확인 타임아웃 추가: `MCP_HEALTH_TIMEOUT_MS`
|
||||
- `/api/health`에 상세 상태 추가
|
||||
- `initialized`, `processRunning`, `processPid`, `pendingRequests`, `authStatus` 노출
|
||||
- 인증 CLI 진행 단계(`starting`, `running`, `restarting`, `success`, `failed`) 추적
|
||||
- UI 연결 점검 중 5초마다 Bridge/MCP/auth 진행 상태 로그 출력
|
||||
- 중복 연결 점검 요청은 기존 Promise를 재사용하도록 변경
|
||||
|
||||
## Verification
|
||||
|
||||
실행한 검증:
|
||||
|
||||
```bash
|
||||
node --check scripts/mcp_bridge.mjs
|
||||
npm run lint
|
||||
npm run build
|
||||
curl -sS --max-time 5 http://127.0.0.1:3002/api/health
|
||||
curl -sS --max-time 25 -X POST -H 'Content-Type: application/json' -d '{}' http://127.0.0.1:3002/api/check-connection
|
||||
```
|
||||
|
||||
검증 결과:
|
||||
|
||||
- 브리지 문법 체크 통과
|
||||
- TypeScript 타입체크 통과
|
||||
- Vite 빌드 통과
|
||||
- Bridge/MCP 프로세스는 실행됨
|
||||
- NotebookLM 연결 확인은 인증 만료 오류로 실패
|
||||
|
||||
## Current Diagnosis
|
||||
|
||||
현재 문제는 앱 실행이나 Bridge 연결 문제가 아니라 NotebookLM MCP 인증 상태 문제다.
|
||||
자동 인증 CLI가 토큰을 저장해도 MCP 서버가 계속 만료로 판단하므로, 다음 단계에서는 NotebookLM MCP 패키지의 인증 저장 형식 또는 권장 인증 방식(`--file` 모드 등)을 확인해야 한다.
|
||||
|
||||
## Operational Note
|
||||
|
||||
확인용으로 실행했던 Bridge/Vite/MCP 프로세스는 종료했다.
|
||||
새 진행 상태 로그를 보려면 앱을 `run_mac.command`로 다시 실행해야 한다.
|
||||
Reference in New Issue
Block a user