docuking-mcp 2.0.1 → 2.0.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.
- package/index.js +57 -12
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -37,6 +37,10 @@ import crypto from 'crypto';
|
|
|
37
37
|
// 환경변수에서 API 엔드포인트 설정 (키는 로컬 config에서 읽음)
|
|
38
38
|
const API_ENDPOINT = process.env.DOCUKING_API_ENDPOINT || 'https://docuking.ai/api';
|
|
39
39
|
|
|
40
|
+
// 파일 크기 제한 (50MB) - Base64 인코딩 시 66MB, 서버 제한 200MB 이내
|
|
41
|
+
const MAX_FILE_SIZE_MB = 50;
|
|
42
|
+
const MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;
|
|
43
|
+
|
|
40
44
|
/**
|
|
41
45
|
* 로컬 프로젝트의 .docuking/config.json에서 설정 읽기
|
|
42
46
|
*
|
|
@@ -1110,9 +1114,11 @@ docuking_init 호출 시 apiKey 파라미터를 포함해주세요.`,
|
|
|
1110
1114
|
}
|
|
1111
1115
|
|
|
1112
1116
|
// Co-worker 권한은 API Key 형식에서 판단 (sk_xxx_cw_이름_)
|
|
1113
|
-
|
|
1117
|
+
// 이름이 비어있는 경우도 처리 (sk_xxx_cw__)
|
|
1118
|
+
const coworkerMatch = apiKey.match(/^sk_[a-f0-9]+_cw_([^_]*)_/);
|
|
1114
1119
|
const isCoworker = !!coworkerMatch;
|
|
1115
|
-
|
|
1120
|
+
// 코워커 이름이 비어있으면 'Coworker'로 기본값 설정
|
|
1121
|
+
const coworkerName = coworkerMatch ? (coworkerMatch[1] || 'Coworker') : null;
|
|
1116
1122
|
|
|
1117
1123
|
// .docuking/config.json에 설정 저장
|
|
1118
1124
|
saveLocalConfig(localPath, {
|
|
@@ -1264,9 +1270,11 @@ Git처럼 무엇을 변경했는지 명확히 작성해주세요.
|
|
|
1264
1270
|
const projectName = projectInfo.projectName;
|
|
1265
1271
|
|
|
1266
1272
|
// Co-worker 권한은 API Key 형식에서 판단 (sk_xxx_cw_이름_)
|
|
1267
|
-
|
|
1273
|
+
// 이름이 비어있는 경우도 처리 (sk_xxx_cw__)
|
|
1274
|
+
const coworkerMatch = apiKey.match(/^sk_[a-f0-9]+_cw_([^_]*)_/);
|
|
1268
1275
|
const isCoworker = !!coworkerMatch;
|
|
1269
|
-
|
|
1276
|
+
// 코워커 이름이 비어있으면 'Coworker'로 기본값 설정
|
|
1277
|
+
const coworkerName = coworkerMatch ? (coworkerMatch[1] || 'Coworker') : null;
|
|
1270
1278
|
const coworkerFolderName = isCoworker ? `yy_Coworker_${coworkerName}` : null;
|
|
1271
1279
|
|
|
1272
1280
|
// 작업 폴더 결정: 모두 yy_All_Docu/ 사용, 협업자는 yy_All_Docu/yy_Coworker_{이름}/ 에서 작업
|
|
@@ -1325,8 +1333,9 @@ docuking_init을 먼저 실행하세요.`,
|
|
|
1325
1333
|
filesToPush.push({ path: filePath, serverPath: serverFilePath, fullPath, fileType });
|
|
1326
1334
|
}
|
|
1327
1335
|
} else {
|
|
1328
|
-
// 전체 파일 - 제외된 파일 목록도 수집
|
|
1329
|
-
|
|
1336
|
+
// 전체 파일 - 제외된 파일 및 대용량 파일 목록도 수집
|
|
1337
|
+
const largeFiles = [];
|
|
1338
|
+
collectFiles(workingPath, '', filesToPush, excludedFiles, largeFiles);
|
|
1330
1339
|
|
|
1331
1340
|
// 서버 경로 추가
|
|
1332
1341
|
for (const file of filesToPush) {
|
|
@@ -1336,6 +1345,15 @@ docuking_init을 먼저 실행하세요.`,
|
|
|
1336
1345
|
if (isCoworker) {
|
|
1337
1346
|
console.log(`[DocuKing] 코워커 Push: ${filesToPush.length}개 파일 (${coworkerFolderName}/)`);
|
|
1338
1347
|
}
|
|
1348
|
+
|
|
1349
|
+
// 대용량 파일 경고
|
|
1350
|
+
if (largeFiles.length > 0) {
|
|
1351
|
+
console.error(`\n[DocuKing] ⚠️ 대용량 파일 ${largeFiles.length}개 제외됨 (${MAX_FILE_SIZE_MB}MB 초과):`);
|
|
1352
|
+
for (const f of largeFiles) {
|
|
1353
|
+
console.error(` - ${f.path} (${f.sizeMB}MB)`);
|
|
1354
|
+
}
|
|
1355
|
+
console.error(`💡 대용량 파일은 Google Drive, NAS 등 별도 방법으로 공유하세요.\n`);
|
|
1356
|
+
}
|
|
1339
1357
|
}
|
|
1340
1358
|
|
|
1341
1359
|
if (filesToPush.length === 0) {
|
|
@@ -1349,6 +1367,9 @@ docuking_init을 먼저 실행하세요.`,
|
|
|
1349
1367
|
};
|
|
1350
1368
|
}
|
|
1351
1369
|
|
|
1370
|
+
// 총 용량 계산
|
|
1371
|
+
const totalSizeMB = filesToPush.reduce((sum, f) => sum + (f.sizeMB || 0), 0);
|
|
1372
|
+
|
|
1352
1373
|
// 파일 업로드 (진행률 표시)
|
|
1353
1374
|
const results = [];
|
|
1354
1375
|
const total = filesToPush.length;
|
|
@@ -1356,7 +1377,7 @@ docuking_init을 먼저 실행하세요.`,
|
|
|
1356
1377
|
let skipped = 0;
|
|
1357
1378
|
|
|
1358
1379
|
// 시작 안내 메시지 출력 (AI가 사용자에게 전달할 수 있도록)
|
|
1359
|
-
console.error(`[DocuKing] Push 시작: ${total}개
|
|
1380
|
+
console.error(`[DocuKing] Push 시작: ${total}개 파일 (총 ${totalSizeMB.toFixed(1)}MB)`);
|
|
1360
1381
|
console.error(`[DocuKing] 💡 실시간 진행상황은 DocuKing 웹(https://docuking.ai)에서 확인하세요`);
|
|
1361
1382
|
|
|
1362
1383
|
// Sync 시작 알림 (웹에서 프로그레스바 표시용)
|
|
@@ -1404,8 +1425,14 @@ docuking_init을 먼저 실행하세요.`,
|
|
|
1404
1425
|
for (const file of filesToPush) {
|
|
1405
1426
|
current++;
|
|
1406
1427
|
const progress = `${current}/${total}`;
|
|
1428
|
+
const sizeInfo = file.sizeMB >= 1 ? ` (${file.sizeMB.toFixed(1)}MB)` : '';
|
|
1407
1429
|
processedLocalPaths.add(file.serverPath);
|
|
1408
1430
|
|
|
1431
|
+
// 1MB 이상 파일은 업로드 시작 시 로그 출력 (사용자가 진행 상황 파악 가능)
|
|
1432
|
+
if (file.sizeMB >= 1) {
|
|
1433
|
+
console.error(`[DocuKing] ${progress} 업로드 중: ${file.path}${sizeInfo}`);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1409
1436
|
try {
|
|
1410
1437
|
// 파일 해시 계산 (변경 감지)
|
|
1411
1438
|
let fileHash;
|
|
@@ -1978,8 +2005,9 @@ function hasAllDocuFolder(projectPath) {
|
|
|
1978
2005
|
|
|
1979
2006
|
// 유틸: 디렉토리 재귀 탐색
|
|
1980
2007
|
// excludedFiles: 제외된 파일 목록을 수집할 배열 (선택)
|
|
2008
|
+
// largeFiles: 대용량 파일 목록을 수집할 배열 (선택)
|
|
1981
2009
|
// zz_* 폴더는 로컬 전용이므로 동기화에서 제외
|
|
1982
|
-
function collectFiles(basePath, relativePath, results, excludedFiles = null) {
|
|
2010
|
+
function collectFiles(basePath, relativePath, results, excludedFiles = null, largeFiles = null) {
|
|
1983
2011
|
const fullPath = path.join(basePath, relativePath);
|
|
1984
2012
|
const entries = fs.readdirSync(fullPath, { withFileTypes: true });
|
|
1985
2013
|
|
|
@@ -1992,7 +2020,7 @@ function collectFiles(basePath, relativePath, results, excludedFiles = null) {
|
|
|
1992
2020
|
console.error(`[DocuKing] 제외됨: ${entryRelPath}/ (zz_* 폴더 - 로컬 전용)`);
|
|
1993
2021
|
continue;
|
|
1994
2022
|
}
|
|
1995
|
-
collectFiles(basePath, entryRelPath, results, excludedFiles);
|
|
2023
|
+
collectFiles(basePath, entryRelPath, results, excludedFiles, largeFiles);
|
|
1996
2024
|
} else if (entry.isFile()) {
|
|
1997
2025
|
const fileType = getFileType(entry.name);
|
|
1998
2026
|
|
|
@@ -2005,10 +2033,25 @@ function collectFiles(basePath, relativePath, results, excludedFiles = null) {
|
|
|
2005
2033
|
continue;
|
|
2006
2034
|
}
|
|
2007
2035
|
|
|
2036
|
+
// 파일 크기 확인
|
|
2037
|
+
const fileFullPath = path.join(fullPath, entry.name);
|
|
2038
|
+
const stats = fs.statSync(fileFullPath);
|
|
2039
|
+
const fileSizeMB = stats.size / (1024 * 1024);
|
|
2040
|
+
|
|
2041
|
+
// 대용량 파일은 별도 추적
|
|
2042
|
+
if (stats.size > MAX_FILE_SIZE_BYTES) {
|
|
2043
|
+
console.error(`[DocuKing] ⚠️ 대용량 파일 제외: ${entryRelPath} (${fileSizeMB.toFixed(1)}MB > ${MAX_FILE_SIZE_MB}MB)`);
|
|
2044
|
+
if (largeFiles) {
|
|
2045
|
+
largeFiles.push({ path: entryRelPath, sizeMB: fileSizeMB.toFixed(1) });
|
|
2046
|
+
}
|
|
2047
|
+
continue;
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2008
2050
|
results.push({
|
|
2009
2051
|
path: entryRelPath,
|
|
2010
|
-
fullPath:
|
|
2052
|
+
fullPath: fileFullPath,
|
|
2011
2053
|
fileType, // 'text' 또는 'binary'
|
|
2054
|
+
sizeMB: fileSizeMB, // 진행률 표시용
|
|
2012
2055
|
});
|
|
2013
2056
|
}
|
|
2014
2057
|
}
|
|
@@ -2066,9 +2109,11 @@ async function handleStatus(args) {
|
|
|
2066
2109
|
const projectName = projectInfo.projectName;
|
|
2067
2110
|
|
|
2068
2111
|
// Co-worker 권한은 API Key 형식에서 판단 (sk_xxx_cw_이름_)
|
|
2069
|
-
|
|
2112
|
+
// 이름이 비어있는 경우도 처리 (sk_xxx_cw__)
|
|
2113
|
+
const coworkerMatch = apiKey.match(/^sk_[a-f0-9]+_cw_([^_]*)_/);
|
|
2070
2114
|
const isCoworker = !!coworkerMatch;
|
|
2071
|
-
|
|
2115
|
+
// 코워커 이름이 비어있으면 'Coworker'로 기본값 설정
|
|
2116
|
+
const coworkerName = coworkerMatch ? (coworkerMatch[1] || 'Coworker') : null;
|
|
2072
2117
|
const coworkerFolderName = isCoworker ? `yy_Coworker_${coworkerName}` : null;
|
|
2073
2118
|
|
|
2074
2119
|
// 권한 정보 구성
|