foliko 2.0.17 → 2.0.18

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.
@@ -239,9 +239,7 @@
239
239
  "Bash(npm start *)",
240
240
  "Bash(xxd)",
241
241
  "Bash(python fix_ext2.py)",
242
- "Bash(npx vitest *)",
243
- "Bash(ls node_modules | wc -l && ls -d node_modules/@* 2>/dev/null | head -5)",
244
- "Bash(node -e \"console.log\\(require.resolve\\('croner'\\)\\)\")"
242
+ "Bash(npx vitest *)"
245
243
  ]
246
244
  }
247
245
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foliko",
3
- "version": "2.0.17",
3
+ "version": "2.0.18",
4
4
  "description": "简约的插件化 Agent 框架",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -234,12 +234,12 @@ class ExplorerLoop {
234
234
  // 非事件驱动目标可以完成
235
235
  this._goalManager.completeGoal(goal.id)
236
236
  this._addActivity('goal_completed', { goalId: goal.id, attempts: goal.attempts })
237
- this._notifyUser('目标完成', `目标 "${goal.title}" 已完成(尝试次数:${goal.attempts})`, 'success')
237
+ await this._notifyUser('目标完成', `目标 "${goal.title}" 已完成(尝试次数:${goal.attempts})`, 'success')
238
238
  } else if (!outcome.shouldContinue && !isEventDriven) {
239
239
  // 非事件驱动目标可以失败
240
240
  this._goalManager.failGoal(goal.id, '达到最大尝试次数')
241
241
  this._addActivity('goal_failed', { goalId: goal.id, reason: '达到最大尝试次数' })
242
- this._notifyUser('目标失败', `目标 "${goal.title}" 失败:达到最大尝试次数`, 'error')
242
+ await this._notifyUser('目标失败', `目标 "${goal.title}" 失败:达到最大尝试次数`, 'error')
243
243
  } else {
244
244
  // 事件驱动目标:不论结果如何,都重置并继续等待下一事件
245
245
  this._addActivity('actions_completed', { goalId: goal.id, actionCount: results.length })
@@ -250,7 +250,7 @@ class ExplorerLoop {
250
250
  // 一次性目标:所有 actions 完成后直接完成
251
251
  this._goalManager.completeGoal(goal.id)
252
252
  this._addActivity('goal_completed', { goalId: goal.id, reason: '一次性任务执行完成' })
253
- this._notifyUser('目标完成', `目标 "${goal.title}" 已完成`, 'success')
253
+ await this._notifyUser('目标完成', `目标 "${goal.title}" 已完成`, 'success')
254
254
  } else if (hasNewEvents) {
255
255
  // 持久化目标且有新事件,重置 actions
256
256
  this._resetGoalForNextEvent(goal)
@@ -269,7 +269,7 @@ class ExplorerLoop {
269
269
  // 一次性目标:所有 actions 完成后直接完成
270
270
  this._goalManager.completeGoal(goal.id)
271
271
  this._addActivity('goal_completed', { goalId: goal.id, reason: '一次性任务执行完成' })
272
- this._notifyUser('目标完成', `目标 "${goal.title}" 已完成`, 'success')
272
+ await this._notifyUser('目标完成', `目标 "${goal.title}" 已完成`, 'success')
273
273
  } else {
274
274
  // 持久化目标:等待下一事件
275
275
  this._resetGoalForNextEvent(goal)
@@ -281,7 +281,7 @@ class ExplorerLoop {
281
281
  if (!hasNewEvents && this._reflector.checkLoopDetection(goal, action.id)) {
282
282
  this._addActivity('goal_failed', { goalId: goal.id, reason: '检测到循环' })
283
283
  // 通知用户目标失败
284
- this._notifyUser('目标失败', `目标 "${goal.title}" 失败:检测到循环(同一操作连续重复)`, 'error')
284
+ await this._notifyUser('目标失败', `目标 "${goal.title}" 失败:检测到循环(同一操作连续重复)`, 'error')
285
285
  continue
286
286
  }
287
287
 
@@ -298,12 +298,12 @@ class ExplorerLoop {
298
298
  this._goalManager.completeGoal(goal.id)
299
299
  this._addActivity('goal_completed', { goalId: goal.id, attempts: goal.attempts })
300
300
  // 通知用户目标完成
301
- this._notifyUser('目标完成', `目标 "${goal.title}" 已完成(尝试次数:${goal.attempts})`, 'success')
301
+ await this._notifyUser('目标完成', `目标 "${goal.title}" 已完成(尝试次数:${goal.attempts})`, 'success')
302
302
  } else if (!outcome.shouldContinue) {
303
303
  this._goalManager.failGoal(goal.id, '达到最大尝试次数')
304
304
  this._addActivity('goal_failed', { goalId: goal.id, reason: '达到最大尝试次数' })
305
305
  // 通知用户目标失败
306
- this._notifyUser('目标失败', `目标 "${goal.title}" 失败:达到最大尝试次数`, 'error')
306
+ await this._notifyUser('目标失败', `目标 "${goal.title}" 失败:达到最大尝试次数`, 'error')
307
307
  } else {
308
308
  this._addActivity('action_executed', { goalId: goal.id, action: action.id, hasEvents: hasNewEvents })
309
309
 
@@ -313,7 +313,7 @@ class ExplorerLoop {
313
313
  // 一次性目标:所有 actions 完成后直接完成
314
314
  this._goalManager.completeGoal(goal.id)
315
315
  this._addActivity('goal_completed', { goalId: goal.id, reason: '一次性任务执行完成' })
316
- this._notifyUser('目标完成', `目标 "${goal.title}" 已完成`, 'success')
316
+ await this._notifyUser('目标完成', `目标 "${goal.title}" 已完成`, 'success')
317
317
  } else if (hasNewEvents) {
318
318
  // 持久化目标且有新事件,重置 actions
319
319
  this._resetGoalForNextEvent(goal)
@@ -1019,14 +1019,14 @@ ${lastResultStr}
1019
1019
  /**
1020
1020
  * 通知用户(通过事件发送给消息插件)
1021
1021
  */
1022
- _notifyUser(title, message, level = 'info') {
1022
+ async _notifyUser(title, message, level = 'info') {
1023
1023
  if (!this._framework) return
1024
1024
 
1025
1025
  // 获取目标相关的sessionId(如果有)
1026
1026
  let sessionId = null
1027
1027
  const sessionPlugin = this._framework.pluginManager.get('session')
1028
1028
  if (sessionPlugin) {
1029
- const sessions = sessionPlugin.listSessions()
1029
+ const sessions = await sessionPlugin.listSessions()
1030
1030
  if (sessions.length > 0) {
1031
1031
  // 取最新的会话
1032
1032
  sessions.sort((a, b) => new Date(b.lastActive).getTime() - new Date(a.lastActive).getTime())
@@ -391,7 +391,7 @@ class SchedulerPlugin extends Plugin {
391
391
  if (!targetSessionId) {
392
392
  const sessionPlugin = this._framework?.pluginManager?.get('session');
393
393
  if (sessionPlugin) {
394
- const sessions = sessionPlugin.listSessions();
394
+ const sessions = await sessionPlugin.listSessions();
395
395
  if (sessions.length > 0) {
396
396
  sessions.sort((a, b) => {
397
397
  const aTime = a.lastActive ? new Date(a.lastActive).getTime() : 0;
@@ -84,6 +84,7 @@ class SessionPlugin extends Plugin {
84
84
  try {
85
85
  const manager = SessionManager.open(filePath, sessionDir, cwd);
86
86
  sessions.push({
87
+ id:path.basename(filePath, path.extname(filePath)),
87
88
  sessionId: manager.getSessionId(),
88
89
  sessionFile: manager.getSessionFile(),
89
90
  messageCount: manager.getEntries().length,
@@ -221,7 +221,7 @@ class FeishuPlugin extends Plugin {
221
221
  case 'history':
222
222
  if (this._sessionPlugin) {
223
223
  const session = this._sessionPlugin.getSession(`feishu_${openId}`)
224
- const sessions = this._sessionPlugin.listSessions().filter(s => s.id.startsWith('feishu_'))
224
+ const sessions = (await this._sessionPlugin.listSessions()).filter(s => s.id.startsWith('feishu_'))
225
225
  await this._sendMessage(openId,
226
226
  `📊 当前状态\n\n会话数:${sessions.length}\n历史消息:${session?.messages?.length || 0}\n最后活跃:${session?.lastActive?.toLocaleString() || '无'}`,
227
227
  originalMsg)
@@ -312,7 +312,7 @@ class FeishuPlugin extends Plugin {
312
312
  }
313
313
 
314
314
  if (this._sessionPlugin) {
315
- const sessions = this._sessionPlugin.listSessions()
315
+ const sessions = (await this._sessionPlugin.listSessions())
316
316
  .filter(s => s.id.startsWith('feishu_'))
317
317
  .sort((a, b) => new Date(b.lastActive).getTime() - new Date(a.lastActive).getTime())
318
318
 
@@ -370,7 +370,7 @@ class FeishuPlugin extends Plugin {
370
370
  openId = effectiveSessionId.replace('feishu_', '')
371
371
  } else if (this._sessionPlugin) {
372
372
  // 获取最近的 feishu 会话
373
- const sessions = this._sessionPlugin.listSessions()
373
+ const sessions = (await this._sessionPlugin.listSessions())
374
374
  .filter(s => s.id.startsWith('feishu_'))
375
375
  .sort((a, b) => new Date(b.lastActive).getTime() - new Date(a.lastActive).getTime())
376
376
  if (sessions.length > 0) {
@@ -587,10 +587,10 @@ class FeishuPlugin extends Plugin {
587
587
  }
588
588
  }
589
589
 
590
- getStatus() {
590
+ async getStatus() {
591
591
  let sessions = []
592
592
  if (this._sessionPlugin) {
593
- sessions = this._sessionPlugin.listSessions()
593
+ sessions = (await this._sessionPlugin.listSessions())
594
594
  .filter(s => s.id.startsWith('feishu_'))
595
595
  .map(s => ({
596
596
  openId: s.id.replace('feishu_', ''),
@@ -958,7 +958,7 @@ class QQPlugin extends Plugin {
958
958
  identifier = sessionId.replace('qq_c2c_', '')
959
959
  }
960
960
  } else if (this._sessionPlugin) {
961
- const sessions = this._sessionPlugin.listSessions()
961
+ const sessions = (await this._sessionPlugin.listSessions())
962
962
  .filter(s => s.id.startsWith('qq_'))
963
963
  .sort((a, b) => new Date(b.lastActive).getTime() - new Date(a.lastActive).getTime())
964
964
  if (sessions.length > 0) {
@@ -1000,10 +1000,10 @@ class QQPlugin extends Plugin {
1000
1000
  /**
1001
1001
  * 获取插件状态
1002
1002
  */
1003
- getStatus() {
1003
+ async getStatus() {
1004
1004
  let sessions = []
1005
1005
  if (this._sessionPlugin) {
1006
- const allSessions = this._sessionPlugin.listSessions()
1006
+ const allSessions = await this._sessionPlugin.listSessions()
1007
1007
  sessions = allSessions
1008
1008
  .filter(s => s.id.startsWith('qq_'))
1009
1009
  .map(s => ({
@@ -157,7 +157,7 @@ class TelegramPlugin extends Plugin {
157
157
  chatId = effectiveSessionId.replace('telegram_', '')
158
158
  } else if (this._sessionPlugin) {
159
159
  // 获取最近的 telegram 会话
160
- const sessions = this._sessionPlugin.listSessions()
160
+ const sessions = (await this._sessionPlugin.listSessions())
161
161
  .filter(s => s.id.startsWith('telegram_'))
162
162
  .sort((a, b) => new Date(b.lastActive).getTime() - new Date(a.lastActive).getTime())
163
163
  if (sessions.length > 0) {
@@ -607,10 +607,10 @@ class TelegramPlugin extends Plugin {
607
607
  return this._bot.sendMessage(chatId, text, { reply_to_message_id: replyToMessageId })
608
608
  }
609
609
 
610
- getStatus() {
610
+ async getStatus() {
611
611
  let sessions = []
612
612
  if (this._sessionPlugin) {
613
- sessions = this._sessionPlugin.listSessions()
613
+ sessions = (await this._sessionPlugin.listSessions())
614
614
  .filter(s => s.id.startsWith('telegram_'))
615
615
  .map(s => ({
616
616
  chatId: s.id.replace('telegram_', ''),
@@ -905,7 +905,7 @@ class WeixinPlugin extends Plugin {
905
905
 
906
906
  // 其他情况(包括 null 或其他 sessionId),发送到最近的 WeChat 会话
907
907
  if (this._sessionPlugin) {
908
- const allSessions = this._sessionPlugin.listSessions()
908
+ const allSessions = await this._sessionPlugin?.listSessions()
909
909
  const weixinSessions = allSessions
910
910
  .filter(s => s.id.startsWith('weixin_'))
911
911
  .sort((a, b) => new Date(b.lastActive).getTime() - new Date(a.lastActive).getTime())
@@ -977,8 +977,8 @@ class WeixinPlugin extends Plugin {
977
977
  userId = effectiveSessionId.replace('weixin_', '')
978
978
  } else if (this._sessionPlugin) {
979
979
  // 获取最近的 weixin 会话
980
- const sessions = this._sessionPlugin.listSessions()
981
- .filter(s => s.id.startsWith('weixin_'))
980
+ const allSessions=await this._sessionPlugin?.listSessions()
981
+ const sessions = (allSessions||[]).filter(s => s.id.startsWith('weixin_'))
982
982
  .sort((a, b) => new Date(b.lastActive).getTime() - new Date(a.lastActive).getTime())
983
983
  if (sessions.length > 0) {
984
984
  userId = sessions[0].id.replace('weixin_', '')
@@ -1011,11 +1011,11 @@ class WeixinPlugin extends Plugin {
1011
1011
  /**
1012
1012
  * 获取插件状态
1013
1013
  */
1014
- getStatus() {
1014
+ async getStatus() {
1015
1015
  // 从 SessionPlugin 获取 WeChat 相关会话
1016
1016
  let sessions = []
1017
1017
  if (this._sessionPlugin) {
1018
- const allSessions = this._sessionPlugin.listSessions()
1018
+ const allSessions = await this._sessionPlugin.listSessions()
1019
1019
  sessions = allSessions
1020
1020
  .filter(s => s.id.startsWith('weixin_'))
1021
1021
  .map(s => ({
@@ -54,7 +54,7 @@ class SessionManager {
54
54
  this.labelTimestampsById = new Map();
55
55
  this.leafId = null;
56
56
  this.sessionId = '';
57
-
57
+ this.fileName=''
58
58
  if (persist && sessionDir && !fs.existsSync(sessionDir)) {
59
59
  fs.mkdirSync(sessionDir, { recursive: true });
60
60
  }
@@ -84,6 +84,7 @@ class SessionManager {
84
84
  }
85
85
 
86
86
  const header = this.fileEntries.find(e => e.type === 'session');
87
+ this.fileName = path.basename(sessionFile);
87
88
  this.sessionId = header?.id || createSessionId();
88
89
 
89
90
  this._buildIndex();