@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,17 @@
1
+ /** Read the named entries (exact names) as UTF-8 text. Missing names are left out. */
2
+ export declare function readZipTexts(buf: Buffer, wanted: (name: string) => boolean): Map<string, string>;
3
+ export declare function decodeXml(s: string): string;
4
+ /**
5
+ * Paragraph texts of one XML part. `ns` is the text namespace prefix: "w" for Word, "a" for DrawingML.
6
+ * Inside a paragraph: <ns:t> text, <ns:tab/> → tab, <ns:br/> and <w:cr/> → newline. Empty paragraphs are kept
7
+ * as "" so callers can decide how to join them.
8
+ */
9
+ export declare function paragraphs(xml: string, ns: 'w' | 'a'): string[];
10
+ /** .docx → plain text, paragraphs separated by a blank line. */
11
+ export declare function docxText(buf: Buffer): string;
12
+ /**
13
+ * .pptx → "## Slide N" sections: the slide's text, then text of SmartArt diagrams and charts on that slide,
14
+ * then speaker notes. Diagrams, charts and notes are found through the slide's relationship file
15
+ * (ppt/slides/_rels/slideN.xml.rels), so they stay with the right slide even when numbering differs.
16
+ */
17
+ export declare function pptxText(buf: Buffer): string;
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Word(.docx), PowerPoint(.pptx) 본문 텍스트 추출 — 의존성 없이 zip 과 XML 만 읽는다.
3
+ *
4
+ * 왜 직접: 예전엔 docx 는 mammoth, pptx 는 officeparser 를 썼다. mammoth 최신판도 argparse → sprintf-js
5
+ * (보안 권고)를, officeparser 7 은 취약한 pdfjs-dist 를, 8 은 OCR 엔진(tesseract.js)까지 끌어와 설치마다
6
+ * 경고가 났다. 색인에 필요한 건 본문 텍스트뿐이라 zip 목록과 XML 의 글자 노드만 읽으면 된다.
7
+ *
8
+ * docx: word/document.xml 의 문단(<w:p>)마다 글자(<w:t>), 탭, 줄바꿈 → 문단 사이 빈 줄 (mammoth extractRawText 와 같은 모양)
9
+ * pptx: ppt/slides/slideN.xml 을 번호 순으로, 문단(<a:p>)마다 글자(<a:t>). 그 슬라이드의 SmartArt, 차트 글자와
10
+ * 발표자 노트를 관계 파일(_rels)로 찾아 뒤에 붙인다
11
+ *
12
+ * 압축 폭탄 방어: 항목 하나 MAX_ENTRY_BYTES, 합계 MAX_TOTAL_BYTES 를 넘으면 멈춘다.
13
+ */
14
+ import { inflateRawSync } from 'node:zlib';
15
+ const MAX_ENTRY_BYTES = 64 * 1024 * 1024;
16
+ const MAX_TOTAL_BYTES = 256 * 1024 * 1024;
17
+ /** Central directory 목록. ZIP64 는 Office 문서에 쓰이지 않아(4GB 미만) 다루지 않는다. */
18
+ function listEntries(buf) {
19
+ // End of central directory: 0x06054b50, 파일 끝에서 최대 64KB(주석) + 22바이트 안에 있다.
20
+ const min = Math.max(0, buf.length - 65_557);
21
+ let eocd = -1;
22
+ for (let i = buf.length - 22; i >= min; i--) {
23
+ if (buf.readUInt32LE(i) === 0x06054b50) {
24
+ eocd = i;
25
+ break;
26
+ }
27
+ }
28
+ if (eocd < 0)
29
+ throw new Error('not a zip file (no end of central directory)');
30
+ const count = buf.readUInt16LE(eocd + 10);
31
+ let p = buf.readUInt32LE(eocd + 16);
32
+ const out = [];
33
+ for (let n = 0; n < count; n++) {
34
+ if (p + 46 > buf.length || buf.readUInt32LE(p) !== 0x02014b50)
35
+ throw new Error('corrupt zip central directory');
36
+ const nameLen = buf.readUInt16LE(p + 28);
37
+ const extraLen = buf.readUInt16LE(p + 30);
38
+ const commentLen = buf.readUInt16LE(p + 32);
39
+ out.push({
40
+ method: buf.readUInt16LE(p + 10),
41
+ compressedSize: buf.readUInt32LE(p + 20),
42
+ size: buf.readUInt32LE(p + 24),
43
+ localOffset: buf.readUInt32LE(p + 42),
44
+ name: buf.toString('utf8', p + 46, p + 46 + nameLen),
45
+ });
46
+ p += 46 + nameLen + extraLen + commentLen;
47
+ }
48
+ return out;
49
+ }
50
+ function readEntry(buf, e) {
51
+ const p = e.localOffset;
52
+ if (p + 30 > buf.length || buf.readUInt32LE(p) !== 0x04034b50)
53
+ throw new Error(`corrupt zip entry ${e.name}`);
54
+ const start = p + 30 + buf.readUInt16LE(p + 26) + buf.readUInt16LE(p + 28);
55
+ const data = buf.subarray(start, start + e.compressedSize);
56
+ if (e.size > MAX_ENTRY_BYTES)
57
+ throw new Error(`zip entry too large: ${e.name}`);
58
+ if (e.method === 0)
59
+ return data;
60
+ if (e.method === 8)
61
+ return inflateRawSync(data, { maxOutputLength: MAX_ENTRY_BYTES });
62
+ throw new Error(`unsupported zip compression ${e.method} in ${e.name}`);
63
+ }
64
+ /** Read the named entries (exact names) as UTF-8 text. Missing names are left out. */
65
+ export function readZipTexts(buf, wanted) {
66
+ const out = new Map();
67
+ let total = 0;
68
+ for (const e of listEntries(buf)) {
69
+ if (!wanted(e.name))
70
+ continue;
71
+ const data = readEntry(buf, e);
72
+ total += data.length;
73
+ if (total > MAX_TOTAL_BYTES)
74
+ throw new Error('zip content too large');
75
+ out.set(e.name, data.toString('utf8'));
76
+ }
77
+ return out;
78
+ }
79
+ const ENTITIES = { amp: '&', lt: '<', gt: '>', quot: '"', apos: "'" };
80
+ export function decodeXml(s) {
81
+ return s.replace(/&(#x[0-9a-fA-F]+|#\d+|[a-z]+);/g, (m, ent) => {
82
+ if (ent[0] === '#') {
83
+ const code = ent[1] === 'x' ? parseInt(ent.slice(2), 16) : parseInt(ent.slice(1), 10);
84
+ return Number.isFinite(code) && code <= 0x10ffff ? String.fromCodePoint(code) : m;
85
+ }
86
+ return ENTITIES[ent] ?? m;
87
+ });
88
+ }
89
+ /**
90
+ * Paragraph texts of one XML part. `ns` is the text namespace prefix: "w" for Word, "a" for DrawingML.
91
+ * Inside a paragraph: <ns:t> text, <ns:tab/> → tab, <ns:br/> and <w:cr/> → newline. Empty paragraphs are kept
92
+ * as "" so callers can decide how to join them.
93
+ */
94
+ export function paragraphs(xml, ns) {
95
+ const out = [];
96
+ const paraRe = new RegExp(`<${ns}:p[\\s>][\\s\\S]*?</${ns}:p>|<${ns}:p/>`, 'g');
97
+ const tokenRe = new RegExp(`<${ns}:t(?:\\s[^>]*)?>([\\s\\S]*?)</${ns}:t>|<${ns}:t(?:\\s[^>]*)?/>|<${ns}:tab/>|<${ns}:br(?:\\s[^>]*)?/?>|<w:cr/>`, 'g');
98
+ for (const para of xml.match(paraRe) ?? []) {
99
+ let text = '';
100
+ for (const m of para.matchAll(tokenRe)) {
101
+ if (m[1] !== undefined)
102
+ text += decodeXml(m[1]);
103
+ else if (m[0].startsWith(`<${ns}:tab`))
104
+ text += '\t';
105
+ else if (m[0].startsWith(`<${ns}:br`) || m[0] === '<w:cr/>')
106
+ text += '\n';
107
+ }
108
+ out.push(text);
109
+ }
110
+ return out;
111
+ }
112
+ /** .docx → plain text, paragraphs separated by a blank line. */
113
+ export function docxText(buf) {
114
+ const xml = readZipTexts(buf, (n) => n === 'word/document.xml').get('word/document.xml');
115
+ if (xml === undefined)
116
+ throw new Error('word/document.xml not found (not a .docx?)');
117
+ return paragraphs(xml, 'w')
118
+ .filter((p) => p.trim())
119
+ .join('\n\n');
120
+ }
121
+ const slideNo = (name) => Number(/(\d+)\.xml$/.exec(name)?.[1] ?? 0);
122
+ /** Non-empty paragraph lines of one DrawingML part. */
123
+ const lines = (xml) => (xml ? paragraphs(xml, 'a').filter((p) => p.trim()) : []);
124
+ /**
125
+ * .pptx → "## Slide N" sections: the slide's text, then text of SmartArt diagrams and charts on that slide,
126
+ * then speaker notes. Diagrams, charts and notes are found through the slide's relationship file
127
+ * (ppt/slides/_rels/slideN.xml.rels), so they stay with the right slide even when numbering differs.
128
+ */
129
+ export function pptxText(buf) {
130
+ const parts = readZipTexts(buf, (n) => /^ppt\/(slides\/slide\d+\.xml|slides\/_rels\/slide\d+\.xml\.rels|notesSlides\/notesSlide\d+\.xml|diagrams\/data\d+\.xml|charts\/chart\d+\.xml)$/.test(n));
131
+ const slides = [...parts.keys()].filter((n) => /^ppt\/slides\/slide\d+\.xml$/.test(n)).sort((a, b) => slideNo(a) - slideNo(b));
132
+ if (!slides.length)
133
+ throw new Error('no slides found (not a .pptx?)');
134
+ return slides
135
+ .map((name) => {
136
+ const n = slideNo(name);
137
+ const rels = parts.get(`ppt/slides/_rels/slide${n}.xml.rels`) ?? '';
138
+ const targets = [...rels.matchAll(/Target="\.\.\/((?:diagrams\/data|charts\/chart|notesSlides\/notesSlide)\d+\.xml)"/g)].map((m) => `ppt/${m[1]}`);
139
+ const notesPart = targets.find((t) => t.includes('notesSlides/')) ?? `ppt/notesSlides/notesSlide${n}.xml`;
140
+ const body = [
141
+ ...lines(parts.get(name)),
142
+ ...targets.filter((t) => !t.includes('notesSlides/')).flatMap((t) => lines(parts.get(t))),
143
+ ].join('\n');
144
+ // 노트 틀의 슬라이드 번호 자리(숫자만 있는 문단)는 뺀다
145
+ const notes = lines(parts.get(notesPart))
146
+ .filter((p) => !/^\d+$/.test(p.trim()))
147
+ .join('\n');
148
+ return [`## Slide ${n}`, body, notes ? `Notes:\n${notes}` : ''].filter(Boolean).join('\n\n');
149
+ })
150
+ .join('\n\n');
151
+ }
152
+ //# sourceMappingURL=ooxml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ooxml.js","sourceRoot":"","sources":["../../../src/plugins/drive/ooxml.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Drive 파일의 부모 체인 분류 — search_drive 가 민감/제외 폴더를 응답에서 거르는 데 사용.
3
+ *
4
+ * 왜: semantic 색인은 `06_증빙_PII`·`02_계약_법무`·`07_채용_HR`·deprecated 를 제외(exclude.ts)하지만,
5
+ * search_drive 는 Drive API 를 직접 때려 service account 가 공유받은 전체를 노출했다 → 계약·PII·HR 유출 위험.
6
+ * 이 모듈로 검색 결과를 "dev/biz root 하위 + 제외 폴더 미경유"로 한정한다.
7
+ *
8
+ * 성능: 폴더 메타(id→name,parent)는 거의 변하지 않으므로 프로세스 캐시 → 부모 walk 가 warmup 후 캐시 hit.
9
+ */
10
+ import type { DriveClient } from './client.js';
11
+ export declare function getFolderMeta(drive: DriveClient, id: string): Promise<{
12
+ name: string;
13
+ parent: string | undefined;
14
+ }>;
15
+ export type SearchClass = 'ok' | 'excluded' | 'outside';
16
+ /**
17
+ * 파일의 immediate parents 에서 root 까지 올라가며 분류:
18
+ * - 'excluded' : 제외 폴더(PII/계약/HR/deprecated/node_modules 등)를 경유 → 응답에서 제거
19
+ * - 'ok' : dev/biz root 하위 + 제외 미경유 → 노출
20
+ * - 'outside' : root 에 닿지 못함(색인 대상 밖) → 보수적으로 제거
21
+ * resolvePathAndSource(drive_sync) 와 동일하게 parents[0] 만 따라간다(최대 12 hop).
22
+ */
23
+ export declare function classifyForSearch(drive: DriveClient, parents: string[] | undefined): Promise<SearchClass>;
24
+ /**
25
+ * classifyForSearch + 폴더 경로(root 하위) 반환 — 직원별 Drive 폴더 scope 필터용.
26
+ * path 는 폴더만(파일명 제외), root 바로 아래부터, 예: "01_고객사/Acme". cls!=='ok' 면 path 무의미.
27
+ */
28
+ export declare function classifyAndPath(drive: DriveClient, parents: string[] | undefined): Promise<{
29
+ cls: SearchClass;
30
+ path: string;
31
+ }>;
32
+ /**
33
+ * 폴더 자신을 분류 — list_drive_folder 의 시작 폴더 검사용.
34
+ * root 폴더면 'ok'(path ''), 그 밖에는 자기 이름이 제외 대상인지 본 뒤 부모 체인을 classifyAndPath 로 분류한다.
35
+ * path 는 root 바로 아래부터 이 폴더까지(자기 이름 포함). 예: root/01_고객사/Acme → "01_고객사/Acme".
36
+ */
37
+ export declare function classifyFolder(drive: DriveClient, folderId: string): Promise<{
38
+ cls: SearchClass;
39
+ path: string;
40
+ }>;
@@ -0,0 +1,87 @@
1
+ import { DRIVE_ROOTS } from './settings.js';
2
+ import { isExcludedName } from './exclude.js';
3
+ const ROOT_IDS = new Set(DRIVE_ROOTS.map((r) => r.id));
4
+ // 폴더 메타 캐시 (id → {name, parent}). TTL 부여 — 영구 캐시면 폴더를 민감 분류(`06_증빙_PII` 등)로
5
+ // rename 하거나 제외 폴더로 move 해도 옛 이름으로 분류돼 새로 민감해진 폴더가 재배포 전까지
6
+ // 노출(under-exclude)된다. 짧은 TTL(기본 10분)로 분류 변경을 반영. rename/move 는 드물어 캐시 효과는 유지.
7
+ const FOLDER_META_TTL_MS = Number(process.env.FOLDER_META_TTL_MS ?? 600_000);
8
+ const _folderMeta = new Map();
9
+ export async function getFolderMeta(drive, id) {
10
+ const now = Date.now();
11
+ const cached = _folderMeta.get(id);
12
+ if (cached && cached.expiresAt > now)
13
+ return { name: cached.name, parent: cached.parent };
14
+ try {
15
+ const d = (await drive.files.get({ fileId: id, fields: 'name,parents', supportsAllDrives: true }))
16
+ .data;
17
+ const meta = { name: d.name ?? '', parent: d.parents?.[0], expiresAt: now + FOLDER_META_TTL_MS };
18
+ _folderMeta.set(id, meta);
19
+ return { name: meta.name, parent: meta.parent };
20
+ }
21
+ catch {
22
+ return { name: '', parent: undefined };
23
+ }
24
+ }
25
+ /**
26
+ * 파일의 immediate parents 에서 root 까지 올라가며 분류:
27
+ * - 'excluded' : 제외 폴더(PII/계약/HR/deprecated/node_modules 등)를 경유 → 응답에서 제거
28
+ * - 'ok' : dev/biz root 하위 + 제외 미경유 → 노출
29
+ * - 'outside' : root 에 닿지 못함(색인 대상 밖) → 보수적으로 제거
30
+ * resolvePathAndSource(drive_sync) 와 동일하게 parents[0] 만 따라간다(최대 12 hop).
31
+ */
32
+ export async function classifyForSearch(drive, parents) {
33
+ let chain = parents;
34
+ for (let hop = 0; hop < 12 && chain && chain.length > 0; hop++) {
35
+ const pid = chain[0];
36
+ if (ROOT_IDS.has(pid))
37
+ return 'ok';
38
+ const meta = await getFolderMeta(drive, pid);
39
+ if (isExcludedName(meta.name))
40
+ return 'excluded';
41
+ chain = meta.parent ? [meta.parent] : undefined;
42
+ }
43
+ return 'outside';
44
+ }
45
+ /**
46
+ * classifyForSearch + 폴더 경로(root 하위) 반환 — 직원별 Drive 폴더 scope 필터용.
47
+ * path 는 폴더만(파일명 제외), root 바로 아래부터, 예: "01_고객사/Acme". cls!=='ok' 면 path 무의미.
48
+ */
49
+ export async function classifyAndPath(drive, parents) {
50
+ const names = [];
51
+ let chain = parents;
52
+ for (let hop = 0; hop < 12 && chain && chain.length > 0; hop++) {
53
+ const pid = chain[0];
54
+ if (ROOT_IDS.has(pid))
55
+ return { cls: 'ok', path: names.reverse().join('/') };
56
+ const meta = await getFolderMeta(drive, pid);
57
+ if (isExcludedName(meta.name))
58
+ return { cls: 'excluded', path: '' };
59
+ if (meta.name)
60
+ names.push(meta.name);
61
+ chain = meta.parent ? [meta.parent] : undefined;
62
+ }
63
+ return { cls: 'outside', path: '' };
64
+ }
65
+ /**
66
+ * 폴더 자신을 분류 — list_drive_folder 의 시작 폴더 검사용.
67
+ * root 폴더면 'ok'(path ''), 그 밖에는 자기 이름이 제외 대상인지 본 뒤 부모 체인을 classifyAndPath 로 분류한다.
68
+ * path 는 root 바로 아래부터 이 폴더까지(자기 이름 포함). 예: root/01_고객사/Acme → "01_고객사/Acme".
69
+ */
70
+ export async function classifyFolder(drive, folderId) {
71
+ if (ROOT_IDS.has(folderId))
72
+ return { cls: 'ok', path: '' };
73
+ let d;
74
+ try {
75
+ d = (await drive.files.get({ fileId: folderId, fields: 'name,parents', supportsAllDrives: true })).data;
76
+ }
77
+ catch {
78
+ return { cls: 'outside', path: '' };
79
+ }
80
+ if (isExcludedName(d.name))
81
+ return { cls: 'excluded', path: '' };
82
+ const parent = await classifyAndPath(drive, d.parents ?? undefined);
83
+ if (parent.cls !== 'ok')
84
+ return { cls: parent.cls, path: '' };
85
+ return { cls: 'ok', path: parent.path ? `${parent.path}/${d.name ?? ''}` : d.name ?? '' };
86
+ }
87
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../../../src/plugins/drive/path.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Qdrant REST client + collection 관리.
3
+ *
4
+ * Collection: config.qdrant.collection (default knowledge_v1), or env QDRANT_COLLECTION.
5
+ * Vector size: 1536 (text-embedding-3-small)
6
+ * Distance: Cosine
7
+ *
8
+ * @qdrant/js-client-rest 대신 Node 내장 fetch 로 REST API 를 부른다. 그 라이브러리는 최신판(1.19)도 취약한
9
+ * undici 7.29 를 고정 의존성으로 끌어와, 이 패키지를 설치하는 모든 사람에게 npm audit 경고를 남겼다.
10
+ * 쓰는 엔드포인트가 9개뿐이라 직접 부르는 편이 가볍다. 메서드 이름과 반환 모양은 그 라이브러리와 같게 뒀다.
11
+ */
12
+ import { EMBEDDING_DIM } from './embeddings.js';
13
+ export type PointId = string | number;
14
+ export type QdrantFilter = {
15
+ must?: unknown[];
16
+ should?: unknown[];
17
+ must_not?: unknown[];
18
+ };
19
+ export interface QdrantPoint {
20
+ id: PointId;
21
+ vector?: number[];
22
+ payload?: Record<string, unknown> | null;
23
+ }
24
+ export interface ScoredPoint extends QdrantPoint {
25
+ score: number;
26
+ version?: number;
27
+ }
28
+ export declare class QdrantError extends Error {
29
+ readonly status: number;
30
+ constructor(message: string, status: number);
31
+ }
32
+ export declare class QdrantClient {
33
+ private readonly apiKey?;
34
+ private readonly base;
35
+ constructor(url: string, apiKey?: string | undefined);
36
+ private call;
37
+ private col;
38
+ getCollections(): Promise<{
39
+ collections: Array<{
40
+ name: string;
41
+ }>;
42
+ }>;
43
+ createCollection(name: string, body: Record<string, unknown>): Promise<boolean>;
44
+ deleteCollection(name: string): Promise<boolean>;
45
+ createPayloadIndex(name: string, body: {
46
+ field_name: string;
47
+ field_schema: string;
48
+ wait?: boolean;
49
+ }): Promise<unknown>;
50
+ upsert(name: string, body: {
51
+ points: QdrantPoint[];
52
+ wait?: boolean;
53
+ }): Promise<unknown>;
54
+ /** Delete by point ids or by filter. Waits by default, like the official client. */
55
+ delete(name: string, body: {
56
+ points?: PointId[];
57
+ filter?: QdrantFilter;
58
+ wait?: boolean;
59
+ }): Promise<unknown>;
60
+ retrieve(name: string, body: {
61
+ ids: PointId[];
62
+ with_payload?: boolean | string[];
63
+ with_vector?: boolean;
64
+ }): Promise<QdrantPoint[]>;
65
+ scroll(name: string, body: {
66
+ filter?: QdrantFilter;
67
+ limit?: number;
68
+ offset?: PointId;
69
+ with_payload?: boolean | string[];
70
+ with_vector?: boolean;
71
+ }): Promise<{
72
+ points: QdrantPoint[];
73
+ next_page_offset?: PointId | null;
74
+ }>;
75
+ search(name: string, body: {
76
+ vector: number[];
77
+ limit: number;
78
+ filter?: QdrantFilter;
79
+ with_payload?: boolean | string[];
80
+ score_threshold?: number;
81
+ }): Promise<ScoredPoint[]>;
82
+ }
83
+ export declare const DRIVE_COLLECTION: string;
84
+ export { EMBEDDING_DIM };
85
+ /** Qdrant 클라이언트(프로세스당 하나). */
86
+ export declare function getQdrantClient(): Promise<QdrantClient>;
87
+ /**
88
+ * Collection 이 없으면 생성. Idempotent.
89
+ * Payload field 중 자주 filter 하는 것은 indexed payload 로 등록.
90
+ */
91
+ export declare function ensureCollection(): Promise<void>;
92
+ export type ChunkPayload = {
93
+ chunk_id: string;
94
+ file_id: string;
95
+ file_name: string;
96
+ file_path: string;
97
+ heading: string;
98
+ chunk_index: number;
99
+ chunk_count: number;
100
+ content: string;
101
+ modified_time: string;
102
+ content_hash: string;
103
+ file_type: 'dev_log' | 'decision' | 'rule' | 'template' | 'biz' | 'other';
104
+ cluster: string | null;
105
+ source: 'dev' | 'biz';
106
+ image_urls: string[];
107
+ has_image: boolean;
108
+ table_count: number;
109
+ has_code_block: boolean;
110
+ doc_status: string | null;
111
+ doc_tier: string | null;
112
+ doc_date: string | null;
113
+ doc_authors: string[];
114
+ doc_related: string[];
115
+ doc_tags: string[];
116
+ doc_source_refs: string[];
117
+ doc_affects: string[];
118
+ doc_products: string[];
119
+ doc_type: string | null;
120
+ doc_confidence: string | null;
121
+ doc_category: string | null;
122
+ doc_customer: string | null;
123
+ };
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Qdrant REST client + collection 관리.
3
+ *
4
+ * Collection: config.qdrant.collection (default knowledge_v1), or env QDRANT_COLLECTION.
5
+ * Vector size: 1536 (text-embedding-3-small)
6
+ * Distance: Cosine
7
+ *
8
+ * @qdrant/js-client-rest 대신 Node 내장 fetch 로 REST API 를 부른다. 그 라이브러리는 최신판(1.19)도 취약한
9
+ * undici 7.29 를 고정 의존성으로 끌어와, 이 패키지를 설치하는 모든 사람에게 npm audit 경고를 남겼다.
10
+ * 쓰는 엔드포인트가 9개뿐이라 직접 부르는 편이 가볍다. 메서드 이름과 반환 모양은 그 라이브러리와 같게 뒀다.
11
+ */
12
+ import { EMBEDDING_DIM } from './embeddings.js';
13
+ import { getConfig } from '../../core/config.js';
14
+ const QDRANT_TIMEOUT_MS = 10_000; // 짧은 timeout 으로 cold-start hang 회피
15
+ export class QdrantError extends Error {
16
+ status;
17
+ constructor(message, status) {
18
+ super(message);
19
+ this.status = status;
20
+ this.name = 'QdrantError';
21
+ }
22
+ }
23
+ export class QdrantClient {
24
+ apiKey;
25
+ base;
26
+ constructor(url, apiKey) {
27
+ this.apiKey = apiKey;
28
+ this.base = url.replace(/\/+$/, '');
29
+ }
30
+ async call(method, path, body) {
31
+ const headers = { Accept: 'application/json' };
32
+ if (body !== undefined)
33
+ headers['Content-Type'] = 'application/json';
34
+ if (this.apiKey)
35
+ headers['api-key'] = this.apiKey;
36
+ let res;
37
+ try {
38
+ res = await fetch(`${this.base}${path}`, {
39
+ method,
40
+ headers,
41
+ body: body === undefined ? undefined : JSON.stringify(body),
42
+ signal: AbortSignal.timeout(QDRANT_TIMEOUT_MS),
43
+ });
44
+ }
45
+ catch (e) {
46
+ const reason = e instanceof Error && e.name === 'TimeoutError' ? `timeout ${QDRANT_TIMEOUT_MS}ms` : String(e);
47
+ throw new QdrantError(`[qdrant] ${method} ${path} failed: ${reason}`, 0);
48
+ }
49
+ const text = await res.text();
50
+ let json = null;
51
+ try {
52
+ json = text ? JSON.parse(text) : null;
53
+ }
54
+ catch {
55
+ /* non-JSON error page */
56
+ }
57
+ if (!res.ok) {
58
+ const detail = json?.status?.error ?? text.slice(0, 200);
59
+ throw new QdrantError(`[qdrant] ${method} ${path} ${res.status}: ${detail}`, res.status);
60
+ }
61
+ return json?.result;
62
+ }
63
+ col(name) {
64
+ return `/collections/${encodeURIComponent(name)}`;
65
+ }
66
+ getCollections() {
67
+ return this.call('GET', '/collections');
68
+ }
69
+ createCollection(name, body) {
70
+ return this.call('PUT', this.col(name), body);
71
+ }
72
+ deleteCollection(name) {
73
+ return this.call('DELETE', this.col(name));
74
+ }
75
+ createPayloadIndex(name, body) {
76
+ const { wait = true, ...rest } = body;
77
+ return this.call('PUT', `${this.col(name)}/index?wait=${wait}`, rest);
78
+ }
79
+ upsert(name, body) {
80
+ const { wait = true, ...rest } = body;
81
+ return this.call('PUT', `${this.col(name)}/points?wait=${wait}`, rest);
82
+ }
83
+ /** Delete by point ids or by filter. Waits by default, like the official client. */
84
+ delete(name, body) {
85
+ const { wait = true, ...rest } = body;
86
+ return this.call('POST', `${this.col(name)}/points/delete?wait=${wait}`, rest);
87
+ }
88
+ retrieve(name, body) {
89
+ return this.call('POST', `${this.col(name)}/points`, body);
90
+ }
91
+ scroll(name, body) {
92
+ return this.call('POST', `${this.col(name)}/points/scroll`, body);
93
+ }
94
+ search(name, body) {
95
+ return this.call('POST', `${this.col(name)}/points/search`, body);
96
+ }
97
+ }
98
+ let _client = null;
99
+ // Zero-downtime reindex: env QDRANT_COLLECTION overrides (index into a new collection, then swap the
100
+ // env var -> 0 downtime; remove it to roll back). Falls back to config.qdrant.collection.
101
+ export const DRIVE_COLLECTION = process.env.QDRANT_COLLECTION || getConfig().qdrant.collection;
102
+ // 차원 SSOT = embeddings.ts (모델 출력 차원). collection size 가 임베딩 차원과 항상 일치하도록 재노출.
103
+ export { EMBEDDING_DIM };
104
+ /** Qdrant 클라이언트(프로세스당 하나). */
105
+ export async function getQdrantClient() {
106
+ if (_client)
107
+ return _client;
108
+ const url = process.env.QDRANT_URL;
109
+ if (!url)
110
+ throw new Error('[qdrant] QDRANT_URL env missing');
111
+ _client = new QdrantClient(url, process.env.QDRANT_API_KEY || undefined);
112
+ return _client;
113
+ }
114
+ /**
115
+ * Collection 이 없으면 생성. Idempotent.
116
+ * Payload field 중 자주 filter 하는 것은 indexed payload 로 등록.
117
+ */
118
+ export async function ensureCollection() {
119
+ const client = await getQdrantClient();
120
+ const collections = await client.getCollections();
121
+ const exists = collections.collections.some((c) => c.name === DRIVE_COLLECTION);
122
+ if (exists)
123
+ return;
124
+ await client.createCollection(DRIVE_COLLECTION, {
125
+ vectors: {
126
+ size: EMBEDDING_DIM,
127
+ distance: 'Cosine',
128
+ },
129
+ // HNSW 기본 (m=16, ef_construct=100) — 1만 vec 까지 충분
130
+ optimizers_config: {
131
+ default_segment_number: 2,
132
+ },
133
+ });
134
+ // 자주 filter 하는 payload field 에 index (검색 빠름)
135
+ for (const fieldName of [
136
+ 'file_type', 'cluster', 'file_id', 'source',
137
+ // 이미지 유무 / frontmatter 메타 filter
138
+ 'has_image', 'doc_status', 'doc_tier',
139
+ // 신규 — 태그·모드·경로 파생 filter (배열 doc_tags 는 원소 단위 keyword 매칭)
140
+ 'doc_tags', 'doc_type', 'doc_category', 'doc_customer',
141
+ ]) {
142
+ await client.createPayloadIndex(DRIVE_COLLECTION, {
143
+ field_name: fieldName,
144
+ field_schema: fieldName === 'has_image' ? 'bool' : 'keyword',
145
+ });
146
+ }
147
+ }
148
+ //# sourceMappingURL=qdrant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdrant.js","sourceRoot":"","sources":["../../../src/plugins/drive/qdrant.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAcjD,MAAM,iBAAiB,GAAG,MAAM,CAAC,CAAC,mCAAmC;AAErE,MAAM,OAAO,WAAY,SAAQ,KAAK;IAGzB;IAFX,YACE,OAAe,EACN,MAAc;QAEvB,KAAK,CAAC,OAAO,CAAC,CAAC;QAFN,WAAM,GAAN,MAAM,CAAQ;QAGvB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,YAAY;IAKJ;IAJF,IAAI,CAAS;IAE9B,YACE,GAAW,EACM,MAAe;QAAf,WAAM,GAAN,MAAM,CAAS;QAEhC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACtC,CAAC;IAEO,KAAK,CAAC,IAAI,CAAI,MAAyC,EAAE,IAAY,EAAE,IAAc;QAC3F,MAAM,OAAO,GAA2B,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;QACvE,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;QACrE,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QAClD,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,EAAE,EAAE;gBACvC,MAAM;gBACN,OAAO;gBACP,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC3D,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,iBAAiB,CAAC;aAC/C,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,MAAM,GAAG,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,WAAW,iBAAiB,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC9G,MAAM,IAAI,WAAW,CAAC,YAAY,MAAM,IAAI,IAAI,YAAY,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,IAAI,GAA4C,IAAI,CAAC;QACzD,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,MAAM,GAAI,IAAI,EAAE,MAAyC,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YAC7F,MAAM,IAAI,WAAW,CAAC,YAAY,MAAM,IAAI,IAAI,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAC3F,CAAC;QACD,OAAO,IAAI,EAAE,MAAW,CAAC;IAC3B,CAAC;IAEO,GAAG,CAAC,IAAY;QACtB,OAAO,gBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;IACpD,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED,gBAAgB,CAAC,IAAY,EAAE,IAA6B;QAC1D,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;IAED,gBAAgB,CAAC,IAAY;QAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,kBAAkB,CAAC,IAAY,EAAE,IAAkE;QACjG,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACtC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,IAA+C;QAClE,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACtC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACzE,CAAC;IAED,oFAAoF;IACpF,MAAM,CAAC,IAAY,EAAE,IAAmE;QACtF,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACtC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACjF,CAAC;IAED,QAAQ,CAAC,IAAY,EAAE,IAAkF;QACvG,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,CACJ,IAAY,EACZ,IAA2H;QAE3H,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,CACJ,IAAY,EACZ,IAA6H;QAE7H,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC;CACF;AAED,IAAI,OAAO,GAAwB,IAAI,CAAC;AAExC,qGAAqG;AACrG,0FAA0F;AAC1F,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,SAAS,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC;AAC/F,8EAA8E;AAC9E,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB,8BAA8B;AAC9B,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;IACnC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC7D,OAAO,GAAG,IAAI,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,SAAS,CAAC,CAAC;IACzE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;IACvC,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;IAClD,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;IAEhF,IAAI,MAAM;QAAE,OAAO;IAEnB,MAAM,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,EAAE;QAC9C,OAAO,EAAE;YACP,IAAI,EAAE,aAAa;YACnB,QAAQ,EAAE,QAAQ;SACnB;QACD,kDAAkD;QAClD,iBAAiB,EAAE;YACjB,sBAAsB,EAAE,CAAC;SAC1B;KACF,CAAC,CAAC;IAEH,6CAA6C;IAC7C,KAAK,MAAM,SAAS,IAAI;QACtB,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ;QAC3C,iCAAiC;QACjC,WAAW,EAAE,YAAY,EAAE,UAAU;QACrC,2DAA2D;QAC3D,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc;KAC9C,EAAE,CAAC;QACX,MAAM,MAAM,CAAC,kBAAkB,CAAC,gBAAgB,EAAE;YAChD,UAAU,EAAE,SAAS;YACrB,YAAY,EAAE,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;SAC7D,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ /** `knowledge-mcp drive reindex [--root ID | --dev-only | --biz-only] [--dry-run] [--recreate]` */
2
+ export declare function runReindex(argv: string[]): Promise<void>;