@chnxthr/knowledge-mcp 0.3.0 → 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.
- package/dist/plugins/drive/client.d.ts +92 -23
- package/dist/plugins/drive/client.js +202 -44
- package/dist/plugins/drive/client.js.map +1 -1
- package/dist/plugins/drive/extract_text.d.ts +4 -4
- package/dist/plugins/drive/extract_text.js +6 -19
- package/dist/plugins/drive/extract_text.js.map +1 -1
- package/dist/plugins/drive/get_token.js +23 -8
- package/dist/plugins/drive/get_token.js.map +1 -1
- package/dist/plugins/drive/indexer.d.ts +2 -2
- package/dist/plugins/drive/indexer.js.map +1 -1
- package/dist/plugins/drive/ooxml.d.ts +17 -0
- package/dist/plugins/drive/ooxml.js +152 -0
- package/dist/plugins/drive/ooxml.js.map +1 -0
- package/dist/plugins/drive/path.d.ts +5 -5
- package/dist/plugins/drive/path.js.map +1 -1
- package/dist/plugins/drive/qdrant.d.ts +76 -3
- package/dist/plugins/drive/qdrant.js +98 -11
- package/dist/plugins/drive/qdrant.js.map +1 -1
- package/dist/plugins/drive/reindex.js.map +1 -1
- package/dist/plugins/drive/sync.js.map +1 -1
- package/dist/plugins/drive/tools/read_drive_file.js +1 -1
- package/dist/plugins/drive/tools/read_drive_file.js.map +1 -1
- package/package.json +1 -5
|
@@ -1,25 +1,94 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
export interface DriveFile {
|
|
2
|
+
id?: string | null;
|
|
3
|
+
name?: string | null;
|
|
4
|
+
mimeType?: string | null;
|
|
5
|
+
parents?: string[] | null;
|
|
6
|
+
modifiedTime?: string | null;
|
|
7
|
+
size?: string | null;
|
|
8
|
+
webViewLink?: string | null;
|
|
9
|
+
trashed?: boolean | null;
|
|
10
|
+
owners?: Array<{
|
|
11
|
+
emailAddress?: string | null;
|
|
12
|
+
displayName?: string | null;
|
|
13
|
+
}> | null;
|
|
14
|
+
[field: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface DriveChange {
|
|
17
|
+
removed?: boolean | null;
|
|
18
|
+
fileId?: string | null;
|
|
19
|
+
file?: DriveFile | null;
|
|
20
|
+
}
|
|
21
|
+
export interface DriveChangeList {
|
|
22
|
+
nextPageToken?: string | null;
|
|
23
|
+
newStartPageToken?: string | null;
|
|
24
|
+
changes?: DriveChange[];
|
|
25
|
+
}
|
|
26
|
+
export interface DriveFileList {
|
|
27
|
+
files?: DriveFile[];
|
|
28
|
+
nextPageToken?: string | null;
|
|
29
|
+
}
|
|
30
|
+
type Params = Record<string, string | number | boolean | undefined>;
|
|
31
|
+
type ResponseType = 'json' | 'text' | 'arraybuffer';
|
|
32
|
+
export interface DriveClient {
|
|
33
|
+
files: {
|
|
34
|
+
list(params: Params): Promise<{
|
|
35
|
+
data: DriveFileList;
|
|
36
|
+
}>;
|
|
37
|
+
/** Metadata, or the file body with `alt: 'media'` and a response type. */
|
|
38
|
+
get(params: Params & {
|
|
39
|
+
fileId: string;
|
|
40
|
+
}, opts?: {
|
|
41
|
+
responseType?: ResponseType;
|
|
42
|
+
}): Promise<{
|
|
43
|
+
data: any;
|
|
44
|
+
}>;
|
|
45
|
+
export(params: Params & {
|
|
46
|
+
fileId: string;
|
|
47
|
+
mimeType: string;
|
|
48
|
+
}, opts?: {
|
|
49
|
+
responseType?: ResponseType;
|
|
50
|
+
}): Promise<{
|
|
51
|
+
data: any;
|
|
52
|
+
}>;
|
|
53
|
+
};
|
|
54
|
+
changes: {
|
|
55
|
+
getStartPageToken(params?: Params): Promise<{
|
|
56
|
+
data: {
|
|
57
|
+
startPageToken?: string | null;
|
|
58
|
+
};
|
|
59
|
+
}>;
|
|
60
|
+
list(params: Params & {
|
|
61
|
+
pageToken: string;
|
|
62
|
+
}): Promise<{
|
|
63
|
+
data: DriveChangeList;
|
|
64
|
+
}>;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export declare class DriveApiError extends Error {
|
|
68
|
+
/** HTTP status (0 = network or timeout). googleapis put the same value in `code`. */
|
|
69
|
+
readonly code: number;
|
|
70
|
+
constructor(message: string,
|
|
71
|
+
/** HTTP status (0 = network or timeout). googleapis put the same value in `code`. */
|
|
72
|
+
code: number);
|
|
73
|
+
}
|
|
74
|
+
type Credentials = {
|
|
75
|
+
kind: 'service_account';
|
|
76
|
+
clientEmail: string;
|
|
77
|
+
privateKey: string;
|
|
78
|
+
tokenUri: string;
|
|
79
|
+
} | {
|
|
80
|
+
kind: 'refresh_token';
|
|
81
|
+
clientId: string;
|
|
82
|
+
clientSecret: string;
|
|
83
|
+
refreshToken: string;
|
|
84
|
+
tokenUri: string;
|
|
85
|
+
};
|
|
86
|
+
/** Which credentials the env provides. Throws with the options when none are set. */
|
|
87
|
+
export declare function resolveCredentials(env?: NodeJS.ProcessEnv): Credentials;
|
|
88
|
+
/** Builds a client. `apiBase` and credentials are injectable for tests; production uses env and Google URLs. */
|
|
89
|
+
export declare function createDriveClient(creds: Credentials, apiBase?: string): DriveClient;
|
|
90
|
+
/** The process-wide Drive client, built from env on first use. */
|
|
91
|
+
export declare function getDriveClient(): Promise<DriveClient>;
|
|
24
92
|
/** Google Drive query language 의 single-quote escape. */
|
|
25
93
|
export declare function escapeDriveQuery(s: string): string;
|
|
94
|
+
export {};
|
|
@@ -1,60 +1,218 @@
|
|
|
1
|
-
let _client = null;
|
|
2
|
-
const DRIVE_READONLY_SCOPE = 'https://www.googleapis.com/auth/drive.readonly';
|
|
3
|
-
// Drive API 전역 timeout — googleapis 는 명시 timeout 이 없으면 무한에 가깝게 hang 할 수 있어
|
|
4
|
-
// (search/read/list·classifyAndPath 부모 walk가 매달리면 stateless transport 에서 도구 호출
|
|
5
|
-
// 전체가 멈춤). google.options 로 전역 15s 부여. internal-mcp 는 google API 를 drive 만 쓴다.
|
|
6
|
-
const DRIVE_TIMEOUT_MS = Number(process.env.DRIVE_TIMEOUT_MS ?? 15_000);
|
|
7
1
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
2
|
+
* Google Drive API (v3, read-only) over plain HTTPS.
|
|
3
|
+
*
|
|
4
|
+
* 인증 옵션 (우선순위 순):
|
|
5
|
+
* 1. Service Account JSON (권장 — production-grade)
|
|
6
|
+
* - GOOGLE_SERVICE_ACCOUNT_KEY (inline JSON, Railway 친화)
|
|
7
|
+
* - GOOGLE_APPLICATION_CREDENTIALS (JSON 파일 path. service_account 또는 authorized_user)
|
|
8
|
+
*
|
|
9
|
+
* 2. OAuth Refresh Token (fallback, single-user)
|
|
10
|
+
* - GOOGLE_OAUTH_CLIENT_ID + GOOGLE_OAUTH_CLIENT_SECRET + GOOGLE_OAUTH_REFRESH_TOKEN
|
|
11
|
+
* - Legacy DRIVE_* fallback
|
|
12
|
+
*
|
|
13
|
+
* Service Account 사용 시:
|
|
14
|
+
* - Drive 폴더에 service account email (xxx@<project>.iam.gserviceaccount.com) viewer 공유 필수
|
|
15
|
+
* - refresh_token 만료·rotation 없음
|
|
16
|
+
*
|
|
17
|
+
* googleapis 대신 직접 부르는 이유: googleapis(google-auth-library → gaxios → node-fetch → fetch-blob)는
|
|
18
|
+
* 최신판도 폐기된 패키지(node-domexception, 옛 판은 uuid)를 끌어와 설치마다 경고를 남겼고, 불러오는 데만
|
|
19
|
+
* CPU 1초가 넘게 들었다. 이 서버가 쓰는 Drive 엔드포인트는 5개뿐이다. 호출 모양(drive.files.list 등,
|
|
20
|
+
* { data } 반환)은 googleapis 와 같게 둬서 도구 코드는 바꾸지 않았다.
|
|
10
21
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
import { readFileSync } from 'node:fs';
|
|
23
|
+
import { SignJWT, importPKCS8 } from 'jose';
|
|
24
|
+
const DRIVE_READONLY_SCOPE = 'https://www.googleapis.com/auth/drive.readonly';
|
|
25
|
+
const DEFAULT_TOKEN_URI = 'https://oauth2.googleapis.com/token';
|
|
26
|
+
const DRIVE_API = 'https://www.googleapis.com/drive/v3';
|
|
27
|
+
// Drive API 전역 timeout — 명시 timeout 이 없으면 매달린 호출 하나가 도구 호출 전체를 멈춘다.
|
|
28
|
+
const DRIVE_TIMEOUT_MS = Number(process.env.DRIVE_TIMEOUT_MS ?? 15_000);
|
|
29
|
+
const RETRIES = 3; // 429·5xx·네트워크 오류. GET 만 쓰므로 다시 보내도 안전하다
|
|
30
|
+
export class DriveApiError extends Error {
|
|
31
|
+
code;
|
|
32
|
+
constructor(message,
|
|
33
|
+
/** HTTP status (0 = network or timeout). googleapis put the same value in `code`. */
|
|
34
|
+
code) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.code = code;
|
|
37
|
+
this.name = 'DriveApiError';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function credentialsFromJson(raw, source) {
|
|
41
|
+
let j;
|
|
42
|
+
try {
|
|
43
|
+
j = JSON.parse(raw);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
throw new Error(`[drive] ${source} is not valid JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
47
|
+
}
|
|
48
|
+
if (j.type === 'authorized_user') {
|
|
49
|
+
return {
|
|
50
|
+
kind: 'refresh_token',
|
|
51
|
+
clientId: String(j.client_id ?? ''),
|
|
52
|
+
clientSecret: String(j.client_secret ?? ''),
|
|
53
|
+
refreshToken: String(j.refresh_token ?? ''),
|
|
54
|
+
tokenUri: DEFAULT_TOKEN_URI,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (typeof j.client_email !== 'string' || typeof j.private_key !== 'string') {
|
|
58
|
+
throw new Error(`[drive] ${source} must be a service account key (client_email, private_key) or an authorized_user file`);
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
kind: 'service_account',
|
|
62
|
+
clientEmail: j.client_email,
|
|
63
|
+
privateKey: j.private_key,
|
|
64
|
+
tokenUri: typeof j.token_uri === 'string' ? j.token_uri : DEFAULT_TOKEN_URI,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Which credentials the env provides. Throws with the options when none are set. */
|
|
68
|
+
export function resolveCredentials(env = process.env) {
|
|
69
|
+
if (env.GOOGLE_SERVICE_ACCOUNT_KEY)
|
|
70
|
+
return credentialsFromJson(env.GOOGLE_SERVICE_ACCOUNT_KEY, 'GOOGLE_SERVICE_ACCOUNT_KEY');
|
|
71
|
+
if (env.GOOGLE_APPLICATION_CREDENTIALS) {
|
|
72
|
+
const path = env.GOOGLE_APPLICATION_CREDENTIALS;
|
|
73
|
+
let raw;
|
|
23
74
|
try {
|
|
24
|
-
|
|
75
|
+
raw = readFileSync(path, 'utf8');
|
|
25
76
|
}
|
|
26
77
|
catch (e) {
|
|
27
|
-
throw new Error(
|
|
28
|
-
(e instanceof Error ? e.message : String(e)));
|
|
78
|
+
throw new Error(`[drive] cannot read GOOGLE_APPLICATION_CREDENTIALS (${path}): ${e instanceof Error ? e.message : String(e)}`);
|
|
29
79
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return _client;
|
|
36
|
-
}
|
|
37
|
-
if (credentialsPath) {
|
|
38
|
-
// GoogleAuth 가 자동 GOOGLE_APPLICATION_CREDENTIALS env 인식
|
|
39
|
-
const auth = new GoogleAuth({ scopes: [DRIVE_READONLY_SCOPE] });
|
|
40
|
-
_client = google.drive({ version: 'v3', auth });
|
|
41
|
-
return _client;
|
|
42
|
-
}
|
|
43
|
-
// ── Option 2: OAuth Refresh Token (fallback) ────────────
|
|
44
|
-
const clientId = process.env.GOOGLE_OAUTH_CLIENT_ID || process.env.DRIVE_CLIENT_ID;
|
|
45
|
-
const clientSecret = process.env.GOOGLE_OAUTH_CLIENT_SECRET || process.env.DRIVE_CLIENT_SECRET;
|
|
46
|
-
const refreshToken = process.env.GOOGLE_OAUTH_REFRESH_TOKEN || process.env.DRIVE_REFRESH_TOKEN;
|
|
80
|
+
return credentialsFromJson(raw, 'GOOGLE_APPLICATION_CREDENTIALS');
|
|
81
|
+
}
|
|
82
|
+
const clientId = env.GOOGLE_OAUTH_CLIENT_ID || env.DRIVE_CLIENT_ID;
|
|
83
|
+
const clientSecret = env.GOOGLE_OAUTH_CLIENT_SECRET || env.DRIVE_CLIENT_SECRET;
|
|
84
|
+
const refreshToken = env.GOOGLE_OAUTH_REFRESH_TOKEN || env.DRIVE_REFRESH_TOKEN;
|
|
47
85
|
if (clientId && clientSecret && refreshToken) {
|
|
48
|
-
|
|
49
|
-
oauth.setCredentials({ refresh_token: refreshToken });
|
|
50
|
-
_client = google.drive({ version: 'v3', auth: oauth });
|
|
51
|
-
return _client;
|
|
86
|
+
return { kind: 'refresh_token', clientId, clientSecret, refreshToken, tokenUri: DEFAULT_TOKEN_URI };
|
|
52
87
|
}
|
|
53
88
|
throw new Error('[drive] Drive credentials missing. Use one of:\n' +
|
|
54
89
|
' (1) GOOGLE_SERVICE_ACCOUNT_KEY (inline JSON) ← 권장\n' +
|
|
55
90
|
' (2) GOOGLE_APPLICATION_CREDENTIALS (JSON file path) ← 권장\n' +
|
|
56
91
|
' (3) GOOGLE_OAUTH_CLIENT_ID + _SECRET + _REFRESH_TOKEN ← fallback');
|
|
57
92
|
}
|
|
93
|
+
async function requestToken(creds) {
|
|
94
|
+
const form = new URLSearchParams();
|
|
95
|
+
if (creds.kind === 'service_account') {
|
|
96
|
+
// OAuth 2.0 JWT bearer grant (RFC 7523): 서비스 계정 키로 서명한 assertion 을 토큰으로 바꾼다.
|
|
97
|
+
const now = Math.floor(Date.now() / 1000);
|
|
98
|
+
const key = await importPKCS8(creds.privateKey, 'RS256');
|
|
99
|
+
const assertion = await new SignJWT({ scope: DRIVE_READONLY_SCOPE })
|
|
100
|
+
.setProtectedHeader({ alg: 'RS256', typ: 'JWT' })
|
|
101
|
+
.setIssuer(creds.clientEmail)
|
|
102
|
+
.setAudience(creds.tokenUri)
|
|
103
|
+
.setIssuedAt(now)
|
|
104
|
+
.setExpirationTime(now + 3600)
|
|
105
|
+
.sign(key);
|
|
106
|
+
form.set('grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer');
|
|
107
|
+
form.set('assertion', assertion);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
form.set('grant_type', 'refresh_token');
|
|
111
|
+
form.set('client_id', creds.clientId);
|
|
112
|
+
form.set('client_secret', creds.clientSecret);
|
|
113
|
+
form.set('refresh_token', creds.refreshToken);
|
|
114
|
+
}
|
|
115
|
+
const res = await fetch(creds.tokenUri, {
|
|
116
|
+
method: 'POST',
|
|
117
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
118
|
+
body: form,
|
|
119
|
+
signal: AbortSignal.timeout(DRIVE_TIMEOUT_MS),
|
|
120
|
+
});
|
|
121
|
+
const body = (await res.json().catch(() => ({})));
|
|
122
|
+
if (!res.ok || !body.access_token) {
|
|
123
|
+
// Google 은 오류 본문에 토큰이나 키를 돌려주지 않는다. 오류 코드와 설명만 남긴다.
|
|
124
|
+
throw new DriveApiError(`[drive] token request failed ${res.status}: ${body.error ?? ''} ${body.error_description ?? ''}`.trim(), res.status);
|
|
125
|
+
}
|
|
126
|
+
return { token: body.access_token, expiresAt: Date.now() + (body.expires_in ?? 3600) * 1000 };
|
|
127
|
+
}
|
|
128
|
+
/** Builds a client. `apiBase` and credentials are injectable for tests; production uses env and Google URLs. */
|
|
129
|
+
export function createDriveClient(creds, apiBase = DRIVE_API) {
|
|
130
|
+
let cached = null;
|
|
131
|
+
let pending = null;
|
|
132
|
+
const accessToken = () => {
|
|
133
|
+
if (cached && cached.expiresAt - 60_000 > Date.now())
|
|
134
|
+
return Promise.resolve(cached.token);
|
|
135
|
+
pending ??= requestToken(creds)
|
|
136
|
+
.then((t) => {
|
|
137
|
+
cached = t;
|
|
138
|
+
return t.token;
|
|
139
|
+
})
|
|
140
|
+
.finally(() => {
|
|
141
|
+
pending = null;
|
|
142
|
+
});
|
|
143
|
+
return pending;
|
|
144
|
+
};
|
|
145
|
+
const get = async (path, params = {}, responseType = 'json') => {
|
|
146
|
+
const qs = new URLSearchParams();
|
|
147
|
+
for (const [k, v] of Object.entries(params))
|
|
148
|
+
if (v !== undefined)
|
|
149
|
+
qs.set(k, String(v));
|
|
150
|
+
const url = `${apiBase}${path}${qs.size ? `?${qs}` : ''}`;
|
|
151
|
+
for (let attempt = 0;; attempt++) {
|
|
152
|
+
let res;
|
|
153
|
+
try {
|
|
154
|
+
res = await fetch(url, {
|
|
155
|
+
headers: { Authorization: `Bearer ${await accessToken()}`, Accept: responseType === 'json' ? 'application/json' : '*/*' },
|
|
156
|
+
signal: AbortSignal.timeout(DRIVE_TIMEOUT_MS),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
if (e instanceof DriveApiError)
|
|
161
|
+
throw e; // token request failed
|
|
162
|
+
if (attempt + 1 < RETRIES) {
|
|
163
|
+
await new Promise((r) => setTimeout(r, 500 * 2 ** attempt));
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const reason = e instanceof Error && e.name === 'TimeoutError' ? `timeout ${DRIVE_TIMEOUT_MS}ms` : String(e);
|
|
167
|
+
throw new DriveApiError(`[drive] GET ${path} failed: ${reason}`, 0);
|
|
168
|
+
}
|
|
169
|
+
if (res.status === 401 && attempt === 0) {
|
|
170
|
+
cached = null; // revoked or expired early: get a new token once
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if ((res.status === 429 || res.status >= 500) && attempt + 1 < RETRIES) {
|
|
174
|
+
const after = Number(res.headers.get('retry-after'));
|
|
175
|
+
await res.arrayBuffer().catch(() => undefined);
|
|
176
|
+
await new Promise((r) => setTimeout(r, Number.isFinite(after) && after > 0 ? after * 1000 : 500 * 2 ** attempt));
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (!res.ok) {
|
|
180
|
+
const text = await res.text().catch(() => '');
|
|
181
|
+
let msg = text.slice(0, 300);
|
|
182
|
+
try {
|
|
183
|
+
msg = JSON.parse(text).error?.message ?? msg;
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
/* not JSON */
|
|
187
|
+
}
|
|
188
|
+
throw new DriveApiError(`[drive] ${res.status} ${path}: ${msg}`, res.status);
|
|
189
|
+
}
|
|
190
|
+
if (responseType === 'arraybuffer')
|
|
191
|
+
return { data: await res.arrayBuffer() };
|
|
192
|
+
if (responseType === 'text')
|
|
193
|
+
return { data: await res.text() };
|
|
194
|
+
return { data: await res.json() };
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const fileId = (id) => encodeURIComponent(id);
|
|
198
|
+
return {
|
|
199
|
+
files: {
|
|
200
|
+
list: (params) => get('/files', params),
|
|
201
|
+
get: ({ fileId: id, ...params }, opts) => get(`/files/${fileId(id)}`, params, opts?.responseType ?? 'json'),
|
|
202
|
+
export: ({ fileId: id, ...params }, opts) => get(`/files/${fileId(id)}/export`, params, opts?.responseType ?? 'text'),
|
|
203
|
+
},
|
|
204
|
+
changes: {
|
|
205
|
+
getStartPageToken: (params) => get('/changes/startPageToken', params),
|
|
206
|
+
list: (params) => get('/changes', params),
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
let _client = null;
|
|
211
|
+
/** The process-wide Drive client, built from env on first use. */
|
|
212
|
+
export async function getDriveClient() {
|
|
213
|
+
_client ??= createDriveClient(resolveCredentials());
|
|
214
|
+
return _client;
|
|
215
|
+
}
|
|
58
216
|
/** Google Drive query language 의 single-quote escape. */
|
|
59
217
|
export function escapeDriveQuery(s) {
|
|
60
218
|
return s.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/plugins/drive/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/plugins/drive/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,16 +6,16 @@
|
|
|
6
6
|
* - Google Docs → Drive export text/markdown
|
|
7
7
|
* - Google Sheets → Drive export text/csv
|
|
8
8
|
* - Google Slides → Drive export text/plain
|
|
9
|
-
* - Word .docx →
|
|
9
|
+
* - Word .docx → ooxml.ts (zip 안 XML 의 문단 텍스트)
|
|
10
10
|
* - PDF (digital) → pdf-parse (텍스트 레이어)
|
|
11
11
|
*
|
|
12
12
|
* OCR 필요 (후속 — Mathpix):
|
|
13
13
|
* - PDF (스캔본, 텍스트 부족) → Mathpix
|
|
14
14
|
* - .pptx / image → Mathpix / Gemini multimodal
|
|
15
15
|
*
|
|
16
|
-
* lazy import (
|
|
16
|
+
* lazy import (pdf-parse, xlsx) — 필요 시에만 로드.
|
|
17
17
|
*/
|
|
18
|
-
import type {
|
|
18
|
+
import type { DriveClient } from './client.js';
|
|
19
19
|
export interface ExtractResult {
|
|
20
20
|
text: string;
|
|
21
21
|
method: string;
|
|
@@ -23,4 +23,4 @@ export interface ExtractResult {
|
|
|
23
23
|
meta?: Record<string, unknown>;
|
|
24
24
|
}
|
|
25
25
|
/** 추출 + 정제 (노이즈 cleanup). 색인·검색 진입점. */
|
|
26
|
-
export declare function extractText(drive:
|
|
26
|
+
export declare function extractText(drive: DriveClient, fileId: string, mimeType: string): Promise<ExtractResult>;
|
|
@@ -34,12 +34,11 @@ async function extractRaw(drive, fileId, mimeType) {
|
|
|
34
34
|
if (mimeType === 'application/vnd.google-apps.presentation') {
|
|
35
35
|
return { text: await exportGoogle(drive, fileId, 'text/plain'), method: 'gslide→txt' };
|
|
36
36
|
}
|
|
37
|
-
// 3. Word .docx —
|
|
37
|
+
// 3. Word .docx — 의존성 없는 zip/XML 읽기 (ooxml.ts). 문단 사이 빈 줄 — 예전 mammoth extractRawText 와 같은 모양
|
|
38
38
|
if (mimeType.includes('wordprocessingml')) {
|
|
39
|
-
const
|
|
39
|
+
const { docxText } = await import('./ooxml.js');
|
|
40
40
|
const buffer = await downloadBuffer(drive, fileId);
|
|
41
|
-
|
|
42
|
-
return { text: result.value, method: 'docx→mammoth' };
|
|
41
|
+
return { text: docxText(buffer), method: 'docx→ooxml' };
|
|
43
42
|
}
|
|
44
43
|
// 4. PDF — pdf-parse v2. digital 텍스트, 스캔본(<MIN) 은 Mathpix OCR fallback
|
|
45
44
|
if (mimeType === 'application/pdf') {
|
|
@@ -69,23 +68,11 @@ async function extractRaw(drive, fileId, mimeType) {
|
|
|
69
68
|
meta: { pages, charsPerPage: Math.round(charsPerPage), ocr: true },
|
|
70
69
|
};
|
|
71
70
|
}
|
|
72
|
-
// 5. PowerPoint .pptx →
|
|
73
|
-
// v7 parseOffice 는 OfficeParserAST 반환 → markdown(.to('md')) 우선, 실패 시 toText().
|
|
71
|
+
// 5. PowerPoint .pptx → 슬라이드마다 "## Slide N" + 본문 + 발표자 노트 (ooxml.ts)
|
|
74
72
|
if (mimeType.includes('presentationml')) {
|
|
75
|
-
const {
|
|
73
|
+
const { pptxText } = await import('./ooxml.js');
|
|
76
74
|
const buffer = await downloadBuffer(drive, fileId);
|
|
77
|
-
|
|
78
|
-
let text = '';
|
|
79
|
-
try {
|
|
80
|
-
const md = await ast.to('md');
|
|
81
|
-
text = md?.value ?? '';
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
/* md 변환 실패 → toText fallback */
|
|
85
|
-
}
|
|
86
|
-
if (!text.trim())
|
|
87
|
-
text = ast.toText();
|
|
88
|
-
return { text, method: 'pptx→officeparser' };
|
|
75
|
+
return { text: pptxText(buffer), method: 'pptx→ooxml' };
|
|
89
76
|
}
|
|
90
77
|
// 6. Excel .xlsx → SheetJS (시트별 csv)
|
|
91
78
|
if (mimeType.includes('spreadsheetml')) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract_text.js","sourceRoot":"","sources":["../../../src/plugins/drive/extract_text.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AASrD,sCAAsC;AACtC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B,KAAK,UAAU,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"extract_text.js","sourceRoot":"","sources":["../../../src/plugins/drive/extract_text.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
* 5. callback 받으면 콘솔에 refresh token 출력
|
|
12
12
|
* 6. .env 에 GOOGLE_OAUTH_REFRESH_TOKEN= 라인 추가
|
|
13
13
|
*/
|
|
14
|
-
import { google } from 'googleapis';
|
|
15
14
|
import http from 'http';
|
|
16
15
|
import { URL } from 'url';
|
|
17
16
|
import { execFile } from 'child_process';
|
|
@@ -29,12 +28,15 @@ export async function runGetToken() {
|
|
|
29
28
|
console.error('❌ GOOGLE_OAUTH_CLIENT_ID / CLIENT_SECRET 가 .env 에 없습니다.');
|
|
30
29
|
process.exit(1);
|
|
31
30
|
}
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
const authUrl = 'https://accounts.google.com/o/oauth2/v2/auth?' +
|
|
32
|
+
new URLSearchParams({
|
|
33
|
+
client_id: clientId,
|
|
34
|
+
redirect_uri: REDIRECT_URI,
|
|
35
|
+
response_type: 'code',
|
|
36
|
+
scope: SCOPE,
|
|
37
|
+
access_type: 'offline',
|
|
38
|
+
prompt: 'consent', // refresh_token 강제 발급
|
|
39
|
+
}).toString();
|
|
38
40
|
console.log('\n========================================');
|
|
39
41
|
console.log(' OAuth Refresh Token 발급');
|
|
40
42
|
console.log('========================================\n');
|
|
@@ -64,7 +66,20 @@ export async function runGetToken() {
|
|
|
64
66
|
return;
|
|
65
67
|
}
|
|
66
68
|
try {
|
|
67
|
-
const
|
|
69
|
+
const tokenRes = await fetch('https://oauth2.googleapis.com/token', {
|
|
70
|
+
method: 'POST',
|
|
71
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
72
|
+
body: new URLSearchParams({
|
|
73
|
+
grant_type: 'authorization_code',
|
|
74
|
+
code,
|
|
75
|
+
client_id: clientId,
|
|
76
|
+
client_secret: clientSecret,
|
|
77
|
+
redirect_uri: REDIRECT_URI,
|
|
78
|
+
}),
|
|
79
|
+
});
|
|
80
|
+
const tokens = (await tokenRes.json());
|
|
81
|
+
if (!tokenRes.ok)
|
|
82
|
+
throw new Error(`${tokens.error ?? tokenRes.status} ${tokens.error_description ?? ''}`.trim());
|
|
68
83
|
const refreshToken = tokens.refresh_token;
|
|
69
84
|
if (!refreshToken) {
|
|
70
85
|
console.error('\n❌ refresh_token 미발급. 이미 권한 부여한 경우 일 수 있음.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get_token.js","sourceRoot":"","sources":["../../../src/plugins/drive/get_token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"get_token.js","sourceRoot":"","sources":["../../../src/plugins/drive/get_token.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Drive 파일 1개 → Qdrant 색인/삭제 공통 로직.
|
|
3
3
|
* 전체 reindex (reindex.ts) 와 증분 sync (sync.ts) 가 공유.
|
|
4
4
|
*/
|
|
5
|
-
import type {
|
|
5
|
+
import type { DriveClient } from './client.js';
|
|
6
6
|
import { type RawChunk } from './chunker.js';
|
|
7
7
|
import { type ChunkPayload } from './qdrant.js';
|
|
8
8
|
import { DRIVE_ROOTS, MAX_FILE_BYTES } from './settings.js';
|
|
@@ -64,6 +64,6 @@ export declare function buildChunkPayload(chunk: RawChunk, file: IndexableFile,
|
|
|
64
64
|
* - B-1: 재색인 시 청크 수가 줄면 옛 청크(chunk_index >= 새 수)를 삭제해 유령 청크(폐기된 사실) 잔류 방지.
|
|
65
65
|
* - B-9: 증분 경로는 wait:true 로 색인 직후 검색 가시성 + 실패 인지.
|
|
66
66
|
*/
|
|
67
|
-
export declare function indexFile(drive:
|
|
67
|
+
export declare function indexFile(drive: DriveClient, file: IndexableFile): Promise<number>;
|
|
68
68
|
/** 특정 파일의 모든 chunk 를 Qdrant 에서 삭제 (파일 삭제·trashed 시). */
|
|
69
69
|
export declare function deleteFileVectors(fileId: string): Promise<void>;
|