chaimi-keep-mcp 3.3.0-beta.0 → 3.3.0-beta.2
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 +15 -1
- package/package.json +1 -1
- package/server.js +45 -19
package/oauth.js
CHANGED
|
@@ -431,6 +431,10 @@ class FileTokenStorage extends TokenStorage {
|
|
|
431
431
|
const dir = this.path.dirname(this.filePath);
|
|
432
432
|
await this.fs.mkdir(dir, { recursive: true });
|
|
433
433
|
|
|
434
|
+
console.error('🔍 [DEBUG] 开始保存 Token');
|
|
435
|
+
console.error('🔍 [DEBUG] 加密密钥 (前8位):', this.key.substring(0, 8));
|
|
436
|
+
console.error('🔍 [DEBUG] Token 过期时间:', token.expiresAt);
|
|
437
|
+
|
|
434
438
|
// 加密 Token 后保存
|
|
435
439
|
const encrypted = encryptToken(token, this.key);
|
|
436
440
|
const data = {
|
|
@@ -445,6 +449,7 @@ class FileTokenStorage extends TokenStorage {
|
|
|
445
449
|
JSON.stringify(data, null, 2),
|
|
446
450
|
{ mode: 0o600 }
|
|
447
451
|
);
|
|
452
|
+
console.error('🔍 [DEBUG] Token 保存成功:', this.filePath);
|
|
448
453
|
}
|
|
449
454
|
|
|
450
455
|
async load() {
|
|
@@ -452,6 +457,10 @@ class FileTokenStorage extends TokenStorage {
|
|
|
452
457
|
const data = await this.fs.readFile(this.filePath, 'utf8');
|
|
453
458
|
const parsed = JSON.parse(data);
|
|
454
459
|
|
|
460
|
+
console.error('🔍 [DEBUG] 开始加载 Token 文件');
|
|
461
|
+
console.error('🔍 [DEBUG] 文件版本:', parsed.version);
|
|
462
|
+
console.error('🔍 [DEBUG] 加密密钥 (前8位):', this.key.substring(0, 8));
|
|
463
|
+
|
|
455
464
|
// 向后兼容:检测旧版明文格式
|
|
456
465
|
if (!parsed.version || parsed.version === '1.0') {
|
|
457
466
|
console.error('检测到旧版 Token 格式,自动升级...');
|
|
@@ -466,11 +475,16 @@ class FileTokenStorage extends TokenStorage {
|
|
|
466
475
|
}
|
|
467
476
|
|
|
468
477
|
// 新版加密格式,解密后返回
|
|
469
|
-
|
|
478
|
+
console.error('🔍 [DEBUG] 开始解密 Token...');
|
|
479
|
+
const decrypted = decryptToken(parsed.encrypted, this.key);
|
|
480
|
+
console.error('🔍 [DEBUG] 解密成功,Token 过期时间:', decrypted.expiresAt);
|
|
481
|
+
return decrypted;
|
|
470
482
|
} catch (err) {
|
|
471
483
|
if (err.code === 'ENOENT') {
|
|
484
|
+
console.error('🔍 [DEBUG] Token 文件不存在');
|
|
472
485
|
return null;
|
|
473
486
|
}
|
|
487
|
+
console.error('🔍 [DEBUG] 加载 Token 失败:', err.message);
|
|
474
488
|
throw err;
|
|
475
489
|
}
|
|
476
490
|
}
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -466,7 +466,35 @@ const TOKEN_REFRESH_INTERVAL = 2 * 60 * 60 * 1000;
|
|
|
466
466
|
let lastRefreshTime = 0;
|
|
467
467
|
|
|
468
468
|
async function getToken() {
|
|
469
|
-
//
|
|
469
|
+
// 【优化1】优先检查内存中的 token 是否有效
|
|
470
|
+
if (cachedToken && tokenExpireTime > Date.now() + 5 * 60 * 1000) {
|
|
471
|
+
if (Date.now() - lastRefreshTime < TOKEN_REFRESH_INTERVAL) {
|
|
472
|
+
return cachedToken;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// 【优化2】尝试从文件加载 token(优先级高于授权状态检查)
|
|
477
|
+
try {
|
|
478
|
+
const existingToken = await oauthManager.tokenStorage.load();
|
|
479
|
+
if (existingToken && existingToken.accessToken && existingToken.expiresAt) {
|
|
480
|
+
const expiresAt = new Date(existingToken.expiresAt).getTime();
|
|
481
|
+
if (expiresAt > Date.now() + 5 * 60 * 1000) {
|
|
482
|
+
// Token 有效,直接使用
|
|
483
|
+
cachedToken = existingToken.accessToken;
|
|
484
|
+
tokenExpireTime = expiresAt;
|
|
485
|
+
authState.isAuthorized = true;
|
|
486
|
+
lastRefreshTime = Date.now();
|
|
487
|
+
console.error('✅ 已从文件加载有效 Token,无需重新授权');
|
|
488
|
+
return cachedToken;
|
|
489
|
+
} else {
|
|
490
|
+
console.error('⏰ 保存的 Token 已过期,需要重新授权');
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
} catch (err) {
|
|
494
|
+
console.error('⚠️ 加载保存的 Token 失败:', err.message);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// 【优化3】Token 不存在或已过期,检查是否需要授权
|
|
470
498
|
if (!authState.isAuthorized) {
|
|
471
499
|
// 先检查是否有保存的授权状态(从文件加载)
|
|
472
500
|
const savedAuthState = await oauthManager.loadAuthState();
|
|
@@ -507,20 +535,15 @@ async function getToken() {
|
|
|
507
535
|
}
|
|
508
536
|
}
|
|
509
537
|
}
|
|
510
|
-
|
|
538
|
+
|
|
511
539
|
// 没有保存的授权状态或已过期,启动新的授权流程
|
|
512
540
|
await startAuthFlow();
|
|
513
|
-
|
|
541
|
+
|
|
514
542
|
// 返回验证码给Agent
|
|
515
543
|
throw new Error(`NEED_AUTH:${authState.userCode || '等待生成验证码'}`);
|
|
516
544
|
}
|
|
517
545
|
|
|
518
|
-
|
|
519
|
-
if (Date.now() - lastRefreshTime < TOKEN_REFRESH_INTERVAL) {
|
|
520
|
-
return cachedToken;
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
546
|
+
// 【优化4】已授权,尝试刷新 token
|
|
524
547
|
if (!oauthManager) {
|
|
525
548
|
throw new Error('OAuth 管理器未初始化,请检查 MCP_OAUTH_URL 配置');
|
|
526
549
|
}
|
|
@@ -2158,21 +2181,23 @@ async function pollForAuthInBackground(deviceCode, interval) {
|
|
|
2158
2181
|
tokenExpireTime = token.expiresAt;
|
|
2159
2182
|
authState.isAuthorized = true;
|
|
2160
2183
|
authState.isWaiting = false;
|
|
2161
|
-
|
|
2184
|
+
|
|
2162
2185
|
// 保存token到文件
|
|
2163
2186
|
await oauthManager.tokenStorage.save(token);
|
|
2164
|
-
|
|
2187
|
+
|
|
2165
2188
|
// 【新增】保存默认 Agent 名称和 deviceCode(首次记账时会获取真实名称)
|
|
2166
2189
|
await oauthManager.tokenStorage.saveAgentName('柴米AI助手');
|
|
2167
2190
|
await oauthManager.tokenStorage.saveDeviceCode(authState.deviceCode);
|
|
2168
|
-
|
|
2191
|
+
|
|
2169
2192
|
// 清除授权状态
|
|
2170
2193
|
await oauthManager.clearAuthState();
|
|
2171
|
-
|
|
2172
|
-
console.error('✅
|
|
2173
|
-
|
|
2174
|
-
//
|
|
2175
|
-
|
|
2194
|
+
|
|
2195
|
+
console.error('✅ 授权成功!可以继续使用记账功能');
|
|
2196
|
+
|
|
2197
|
+
// 【修复】不退出进程,让 Agent 可以在同一会话中继续执行记账操作
|
|
2198
|
+
// 这样 Agent 调用 get_skill 授权后,可以立即调用 save_expense 记账
|
|
2199
|
+
// process.exit(0); // 注释掉,避免授权成功后进程退出
|
|
2200
|
+
return; // 直接返回,停止轮询
|
|
2176
2201
|
}
|
|
2177
2202
|
} catch (err) {
|
|
2178
2203
|
if (err.message.includes('expired') || err.message.includes('invalid')) {
|
|
@@ -2187,8 +2212,9 @@ async function pollForAuthInBackground(deviceCode, interval) {
|
|
|
2187
2212
|
|
|
2188
2213
|
// 3分钟超时
|
|
2189
2214
|
authState.isWaiting = false;
|
|
2190
|
-
console.error('⏰
|
|
2191
|
-
|
|
2215
|
+
console.error('⏰ 授权超时(3分钟),请重新调用获取新验证码');
|
|
2216
|
+
// 【修复】不退出进程,让用户可以重新尝试
|
|
2217
|
+
// process.exit(0);
|
|
2192
2218
|
}
|
|
2193
2219
|
|
|
2194
2220
|
// 延迟函数
|