docuking-mcp 1.9.1 → 2.0.0
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/index.js +113 -105
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* DocuKing MCP Server
|
|
4
|
+
* DocuKing MCP Server v2.0
|
|
5
5
|
*
|
|
6
6
|
* AI 시대의 문서 협업 플랫폼 - AI가 문서를 Push/Pull 할 수 있게 해주는 MCP 서버
|
|
7
7
|
*
|
|
8
|
+
* 폴더 구조:
|
|
9
|
+
* - yy_All_Docu/ : 킹폴더와 동기화 (Push/Pull 대상)
|
|
10
|
+
* - yy_All_Docu/yy_{이름}/ : 협업자 폴더 (동기화 대상)
|
|
11
|
+
* - zz_AI_Talk/ : AI 대화록 (로컬 전용, 킹톡)
|
|
12
|
+
* - zz_AI_Todo/ : AI 투두 (로컬 전용, 킹투두)
|
|
13
|
+
* - zz_AI_Plan/ : AI 플랜 (로컬 전용, 킹플랜)
|
|
14
|
+
*
|
|
15
|
+
* 접두사 규칙:
|
|
16
|
+
* - yy_* : 동기화 대상 (Push/Pull)
|
|
17
|
+
* - zz_* : 로컬 전용 (동기화 안 됨)
|
|
18
|
+
*
|
|
8
19
|
* 도구:
|
|
9
|
-
* - docuking_init: 레포 연결,
|
|
20
|
+
* - docuking_init: 레포 연결, yy_All_Docu/ 폴더 생성
|
|
10
21
|
* - docuking_push: 로컬 → 서버
|
|
11
22
|
* - docuking_pull: 서버 → 로컬
|
|
12
23
|
*/
|
|
@@ -130,7 +141,7 @@ docuking_done({
|
|
|
130
141
|
### 절대 규칙
|
|
131
142
|
- **작업 시작 전 반드시 \`docuking_plan\` 호출**
|
|
132
143
|
- **작업 완료 후 반드시 \`docuking_done\` 호출**
|
|
133
|
-
- 결과는 \`
|
|
144
|
+
- 결과는 \`zz_AI_Plan/\`에 자동 저장됨 (로컬 전용)
|
|
134
145
|
`;
|
|
135
146
|
|
|
136
147
|
try {
|
|
@@ -248,7 +259,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
248
259
|
tools: [
|
|
249
260
|
{
|
|
250
261
|
name: 'docuking_init',
|
|
251
|
-
description: '프로젝트를 DocuKing에 연결합니다. .docuking/config.json에 설정 저장,
|
|
262
|
+
description: '프로젝트를 DocuKing에 연결합니다. .docuking/config.json에 설정 저장, yy_All_Docu/ 폴더 생성.\n\n**필수 파라미터:**\n- projectId: 프로젝트 UUID\n- projectName: 프로젝트 이름 (표시용)\n- apiKey: API 키 (sk_xxx 형식)\n- localPath: 로컬 프로젝트 경로',
|
|
252
263
|
inputSchema: {
|
|
253
264
|
type: 'object',
|
|
254
265
|
properties: {
|
|
@@ -274,7 +285,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
274
285
|
},
|
|
275
286
|
{
|
|
276
287
|
name: 'docuking_push',
|
|
277
|
-
description: '
|
|
288
|
+
description: 'yy_All_Docu/ 폴더의 문서를 서버에 업로드합니다. "DocuKing에 올려줘" 요청 시 사용. Git의 add + commit + push를 한 번에 수행.',
|
|
278
289
|
inputSchema: {
|
|
279
290
|
type: 'object',
|
|
280
291
|
properties: {
|
|
@@ -300,7 +311,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
300
311
|
},
|
|
301
312
|
{
|
|
302
313
|
name: 'docuking_pull',
|
|
303
|
-
description: '서버에서 문서를 다운로드하여
|
|
314
|
+
description: '서버에서 문서를 다운로드하여 yy_All_Docu/ 폴더에 저장합니다. "DocuKing에서 가져와" 요청 시 사용.',
|
|
304
315
|
inputSchema: {
|
|
305
316
|
type: 'object',
|
|
306
317
|
properties: {
|
|
@@ -412,7 +423,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
412
423
|
},
|
|
413
424
|
{
|
|
414
425
|
name: 'docuking_talk',
|
|
415
|
-
description: '의미 있는 대화 내용을
|
|
426
|
+
description: '의미 있는 대화 내용을 zz_AI_Talk/ 폴더에 기록합니다 (로컬 전용, 킹톡). AI가 중요한 논의/결정이라고 판단하거나, 사용자가 "이거 기록해줘"라고 요청할 때 사용.',
|
|
416
427
|
inputSchema: {
|
|
417
428
|
type: 'object',
|
|
418
429
|
properties: {
|
|
@@ -439,7 +450,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
439
450
|
},
|
|
440
451
|
{
|
|
441
452
|
name: 'docuking_plan',
|
|
442
|
-
description: '작업 계획 문서를
|
|
453
|
+
description: '작업 계획 문서를 zz_AI_Plan/ 폴더에 생성/업데이트합니다 (로컬 전용, 킹플랜). 작업 시작 시 계획을 작성하고, 진행하면서 결과를 upsert합니다.',
|
|
443
454
|
inputSchema: {
|
|
444
455
|
type: 'object',
|
|
445
456
|
properties: {
|
|
@@ -508,7 +519,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
508
519
|
},
|
|
509
520
|
{
|
|
510
521
|
name: 'docuking_todo',
|
|
511
|
-
description: `킹투두(King Todo) - 프로젝트 공식 할일을
|
|
522
|
+
description: `킹투두(King Todo) - 프로젝트 공식 할일을 zz_AI_Todo/z_King_Todo.md에 관리합니다 (로컬 전용).
|
|
512
523
|
|
|
513
524
|
**AI 내장 TodoWrite와 다름!** 킹투두는 웹에 동기화되고 팀과 공유됩니다.
|
|
514
525
|
|
|
@@ -579,11 +590,12 @@ DocuKing은 문서 버전 관리 시스템입니다. Git이 코드를 관리하
|
|
|
579
590
|
|
|
580
591
|
## 핵심 개념
|
|
581
592
|
|
|
582
|
-
- **로컬**: 사용자의
|
|
583
|
-
- **웹탐색기**: DocuKing 서버의 파일 저장소 (
|
|
593
|
+
- **로컬**: 사용자의 yy_All_Docu/ 폴더 (동기화 대상)
|
|
594
|
+
- **웹탐색기**: DocuKing 서버의 파일 저장소 (킹폴더)
|
|
584
595
|
- **캔버스**: 선택된 파일을 시각화하는 작업 공간
|
|
596
|
+
- **AI 작업 폴더**: zz_AI_Talk/, zz_AI_Todo/, zz_AI_Plan/ (로컬 전용)
|
|
585
597
|
|
|
586
|
-
작동 방식: 로컬
|
|
598
|
+
작동 방식: 로컬 yy_All_Docu/ → Push → 킹폴더 → 캔버스에서 시각화
|
|
587
599
|
|
|
588
600
|
## MCP 설정과 프로젝트 연결의 차이 (매우 중요!)
|
|
589
601
|
|
|
@@ -600,7 +612,7 @@ DocuKing은 문서 버전 관리 시스템입니다. Git이 코드를 관리하
|
|
|
600
612
|
### 프로젝트 연결 (각 폴더마다)
|
|
601
613
|
- **목적**: 특정 로컬 폴더를 DocuKing 서버의 프로젝트 ID와 연결
|
|
602
614
|
- **실행 방법**: \`docuking_init(projectId, localPath)\` 도구 호출
|
|
603
|
-
- **결과**: 해당 폴더에 \`
|
|
615
|
+
- **결과**: 해당 폴더에 \`yy_All_Docu/\` 폴더 생성 및 프로젝트 매핑 저장
|
|
604
616
|
- **재시작 불필요**: MCP가 이미 작동 중이면 바로 실행 가능
|
|
605
617
|
- **다중 프로젝트**: 한 컴퓨터에서 여러 폴더를 각각 다른 DocuKing 프로젝트와 연결 가능
|
|
606
618
|
|
|
@@ -615,10 +627,10 @@ DocuKing 문서 폴더는 git에서 제외해야 합니다. 코드는 git으로,
|
|
|
615
627
|
|
|
616
628
|
\`\`\`gitignore
|
|
617
629
|
# DocuKing 문서 폴더 (문서는 DocuKing으로 관리)
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
630
|
+
yy_All_Docu/
|
|
631
|
+
zz_AI_Talk/
|
|
632
|
+
zz_AI_Todo/
|
|
633
|
+
zz_AI_Plan/
|
|
622
634
|
\`\`\`
|
|
623
635
|
|
|
624
636
|
**왜 gitignore에 등록해야 하나요?**
|
|
@@ -654,12 +666,12 @@ zz_Coworker_*/
|
|
|
654
666
|
특정 커밋으로 되돌립니다. (웹 탐색기에서 사용 가능)
|
|
655
667
|
|
|
656
668
|
### 9. docuking_talk
|
|
657
|
-
의미 있는 대화 내용을 \`
|
|
669
|
+
의미 있는 대화 내용을 \`zz_AI_Talk/\` 폴더에 기록합니다 (로컬 전용, 킹톡).
|
|
658
670
|
- AI가 중요한 논의/결정이라고 판단할 때
|
|
659
671
|
- 사용자가 "이거 기록해줘"라고 요청할 때
|
|
660
672
|
|
|
661
673
|
### 10. docuking_plan
|
|
662
|
-
작업 계획을 \`
|
|
674
|
+
작업 계획을 \`zz_AI_Plan/\` 폴더에 생성/업데이트합니다 (로컬 전용, 킹플랜).
|
|
663
675
|
- 작업 시작 시 계획 생성
|
|
664
676
|
- 진행하면서 단계별 결과 upsert
|
|
665
677
|
- planId로 기존 계획 찾아서 업데이트
|
|
@@ -1115,20 +1127,25 @@ docuking_init 호출 시 apiKey 파라미터를 포함해주세요.`,
|
|
|
1115
1127
|
// IDE별 자동 승인 설정 추가 (Claude Code 등)
|
|
1116
1128
|
setupAutoApproval(localPath);
|
|
1117
1129
|
|
|
1118
|
-
// 폴더 생성:
|
|
1119
|
-
|
|
1120
|
-
|
|
1130
|
+
// 폴더 생성: 오너는 yy_All_Docu/, 협업자는 yy_All_Docu/yy_{이름}/
|
|
1131
|
+
const mainFolderName = 'yy_All_Docu';
|
|
1132
|
+
const mainFolderPath = path.join(localPath, mainFolderName);
|
|
1121
1133
|
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
} else {
|
|
1126
|
-
folderName = 'z_DocuKing';
|
|
1127
|
-
workingPath = path.join(localPath, folderName);
|
|
1134
|
+
// yy_All_Docu 폴더는 항상 생성
|
|
1135
|
+
if (!fs.existsSync(mainFolderPath)) {
|
|
1136
|
+
fs.mkdirSync(mainFolderPath, { recursive: true });
|
|
1128
1137
|
}
|
|
1129
1138
|
|
|
1130
|
-
|
|
1131
|
-
|
|
1139
|
+
let coworkerFolderName = null;
|
|
1140
|
+
let coworkerFolderPath = null;
|
|
1141
|
+
|
|
1142
|
+
if (isCoworker) {
|
|
1143
|
+
// 협업자: yy_All_Docu/yy_{이름}/ 폴더 추가 생성
|
|
1144
|
+
coworkerFolderName = `yy_${coworkerName}`;
|
|
1145
|
+
coworkerFolderPath = path.join(mainFolderPath, coworkerFolderName);
|
|
1146
|
+
if (!fs.existsSync(coworkerFolderPath)) {
|
|
1147
|
+
fs.mkdirSync(coworkerFolderPath, { recursive: true });
|
|
1148
|
+
}
|
|
1132
1149
|
}
|
|
1133
1150
|
|
|
1134
1151
|
// 연결 완료 안내 (오너/코워커에 따라 다른 메시지)
|
|
@@ -1140,17 +1157,18 @@ docuking_init 호출 시 apiKey 파라미터를 포함해주세요.`,
|
|
|
1140
1157
|
text: `DocuKing 연결 완료! (참여자)
|
|
1141
1158
|
|
|
1142
1159
|
📁 프로젝트: ${projectName}
|
|
1143
|
-
📂
|
|
1160
|
+
📂 yy_All_Docu/ 폴더가 생성되었습니다.
|
|
1161
|
+
📂 yy_All_Docu/${coworkerFolderName}/ 작업 폴더가 생성되었습니다.
|
|
1144
1162
|
👤 참여자: ${coworkerName}
|
|
1145
1163
|
🔑 설정 저장: .docuking/config.json
|
|
1146
1164
|
|
|
1147
1165
|
참여자 사용법:
|
|
1148
|
-
- "DocuKing에서 가져와" →
|
|
1149
|
-
-
|
|
1166
|
+
- "DocuKing에서 가져와" → 전체 문서를 yy_All_Docu/에 Pull
|
|
1167
|
+
- yy_All_Docu/${coworkerFolderName}/ 폴더에 문서 작성
|
|
1150
1168
|
- "DocuKing에 올려줘" → 내 문서를 서버에 Push
|
|
1151
1169
|
|
|
1152
|
-
💡 참여자는
|
|
1153
|
-
|
|
1170
|
+
💡 참여자는 yy_All_Docu/${coworkerFolderName}/ 폴더에만 Push할 수 있습니다.
|
|
1171
|
+
다른 문서는 Pull로 읽을 수 있지만 수정은 자기 폴더에서 작성하세요.`,
|
|
1154
1172
|
},
|
|
1155
1173
|
],
|
|
1156
1174
|
};
|
|
@@ -1162,16 +1180,22 @@ docuking_init 호출 시 apiKey 파라미터를 포함해주세요.`,
|
|
|
1162
1180
|
text: `DocuKing 연결 완료!
|
|
1163
1181
|
|
|
1164
1182
|
📁 프로젝트: ${projectName}
|
|
1165
|
-
📂
|
|
1183
|
+
📂 yy_All_Docu/ 폴더가 생성되었습니다.
|
|
1166
1184
|
🔑 설정 저장: .docuking/config.json
|
|
1167
1185
|
|
|
1168
1186
|
이제부터 문서 관리는 DocuKing에서 시작합니다:
|
|
1169
|
-
-
|
|
1187
|
+
- yy_All_Docu/ 하위에 문서를 넣으면 DocuKing 서버로 암호화되어 저장됩니다
|
|
1170
1188
|
- 협업자들과 안전하게 문서를 공유할 수 있습니다
|
|
1171
1189
|
|
|
1172
1190
|
사용법:
|
|
1173
1191
|
- "DocuKing에 올려줘" → 로컬 문서를 서버에 Push
|
|
1174
|
-
- "DocuKing에서 가져와" → 서버 문서를 로컬로 Pull
|
|
1192
|
+
- "DocuKing에서 가져와" → 서버 문서를 로컬로 Pull
|
|
1193
|
+
|
|
1194
|
+
폴더 구조:
|
|
1195
|
+
- yy_All_Docu/ : 동기화 대상 (킹폴더)
|
|
1196
|
+
- zz_AI_Talk/ : AI 대화록 (로컬 전용, 킹톡)
|
|
1197
|
+
- zz_AI_Todo/ : AI 투두 (로컬 전용, 킹투두)
|
|
1198
|
+
- zz_AI_Plan/ : AI 플랜 (로컬 전용, 킹플랜)`,
|
|
1175
1199
|
},
|
|
1176
1200
|
],
|
|
1177
1201
|
};
|
|
@@ -1231,37 +1255,37 @@ Git처럼 무엇을 변경했는지 명확히 작성해주세요.
|
|
|
1231
1255
|
const coworkerMatch = apiKey.match(/^sk_[a-f0-9]+_cw_([^_]+)_/);
|
|
1232
1256
|
const isCoworker = !!coworkerMatch;
|
|
1233
1257
|
const coworkerName = coworkerMatch ? coworkerMatch[1] : null;
|
|
1234
|
-
const coworkerFolderName = isCoworker ? `
|
|
1258
|
+
const coworkerFolderName = isCoworker ? `yy_${coworkerName}` : null;
|
|
1235
1259
|
|
|
1236
|
-
// 작업 폴더 결정:
|
|
1260
|
+
// 작업 폴더 결정: 모두 yy_All_Docu/ 사용, 협업자는 yy_All_Docu/yy_{이름}/ 에서 작업
|
|
1261
|
+
const mainFolderPath = path.join(localPath, 'yy_All_Docu');
|
|
1237
1262
|
let workingPath;
|
|
1238
1263
|
let serverPathPrefix = ''; // 서버에 저장될 때 경로 접두사
|
|
1239
1264
|
|
|
1240
1265
|
if (isCoworker) {
|
|
1241
|
-
//
|
|
1242
|
-
workingPath = path.join(
|
|
1266
|
+
// 협업자: yy_All_Docu/yy_{이름}/ 폴더에서 Push
|
|
1267
|
+
workingPath = path.join(mainFolderPath, coworkerFolderName);
|
|
1243
1268
|
serverPathPrefix = `${coworkerFolderName}/`;
|
|
1244
1269
|
|
|
1245
1270
|
if (!fs.existsSync(workingPath)) {
|
|
1246
1271
|
// 폴더가 없으면 생성
|
|
1247
1272
|
fs.mkdirSync(workingPath, { recursive: true });
|
|
1248
|
-
console.log(`[DocuKing]
|
|
1273
|
+
console.log(`[DocuKing] 협업자 폴더 생성: yy_All_Docu/${coworkerFolderName}/`);
|
|
1249
1274
|
}
|
|
1250
1275
|
} else {
|
|
1251
|
-
// 오너:
|
|
1252
|
-
|
|
1253
|
-
if (!folderName) {
|
|
1276
|
+
// 오너: yy_All_Docu/ 폴더 사용
|
|
1277
|
+
if (!fs.existsSync(mainFolderPath)) {
|
|
1254
1278
|
return {
|
|
1255
1279
|
content: [
|
|
1256
1280
|
{
|
|
1257
1281
|
type: 'text',
|
|
1258
|
-
text: `오류:
|
|
1282
|
+
text: `오류: yy_All_Docu 폴더가 없습니다.
|
|
1259
1283
|
docuking_init을 먼저 실행하세요.`,
|
|
1260
1284
|
},
|
|
1261
1285
|
],
|
|
1262
1286
|
};
|
|
1263
1287
|
}
|
|
1264
|
-
workingPath =
|
|
1288
|
+
workingPath = mainFolderPath;
|
|
1265
1289
|
}
|
|
1266
1290
|
|
|
1267
1291
|
// 파일 목록 수집
|
|
@@ -1679,10 +1703,11 @@ async function handlePull(args) {
|
|
|
1679
1703
|
|
|
1680
1704
|
const projectId = projectInfo.projectId;
|
|
1681
1705
|
|
|
1682
|
-
//
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1706
|
+
// yy_All_Docu 폴더 (없으면 생성)
|
|
1707
|
+
const mainFolderName = 'yy_All_Docu';
|
|
1708
|
+
const mainFolderPath = path.join(localPath, mainFolderName);
|
|
1709
|
+
if (!fs.existsSync(mainFolderPath)) {
|
|
1710
|
+
fs.mkdirSync(mainFolderPath, { recursive: true });
|
|
1686
1711
|
}
|
|
1687
1712
|
|
|
1688
1713
|
// 파일 목록 조회
|
|
@@ -1750,17 +1775,9 @@ async function handlePull(args) {
|
|
|
1750
1775
|
|
|
1751
1776
|
const data = await response.json();
|
|
1752
1777
|
|
|
1753
|
-
// 서버
|
|
1754
|
-
//
|
|
1755
|
-
|
|
1756
|
-
const coworkerPrefixMatch = file.path.match(/^(zz_Coworker_[^/]+)\//);
|
|
1757
|
-
if (coworkerPrefixMatch) {
|
|
1758
|
-
// 코워커 폴더 파일: 프로젝트 루트에 zz_Coworker_{이름}/ 폴더로 저장
|
|
1759
|
-
fullPath = path.join(localPath, file.path);
|
|
1760
|
-
} else {
|
|
1761
|
-
// 오너 폴더 파일: z_DocuKing/ 폴더에 저장
|
|
1762
|
-
fullPath = path.join(localPath, ownerFolderName, file.path);
|
|
1763
|
-
}
|
|
1778
|
+
// 서버 경로를 그대로 yy_All_Docu/ 아래에 저장
|
|
1779
|
+
// 협업자 폴더(yy_이름/)도 yy_All_Docu/ 안에 있으므로 동일하게 처리
|
|
1780
|
+
const fullPath = path.join(mainFolderPath, file.path);
|
|
1764
1781
|
|
|
1765
1782
|
// 디렉토리 생성
|
|
1766
1783
|
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
@@ -1941,28 +1958,15 @@ function getFileType(fileName) {
|
|
|
1941
1958
|
return 'binary';
|
|
1942
1959
|
}
|
|
1943
1960
|
|
|
1944
|
-
// 유틸:
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
const entries = fs.readdirSync(projectPath, { withFileTypes: true });
|
|
1949
|
-
for (const entry of entries) {
|
|
1950
|
-
// .docuking은 설정 폴더이므로 제외 (숨김 폴더)
|
|
1951
|
-
if (entry.name.startsWith('.')) {
|
|
1952
|
-
continue;
|
|
1953
|
-
}
|
|
1954
|
-
if (entry.isDirectory() && entry.name.toLowerCase().includes('docuking')) {
|
|
1955
|
-
return entry.name;
|
|
1956
|
-
}
|
|
1957
|
-
}
|
|
1958
|
-
} catch (e) {
|
|
1959
|
-
// 디렉토리 읽기 실패
|
|
1960
|
-
}
|
|
1961
|
-
return null;
|
|
1961
|
+
// 유틸: yy_All_Docu 폴더 존재 확인
|
|
1962
|
+
function hasAllDocuFolder(projectPath) {
|
|
1963
|
+
const allDocuPath = path.join(projectPath, 'yy_All_Docu');
|
|
1964
|
+
return fs.existsSync(allDocuPath);
|
|
1962
1965
|
}
|
|
1963
1966
|
|
|
1964
1967
|
// 유틸: 디렉토리 재귀 탐색
|
|
1965
1968
|
// excludedFiles: 제외된 파일 목록을 수집할 배열 (선택)
|
|
1969
|
+
// zz_* 폴더는 로컬 전용이므로 동기화에서 제외
|
|
1966
1970
|
function collectFiles(basePath, relativePath, results, excludedFiles = null) {
|
|
1967
1971
|
const fullPath = path.join(basePath, relativePath);
|
|
1968
1972
|
const entries = fs.readdirSync(fullPath, { withFileTypes: true });
|
|
@@ -1971,6 +1975,11 @@ function collectFiles(basePath, relativePath, results, excludedFiles = null) {
|
|
|
1971
1975
|
const entryRelPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
|
1972
1976
|
|
|
1973
1977
|
if (entry.isDirectory()) {
|
|
1978
|
+
// zz_* 폴더는 로컬 전용 (AI 작업 기록 등)이므로 동기화에서 제외
|
|
1979
|
+
if (entry.name.startsWith('zz_')) {
|
|
1980
|
+
console.error(`[DocuKing] 제외됨: ${entryRelPath}/ (zz_* 폴더 - 로컬 전용)`);
|
|
1981
|
+
continue;
|
|
1982
|
+
}
|
|
1974
1983
|
collectFiles(basePath, entryRelPath, results, excludedFiles);
|
|
1975
1984
|
} else if (entry.isFile()) {
|
|
1976
1985
|
const fileType = getFileType(entry.name);
|
|
@@ -2048,20 +2057,20 @@ async function handleStatus(args) {
|
|
|
2048
2057
|
const coworkerMatch = apiKey.match(/^sk_[a-f0-9]+_cw_([^_]+)_/);
|
|
2049
2058
|
const isCoworker = !!coworkerMatch;
|
|
2050
2059
|
const coworkerName = coworkerMatch ? coworkerMatch[1] : null;
|
|
2051
|
-
const coworkerFolderName = isCoworker ? `
|
|
2060
|
+
const coworkerFolderName = isCoworker ? `yy_${coworkerName}` : null;
|
|
2052
2061
|
|
|
2053
2062
|
// 권한 정보 구성
|
|
2054
2063
|
let permissionInfo = '';
|
|
2055
2064
|
if (isCoworker) {
|
|
2056
2065
|
permissionInfo = `\n\n## 현재 권한: 참여자 (Co-worker)
|
|
2057
2066
|
- 이름: ${coworkerName}
|
|
2058
|
-
- 읽기 권한: 전체 문서 (Pull로
|
|
2059
|
-
- 쓰기 권한:
|
|
2060
|
-
- 설명:
|
|
2067
|
+
- 읽기 권한: 전체 문서 (Pull로 yy_All_Docu/ 폴더의 문서 가져오기 가능)
|
|
2068
|
+
- 쓰기 권한: yy_All_Docu/${coworkerFolderName}/ 폴더만
|
|
2069
|
+
- 설명: 협업자 폴더에서 작업하면 자동으로 서버에 Push됩니다.`;
|
|
2061
2070
|
} else {
|
|
2062
2071
|
permissionInfo = `\n\n## 현재 권한: 오너 (Owner)
|
|
2063
2072
|
- 읽기 권한: 전체 문서
|
|
2064
|
-
- 쓰기 권한:
|
|
2073
|
+
- 쓰기 권한: yy_All_Docu/ 폴더 전체 (제한 없음)
|
|
2065
2074
|
- 설명: 프로젝트의 모든 폴더에 Push할 수 있습니다.`;
|
|
2066
2075
|
}
|
|
2067
2076
|
|
|
@@ -2087,26 +2096,25 @@ async function handleStatus(args) {
|
|
|
2087
2096
|
// 로컬 파일 목록 조회
|
|
2088
2097
|
let localFiles = [];
|
|
2089
2098
|
let pushableFiles = [];
|
|
2099
|
+
const mainFolderPath = path.join(localPath, 'yy_All_Docu');
|
|
2090
2100
|
|
|
2091
2101
|
if (isCoworker) {
|
|
2092
|
-
//
|
|
2093
|
-
const coworkerPath = path.join(
|
|
2102
|
+
// 협업자: yy_All_Docu/yy_{이름}/ 폴더에서 파일 수집
|
|
2103
|
+
const coworkerPath = path.join(mainFolderPath, coworkerFolderName);
|
|
2094
2104
|
if (fs.existsSync(coworkerPath)) {
|
|
2095
2105
|
collectFiles(coworkerPath, '', localFiles);
|
|
2096
2106
|
}
|
|
2097
|
-
pushableFiles = localFiles; //
|
|
2107
|
+
pushableFiles = localFiles; // 협업자는 자기 폴더의 모든 파일 Push 가능
|
|
2098
2108
|
} else {
|
|
2099
|
-
// 오너:
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
if (docuKingPath && fs.existsSync(docuKingPath)) {
|
|
2103
|
-
collectFiles(docuKingPath, '', localFiles);
|
|
2109
|
+
// 오너: yy_All_Docu/ 폴더에서 파일 수집
|
|
2110
|
+
if (fs.existsSync(mainFolderPath)) {
|
|
2111
|
+
collectFiles(mainFolderPath, '', localFiles);
|
|
2104
2112
|
}
|
|
2105
2113
|
pushableFiles = localFiles; // 오너는 모든 파일 Push 가능
|
|
2106
2114
|
}
|
|
2107
2115
|
|
|
2108
2116
|
const projectNameInfo = projectName ? ` (${projectName})` : '';
|
|
2109
|
-
const workingFolder = isCoworker ? coworkerFolderName : '
|
|
2117
|
+
const workingFolder = isCoworker ? `yy_All_Docu/${coworkerFolderName}` : 'yy_All_Docu';
|
|
2110
2118
|
const statusText = `DocuKing 동기화 상태
|
|
2111
2119
|
|
|
2112
2120
|
**프로젝트**: ${projectId}${projectNameInfo}
|
|
@@ -2244,8 +2252,8 @@ function generatePlanId() {
|
|
|
2244
2252
|
async function handleTodo(args) {
|
|
2245
2253
|
const { localPath, action, todo, todoId } = args;
|
|
2246
2254
|
|
|
2247
|
-
//
|
|
2248
|
-
const todoBasePath = path.join(localPath, '
|
|
2255
|
+
// zz_AI_Todo 폴더 경로 (로컬 전용, 킹투두)
|
|
2256
|
+
const todoBasePath = path.join(localPath, 'zz_AI_Todo');
|
|
2249
2257
|
const todoFilePath = path.join(todoBasePath, 'z_King_Todo.md');
|
|
2250
2258
|
|
|
2251
2259
|
// 폴더 생성
|
|
@@ -2406,7 +2414,7 @@ async function handleTodo(args) {
|
|
|
2406
2414
|
text: `📋 킹투두 미결: 없음
|
|
2407
2415
|
|
|
2408
2416
|
✅ 완료: ${completedCount}개
|
|
2409
|
-
📁 전체 기록:
|
|
2417
|
+
📁 전체 기록: zz_AI_Todo/z_King_Todo.md`,
|
|
2410
2418
|
}],
|
|
2411
2419
|
};
|
|
2412
2420
|
}
|
|
@@ -2421,7 +2429,7 @@ async function handleTodo(args) {
|
|
|
2421
2429
|
${listText}
|
|
2422
2430
|
|
|
2423
2431
|
✅ 완료: ${completedCount}개
|
|
2424
|
-
📁 전체 기록:
|
|
2432
|
+
📁 전체 기록: zz_AI_Todo/z_King_Todo.md`,
|
|
2425
2433
|
}],
|
|
2426
2434
|
};
|
|
2427
2435
|
}
|
|
@@ -2435,8 +2443,8 @@ ${listText}
|
|
|
2435
2443
|
async function handleTalk(args) {
|
|
2436
2444
|
const { localPath, title, content, tags = [] } = args;
|
|
2437
2445
|
|
|
2438
|
-
//
|
|
2439
|
-
const talkBasePath = path.join(localPath, '
|
|
2446
|
+
// zz_AI_Talk 폴더 경로 (로컬 전용, 킹톡)
|
|
2447
|
+
const talkBasePath = path.join(localPath, 'zz_AI_Talk');
|
|
2440
2448
|
|
|
2441
2449
|
// 날짜 기반 파일명 생성
|
|
2442
2450
|
const { fileName, timestamp } = generateDateFileName(title);
|
|
@@ -2488,8 +2496,8 @@ ${content}
|
|
|
2488
2496
|
async function handlePlan(args) {
|
|
2489
2497
|
const { localPath, planId, title, goal, steps = [], notes } = args;
|
|
2490
2498
|
|
|
2491
|
-
//
|
|
2492
|
-
const planBasePath = path.join(localPath, '
|
|
2499
|
+
// zz_AI_Plan 폴더 경로 (로컬 전용, 킹플랜)
|
|
2500
|
+
const planBasePath = path.join(localPath, 'zz_AI_Plan');
|
|
2493
2501
|
|
|
2494
2502
|
// 기존 계획 업데이트 또는 새 계획 생성
|
|
2495
2503
|
let targetPlanId = planId;
|
|
@@ -2638,8 +2646,8 @@ function findPlanFiles(basePath, planId) {
|
|
|
2638
2646
|
async function handleDone(args) {
|
|
2639
2647
|
const { localPath, planId, summary, artifacts = [] } = args;
|
|
2640
2648
|
|
|
2641
|
-
//
|
|
2642
|
-
const planBasePath = path.join(localPath, '
|
|
2649
|
+
// zz_AI_Plan 폴더 경로 (로컬 전용, 킹플랜)
|
|
2650
|
+
const planBasePath = path.join(localPath, 'zz_AI_Plan');
|
|
2643
2651
|
|
|
2644
2652
|
// 계획 파일 찾기
|
|
2645
2653
|
const planFiles = findPlanFiles(planBasePath, planId);
|