feishu-mcp 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -64
- package/dist/mcp/feishuMcp.js +1 -1
- package/dist/mcp/tools/feishuBlockTools.js +43 -2
- package/dist/mcp/tools/feishuTools.js +20 -3
- package/dist/server.js +42 -22
- package/dist/services/baseService.js +122 -34
- package/dist/services/blockFactory.js +88 -0
- package/dist/services/callbackService.js +37 -22
- package/dist/services/feishuApiService.js +225 -19
- package/dist/services/feishuAuthService.js +0 -137
- package/dist/types/feishuSchema.js +27 -0
- package/dist/utils/auth/authUtils.js +71 -0
- package/dist/utils/auth/index.js +4 -0
- package/dist/utils/auth/tokenCacheManager.js +420 -0
- package/dist/utils/auth/userAuthManager.js +104 -0
- package/dist/utils/auth/userContextManager.js +81 -0
- package/dist/utils/cache.js +0 -98
- package/dist/utils/error.js +31 -0
- package/package.json +1 -1
package/dist/utils/cache.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { Config } from './config.js';
|
|
2
2
|
import { Logger } from './logger.js';
|
|
3
|
-
import * as fs from 'fs';
|
|
4
|
-
import * as path from 'path';
|
|
5
3
|
/**
|
|
6
4
|
* 缓存管理器类
|
|
7
5
|
* 提供内存缓存功能,支持TTL和最大容量限制
|
|
8
|
-
* 只用于缓存用户token和wiki转docid结果
|
|
9
6
|
*/
|
|
10
7
|
export class CacheManager {
|
|
11
8
|
/**
|
|
@@ -24,15 +21,8 @@ export class CacheManager {
|
|
|
24
21
|
writable: true,
|
|
25
22
|
value: void 0
|
|
26
23
|
});
|
|
27
|
-
Object.defineProperty(this, "userTokenCacheFile", {
|
|
28
|
-
enumerable: true,
|
|
29
|
-
configurable: true,
|
|
30
|
-
writable: true,
|
|
31
|
-
value: path.resolve(process.cwd(), 'user_token_cache.json')
|
|
32
|
-
});
|
|
33
24
|
this.cache = new Map();
|
|
34
25
|
this.config = Config.getInstance();
|
|
35
|
-
this.loadUserTokenCache();
|
|
36
26
|
// 定期清理过期缓存
|
|
37
27
|
setInterval(() => {
|
|
38
28
|
this.cleanExpiredCache();
|
|
@@ -71,9 +61,6 @@ export class CacheManager {
|
|
|
71
61
|
expiresAt: now + (actualTtl * 1000)
|
|
72
62
|
});
|
|
73
63
|
Logger.debug(`缓存设置: ${key} (TTL: ${actualTtl}秒)`);
|
|
74
|
-
if (key.startsWith('user_access_token:')) {
|
|
75
|
-
this.saveUserTokenCache();
|
|
76
|
-
}
|
|
77
64
|
return true;
|
|
78
65
|
}
|
|
79
66
|
/**
|
|
@@ -111,9 +98,6 @@ export class CacheManager {
|
|
|
111
98
|
const result = this.cache.delete(key);
|
|
112
99
|
if (result) {
|
|
113
100
|
Logger.debug(`缓存删除: ${key}`);
|
|
114
|
-
if (key.startsWith('user_access_token:')) {
|
|
115
|
-
this.saveUserTokenCache();
|
|
116
|
-
}
|
|
117
101
|
}
|
|
118
102
|
return result;
|
|
119
103
|
}
|
|
@@ -217,86 +201,4 @@ export class CacheManager {
|
|
|
217
201
|
getWikiToDocId(wikiToken) {
|
|
218
202
|
return this.get(`wiki:${wikiToken}`);
|
|
219
203
|
}
|
|
220
|
-
/**
|
|
221
|
-
* 缓存tenant访问令牌
|
|
222
|
-
* @param token 访问令牌
|
|
223
|
-
* @param expiresInSeconds 过期时间(秒)
|
|
224
|
-
* @param key 缓存键,默认为'access_token'
|
|
225
|
-
* @returns 是否成功设置缓存
|
|
226
|
-
*/
|
|
227
|
-
cacheTenantToken(key, token, expiresInSeconds) {
|
|
228
|
-
return this.set(`tenant_access_token:${key}`, token, expiresInSeconds);
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* 获取tenant缓存的访问令牌
|
|
232
|
-
* @param key 缓存键,默认为'access_token'
|
|
233
|
-
* @returns 访问令牌,如果未找到或已过期则返回null
|
|
234
|
-
*/
|
|
235
|
-
getTenantToken(key) {
|
|
236
|
-
return this.get(`tenant_access_token:${key}`);
|
|
237
|
-
}
|
|
238
|
-
cacheUserToken(key, tokenObj, expiresIn) {
|
|
239
|
-
return this.set(`user_access_token:${key}`, tokenObj, expiresIn);
|
|
240
|
-
}
|
|
241
|
-
getUserToken(key) {
|
|
242
|
-
return this.get(`user_access_token:${key}`);
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* 缓存访问令牌
|
|
246
|
-
* @param token 访问令牌
|
|
247
|
-
* @param expiresInSeconds 过期时间(秒)
|
|
248
|
-
* @returns 是否成功设置缓存
|
|
249
|
-
*/
|
|
250
|
-
cacheToken(token, expiresInSeconds) {
|
|
251
|
-
return this.set(`access_token`, token, expiresInSeconds);
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* 获取缓存的访问令牌
|
|
255
|
-
* @returns 访问令牌,如果未找到或已过期则返回null
|
|
256
|
-
*/
|
|
257
|
-
getToken() {
|
|
258
|
-
return this.get(`access_token`);
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* 生成client_id+client_secret签名
|
|
262
|
-
* @param client_id
|
|
263
|
-
* @param client_secret
|
|
264
|
-
* @returns 唯一key
|
|
265
|
-
*/
|
|
266
|
-
static async getClientKey(client_id, client_secret) {
|
|
267
|
-
const crypto = await import('crypto');
|
|
268
|
-
return crypto.createHash('sha256').update(client_id + ':' + client_secret).digest('hex');
|
|
269
|
-
}
|
|
270
|
-
loadUserTokenCache() {
|
|
271
|
-
if (fs.existsSync(this.userTokenCacheFile)) {
|
|
272
|
-
try {
|
|
273
|
-
const raw = fs.readFileSync(this.userTokenCacheFile, 'utf-8');
|
|
274
|
-
const obj = JSON.parse(raw);
|
|
275
|
-
for (const k in obj) {
|
|
276
|
-
if (k.startsWith('user_access_token:')) {
|
|
277
|
-
this.cache.set(k, obj[k]);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
Logger.info(`已加载本地 user_token_cache.json,共${Object.keys(obj).length}条`);
|
|
281
|
-
}
|
|
282
|
-
catch (e) {
|
|
283
|
-
Logger.warn('加载 user_token_cache.json 失败', e);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
saveUserTokenCache() {
|
|
288
|
-
const obj = {};
|
|
289
|
-
for (const [k, v] of this.cache.entries()) {
|
|
290
|
-
if (k.startsWith('user_access_token:')) {
|
|
291
|
-
obj[k] = v;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
try {
|
|
295
|
-
fs.writeFileSync(this.userTokenCacheFile, JSON.stringify(obj, null, 2), 'utf-8');
|
|
296
|
-
Logger.debug('user_token_cache.json 已写入');
|
|
297
|
-
}
|
|
298
|
-
catch (e) {
|
|
299
|
-
Logger.warn('写入 user_token_cache.json 失败', e);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
204
|
}
|
package/dist/utils/error.js
CHANGED
|
@@ -152,3 +152,34 @@ export function wrapError(message, originalError) {
|
|
|
152
152
|
const errorMessage = formatErrorMessage(originalError);
|
|
153
153
|
return new Error(`${message}: ${errorMessage}`);
|
|
154
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* 授权异常类
|
|
157
|
+
* 用于处理需要用户授权的情况
|
|
158
|
+
*/
|
|
159
|
+
export class AuthRequiredError extends Error {
|
|
160
|
+
constructor(authType, message, authUrl) {
|
|
161
|
+
super(message);
|
|
162
|
+
Object.defineProperty(this, "authType", {
|
|
163
|
+
enumerable: true,
|
|
164
|
+
configurable: true,
|
|
165
|
+
writable: true,
|
|
166
|
+
value: void 0
|
|
167
|
+
});
|
|
168
|
+
Object.defineProperty(this, "authUrl", {
|
|
169
|
+
enumerable: true,
|
|
170
|
+
configurable: true,
|
|
171
|
+
writable: true,
|
|
172
|
+
value: void 0
|
|
173
|
+
});
|
|
174
|
+
Object.defineProperty(this, "message", {
|
|
175
|
+
enumerable: true,
|
|
176
|
+
configurable: true,
|
|
177
|
+
writable: true,
|
|
178
|
+
value: void 0
|
|
179
|
+
});
|
|
180
|
+
this.name = 'AuthRequiredError';
|
|
181
|
+
this.authType = authType;
|
|
182
|
+
this.authUrl = authUrl;
|
|
183
|
+
this.message = message;
|
|
184
|
+
}
|
|
185
|
+
}
|