foliko 2.0.19 → 2.0.20

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.
@@ -689,6 +689,29 @@ class WeixinPlugin extends Plugin {
689
689
  true)
690
690
  }
691
691
  break
692
+ // === Planner 集成:/plan 系列命令 ===
693
+ // 完整 planner 工具在 plugins/core/planner/,这里只是命令入口
694
+ case 'plan':
695
+ // /plan <task>:把 task 发给 main agent,让 LLM 按 PROMPT.md 工作流走
696
+ if (!args || !args.trim()) {
697
+ await this._sendMessageBatch(originalMsg, userId, '用法: /plan <任务描述>', true)
698
+ } else {
699
+ await this._processChat(userId, `请进入计划模式完成:${args}`, originalMsg)
700
+ }
701
+ break
702
+ case 'plan_continue':
703
+ // /plan_continue <planId>:恢复计划
704
+ await this._handlePlanContinue(userId, args, originalMsg)
705
+ break
706
+ case 'plan_list':
707
+ await this._handlePlanList(userId, originalMsg)
708
+ break
709
+ case 'plan_show':
710
+ await this._handlePlanShow(userId, args, originalMsg)
711
+ break
712
+ case 'plan_delete':
713
+ await this._handlePlanDelete(userId, args, originalMsg)
714
+ break
692
715
  default:
693
716
  // 未识别命令,当作普通消息处理
694
717
  await this._processChat(userId, text, originalMsg)
@@ -877,6 +900,128 @@ class WeixinPlugin extends Plugin {
877
900
  }
878
901
  }
879
902
 
903
+ // ============================================================
904
+ // Planner 命令处理器(/plan_continue / /plan_list / /plan_show / /plan_delete)
905
+ // ============================================================
906
+
907
+ async _handlePlanContinue(userId, args, originalMsg) {
908
+ if (!this._framework) {
909
+ await this._sendMessageBatch(originalMsg, userId, '❌ 框架未就绪', true)
910
+ return
911
+ }
912
+ const planId = (args || '').trim()
913
+ if (!planId) {
914
+ await this._sendMessageBatch(originalMsg, userId, '用法: /plan_continue <planId>', true)
915
+ return
916
+ }
917
+ try {
918
+ const result = await this._framework.executeTool('plan_continue', { planId })
919
+ if (!result.success) {
920
+ await this._sendMessageBatch(originalMsg, userId, `❌ ${result.error}`, true)
921
+ return
922
+ }
923
+ const plan = result.plan
924
+ const next = plan.steps[result.resumableFrom]
925
+ const lines = [
926
+ `🔄 恢复计划:${plan.title}`,
927
+ '',
928
+ `进度: ${plan.completedSteps}/${plan.totalSteps}(已完成 ${plan.completedSteps},失败 ${plan.failedSteps})`,
929
+ `下一步: Step ${result.resumableFrom + 1} — ${result.nextStepName}`,
930
+ '',
931
+ '完整步骤:',
932
+ ...plan.steps.map(s => {
933
+ const box = { completed: '✅', failed: '❌', in_progress: '🔄', skipped: '⏭️', pending: '⬜' }[s.status] || '⬜'
934
+ return `${box} ${s.index + 1}. ${s.name}`
935
+ }),
936
+ ]
937
+ await this._sendMessageBatch(originalMsg, userId, lines.join('\n'), true)
938
+ // 把恢复指令作为普通消息发给 agent,让 LLM 继续执行
939
+ const resumeMsg = `请继续执行计划 ${planId} 的 Step ${result.resumableFrom + 1}:${result.nextStepName}`
940
+ await this._processChat(userId, resumeMsg, originalMsg)
941
+ } catch (err) {
942
+ log.error('plan_continue 失败:', err.message)
943
+ await this._sendMessageBatch(originalMsg, userId, `❌ 恢复失败: ${err.message}`, true)
944
+ }
945
+ }
946
+
947
+ async _handlePlanList(userId, originalMsg) {
948
+ if (!this._framework) {
949
+ await this._sendMessageBatch(originalMsg, userId, '❌ 框架未就绪', true)
950
+ return
951
+ }
952
+ try {
953
+ const result = await this._framework.executeTool('plan_list', {})
954
+ if (!result.success || result.count === 0) {
955
+ await this._sendMessageBatch(originalMsg, userId, '📋 当前没有计划', true)
956
+ return
957
+ }
958
+ const statusBox = {
959
+ in_progress: '🔄', completed: '✅', failed: '❌', paused: '⏸️',
960
+ }
961
+ const lines = [
962
+ `📋 计划列表(${result.count})`,
963
+ '',
964
+ ...result.plans.map(p => [
965
+ `${statusBox[p.status] || '❔'} ${p.title}`,
966
+ ` 进度: ${p.completedSteps}/${p.totalSteps} | ${p.status}`,
967
+ ` ID: ${p.planId}`,
968
+ ` 更新: ${p.updatedAt}`,
969
+ ].join('\n')),
970
+ ]
971
+ await this._sendMessageBatch(originalMsg, userId, lines.join('\n\n'), true)
972
+ } catch (err) {
973
+ log.error('plan_list 失败:', err.message)
974
+ await this._sendMessageBatch(originalMsg, userId, `❌ 查询失败: ${err.message}`, true)
975
+ }
976
+ }
977
+
978
+ async _handlePlanShow(userId, args, originalMsg) {
979
+ if (!this._framework) {
980
+ await this._sendMessageBatch(originalMsg, userId, '❌ 框架未就绪', true)
981
+ return
982
+ }
983
+ const planId = (args || '').trim()
984
+ if (!planId) {
985
+ await this._sendMessageBatch(originalMsg, userId, '用法: /plan_show <planId>', true)
986
+ return
987
+ }
988
+ try {
989
+ const result = await this._framework.executeTool('plan_show', { planId })
990
+ if (!result.success) {
991
+ await this._sendMessageBatch(originalMsg, userId, `❌ ${result.error}`, true)
992
+ return
993
+ }
994
+ // markdown 直接发给用户(_sendMessageBatch 会 removeMarkdown)
995
+ await this._sendMessageBatch(originalMsg, userId, result.markdown, true)
996
+ } catch (err) {
997
+ log.error('plan_show 失败:', err.message)
998
+ await this._sendMessageBatch(originalMsg, userId, `❌ ${err.message}`, true)
999
+ }
1000
+ }
1001
+
1002
+ async _handlePlanDelete(userId, args, originalMsg) {
1003
+ if (!this._framework) {
1004
+ await this._sendMessageBatch(originalMsg, userId, '❌ 框架未就绪', true)
1005
+ return
1006
+ }
1007
+ const planId = (args || '').trim()
1008
+ if (!planId) {
1009
+ await this._sendMessageBatch(originalMsg, userId, '用法: /plan_delete <planId>', true)
1010
+ return
1011
+ }
1012
+ try {
1013
+ const result = await this._framework.executeTool('plan_delete', { planId })
1014
+ if (!result.success) {
1015
+ await this._sendMessageBatch(originalMsg, userId, `❌ ${result.error || '删除失败'}`, true)
1016
+ return
1017
+ }
1018
+ await this._sendMessageBatch(originalMsg, userId, `✅ 计划已删除: ${planId}`, true)
1019
+ } catch (err) {
1020
+ log.error('plan_delete 失败:', err.message)
1021
+ await this._sendMessageBatch(originalMsg, userId, `❌ ${err.message}`, true)
1022
+ }
1023
+ }
1024
+
880
1025
  /**
881
1026
  * 处理定时提醒
882
1027
  */