@chnxthr/knowledge-mcp 0.0.0-stage → 0.3.1

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 (190) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -2
  3. package/dist/bootstrap.d.ts +1 -0
  4. package/dist/bootstrap.js +18 -0
  5. package/dist/bootstrap.js.map +1 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +5 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/core/auth.d.ts +38 -0
  10. package/dist/core/auth.js +93 -0
  11. package/dist/core/auth.js.map +1 -0
  12. package/dist/core/config.d.ts +259 -0
  13. package/dist/core/config.js +172 -0
  14. package/dist/core/config.js.map +1 -0
  15. package/dist/core/context.d.ts +25 -0
  16. package/dist/core/context.js +37 -0
  17. package/dist/core/context.js.map +1 -0
  18. package/dist/core/env.d.ts +2 -0
  19. package/dist/core/env.js +5 -0
  20. package/dist/core/env.js.map +1 -0
  21. package/dist/core/log_mask.d.ts +10 -0
  22. package/dist/core/log_mask.js +88 -0
  23. package/dist/core/log_mask.js.map +1 -0
  24. package/dist/core/oauth.d.ts +46 -0
  25. package/dist/core/oauth.js +507 -0
  26. package/dist/core/oauth.js.map +1 -0
  27. package/dist/core/paths.d.ts +5 -0
  28. package/dist/core/paths.js +47 -0
  29. package/dist/core/paths.js.map +1 -0
  30. package/dist/core/scope.d.ts +28 -0
  31. package/dist/core/scope.js +54 -0
  32. package/dist/core/scope.js.map +1 -0
  33. package/dist/core/upstream.d.ts +30 -0
  34. package/dist/core/upstream.js +164 -0
  35. package/dist/core/upstream.js.map +1 -0
  36. package/dist/index.d.ts +23 -0
  37. package/dist/index.js +21 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/plugin/define.d.ts +144 -0
  40. package/dist/plugin/define.js +44 -0
  41. package/dist/plugin/define.js.map +1 -0
  42. package/dist/plugin/load.d.ts +2 -0
  43. package/dist/plugin/load.js +41 -0
  44. package/dist/plugin/load.js.map +1 -0
  45. package/dist/plugin/ping.d.ts +9 -0
  46. package/dist/plugin/ping.js +29 -0
  47. package/dist/plugin/ping.js.map +1 -0
  48. package/dist/plugin/registry.d.ts +62 -0
  49. package/dist/plugin/registry.js +248 -0
  50. package/dist/plugin/registry.js.map +1 -0
  51. package/dist/plugin/result.d.ts +20 -0
  52. package/dist/plugin/result.js +59 -0
  53. package/dist/plugin/result.js.map +1 -0
  54. package/dist/plugins/drive/chunker.d.ts +28 -0
  55. package/dist/plugins/drive/chunker.js +356 -0
  56. package/dist/plugins/drive/chunker.js.map +1 -0
  57. package/dist/plugins/drive/clean_text.d.ts +13 -0
  58. package/dist/plugins/drive/clean_text.js +31 -0
  59. package/dist/plugins/drive/clean_text.js.map +1 -0
  60. package/dist/plugins/drive/client.d.ts +94 -0
  61. package/dist/plugins/drive/client.js +220 -0
  62. package/dist/plugins/drive/client.js.map +1 -0
  63. package/dist/plugins/drive/embeddings.d.ts +15 -0
  64. package/dist/plugins/drive/embeddings.js +118 -0
  65. package/dist/plugins/drive/embeddings.js.map +1 -0
  66. package/dist/plugins/drive/exclude.d.ts +11 -0
  67. package/dist/plugins/drive/exclude.js +36 -0
  68. package/dist/plugins/drive/exclude.js.map +1 -0
  69. package/dist/plugins/drive/extract_text.d.ts +26 -0
  70. package/dist/plugins/drive/extract_text.js +95 -0
  71. package/dist/plugins/drive/extract_text.js.map +1 -0
  72. package/dist/plugins/drive/get_token.d.ts +5 -0
  73. package/dist/plugins/drive/get_token.js +128 -0
  74. package/dist/plugins/drive/get_token.js.map +1 -0
  75. package/dist/plugins/drive/index.d.ts +5 -0
  76. package/dist/plugins/drive/index.js +72 -0
  77. package/dist/plugins/drive/index.js.map +1 -0
  78. package/dist/plugins/drive/indexer.d.ts +69 -0
  79. package/dist/plugins/drive/indexer.js +204 -0
  80. package/dist/plugins/drive/indexer.js.map +1 -0
  81. package/dist/plugins/drive/mathpix.d.ts +4 -0
  82. package/dist/plugins/drive/mathpix.js +102 -0
  83. package/dist/plugins/drive/mathpix.js.map +1 -0
  84. package/dist/plugins/drive/ooxml.d.ts +17 -0
  85. package/dist/plugins/drive/ooxml.js +152 -0
  86. package/dist/plugins/drive/ooxml.js.map +1 -0
  87. package/dist/plugins/drive/path.d.ts +40 -0
  88. package/dist/plugins/drive/path.js +87 -0
  89. package/dist/plugins/drive/path.js.map +1 -0
  90. package/dist/plugins/drive/qdrant.d.ts +123 -0
  91. package/dist/plugins/drive/qdrant.js +148 -0
  92. package/dist/plugins/drive/qdrant.js.map +1 -0
  93. package/dist/plugins/drive/reindex.d.ts +2 -0
  94. package/dist/plugins/drive/reindex.js +263 -0
  95. package/dist/plugins/drive/reindex.js.map +1 -0
  96. package/dist/plugins/drive/settings.d.ts +11 -0
  97. package/dist/plugins/drive/settings.js +13 -0
  98. package/dist/plugins/drive/settings.js.map +1 -0
  99. package/dist/plugins/drive/sync.d.ts +16 -0
  100. package/dist/plugins/drive/sync.js +139 -0
  101. package/dist/plugins/drive/sync.js.map +1 -0
  102. package/dist/plugins/drive/sync_state.d.ts +3 -0
  103. package/dist/plugins/drive/sync_state.js +26 -0
  104. package/dist/plugins/drive/sync_state.js.map +1 -0
  105. package/dist/plugins/drive/tools/list_drive_folder.d.ts +104 -0
  106. package/dist/plugins/drive/tools/list_drive_folder.js +221 -0
  107. package/dist/plugins/drive/tools/list_drive_folder.js.map +1 -0
  108. package/dist/plugins/drive/tools/read_drive_file.d.ts +66 -0
  109. package/dist/plugins/drive/tools/read_drive_file.js +206 -0
  110. package/dist/plugins/drive/tools/read_drive_file.js.map +1 -0
  111. package/dist/plugins/drive/tools/search_drive.d.ts +52 -0
  112. package/dist/plugins/drive/tools/search_drive.js +78 -0
  113. package/dist/plugins/drive/tools/search_drive.js.map +1 -0
  114. package/dist/plugins/drive/tools/semantic_search_drive.d.ts +109 -0
  115. package/dist/plugins/drive/tools/semantic_search_drive.js +228 -0
  116. package/dist/plugins/drive/tools/semantic_search_drive.js.map +1 -0
  117. package/dist/plugins/github/index.d.ts +1 -0
  118. package/dist/plugins/github/index.js +27 -0
  119. package/dist/plugins/github/index.js.map +1 -0
  120. package/dist/plugins/github/repo_tree.d.ts +57 -0
  121. package/dist/plugins/github/repo_tree.js +123 -0
  122. package/dist/plugins/github/repo_tree.js.map +1 -0
  123. package/dist/plugins/index.d.ts +11 -0
  124. package/dist/plugins/index.js +7 -0
  125. package/dist/plugins/index.js.map +1 -0
  126. package/dist/plugins/railway/index.d.ts +1 -0
  127. package/dist/plugins/railway/index.js +21 -0
  128. package/dist/plugins/railway/index.js.map +1 -0
  129. package/dist/plugins/railway/tools.d.ts +114 -0
  130. package/dist/plugins/railway/tools.js +165 -0
  131. package/dist/plugins/railway/tools.js.map +1 -0
  132. package/dist/plugins/slack/api.d.ts +63 -0
  133. package/dist/plugins/slack/api.js +280 -0
  134. package/dist/plugins/slack/api.js.map +1 -0
  135. package/dist/plugins/slack/index.d.ts +1 -0
  136. package/dist/plugins/slack/index.js +80 -0
  137. package/dist/plugins/slack/index.js.map +1 -0
  138. package/dist/plugins/slack/tools/slack_files.d.ts +87 -0
  139. package/dist/plugins/slack/tools/slack_files.js +204 -0
  140. package/dist/plugins/slack/tools/slack_files.js.map +1 -0
  141. package/dist/plugins/slack/tools/slack_list_channels.d.ts +46 -0
  142. package/dist/plugins/slack/tools/slack_list_channels.js +197 -0
  143. package/dist/plugins/slack/tools/slack_list_channels.js.map +1 -0
  144. package/dist/plugins/slack/tools/slack_read_channel.d.ts +56 -0
  145. package/dist/plugins/slack/tools/slack_read_channel.js +150 -0
  146. package/dist/plugins/slack/tools/slack_read_channel.js.map +1 -0
  147. package/dist/plugins/slack/tools/slack_search.d.ts +53 -0
  148. package/dist/plugins/slack/tools/slack_search.js +132 -0
  149. package/dist/plugins/slack/tools/slack_search.js.map +1 -0
  150. package/dist/run.d.ts +8 -0
  151. package/dist/run.js +270 -0
  152. package/dist/run.js.map +1 -0
  153. package/dist/server/http.d.ts +5 -0
  154. package/dist/server/http.js +406 -0
  155. package/dist/server/http.js.map +1 -0
  156. package/dist/server/identity.d.ts +17 -0
  157. package/dist/server/identity.js +47 -0
  158. package/dist/server/identity.js.map +1 -0
  159. package/dist/server/mcp.d.ts +7 -0
  160. package/dist/server/mcp.js +55 -0
  161. package/dist/server/mcp.js.map +1 -0
  162. package/dist/server/stdio.d.ts +2 -0
  163. package/dist/server/stdio.js +40 -0
  164. package/dist/server/stdio.js.map +1 -0
  165. package/dist/store/index.d.ts +11 -0
  166. package/dist/store/index.js +31 -0
  167. package/dist/store/index.js.map +1 -0
  168. package/dist/store/keys.d.ts +9 -0
  169. package/dist/store/keys.js +32 -0
  170. package/dist/store/keys.js.map +1 -0
  171. package/dist/store/sqlite.d.ts +38 -0
  172. package/dist/store/sqlite.js +316 -0
  173. package/dist/store/sqlite.js.map +1 -0
  174. package/dist/store/supabase.d.ts +35 -0
  175. package/dist/store/supabase.js +269 -0
  176. package/dist/store/supabase.js.map +1 -0
  177. package/dist/store/supabase_client.d.ts +10 -0
  178. package/dist/store/supabase_client.js +31 -0
  179. package/dist/store/supabase_client.js.map +1 -0
  180. package/dist/store/tool_log.d.ts +12 -0
  181. package/dist/store/tool_log.js +8 -0
  182. package/dist/store/tool_log.js.map +1 -0
  183. package/dist/store/types.d.ts +96 -0
  184. package/dist/store/types.js +2 -0
  185. package/dist/store/types.js.map +1 -0
  186. package/dist/version.d.ts +1 -0
  187. package/dist/version.js +11 -0
  188. package/dist/version.js.map +1 -0
  189. package/package.json +80 -4
  190. package/sql/supabase.sql +185 -0
