seogitan 1.4.1 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/setup.js +61 -40
- package/package.json +1 -1
- package/skills/doctor/SKILL.md +72 -0
- package/skills/meetings/SKILL.md +4 -0
- package/skills/record/SKILL.md +25 -9
- package/skills/summary/SKILL.md +4 -0
- package/skills/upload/SKILL.md +4 -0
package/dist/commands/setup.js
CHANGED
|
@@ -7,55 +7,76 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
7
7
|
const BUNDLED_SKILLS_DIR = join(__dirname, "..", "..", "skills");
|
|
8
8
|
// 설치 대상: ~/.claude/skills/
|
|
9
9
|
const TARGET_SKILLS_DIR = join(homedir(), ".claude", "skills");
|
|
10
|
-
const SEOGITAN_SKILLS = ["record", "meetings", "summary", "upload"];
|
|
10
|
+
const SEOGITAN_SKILLS = ["record", "meetings", "summary", "upload", "doctor"];
|
|
11
11
|
export function registerSetupCommand(program) {
|
|
12
12
|
program
|
|
13
13
|
.command("setup")
|
|
14
14
|
.description("Claude Code 스킬을 설치합니다")
|
|
15
15
|
.option("--force", "기존 스킬을 덮어씁니다")
|
|
16
|
+
.option("--debug", "디버그 정보 출력", false)
|
|
16
17
|
.action(async (opts) => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
mkdirSync(TARGET_SKILLS_DIR, { recursive: true });
|
|
24
|
-
let installed = 0;
|
|
25
|
-
let skipped = 0;
|
|
26
|
-
for (const skill of SEOGITAN_SKILLS) {
|
|
27
|
-
const src = join(BUNDLED_SKILLS_DIR, skill);
|
|
28
|
-
const dest = join(TARGET_SKILLS_DIR, `seogitan-${skill}`);
|
|
29
|
-
if (!existsSync(src)) {
|
|
30
|
-
console.log(` ⚠ ${skill} 스킬을 찾을 수 없습니다 (건너뜀)`);
|
|
31
|
-
continue;
|
|
18
|
+
try {
|
|
19
|
+
console.log("Seogitan setup\n");
|
|
20
|
+
if (opts.debug) {
|
|
21
|
+
console.log("[debug] skills dir:", BUNDLED_SKILLS_DIR);
|
|
22
|
+
console.log("[debug] target dir:", TARGET_SKILLS_DIR);
|
|
23
|
+
console.log("[debug] skills dir exists:", existsSync(BUNDLED_SKILLS_DIR));
|
|
32
24
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
25
|
+
// 1. 스킬 설치
|
|
26
|
+
if (!existsSync(BUNDLED_SKILLS_DIR)) {
|
|
27
|
+
console.error("ERROR: 번들된 스킬을 찾을 수 없습니다.");
|
|
28
|
+
console.error("패키지가 손상되었을 수 있습니다. npm i -g seogitan@latest 로 재설치하세요.");
|
|
29
|
+
if (opts.debug)
|
|
30
|
+
console.error("[debug] expected path:", BUNDLED_SKILLS_DIR);
|
|
31
|
+
process.exit(1);
|
|
37
32
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
33
|
+
mkdirSync(TARGET_SKILLS_DIR, { recursive: true });
|
|
34
|
+
let installed = 0;
|
|
35
|
+
let skipped = 0;
|
|
36
|
+
for (const skill of SEOGITAN_SKILLS) {
|
|
37
|
+
const src = join(BUNDLED_SKILLS_DIR, skill);
|
|
38
|
+
const dest = join(TARGET_SKILLS_DIR, `seogitan-${skill}`);
|
|
39
|
+
if (!existsSync(src)) {
|
|
40
|
+
console.log(` [skip] ${skill}`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (existsSync(dest) && !opts.force) {
|
|
44
|
+
console.log(` [ok] seogitan-${skill} (already installed)`);
|
|
45
|
+
skipped++;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
cpSync(src, dest, { recursive: true });
|
|
49
|
+
console.log(` [ok] seogitan-${skill} installed`);
|
|
50
|
+
installed++;
|
|
51
|
+
}
|
|
52
|
+
console.log(`\nSkills: ${installed} installed, ${skipped} skipped`);
|
|
53
|
+
// 2. ffmpeg 확인
|
|
54
|
+
try {
|
|
55
|
+
const { checkFfmpegInstalled } = await import("../lib/audio.js");
|
|
56
|
+
checkFfmpegInstalled();
|
|
57
|
+
console.log("[ok] ffmpeg available");
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
console.log("[warn] ffmpeg not found. Required for recording.");
|
|
61
|
+
if (process.platform === "darwin")
|
|
62
|
+
console.log(" brew install ffmpeg");
|
|
63
|
+
else if (process.platform === "win32")
|
|
64
|
+
console.log(" winget install ffmpeg OR choco install ffmpeg");
|
|
65
|
+
else
|
|
66
|
+
console.log(" sudo apt install ffmpeg");
|
|
67
|
+
}
|
|
68
|
+
// 3. 로그인 안내
|
|
69
|
+
console.log("\nNext steps:");
|
|
70
|
+
console.log(" 1. seogitan login -- Google login");
|
|
71
|
+
console.log(" 2. seogitan record -- Start recording");
|
|
72
|
+
console.log(" 3. Use /seogitan-record, /seogitan-meetings, /seogitan-summary in Claude Code");
|
|
73
|
+
console.log("");
|
|
48
74
|
}
|
|
49
|
-
catch {
|
|
50
|
-
console.
|
|
51
|
-
|
|
52
|
-
|
|
75
|
+
catch (err) {
|
|
76
|
+
console.error("Setup failed:", err instanceof Error ? err.message : String(err));
|
|
77
|
+
if (opts.debug && err instanceof Error)
|
|
78
|
+
console.error(err.stack);
|
|
79
|
+
process.exit(1);
|
|
53
80
|
}
|
|
54
|
-
// 3. 로그인 안내
|
|
55
|
-
console.log("\n📋 다음 단계:");
|
|
56
|
-
console.log(" 1. seogitan login — Google 계정으로 로그인");
|
|
57
|
-
console.log(" 2. seogitan record — 회의 녹음 시작");
|
|
58
|
-
console.log(" 3. Claude Code에서 /seogitan-record, /seogitan-meetings, /seogitan-summary 사용 가능");
|
|
59
|
-
console.log("");
|
|
60
81
|
});
|
|
61
82
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doctor
|
|
3
|
+
description: "서기탄이 시스템의 에러를 진단하고 해결합니다. 녹음/전사/요약/업로드 중 에러가 발생했을 때, 또는 사용자가 '에러', '오류', '안돼', '실패', 'doctor', '진단' 등을 언급할 때 사용. 다른 서기탄이 스킬에서 에러 발생 시 이 스킬로 위임됩니다."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /doctor — 서기탄이 에러 진단
|
|
7
|
+
|
|
8
|
+
## 진단 절차
|
|
9
|
+
|
|
10
|
+
1. 로그 확인: `tail -20 /tmp/seogitan-record.log`
|
|
11
|
+
2. 에러 메시지를 아래 매뉴얼에서 매칭
|
|
12
|
+
3. 해결 방법 안내
|
|
13
|
+
|
|
14
|
+
## 에러 매뉴얼
|
|
15
|
+
|
|
16
|
+
### 인증/토큰
|
|
17
|
+
| 에러 메시지 | 원인 | 해결 |
|
|
18
|
+
|------------|------|------|
|
|
19
|
+
| "로그인이 필요합니다" | 미로그인 또는 토큰 만료 | `seogitan login` 실행 |
|
|
20
|
+
| "Invalid token" / "Invalid JWT" | 토큰 만료 | `seogitan login` 실행 |
|
|
21
|
+
| "Google token refresh failed" | Google 인증 만료 | `seogitan login`으로 재인증 |
|
|
22
|
+
| "Unauthorized" / "401" | 권한 없음 | `seogitan login` 실행 |
|
|
23
|
+
|
|
24
|
+
**주의: `seogitan auth`라는 명령어는 존재하지 않음. 반드시 `seogitan login`**
|
|
25
|
+
|
|
26
|
+
### 녹음/ffmpeg
|
|
27
|
+
| 에러 메시지 | 원인 | 해결 |
|
|
28
|
+
|------------|------|------|
|
|
29
|
+
| "ffmpeg가 설치되어 있지 않습니다" | ffmpeg 미설치 | `seogitan setup` 실행 |
|
|
30
|
+
| "No such device" / "Device not found" | 오디오 장치 없음 | `seogitan record --list-devices`로 확인 후 `--device <index>` 지정 |
|
|
31
|
+
| "ffmpeg 응답 없음, 강제 종료" | ffmpeg 비정상 종료 | 재시도. 반복되면 `brew install ffmpeg`로 시스템 ffmpeg 설치 |
|
|
32
|
+
|
|
33
|
+
### 전사/n8n
|
|
34
|
+
| 에러 메시지 | 원인 | 해결 |
|
|
35
|
+
|------------|------|------|
|
|
36
|
+
| "Edge Function 호출 실패 (401)" | Supabase JWT 만료 | `seogitan login` 실행 |
|
|
37
|
+
| "Edge Function 호출 실패 (500)" | Edge Function 서버 에러 | 잠시 후 재시도 |
|
|
38
|
+
| 전사가 안 됨 (로그에 에러 없음) | n8n 워크플로우 비활성화 | n8n 대시보드에서 워크플로우 활성 상태 확인 |
|
|
39
|
+
|
|
40
|
+
### 삭제
|
|
41
|
+
| 에러 메시지 | 원인 | 해결 |
|
|
42
|
+
|------------|------|------|
|
|
43
|
+
| "회의 삭제 실패" | RLS 정책 (본인 회의만 삭제 가능) | 본인이 생성한 회의만 삭제 가능 |
|
|
44
|
+
| "Direct deletion from storage tables" | Storage 트리거 문제 | CLI `seogitan meetings delete <id>` 사용 |
|
|
45
|
+
|
|
46
|
+
### 설치
|
|
47
|
+
| 에러 메시지 | 원인 | 해결 |
|
|
48
|
+
|------------|------|------|
|
|
49
|
+
| "EACCES: permission denied" | npm 글로벌 설치 권한 없음 | `sudo npm i -g seogitan` 또는 nvm 사용 |
|
|
50
|
+
| "번들된 스킬을 찾을 수 없습니다" | 패키지 손상 | `npm i -g seogitan@latest` 재설치 |
|
|
51
|
+
|
|
52
|
+
## CLI 명령어 레퍼런스
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
seogitan login # Google OAuth 로그인
|
|
56
|
+
seogitan logout # 로그아웃
|
|
57
|
+
seogitan setup # 스킬 설치 + ffmpeg 확인
|
|
58
|
+
seogitan record [title] # 녹음 시작
|
|
59
|
+
seogitan upload <file> # 파일 업로드
|
|
60
|
+
seogitan meetings list # 회의 목록
|
|
61
|
+
seogitan meetings show <id> # 상세 조회
|
|
62
|
+
seogitan meetings delete <id> # 삭제
|
|
63
|
+
seogitan meetings tag <id> <tags...> # 태그 설정
|
|
64
|
+
seogitan summarize <id> # 요약 생성
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 진단이 안 되는 경우
|
|
68
|
+
|
|
69
|
+
위 매뉴얼에 없는 에러면:
|
|
70
|
+
1. `seogitan --version`으로 버전 확인 → 최신이 아니면 `npm i -g seogitan@latest`
|
|
71
|
+
2. `seogitan setup --force`로 재설정
|
|
72
|
+
3. 그래도 안 되면 에러 메시지 전문을 사용자에게 보여주고 GitHub 이슈로 안내
|
package/skills/meetings/SKILL.md
CHANGED
package/skills/record/SKILL.md
CHANGED
|
@@ -5,15 +5,16 @@ description: "터미널에서 회의 녹음을 시작합니다. ffmpeg로 마이
|
|
|
5
5
|
|
|
6
6
|
# /record — 회의 녹음 시작
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## 핵심 원칙: 녹음은 즉시 시작
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
녹음 요청을 받으면 **질문 없이 바로 실행**합니다. 회의는 기다려주지 않습니다.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
12
|
+
## 캘린더 연결 판단 (녹음 시작 전, 질문하지 않음)
|
|
13
|
+
|
|
14
|
+
사용자의 요청 문맥에서 판단:
|
|
15
|
+
- "회의 녹음해줘", "스터디 녹음" 등 **일정과 연관된 언급** → 제목 없이 실행 (캘린더 자동 연결)
|
|
16
|
+
- "녹음해줘", "녹음 시작" 등 **단순 녹음 요청** → 제목 "새 녹음"으로 실행 (캘린더 연결 안 됨)
|
|
17
|
+
- $ARGUMENTS에 명시적 제목이 있으면 → 그 제목으로 실행
|
|
17
18
|
|
|
18
19
|
## 실행
|
|
19
20
|
|
|
@@ -31,16 +32,31 @@ nohup seogitan record "제목" > /tmp/seogitan-record.log 2>&1 &
|
|
|
31
32
|
echo "PID: $!"
|
|
32
33
|
```
|
|
33
34
|
|
|
35
|
+
실행 직후 3초 대기 후 로그 확인:
|
|
36
|
+
```bash
|
|
37
|
+
sleep 3 && cat /tmp/seogitan-record.log
|
|
38
|
+
```
|
|
39
|
+
|
|
34
40
|
실행 후 사용자에게 알려줄 내용:
|
|
35
41
|
- "녹음이 백그라운드에서 시작되었습니다"
|
|
36
42
|
- "종료하려면 별도 터미널에서 `kill -INT <PID>` 실행"
|
|
37
43
|
- "로그 확인: `tail -f /tmp/seogitan-record.log`"
|
|
38
44
|
- 녹음 중에도 대화를 계속할 수 있습니다
|
|
39
45
|
|
|
40
|
-
## 녹음 종료 후
|
|
46
|
+
## 녹음 종료 후
|
|
41
47
|
|
|
42
48
|
사용자가 녹음을 종료했다고 하면:
|
|
43
49
|
```bash
|
|
44
50
|
tail -5 /tmp/seogitan-record.log
|
|
45
51
|
```
|
|
46
|
-
|
|
52
|
+
|
|
53
|
+
1. 로그에서 Meeting ID를 찾는다
|
|
54
|
+
2. 캘린더 자동 연결이 된 경우, 사용자에게 **연결 유지할지 확인**:
|
|
55
|
+
- "캘린더 [일정명]에 연결되었습니다. 유지할까요?"
|
|
56
|
+
- 유지 → 그대로 둠
|
|
57
|
+
- 연결 해제 → `seogitan meetings link <id> ""` 로 calendar_event_id 제거
|
|
58
|
+
3. `/summary` 스킬로 요약 조회
|
|
59
|
+
|
|
60
|
+
## 에러 대응
|
|
61
|
+
|
|
62
|
+
로그에서 에러가 발견되면 `/doctor` 스킬을 호출하여 진단합니다.
|
package/skills/summary/SKILL.md
CHANGED