docuking-mcp 2.1.2 → 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 +124 -17
  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
  // 파일 목록 수집
@@ -2381,8 +2476,11 @@ function generatePlanId() {
2381
2476
  async function handleTodo(args) {
2382
2477
  const { localPath, action, todo, todoId } = args;
2383
2478
 
2384
- // zz_ai_2_Todo 폴더 경로 (로컬 전용, 킹투두)
2385
- 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');
2386
2484
  const todoFilePath = path.join(todoBasePath, 'z_King_Todo.md');
2387
2485
 
2388
2486
  // 폴더 생성
@@ -2572,8 +2670,11 @@ ${listText}
2572
2670
  async function handleTalk(args) {
2573
2671
  const { localPath, title, content, tags = [] } = args;
2574
2672
 
2575
- // zz_ai_1_Talk 폴더 경로 (로컬 전용, 킹톡)
2576
- 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');
2577
2678
 
2578
2679
  // 날짜 기반 파일명 생성 (T_ 접두사)
2579
2680
  const { fileName, timestamp } = generateDateFileName(title, 'T');
@@ -2625,8 +2726,11 @@ ${content}
2625
2726
  async function handlePlan(args) {
2626
2727
  const { localPath, planId, title, goal, steps = [], notes } = args;
2627
2728
 
2628
- // zz_ai_3_Plan 폴더 경로 (로컬 전용, 킹플랜)
2629
- 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');
2630
2734
 
2631
2735
  // 기존 계획 업데이트 또는 새 계획 생성
2632
2736
  let targetPlanId = planId;
@@ -2775,8 +2879,11 @@ function findPlanFiles(basePath, planId) {
2775
2879
  async function handleDone(args) {
2776
2880
  const { localPath, planId, summary, artifacts = [] } = args;
2777
2881
 
2778
- // zz_ai_3_Plan 폴더 경로 (로컬 전용, 킹플랜)
2779
- 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');
2780
2887
 
2781
2888
  // 계획 파일 찾기
2782
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.2",
3
+ "version": "2.1.3",
4
4
  "description": "DocuKing MCP Server - AI 시대의 문서 협업 플랫폼",
5
5
  "type": "module",
6
6
  "main": "index.js",