@@ -0,0 +1,263 @@
1
+ import { getDriveClient } from './client.js';
2
+ import { chunkMarkdown } from './chunker.js';
3
+ import { embedTexts } from './embeddings.js';
4
+ import { extractText } from './extract_text.js';
5
+ import { isExcludedName } from './exclude.js';
6
+ import { ensureCollection, getQdrantClient, DRIVE_COLLECTION, } from './qdrant.js';
7
+ // 색인 코어 로직 SSOT — drive_sync(증분)와 공유해 drift 방지(특히 makeChunkId 일치 = orphan 로직 정합).
8
+ import { makeChunkId, classifyFile, contentHash, buildChunkPayload, deriveBizMeta, embedInputForChunk, SUPPORTED_MIMES, DRIVE_ROOTS, MAX_FILE_BYTES, } from './indexer.js';
9
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
10
+ import { join } from 'path';
11
+ import { dataDir } from '../../core/paths.js';
12
+ // 체크포인트 — 처리 완료 file_id 기록 → 재시작 시 skip (429 중단 후 재개·재실행 비용 절감).
13
+ // 데이터 폴더에 둔다(패키지 폴더는 npm 설치본이라 쓰기 불가일 수 있다).
14
+ const CHECKPOINT_PATH = join(dataDir(), 'drive-reindex-checkpoint.json');
15
+ function loadCheckpoint() {
16
+ if (!existsSync(CHECKPOINT_PATH))
17
+ return new Set();
18
+ try {
19
+ return new Set(JSON.parse(readFileSync(CHECKPOINT_PATH, 'utf8')));
20
+ }
21
+ catch {
22
+ return new Set();
23
+ }
24
+ }
25
+ function saveCheckpoint(done) {
26
+ mkdirSync(dataDir(), { recursive: true, mode: 0o700 });
27
+ writeFileSync(CHECKPOINT_PATH, JSON.stringify([...done]));
28
+ }
29
+ function clearCheckpoint() {
30
+ if (existsSync(CHECKPOINT_PATH))
31
+ unlinkSync(CHECKPOINT_PATH);
32
+ }
33
+ function parseArgs(args) {
34
+ let roots = DRIVE_ROOTS;
35
+ let dryRun = false;
36
+ let recreate = false;
37
+ let partial = false;
38
+ for (let i = 0; i < args.length; i++) {
39
+ if (args[i] === '--root' && args[i + 1]) {
40
+ // override default with single root (source=dev 가정)
41
+ roots = [{ id: args[++i], name: 'custom', source: 'dev' }];
42
+ partial = true;
43
+ }
44
+ else if (args[i] === '--biz-only') {
45
+ roots = DRIVE_ROOTS.filter((r) => r.source === 'biz');
46
+ partial = true;
47
+ }
48
+ else if (args[i] === '--dev-only') {
49
+ roots = DRIVE_ROOTS.filter((r) => r.source === 'dev');
50
+ partial = true;
51
+ }
52
+ else if (args[i] === '--dry-run') {
53
+ dryRun = true;
54
+ }
55
+ else if (args[i] === '--recreate') {
56
+ // collection 비우고 새로 (orphan chunk 제거 — 정제·chunk 수 변동 반영)
57
+ recreate = true;
58
+ }
59
+ }
60
+ return { roots, dryRun, recreate, partial };
61
+ }
62
+ /**
63
+ * 폴더 ID 의 지원 형식 파일 recursive list (deprecated 제외).
64
+ */
65
+ async function listAllMarkdown(drive, folderId, pathPrefix) {
66
+ const out = [];
67
+ const subfolderTasks = []; // 하위 폴더 recursion 을 병렬로
68
+ let pageToken;
69
+ do {
70
+ const resp = await drive.files.list({
71
+ q: `'${folderId}' in parents and trashed=false`,
72
+ fields: 'nextPageToken, files(id,name,mimeType,modifiedTime,size)',
73
+ pageSize: 100,
74
+ pageToken,
75
+ includeItemsFromAllDrives: true,
76
+ supportsAllDrives: true,
77
+ });
78
+ for (const f of resp.data.files ?? []) {
79
+ if (!f.id || !f.name)
80
+ continue;
81
+ const currentPath = pathPrefix ? `${pathPrefix}/${f.name}` : f.name;
82
+ if (f.mimeType === 'application/vnd.google-apps.folder') {
83
+ // 제외 폴더 (민감 PII/계약/HR + 개발 아티팩트. SSOT: exclude.ts) skip — recursion 자체 안 함
84
+ if (isExcludedName(f.name))
85
+ continue;
86
+ // gather as parallel tasks instead of sequential await (hundreds of folders: minutes -> seconds)
87
+ subfolderTasks.push(listAllMarkdown(drive, f.id, currentPath));
88
+ }
89
+ else if (f.mimeType && SUPPORTED_MIMES.has(f.mimeType)) {
90
+ out.push({
91
+ id: f.id,
92
+ name: f.name,
93
+ path: currentPath,
94
+ modifiedTime: f.modifiedTime ?? '',
95
+ mimeType: f.mimeType,
96
+ size: f.size ? Number(f.size) : undefined,
97
+ });
98
+ }
99
+ }
100
+ pageToken = resp.data.nextPageToken ?? undefined;
101
+ } while (pageToken);
102
+ // 하위 폴더 병렬 recursion 결과 합치기
103
+ const childResults = await Promise.all(subfolderTasks);
104
+ for (const child of childResults)
105
+ out.push(...child);
106
+ return out;
107
+ }
108
+ async function downloadMarkdown(drive, fileId) {
109
+ const resp = await drive.files.get({ fileId, alt: 'media', supportsAllDrives: true }, { responseType: 'text' });
110
+ return resp.data;
111
+ }
112
+ /**
113
+ * 이번 목록(keep)에 없는 파일의 벡터를 지운다. 반환 = 지운 파일 수.
114
+ * 목록 단계가 실패하면 main 이 그 전에 FATAL 로 끝나므로, 여기 도달했다면 목록은 완전하다.
115
+ */
116
+ async function pruneStaleVectors(keep) {
117
+ const qdrant = await getQdrantClient();
118
+ const stale = new Set();
119
+ let offset = undefined;
120
+ do {
121
+ const page = await qdrant.scroll(DRIVE_COLLECTION, {
122
+ limit: 1000,
123
+ offset: offset ?? undefined,
124
+ with_payload: ['file_id'],
125
+ with_vector: false,
126
+ });
127
+ for (const pt of page.points) {
128
+ const fid = pt.payload?.file_id;
129
+ if (typeof fid === 'string' && !keep.has(fid))
130
+ stale.add(fid);
131
+ }
132
+ offset = page.next_page_offset ?? null;
133
+ } while (offset !== null);
134
+ for (const fid of stale) {
135
+ await qdrant.delete(DRIVE_COLLECTION, {
136
+ wait: true,
137
+ filter: { must: [{ key: 'file_id', match: { value: fid } }] },
138
+ });
139
+ }
140
+ return stale.size;
141
+ }
142
+ /** `knowledge-mcp drive reindex [--root ID | --dev-only | --biz-only] [--dry-run] [--recreate]` */
143
+ export async function runReindex(argv) {
144
+ const { roots, dryRun, recreate, partial } = parseArgs(argv);
145
+ const startTs = Date.now();
146
+ console.log(`[index] start — roots=${roots.map((r) => r.name).join(',')} dryRun=${dryRun} recreate=${recreate}`);
147
+ // 1. Qdrant collection 보장 (--recreate 시 기존 비우고 새로)
148
+ if (!dryRun) {
149
+ if (recreate) {
150
+ try {
151
+ await (await getQdrantClient()).deleteCollection(DRIVE_COLLECTION);
152
+ console.log(`[index] collection '${DRIVE_COLLECTION}' 삭제 (recreate)`);
153
+ }
154
+ catch {
155
+ /* 없으면 무시 */
156
+ }
157
+ }
158
+ await ensureCollection();
159
+ console.log(`[index] collection '${DRIVE_COLLECTION}' ready`);
160
+ }
161
+ // 2. Drive 모든 markdown list (root 별)
162
+ const drive = await getDriveClient();
163
+ const allFiles = [];
164
+ for (const root of roots) {
165
+ const files = await listAllMarkdown(drive, root.id, '');
166
+ console.log(`[index] '${root.name}' (${root.source}) — ${files.length} files`);
167
+ for (const f of files)
168
+ allFiles.push({ ...f, source: root.source });
169
+ }
170
+ console.log(`[index] total ${allFiles.length} files`);
171
+ // 3. 파일별 download + chunk + embed + upsert
172
+ // 체크포인트 — recreate 면 초기화, 아니면 이전 진행분 skip (429 중단 후 재개)
173
+ if (recreate)
174
+ clearCheckpoint();
175
+ const done = dryRun ? new Set() : loadCheckpoint();
176
+ if (done.size > 0)
177
+ console.log(`[index] 체크포인트 — 이미 처리 ${done.size}개 skip`);
178
+ let totalChunks = 0;
179
+ let totalTokens = 0;
180
+ let processed = 0;
181
+ for (const file of allFiles) {
182
+ processed++;
183
+ if (done.has(file.id))
184
+ continue; // 체크포인트 — 이미 처리됨
185
+ if (file.size && file.size > MAX_FILE_BYTES) {
186
+ console.log(`[index] skip (too large: ${file.size}B > ${MAX_FILE_BYTES}B): [${file.source}] ${file.path}`);
187
+ done.add(file.id);
188
+ if (!dryRun)
189
+ saveCheckpoint(done);
190
+ continue;
191
+ }
192
+ try {
193
+ const { text, needsOcr } = await extractText(drive, file.id, file.mimeType);
194
+ if (needsOcr || text.trim().length === 0) {
195
+ console.log(`[index] skip (ocr/empty): [${file.source}] ${file.path}`);
196
+ done.add(file.id);
197
+ if (!dryRun)
198
+ saveCheckpoint(done);
199
+ continue;
200
+ }
201
+ const chunks = chunkMarkdown(text);
202
+ if (chunks.length === 0) {
203
+ console.log(`[index] skip empty: [${file.source}] ${file.path}`);
204
+ // 처리 완료로 기록 — 빠뜨리면 체크포인트가 영구히 남아 다음 재색인이 바뀐 파일을 건너뛴다.
205
+ done.add(file.id);
206
+ if (!dryRun)
207
+ saveCheckpoint(done);
208
+ continue;
209
+ }
210
+ const classification = classifyFile(file.path, file.source);
211
+ const bizMeta = deriveBizMeta(file.path, file.source);
212
+ const hash = contentHash(text); // 무변경 skip(EFF-1) 판정용 — payload 동봉 (SSOT: drive_indexer)
213
+ const fileTokens = chunks.reduce((s, c) => s + c.tokens, 0);
214
+ totalChunks += chunks.length;
215
+ totalTokens += fileTokens;
216
+ if (dryRun) {
217
+ console.log(`[index] [${processed}/${allFiles.length}] [${file.source}] ${file.path} — ${chunks.length} chunks, ${fileTokens} tok`);
218
+ continue;
219
+ }
220
+ // Embed — heading breadcrumb 포함(embedInputForChunk). 증분 경로(drive_indexer.indexFile)와 동일 입력.
221
+ const vectors = await embedTexts(chunks.map(embedInputForChunk));
222
+ // Qdrant upsert — payload 구성은 buildChunkPayload SSOT (drive_indexer) 공유
223
+ const points = chunks.map((c, idx) => ({
224
+ id: makeChunkId(file.id, idx),
225
+ vector: vectors[idx],
226
+ payload: buildChunkPayload(c, file, idx, chunks.length, classification, bizMeta, hash),
227
+ }));
228
+ const qdrant = await getQdrantClient();
229
+ // B-1: 이 파일의 기존 청크를 전부 제거한 뒤 새로 upsert (줄어든 경우 유령 청크 잔류 방지).
230
+ // 검증된 match 필터만 사용(range 필터는 비인덱싱 payload 에서 400). --recreate 면 매칭 0건(no-op).
231
+ // 풀 reindex 는 배치 작업이라 delete~upsert 사이의 짧은 공백 허용.
232
+ await qdrant.delete(DRIVE_COLLECTION, {
233
+ wait: false,
234
+ filter: { must: [{ key: 'file_id', match: { value: file.id } }] },
235
+ });
236
+ await qdrant.upsert(DRIVE_COLLECTION, {
237
+ wait: false,
238
+ points,
239
+ });
240
+ done.add(file.id); // 체크포인트 기록 (upsert 성공)
241
+ saveCheckpoint(done);
242
+ console.log(`[index] [${processed}/${allFiles.length}] [${file.source}] ${file.path} — ${chunks.length} chunks upserted (${fileTokens} tok)`);
243
+ }
244
+ catch (err) {
245
+ // 실패 파일은 체크포인트에 기록 안 함 → 재실행 시 재시도
246
+ console.error(`[index] ERROR [${file.source}] ${file.path}:`, err instanceof Error ? err.message : err);
247
+ }
248
+ }
249
+ // 4. 이번 목록에 없는 파일의 벡터 정리 (전체 root 실행일 때만)
250
+ if (!dryRun && !partial) {
251
+ const pruned = await pruneStaleVectors(new Set(allFiles.map((f) => f.id)));
252
+ console.log(`[index] 정리 — 목록에 없는 파일 ${pruned}개의 벡터 삭제`);
253
+ }
254
+ const elapsedSec = ((Date.now() - startTs) / 1000).toFixed(1);
255
+ // OpenAI text-embedding-3-small: $0.02/1M tokens.
256
+ const costUsd = ((totalTokens / 1_000_000) * 0.02).toFixed(4);
257
+ console.log(`\n[index] DONE — ${totalChunks} chunks, ${totalTokens} tokens, ` +
258
+ `~$${costUsd} (OpenAI text-embedding-3-small), ${elapsedSec}s`);
259
+ // 전부 성공적으로 끝났으면 체크포인트 정리 (실패가 남아있으면 보존)
260
+ if (!dryRun && done.size >= allFiles.length)
261
+ clearCheckpoint();
262
+ }
263
+ //# sourceMappingURL=reindex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reindex.js","sourceRoot":"","sources":["../../../src/plugins/drive/reindex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /** Drive index roots (SSOT for full reindex + incremental sync). Configured via config.drive.roots. */
2
+ export declare const DRIVE_ROOTS: {
3
+ id: string;
4
+ name: string;
5
+ source: "dev" | "biz";
6
+ }[];
7
+ /**
8
+ * 색인·읽기 파일 크기 상한(바이트). 파일을 통째로 메모리에 올리므로, 거대한 파일 하나가 서버를 죽이지 않게 막는다.
9
+ * Google 문서·시트·슬라이드는 Drive 메타에 size 가 없어(export) 이 검사를 받지 않는다.
10
+ */
11
+ export declare const MAX_FILE_BYTES: number;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Drive 색인 범위와 한도 — 가벼운 상수만 둔다. 도구들이 이 값 때문에 색인기(indexer.ts, 토크나이저·Qdrant)를
3
+ * 통째로 불러오지 않게 따로 뺐다.
4
+ */
5
+ import { getConfig } from '../../core/config.js';
6
+ /** Drive index roots (SSOT for full reindex + incremental sync). Configured via config.drive.roots. */
7
+ export const DRIVE_ROOTS = getConfig().drive.roots;
8
+ /**
9
+ * 색인·읽기 파일 크기 상한(바이트). 파일을 통째로 메모리에 올리므로, 거대한 파일 하나가 서버를 죽이지 않게 막는다.
10
+ * Google 문서·시트·슬라이드는 Drive 메타에 size 가 없어(export) 이 검사를 받지 않는다.
11
+ */
12
+ export const MAX_FILE_BYTES = Number(process.env.DRIVE_MAX_FILE_BYTES ?? 50_000_000);
13
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/plugins/drive/settings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,uGAAuG;AACvG,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC;AAEnD;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,UAAU,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface SyncResult {
2
+ status: string;
3
+ changed: number;
4
+ deleted: number;
5
+ skipped: number;
6
+ errored?: number;
7
+ }
8
+ export declare function runIncrementalSync(): Promise<SyncResult>;
9
+ /**
10
+ * startup 호출 — 1회 실행(첫 실행은 token init) + 주기 polling.
11
+ *
12
+ * setInterval 대신 **자기재귀 setTimeout** — 다음 tick 을 이전 sync 가 끝난 뒤에만 예약해
13
+ * 한 주기가 간격을 초과해도 sync 가 겹치지 않게 한다(중복 임베딩·토큰 되감김 방지).
14
+ * `_running` 재진입 가드는 이중 안전장치.
15
+ */
16
+ export declare function startDriveSyncScheduler(intervalMin?: number): void;
@@ -0,0 +1,139 @@
1
+ import { getDriveClient } from './client.js';
2
+ import { indexFile, deleteFileVectors, SUPPORTED_MIMES, DRIVE_ROOTS } from './indexer.js';
3
+ import { getSyncToken, setSyncToken } from './sync_state.js';
4
+ import { isExcludedPath } from './exclude.js';
5
+ import { getFolderMeta } from './path.js';
6
+ /**
7
+ * fileId 의 parent chain 을 root 까지 추적해 path + source 복원. dev/biz 외면 null.
8
+ * 폴더 hop 은 drive_path.getFolderMeta(프로세스 캐시·10분 TTL)로 조회 — 변경 파일들이 조상 폴더를
9
+ * 공유하므로 warmup 후 캐시 hit 로 Drive API 왕복이 급감(sync 지연·쿼터 절감). 파일 자신의 parents 만
10
+ * 매번 조회(변경 파일이라 캐시 무의미). 폴더 조회 실패 시 getFolderMeta 가 빈 값 → walk 종료(graceful).
11
+ */
12
+ async function resolvePathAndSource(drive, fileId, fileName) {
13
+ const folders = [];
14
+ let parents = (await drive.files.get({ fileId, fields: 'parents', supportsAllDrives: true })).data.parents ?? undefined;
15
+ for (let hop = 0; hop < 12 && parents && parents.length > 0; hop++) {
16
+ const pid = parents[0];
17
+ const root = DRIVE_ROOTS.find((r) => r.id === pid);
18
+ if (root)
19
+ return { path: [...folders, fileName].join('/'), source: root.source };
20
+ const meta = await getFolderMeta(drive, pid);
21
+ if (meta.name)
22
+ folders.unshift(meta.name);
23
+ parents = meta.parent ? [meta.parent] : undefined;
24
+ }
25
+ return null; // dev/biz root 하위 아님 → skip
26
+ }
27
+ export async function runIncrementalSync() {
28
+ const drive = await getDriveClient();
29
+ const token = await getSyncToken();
30
+ // 첫 실행 — startPageToken 저장만 (이후 변경부터 추적). 전체 색인은 knowledge-mcp drive reindex.
31
+ if (!token) {
32
+ const { data } = await drive.changes.getStartPageToken({ supportsAllDrives: true });
33
+ if (data.startPageToken)
34
+ await setSyncToken(data.startPageToken);
35
+ return { status: 'initialized', changed: 0, deleted: 0, skipped: 0 };
36
+ }
37
+ let changed = 0;
38
+ let deleted = 0;
39
+ let skipped = 0;
40
+ let errored = 0;
41
+ let cursor = token;
42
+ while (cursor) {
43
+ const data = (await drive.changes.list({
44
+ pageToken: cursor,
45
+ fields: 'nextPageToken, newStartPageToken, changes(removed, fileId, file(id,name,mimeType,modifiedTime,trashed,size))',
46
+ pageSize: 100,
47
+ includeRemoved: true,
48
+ includeItemsFromAllDrives: true,
49
+ supportsAllDrives: true,
50
+ })).data;
51
+ for (const ch of data.changes ?? []) {
52
+ // 파일 1건 실패(Mathpix timeout·OpenAI 5xx 소진·깨진 docx 등)가 throw 하면 루프를 탈출해
53
+ // runIncrementalSync 가 전체 throw → 그 tick 의 setSyncToken 이 호출 안 돼 pageToken 이
54
+ // 전진 못 하고, 다음 tick 에 같은 깨진 파일에서 또 멈춘다(sync 영구 정체). per-file 격리로
55
+ // 실패 파일만 errored 처리하고 나머지·토큰 전진은 계속한다.
56
+ try {
57
+ const f = ch.file;
58
+ if (ch.removed || f?.trashed) {
59
+ if (ch.fileId) {
60
+ await deleteFileVectors(ch.fileId);
61
+ deleted++;
62
+ }
63
+ continue;
64
+ }
65
+ if (!f?.id || !f.name || !f.mimeType || !SUPPORTED_MIMES.has(f.mimeType)) {
66
+ skipped++;
67
+ continue;
68
+ }
69
+ const resolved = await resolvePathAndSource(drive, f.id, f.name);
70
+ // 제외: dev/biz 외 폴더 + 민감(PII/계약/HR/deprecated) + 개발 아티팩트(node_modules 등). SSOT: exclude.ts
71
+ // 색인 대상 밖으로 옮겨졌거나 제외 폴더로 들어간 파일은 남아 있던 벡터를 지운다
72
+ // (건너뛰기만 하면 옛 청크 본문이 semantic_search_drive 에 계속 나온다).
73
+ if (!resolved || isExcludedPath(resolved.path)) {
74
+ await deleteFileVectors(f.id);
75
+ skipped++;
76
+ continue;
77
+ }
78
+ await indexFile(drive, {
79
+ id: f.id,
80
+ name: f.name,
81
+ path: resolved.path,
82
+ modifiedTime: f.modifiedTime ?? '',
83
+ source: resolved.source,
84
+ mimeType: f.mimeType,
85
+ size: f.size ? Number(f.size) : undefined,
86
+ });
87
+ changed++;
88
+ }
89
+ catch (e) {
90
+ errored++;
91
+ console.error(`[drive-sync] 파일 색인 실패 (skip, 토큰은 전진): fileId=${ch.fileId ?? '?'} — ${e instanceof Error ? e.message : e}`);
92
+ }
93
+ }
94
+ if (data.newStartPageToken) {
95
+ await setSyncToken(data.newStartPageToken);
96
+ break;
97
+ }
98
+ cursor = data.nextPageToken ?? undefined;
99
+ }
100
+ return { status: 'synced', changed, deleted, skipped, errored };
101
+ }
102
+ let _started = false;
103
+ let _running = false;
104
+ let _timer = null;
105
+ /**
106
+ * startup 호출 — 1회 실행(첫 실행은 token init) + 주기 polling.
107
+ *
108
+ * setInterval 대신 **자기재귀 setTimeout** — 다음 tick 을 이전 sync 가 끝난 뒤에만 예약해
109
+ * 한 주기가 간격을 초과해도 sync 가 겹치지 않게 한다(중복 임베딩·토큰 되감김 방지).
110
+ * `_running` 재진입 가드는 이중 안전장치.
111
+ */
112
+ export function startDriveSyncScheduler(intervalMin = 30) {
113
+ if (_started)
114
+ return;
115
+ _started = true;
116
+ const run = async () => {
117
+ if (_running) {
118
+ console.error('[drive-sync] 이전 주기 진행 중 — 이번 tick 건너뜀');
119
+ return;
120
+ }
121
+ _running = true;
122
+ try {
123
+ const r = await runIncrementalSync();
124
+ console.error(`[drive-sync] ${r.status} · changed=${r.changed} deleted=${r.deleted} skipped=${r.skipped} errored=${r.errored ?? 0}`);
125
+ }
126
+ catch (e) {
127
+ console.error('[drive-sync] error:', e instanceof Error ? e.message : e);
128
+ }
129
+ finally {
130
+ _running = false;
131
+ }
132
+ };
133
+ const scheduleNext = () => {
134
+ _timer = setTimeout(() => void run().finally(scheduleNext), intervalMin * 60_000);
135
+ };
136
+ void run().finally(scheduleNext); // startup 1회 후 주기 시작
137
+ console.error(`[drive-sync] scheduler 시작 — ${intervalMin}분 주기 (자기재귀 setTimeout · 재진입 가드)`);
138
+ }
139
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../src/plugins/drive/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** 저장된 토큰. 없으면 null(첫 실행). 저장소 오류는 throw. */
2
+ export declare function getSyncToken(): Promise<string | null>;
3
+ export declare function setSyncToken(token: string): Promise<void>;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Drive 증분 sync 의 pageToken 영속화 — 저장소 plugin state (namespace "drive", key "pageToken").
3
+ *
4
+ * 로컬 파일은 컨테이너 재배포마다 사라져(ephemeral) 재배포~다음 전체 reindex 사이의 Drive 변경분이
5
+ * 인덱스에 영구 누락됐다. 그래서 저장소(SQLite 파일은 볼륨, 또는 Supabase)에 둔다.
6
+ *
7
+ * 읽기 실패는 throw 한다. 예전엔 null(= 첫 실행)로 취급해 "지금부터" 토큰으로 덮어써,
8
+ * 일시 장애 한 번에 그 사이 변경분을 영구히 놓쳤다. 이제 그 주기만 건너뛰고 다음 주기에 다시 읽는다.
9
+ */
10
+ import { getStore } from '../../store/index.js';
11
+ const NS = 'drive';
12
+ const KEY = 'pageToken';
13
+ /** 저장된 토큰. 없으면 null(첫 실행). 저장소 오류는 throw. */
14
+ export async function getSyncToken() {
15
+ const v = await (await getStore()).getState(NS, KEY);
16
+ return typeof v === 'string' && v ? v : null;
17
+ }
18
+ export async function setSyncToken(token) {
19
+ try {
20
+ await (await getStore()).setState(NS, KEY, token);
21
+ }
22
+ catch (e) {
23
+ console.error('[sync_state] setSyncToken failed:', e instanceof Error ? e.message : e);
24
+ }
25
+ }
26
+ //# sourceMappingURL=sync_state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync_state.js","sourceRoot":"","sources":["../../../src/plugins/drive/sync_state.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,MAAM,EAAE,GAAG,OAAO,CAAC;AACnB,MAAM,GAAG,GAAG,WAAW,CAAC;AAExB,6CAA6C;AAC7C,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa;IAC9C,IAAI,CAAC;QACH,MAAM,CAAC,MAAM,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC;AACH,CAAC"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * list_drive_folder — Drive 폴더 자식 list (배치 + 재귀 depth).
3
+ *
4
+ * 배치/재귀: 폴더 N개·하위 트리를 1회 호출로. 에이전트가 폴더마다 순차 호출(= per-call
5
+ * 네트워크 floor + 그 사이 LLM 추론 턴 ×N)하던 것을 1회로 접어 체감 지연을 N→1 로 줄인다.
6
+ * read_drive_file 의 fileIds 배치와 같은 패턴(서버가 Drive I/O 를 자기↔구글 빠른 망에서 병렬).
7
+ *
8
+ * - folderNames[] / folderIds[] : 서로 다른 위치의 폴더 여러 개를 병렬 list.
9
+ * - depth (1~3) : 한 폴더의 하위 트리를 N단계까지 한 번에.
10
+ * 예) 고객사 10곳 + 각 폴더 문서 → list_drive_folder({ folderName: "01_고객사", depth: 2 }).
11
+ *
12
+ * 보안: 시작 폴더는 색인 root 하위이고 제외 폴더(PII·계약·HR 등)를 거치지 않을 때만 연다(read_drive_file 과 동일 가드).
13
+ * 이름으로 찾을 때도 root 하위 후보만 고른다. 재귀 walk 는 제외 폴더로 확산하지 않는다
14
+ * (해당 폴더는 이름만 표기하고 자식 미전개 — excluded:true).
15
+ *
16
+ * 안전장치: 총 폴더 방문(=Drive list 호출) 상한 MAX_FOLDER_VISITS — 깊고 넓은 트리의 호출 폭발 방지.
17
+ */
18
+ import { z } from 'zod';
19
+ declare const inputSchema: z.ZodEffects<z.ZodObject<{
20
+ folderId: z.ZodOptional<z.ZodString>;
21
+ folderName: z.ZodOptional<z.ZodString>;
22
+ folderIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
23
+ folderNames: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
24
+ depth: z.ZodDefault<z.ZodNumber>;
25
+ pageSize: z.ZodDefault<z.ZodNumber>;
26
+ }, "strip", z.ZodTypeAny, {
27
+ depth: number;
28
+ pageSize: number;
29
+ folderId?: string | undefined;
30
+ folderName?: string | undefined;
31
+ folderIds?: string[] | undefined;
32
+ folderNames?: string[] | undefined;
33
+ }, {
34
+ depth?: number | undefined;
35
+ pageSize?: number | undefined;
36
+ folderId?: string | undefined;
37
+ folderName?: string | undefined;
38
+ folderIds?: string[] | undefined;
39
+ folderNames?: string[] | undefined;
40
+ }>, {
41
+ depth: number;
42
+ pageSize: number;
43
+ folderId?: string | undefined;
44
+ folderName?: string | undefined;
45
+ folderIds?: string[] | undefined;
46
+ folderNames?: string[] | undefined;
47
+ }, {
48
+ depth?: number | undefined;
49
+ pageSize?: number | undefined;
50
+ folderId?: string | undefined;
51
+ folderName?: string | undefined;
52
+ folderIds?: string[] | undefined;
53
+ folderNames?: string[] | undefined;
54
+ }>;
55
+ export declare const listDriveFolderTool: import("../../../plugin/define.js").Tool<z.ZodEffects<z.ZodObject<{
56
+ folderId: z.ZodOptional<z.ZodString>;
57
+ folderName: z.ZodOptional<z.ZodString>;
58
+ folderIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
59
+ folderNames: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
60
+ depth: z.ZodDefault<z.ZodNumber>;
61
+ pageSize: z.ZodDefault<z.ZodNumber>;
62
+ }, "strip", z.ZodTypeAny, {
63
+ depth: number;
64
+ pageSize: number;
65
+ folderId?: string | undefined;
66
+ folderName?: string | undefined;
67
+ folderIds?: string[] | undefined;
68
+ folderNames?: string[] | undefined;
69
+ }, {
70
+ depth?: number | undefined;
71
+ pageSize?: number | undefined;
72
+ folderId?: string | undefined;
73
+ folderName?: string | undefined;
74
+ folderIds?: string[] | undefined;
75
+ folderNames?: string[] | undefined;
76
+ }>, {
77
+ depth: number;
78
+ pageSize: number;
79
+ folderId?: string | undefined;
80
+ folderName?: string | undefined;
81
+ folderIds?: string[] | undefined;
82
+ folderNames?: string[] | undefined;
83
+ }, {
84
+ depth?: number | undefined;
85
+ pageSize?: number | undefined;
86
+ folderId?: string | undefined;
87
+ folderName?: string | undefined;
88
+ folderIds?: string[] | undefined;
89
+ folderNames?: string[] | undefined;
90
+ }>>;
91
+ export declare function handleListDriveFolder(args: z.infer<typeof inputSchema>): Promise<{
92
+ content: {
93
+ type: "text";
94
+ text: string;
95
+ }[];
96
+ isError: boolean;
97
+ } | {
98
+ content: {
99
+ type: "text";
100
+ text: string;
101
+ }[];
102
+ isError?: undefined;
103
+ }>;
104
+ export {};