docuking-mcp 2.1.1 → 2.1.3

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.
Files changed (2) hide show
  1. package/index.js +126 -22
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -93,6 +93,30 @@ function saveLocalConfig(localPath, config) {
93
93
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
94
94
  }
95
95
 
96
+ /**
97
+ * 협업자 여부 및 zz_ai 폴더 기본 경로 반환
98
+ * - 오너: localPath (루트에 zz_ai_* 폴더)
99
+ * - 협업자: localPath/yy_Coworker_{폴더명} (협업자 폴더 안에 zz_ai_* 폴더)
100
+ */
101
+ function getAiBasePath(localPath) {
102
+ const config = getLocalConfig(localPath);
103
+ if (!config || !config.apiKey) {
104
+ return { isCoworker: false, basePath: localPath, coworkerFolder: null };
105
+ }
106
+
107
+ const apiKey = config.apiKey;
108
+ // 협업자 키 형식: sk_xxx_cw_폴더명_
109
+ const coworkerMatch = apiKey.match(/_cw_([^_]+)_$/);
110
+
111
+ if (coworkerMatch) {
112
+ const folderName = coworkerMatch[1];
113
+ const coworkerFolderPath = path.join(localPath, `yy_Coworker_${folderName}`);
114
+ return { isCoworker: true, basePath: coworkerFolderPath, coworkerFolder: folderName };
115
+ }
116
+
117
+ return { isCoworker: false, basePath: localPath, coworkerFolder: null };
118
+ }
119
+
96
120
  /**
97
121
  * CLAUDE.md에 DocuKing MCP 작업 기록 규칙 추가
98
122
  * - 파일이 없으면 새로 생성
@@ -1174,18 +1198,12 @@ docuking_init 호출 시 apiKey 파라미터를 포함해주세요.`,
1174
1198
  fs.mkdirSync(mainFolderPath, { recursive: true });
1175
1199
  }
1176
1200
 
1177
- // zz_ai_* 폴더도 함께 생성 (로컬 전용)
1178
- const aiFolders = ['zz_ai_1_Talk', 'zz_ai_2_Todo', 'zz_ai_3_Plan'];
1179
- for (const folder of aiFolders) {
1180
- const folderPath = path.join(localPath, folder);
1181
- if (!fs.existsSync(folderPath)) {
1182
- fs.mkdirSync(folderPath, { recursive: true });
1183
- }
1184
- }
1185
-
1186
1201
  let coworkerFolderName = null;
1187
1202
  let coworkerFolderPath = null;
1188
1203
 
1204
+ // zz_ai_* 폴더 목록
1205
+ const aiFolders = ['zz_ai_1_Talk', 'zz_ai_2_Todo', 'zz_ai_3_Plan'];
1206
+
1189
1207
  if (isCoworker) {
1190
1208
  // 협업자: yy_Coworker_{폴더명}/ 폴더를 yy_All_Docu/ 밖에 별도 생성
1191
1209
  coworkerFolderName = `yy_Coworker_${coworkerFolder}`;
@@ -1193,6 +1211,35 @@ docuking_init 호출 시 apiKey 파라미터를 포함해주세요.`,
1193
1211
  if (!fs.existsSync(coworkerFolderPath)) {
1194
1212
  fs.mkdirSync(coworkerFolderPath, { recursive: true });
1195
1213
  }
1214
+ // 협업자 폴더 안에 _Private/ 생성
1215
+ const coworkerPrivatePath = path.join(coworkerFolderPath, '_Private');
1216
+ if (!fs.existsSync(coworkerPrivatePath)) {
1217
+ fs.mkdirSync(coworkerPrivatePath, { recursive: true });
1218
+ }
1219
+ // 협업자 폴더 안에 zz_ai_* 폴더 생성
1220
+ for (const folder of aiFolders) {
1221
+ const folderPath = path.join(coworkerFolderPath, folder);
1222
+ if (!fs.existsSync(folderPath)) {
1223
+ fs.mkdirSync(folderPath, { recursive: true });
1224
+ }
1225
+ }
1226
+ } else {
1227
+ // 오너: yy_All_Docu/ 안에 _Infra_Config/와 _Private/ 생성
1228
+ const infraConfigPath = path.join(mainFolderPath, '_Infra_Config');
1229
+ if (!fs.existsSync(infraConfigPath)) {
1230
+ fs.mkdirSync(infraConfigPath, { recursive: true });
1231
+ }
1232
+ const ownerPrivatePath = path.join(mainFolderPath, '_Private');
1233
+ if (!fs.existsSync(ownerPrivatePath)) {
1234
+ fs.mkdirSync(ownerPrivatePath, { recursive: true });
1235
+ }
1236
+ // 오너: 루트에 zz_ai_* 폴더 생성
1237
+ for (const folder of aiFolders) {
1238
+ const folderPath = path.join(localPath, folder);
1239
+ if (!fs.existsSync(folderPath)) {
1240
+ fs.mkdirSync(folderPath, { recursive: true });
1241
+ }
1242
+ }
1196
1243
  }
1197
1244
 
1198
1245
  // 연결 완료 안내 (오너/코워커에 따라 다른 메시지)
@@ -1388,6 +1435,54 @@ docuking_init을 먼저 실행하세요.`,
1388
1435
  console.error(`[DocuKing] frontend/.env.local 백업 실패: ${err.message}`);
1389
1436
  }
1390
1437
  }
1438
+
1439
+ // package.json 파일 백업 (루트)
1440
+ const packageJsonPath = path.join(localPath, 'package.json');
1441
+ if (fs.existsSync(packageJsonPath)) {
1442
+ if (!fs.existsSync(infraConfigPath)) {
1443
+ fs.mkdirSync(infraConfigPath, { recursive: true });
1444
+ }
1445
+
1446
+ const packageJsonBackupPath = path.join(infraConfigPath, 'package.json');
1447
+ try {
1448
+ fs.copyFileSync(packageJsonPath, packageJsonBackupPath);
1449
+ console.error(`[DocuKing] package.json → _Infra_Config/package.json 자동 백업 완료`);
1450
+ } catch (err) {
1451
+ console.error(`[DocuKing] package.json 백업 실패: ${err.message}`);
1452
+ }
1453
+ }
1454
+
1455
+ // backend/package.json 파일도 백업
1456
+ const backendPackageJsonPath = path.join(localPath, 'backend', 'package.json');
1457
+ if (fs.existsSync(backendPackageJsonPath)) {
1458
+ if (!fs.existsSync(infraConfigPath)) {
1459
+ fs.mkdirSync(infraConfigPath, { recursive: true });
1460
+ }
1461
+
1462
+ const backendPackageJsonBackupPath = path.join(infraConfigPath, 'backend.package.json');
1463
+ try {
1464
+ fs.copyFileSync(backendPackageJsonPath, backendPackageJsonBackupPath);
1465
+ console.error(`[DocuKing] backend/package.json → _Infra_Config/backend.package.json 자동 백업 완료`);
1466
+ } catch (err) {
1467
+ console.error(`[DocuKing] backend/package.json 백업 실패: ${err.message}`);
1468
+ }
1469
+ }
1470
+
1471
+ // frontend/package.json 파일도 백업
1472
+ const frontendPackageJsonPath = path.join(localPath, 'frontend', 'package.json');
1473
+ if (fs.existsSync(frontendPackageJsonPath)) {
1474
+ if (!fs.existsSync(infraConfigPath)) {
1475
+ fs.mkdirSync(infraConfigPath, { recursive: true });
1476
+ }
1477
+
1478
+ const frontendPackageJsonBackupPath = path.join(infraConfigPath, 'frontend.package.json');
1479
+ try {
1480
+ fs.copyFileSync(frontendPackageJsonPath, frontendPackageJsonBackupPath);
1481
+ console.error(`[DocuKing] frontend/package.json → _Infra_Config/frontend.package.json 자동 백업 완료`);
1482
+ } catch (err) {
1483
+ console.error(`[DocuKing] frontend/package.json 백업 실패: ${err.message}`);
1484
+ }
1485
+ }
1391
1486
  }
1392
1487
 
1393
1488
  // 파일 목록 수집
@@ -2027,7 +2122,8 @@ const FILE_TYPES = {
2027
2122
  '.hwpx', '.hwp',
2028
2123
  ],
2029
2124
 
2030
- // 제외 파일 (업로드 거부) - 설치파일/대용량 파일은 별도 공유 권장
2125
+ // 제외 파일 (업로드 거부) - 실행파일/시스템 이미지만
2126
+ // 영상/오디오는 150MB 이하면 허용 (유튜브 쇼츠 등)
2031
2127
  EXCLUDED: [
2032
2128
  // 압축/아카이브 (설치파일 포함 가능성 높음)
2033
2129
  '.zip', '.tar', '.gz', '.tgz', '.7z', '.rar', '.tar.Z',
@@ -2037,10 +2133,6 @@ const FILE_TYPES = {
2037
2133
  '.exe', '.msi', '.dll', '.so', '.dylib', '.com', '.app', '.pkg', '.deb', '.rpm',
2038
2134
  // macOS 스크립트
2039
2135
  '.scpt',
2040
- // 동영상
2041
- '.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.webm', '.m4v',
2042
- // 오디오
2043
- '.mp3', '.wav', '.flac', '.aac', '.ogg', '.wma', '.m4a',
2044
2136
  // 디스크 이미지
2045
2137
  '.iso', '.dmg', '.img', '.vhd', '.vmdk',
2046
2138
  ],
@@ -2384,8 +2476,11 @@ function generatePlanId() {
2384
2476
  async function handleTodo(args) {
2385
2477
  const { localPath, action, todo, todoId } = args;
2386
2478
 
2387
- // zz_ai_2_Todo 폴더 경로 (로컬 전용, 킹투두)
2388
- const todoBasePath = path.join(localPath, 'zz_ai_2_Todo');
2479
+ // 협업자 여부에 따라 zz_ai 경로 결정
2480
+ // - 오너: localPath/zz_ai_2_Todo/
2481
+ // - 협업자: localPath/yy_Coworker_{폴더명}/zz_ai_2_Todo/
2482
+ const { basePath } = getAiBasePath(localPath);
2483
+ const todoBasePath = path.join(basePath, 'zz_ai_2_Todo');
2389
2484
  const todoFilePath = path.join(todoBasePath, 'z_King_Todo.md');
2390
2485
 
2391
2486
  // 폴더 생성
@@ -2575,8 +2670,11 @@ ${listText}
2575
2670
  async function handleTalk(args) {
2576
2671
  const { localPath, title, content, tags = [] } = args;
2577
2672
 
2578
- // zz_ai_1_Talk 폴더 경로 (로컬 전용, 킹톡)
2579
- const talkBasePath = path.join(localPath, 'zz_ai_1_Talk');
2673
+ // 협업자 여부에 따라 zz_ai 경로 결정
2674
+ // - 오너: localPath/zz_ai_1_Talk/
2675
+ // - 협업자: localPath/yy_Coworker_{폴더명}/zz_ai_1_Talk/
2676
+ const { basePath } = getAiBasePath(localPath);
2677
+ const talkBasePath = path.join(basePath, 'zz_ai_1_Talk');
2580
2678
 
2581
2679
  // 날짜 기반 파일명 생성 (T_ 접두사)
2582
2680
  const { fileName, timestamp } = generateDateFileName(title, 'T');
@@ -2628,8 +2726,11 @@ ${content}
2628
2726
  async function handlePlan(args) {
2629
2727
  const { localPath, planId, title, goal, steps = [], notes } = args;
2630
2728
 
2631
- // zz_ai_3_Plan 폴더 경로 (로컬 전용, 킹플랜)
2632
- const planBasePath = path.join(localPath, 'zz_ai_3_Plan');
2729
+ // 협업자 여부에 따라 zz_ai 경로 결정
2730
+ // - 오너: localPath/zz_ai_3_Plan/
2731
+ // - 협업자: localPath/yy_Coworker_{폴더명}/zz_ai_3_Plan/
2732
+ const { basePath } = getAiBasePath(localPath);
2733
+ const planBasePath = path.join(basePath, 'zz_ai_3_Plan');
2633
2734
 
2634
2735
  // 기존 계획 업데이트 또는 새 계획 생성
2635
2736
  let targetPlanId = planId;
@@ -2778,8 +2879,11 @@ function findPlanFiles(basePath, planId) {
2778
2879
  async function handleDone(args) {
2779
2880
  const { localPath, planId, summary, artifacts = [] } = args;
2780
2881
 
2781
- // zz_ai_3_Plan 폴더 경로 (로컬 전용, 킹플랜)
2782
- const planBasePath = path.join(localPath, 'zz_ai_3_Plan');
2882
+ // 협업자 여부에 따라 zz_ai 경로 결정
2883
+ // - 오너: localPath/zz_ai_3_Plan/
2884
+ // - 협업자: localPath/yy_Coworker_{폴더명}/zz_ai_3_Plan/
2885
+ const { basePath } = getAiBasePath(localPath);
2886
+ const planBasePath = path.join(basePath, 'zz_ai_3_Plan');
2783
2887
 
2784
2888
  // 계획 파일 찾기
2785
2889
  const planFiles = findPlanFiles(planBasePath, planId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docuking-mcp",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "DocuKing MCP Server - AI 시대의 문서 협업 플랫폼",
5
5
  "type": "module",
6
6
  "main": "index.js",