chaimi-keep-mcp 3.3.0-beta.2 → 3.3.0-beta.4
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/oauth.js +48 -22
- package/package.json +1 -1
- package/server.js +34 -4
package/oauth.js
CHANGED
|
@@ -428,28 +428,54 @@ class FileTokenStorage extends TokenStorage {
|
|
|
428
428
|
}
|
|
429
429
|
|
|
430
430
|
async save(token) {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
431
|
+
try {
|
|
432
|
+
const dir = this.path.dirname(this.filePath);
|
|
433
|
+
await this.fs.mkdir(dir, { recursive: true });
|
|
434
|
+
|
|
435
|
+
console.error('🔍 [DEBUG] 开始保存 Token');
|
|
436
|
+
console.error('🔍 [DEBUG] 加密密钥 (前8位):', this.key.substring(0, 8));
|
|
437
|
+
console.error('🔍 [DEBUG] Token 过期时间:', token.expiresAt);
|
|
438
|
+
|
|
439
|
+
// 加密 Token 后保存
|
|
440
|
+
const encrypted = encryptToken(token, this.key);
|
|
441
|
+
const data = {
|
|
442
|
+
version: '2.0',
|
|
443
|
+
encrypted: encrypted,
|
|
444
|
+
algorithm: 'aes-256-cbc',
|
|
445
|
+
updatedAt: new Date().toISOString()
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
const content = JSON.stringify(data, null, 2);
|
|
449
|
+
console.error('🔍 [DEBUG] 准备写入内容长度:', content.length, '字节');
|
|
450
|
+
|
|
451
|
+
await this.fs.writeFile(
|
|
452
|
+
this.filePath,
|
|
453
|
+
content,
|
|
454
|
+
{ mode: 0o600 }
|
|
455
|
+
);
|
|
456
|
+
|
|
457
|
+
// 验证写入是否成功
|
|
458
|
+
const stats = await this.fs.stat(this.filePath);
|
|
459
|
+
console.error('🔍 [DEBUG] Token 文件写入成功');
|
|
460
|
+
console.error('🔍 [DEBUG] 文件路径:', this.filePath);
|
|
461
|
+
console.error('🔍 [DEBUG] 文件大小:', stats.size, '字节');
|
|
462
|
+
|
|
463
|
+
if (stats.size === 0) {
|
|
464
|
+
throw new Error('Token 文件写入后大小为 0,写入失败');
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// 立即读取验证
|
|
468
|
+
const readBack = await this.fs.readFile(this.filePath, 'utf8');
|
|
469
|
+
if (readBack.length === 0) {
|
|
470
|
+
throw new Error('Token 文件读取验证失败,内容为空');
|
|
471
|
+
}
|
|
472
|
+
console.error('🔍 [DEBUG] Token 文件验证成功,内容长度:', readBack.length, '字节');
|
|
473
|
+
|
|
474
|
+
} catch (error) {
|
|
475
|
+
console.error('❌ Token 保存失败:', error.message);
|
|
476
|
+
console.error('❌ 错误详情:', error);
|
|
477
|
+
throw error;
|
|
478
|
+
}
|
|
453
479
|
}
|
|
454
480
|
|
|
455
481
|
async load() {
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -475,10 +475,27 @@ async function getToken() {
|
|
|
475
475
|
|
|
476
476
|
// 【优化2】尝试从文件加载 token(优先级高于授权状态检查)
|
|
477
477
|
try {
|
|
478
|
+
console.error('🔍 [DEBUG] 尝试从文件加载 Token...');
|
|
478
479
|
const existingToken = await oauthManager.tokenStorage.load();
|
|
480
|
+
console.error('🔍 [DEBUG] Token 加载结果:', existingToken ? '成功' : '为空');
|
|
481
|
+
if (existingToken) {
|
|
482
|
+
console.error('🔍 [DEBUG] Token 字段检查:', {
|
|
483
|
+
hasAccessToken: !!existingToken.accessToken,
|
|
484
|
+
hasExpiresAt: !!existingToken.expiresAt,
|
|
485
|
+
expiresAt: existingToken.expiresAt
|
|
486
|
+
});
|
|
487
|
+
}
|
|
479
488
|
if (existingToken && existingToken.accessToken && existingToken.expiresAt) {
|
|
480
489
|
const expiresAt = new Date(existingToken.expiresAt).getTime();
|
|
481
|
-
|
|
490
|
+
const now = Date.now();
|
|
491
|
+
const threshold = now + 5 * 60 * 1000;
|
|
492
|
+
console.error('🔍 [DEBUG] 过期时间检查:', {
|
|
493
|
+
expiresAt,
|
|
494
|
+
now,
|
|
495
|
+
threshold,
|
|
496
|
+
isValid: expiresAt > threshold
|
|
497
|
+
});
|
|
498
|
+
if (expiresAt > threshold) {
|
|
482
499
|
// Token 有效,直接使用
|
|
483
500
|
cachedToken = existingToken.accessToken;
|
|
484
501
|
tokenExpireTime = expiresAt;
|
|
@@ -492,6 +509,7 @@ async function getToken() {
|
|
|
492
509
|
}
|
|
493
510
|
} catch (err) {
|
|
494
511
|
console.error('⚠️ 加载保存的 Token 失败:', err.message);
|
|
512
|
+
console.error('⚠️ 错误堆栈:', err.stack);
|
|
495
513
|
}
|
|
496
514
|
|
|
497
515
|
// 【优化3】Token 不存在或已过期,检查是否需要授权
|
|
@@ -2183,11 +2201,23 @@ async function pollForAuthInBackground(deviceCode, interval) {
|
|
|
2183
2201
|
authState.isWaiting = false;
|
|
2184
2202
|
|
|
2185
2203
|
// 保存token到文件
|
|
2186
|
-
|
|
2204
|
+
try {
|
|
2205
|
+
await oauthManager.tokenStorage.save(token);
|
|
2206
|
+
console.error('🔍 [DEBUG] Token 保存完成');
|
|
2207
|
+
} catch (error) {
|
|
2208
|
+
console.error('❌ Token 保存失败:', error.message);
|
|
2209
|
+
throw error;
|
|
2210
|
+
}
|
|
2187
2211
|
|
|
2188
2212
|
// 【新增】保存默认 Agent 名称和 deviceCode(首次记账时会获取真实名称)
|
|
2189
|
-
|
|
2190
|
-
|
|
2213
|
+
try {
|
|
2214
|
+
await oauthManager.tokenStorage.saveAgentName('柴米AI助手');
|
|
2215
|
+
await oauthManager.tokenStorage.saveDeviceCode(authState.deviceCode);
|
|
2216
|
+
console.error('🔍 [DEBUG] Agent 名称和 deviceCode 保存完成');
|
|
2217
|
+
} catch (error) {
|
|
2218
|
+
console.error('❌ Agent 信息保存失败:', error.message);
|
|
2219
|
+
// 这个失败不影响授权,只记录日志
|
|
2220
|
+
}
|
|
2191
2221
|
|
|
2192
2222
|
// 清除授权状态
|
|
2193
2223
|
await oauthManager.clearAuthState();
|