foliko 1.1.92 → 2.0.0

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.
Files changed (212) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/CLAUDE.md +56 -30
  3. package/REFACTORING_PLAN.md +645 -0
  4. package/docs/architecture.md +131 -0
  5. package/docs/migration.md +57 -0
  6. package/docs/public-api.md +138 -0
  7. package/docs/usage.md +385 -0
  8. package/examples/ambient-example.js +20 -137
  9. package/examples/basic.js +21 -48
  10. package/examples/bootstrap.js +16 -74
  11. package/examples/mcp-example.js +6 -29
  12. package/examples/skill-example.js +6 -19
  13. package/examples/workflow.js +8 -56
  14. package/package.json +8 -4
  15. package/plugins/README.md +49 -0
  16. package/plugins/{ambient-agent → ambient}/EventWatcher.js +1 -1
  17. package/plugins/{ambient-agent → ambient}/ExplorerLoop.js +3 -3
  18. package/plugins/{ambient-agent → ambient}/GoalManager.js +2 -2
  19. package/plugins/ambient/README.md +14 -0
  20. package/plugins/{ambient-agent → ambient}/Reflector.js +1 -1
  21. package/plugins/{ambient-agent → ambient}/StateStore.js +1 -1
  22. package/plugins/{ambient-agent → ambient}/index.js +2 -2
  23. package/plugins/{ai-plugin.js → core/ai/index.js} +14 -30
  24. package/plugins/{audit-plugin.js → core/audit/index.js} +3 -30
  25. package/plugins/{coordinator-plugin.js → core/coordinator/index.js} +3 -35
  26. package/plugins/core/default/bootstrap.js +202 -0
  27. package/plugins/core/default/config.js +220 -0
  28. package/plugins/core/default/index.js +58 -0
  29. package/plugins/core/mcp/index.js +1 -0
  30. package/plugins/{python-plugin-loader.js → core/python-loader/index.js} +7 -187
  31. package/plugins/{rules-plugin.js → core/rules/index.js} +121 -64
  32. package/plugins/{scheduler-plugin.js → core/scheduler/index.js} +12 -114
  33. package/plugins/{session-plugin.js → core/session/index.js} +9 -73
  34. package/{src/capabilities/skill-manager.js → plugins/core/skill-manager/index.js} +64 -18
  35. package/plugins/{storage-plugin.js → core/storage/index.js} +5 -29
  36. package/plugins/{subagent-plugin.js → core/sub-agent/index.js} +10 -171
  37. package/plugins/{think-plugin.js → core/think/index.js} +24 -91
  38. package/{src/capabilities/workflow-engine.js → plugins/core/workflow/index.js} +87 -85
  39. package/plugins/default-plugins.js +6 -720
  40. package/plugins/{data-splitter-plugin.js → executors/data-splitter/index.js} +9 -83
  41. package/plugins/{extension-executor-plugin.js → executors/extension/index.js} +13 -97
  42. package/plugins/{python-executor-plugin.js → executors/python/index.js} +6 -31
  43. package/plugins/{shell-executor-plugin.js → executors/shell/index.js} +2 -5
  44. package/plugins/install/README.md +9 -0
  45. package/plugins/{install-plugin.js → install/index.js} +3 -3
  46. package/plugins/{file-system-plugin.js → io/file-system/index.js} +34 -236
  47. package/plugins/{web-plugin.js → io/web/index.js} +11 -113
  48. package/plugins/memory/README.md +13 -0
  49. package/plugins/{memory-plugin.js → memory/index.js} +4 -18
  50. package/plugins/messaging/email/README.md +19 -0
  51. package/plugins/{email → messaging/email}/index.js +2 -2
  52. package/plugins/{feishu-plugin.js → messaging/feishu/index.js} +3 -3
  53. package/plugins/{qq-plugin.js → messaging/qq/index.js} +5 -16
  54. package/plugins/{telegram-plugin.js → messaging/telegram/index.js} +3 -3
  55. package/plugins/{weixin-plugin.js → messaging/weixin/index.js} +15 -15
  56. package/plugins/{plugin-manager-plugin.js → plugin-manager/index.js} +36 -180
  57. package/plugins/{tools-plugin.js → tools/index.js} +68 -116
  58. package/plugins/trading/README.md +15 -0
  59. package/plugins/{gate-trading.js → trading/index.js} +8 -8
  60. package/{examples → sandbox}/test-concurrent-chat.js +2 -2
  61. package/{examples → sandbox}/test-long-chat.js +2 -2
  62. package/{examples → sandbox}/test-session-chat.js +2 -2
  63. package/{examples → sandbox}/test-web-plugin.js +1 -1
  64. package/{examples → sandbox}/test-weixin-feishu.js +2 -2
  65. package/src/agent/base.js +56 -0
  66. package/src/{core/agent-chat.js → agent/chat.js} +11 -11
  67. package/src/{core/coordinator-manager.js → agent/coordinator.js} +3 -3
  68. package/src/agent/index.js +111 -0
  69. package/src/agent/main.js +337 -0
  70. package/src/agent/prompt.js +78 -0
  71. package/src/agent/sub.js +198 -0
  72. package/src/agent/worker.js +104 -0
  73. package/{cli/bin/foliko.js → src/cli/bin.js} +1 -1
  74. package/{cli/src → src/cli}/commands/chat.js +25 -21
  75. package/{cli/src → src/cli}/index.js +1 -0
  76. package/{cli/src → src/cli}/ui/chat-ui-old.js +40 -178
  77. package/{cli/src → src/cli}/ui/chat-ui.js +3 -3
  78. package/{cli/src → src/cli}/ui/components/footer-bar.js +1 -1
  79. package/src/{core → common}/constants.js +3 -0
  80. package/src/common/errors.js +402 -0
  81. package/src/{utils → common}/logger.js +33 -0
  82. package/src/{utils/chat-queue.js → common/queue.js} +2 -2
  83. package/src/config/plugin-config.js +50 -0
  84. package/src/context/agent.js +32 -0
  85. package/src/context/compaction-prompts.js +170 -0
  86. package/src/context/compaction-utils.js +191 -0
  87. package/src/context/compressor.js +413 -0
  88. package/src/context/index.js +9 -0
  89. package/src/{core/context-manager.js → context/manager.js} +1 -1
  90. package/src/context/request.js +50 -0
  91. package/src/context/session.js +33 -0
  92. package/src/context/storage.js +30 -0
  93. package/src/executors/mcp-client.js +153 -0
  94. package/src/executors/mcp-desc.js +236 -0
  95. package/src/executors/mcp-executor.js +91 -956
  96. package/src/{core → framework}/command-registry.js +1 -1
  97. package/src/framework/framework.js +300 -0
  98. package/src/framework/index.js +18 -0
  99. package/src/framework/lifecycle.js +203 -0
  100. package/src/framework/loader.js +78 -0
  101. package/src/framework/registry.js +86 -0
  102. package/src/{core/ui-extension-context.js → framework/ui-extension.js} +1 -1
  103. package/src/index.js +130 -15
  104. package/src/llm/index.js +26 -0
  105. package/src/llm/provider.js +212 -0
  106. package/src/llm/registry.js +11 -0
  107. package/src/{core/token-counter.js → llm/tokens.js} +4 -37
  108. package/src/{core/plugin-base.js → plugin/base.js} +10 -136
  109. package/src/plugin/index.js +14 -0
  110. package/src/plugin/loader.js +101 -0
  111. package/src/plugin/manager.js +261 -0
  112. package/src/{core → session}/branch-summary-auto.js +2 -2
  113. package/src/{core/chat-session.js → session/chat.js} +2 -2
  114. package/src/session/index.js +7 -0
  115. package/src/{core/session-manager.js → session/session.js} +2 -2
  116. package/src/session/ttl.js +92 -0
  117. package/src/{core/jsonl-storage.js → storage/jsonl.js} +1 -1
  118. package/src/tool/executor.js +85 -0
  119. package/src/tool/index.js +15 -0
  120. package/src/tool/registry.js +143 -0
  121. package/src/{core/tool-router.js → tool/router.js} +17 -124
  122. package/src/tool/schema.js +108 -0
  123. package/src/utils/data-splitter.js +1 -1
  124. package/src/utils/download.js +1 -1
  125. package/src/utils/index.js +6 -6
  126. package/src/utils/message-validator.js +1 -1
  127. package/tests/core/context-storage.test.js +46 -0
  128. package/tests/core/llm.test.js +54 -0
  129. package/tests/core/plugin.test.js +42 -0
  130. package/tests/core/tool.test.js +60 -0
  131. package/tests/setup.js +10 -0
  132. package/tests/smoke.test.js +58 -0
  133. package/vitest.config.js +9 -0
  134. package/cli/src/daemon.js +0 -149
  135. package/docs/CONTEXT_DESIGN.md +0 -1596
  136. package/docs/ai-sdk-optimization.md +0 -655
  137. package/docs/features.md +0 -120
  138. package/docs/qq-bot.md +0 -976
  139. package/docs/quick-reference.md +0 -160
  140. package/docs/user-manual.md +0 -1391
  141. package/images/geometric_shapes.jpg +0 -0
  142. package/images/sunset_mountain_lake.jpg +0 -0
  143. package/skills/poster-guide/SKILL.md +0 -792
  144. package/src/capabilities/index.js +0 -11
  145. package/src/core/agent.js +0 -808
  146. package/src/core/context-compressor.js +0 -959
  147. package/src/core/enhanced-context-compressor.js +0 -210
  148. package/src/core/framework.js +0 -1422
  149. package/src/core/index.js +0 -30
  150. package/src/core/plugin-manager.js +0 -961
  151. package/src/core/provider-registry.js +0 -159
  152. package/src/core/provider.js +0 -156
  153. package/src/core/request-context.js +0 -98
  154. package/src/core/subagent.js +0 -442
  155. package/src/core/system-prompt-builder.js +0 -120
  156. package/src/core/tool-executor.js +0 -202
  157. package/src/core/tool-registry.js +0 -517
  158. package/src/core/worker-agent.js +0 -192
  159. package/src/executors/executor-base.js +0 -58
  160. package/src/utils/error-boundary.js +0 -363
  161. package/src/utils/error.js +0 -374
  162. package/system.md +0 -1645
  163. package/website_v2/README.md +0 -57
  164. package/website_v2/SPEC.md +0 -1
  165. package/website_v2/docs/api.html +0 -128
  166. package/website_v2/docs/configuration.html +0 -147
  167. package/website_v2/docs/plugin-development.html +0 -129
  168. package/website_v2/docs/project-structure.html +0 -89
  169. package/website_v2/docs/skill-development.html +0 -85
  170. package/website_v2/index.html +0 -489
  171. package/website_v2/scripts/main.js +0 -93
  172. package/website_v2/styles/animations.css +0 -8
  173. package/website_v2/styles/docs.css +0 -83
  174. package/website_v2/styles/main.css +0 -417
  175. package/xhs_auth.json +0 -268
  176. package//346/265/267/346/212/245/346/217/222/344/273/266.md +0 -621
  177. /package/plugins/{ambient-agent → ambient}/constants.js +0 -0
  178. /package/plugins/{email → messaging/email}/constants.js +0 -0
  179. /package/plugins/{email → messaging/email}/handlers.js +0 -0
  180. /package/plugins/{email → messaging/email}/monitor.js +0 -0
  181. /package/plugins/{email → messaging/email}/parser.js +0 -0
  182. /package/plugins/{email → messaging/email}/reply.js +0 -0
  183. /package/plugins/{email → messaging/email}/utils.js +0 -0
  184. /package/{examples → sandbox}/test-chat.js +0 -0
  185. /package/{examples → sandbox}/test-mcp.js +0 -0
  186. /package/{examples → sandbox}/test-reload.js +0 -0
  187. /package/{examples → sandbox}/test-telegram.js +0 -0
  188. /package/{examples → sandbox}/test-tg-bot.js +0 -0
  189. /package/{examples → sandbox}/test-tg-simple.js +0 -0
  190. /package/{examples → sandbox}/test-tg.js +0 -0
  191. /package/{examples → sandbox}/test-think.js +0 -0
  192. /package/src/{core/sub-agent-config.js → agent/sub-config.js} +0 -0
  193. /package/{cli/src → src/cli}/commands/daemon.js +0 -0
  194. /package/{cli/src → src/cli}/commands/list.js +0 -0
  195. /package/{cli/src → src/cli}/commands/plugin.js +0 -0
  196. /package/{cli/src → src/cli}/ui/components/agent-mention-provider.js +0 -0
  197. /package/{cli/src → src/cli}/ui/components/chained-autocomplete-provider.js +0 -0
  198. /package/{cli/src → src/cli}/ui/components/message-bubble.js +0 -0
  199. /package/{cli/src → src/cli}/ui/components/status-bar.js +0 -0
  200. /package/{cli/src → src/cli}/utils/ansi.js +0 -0
  201. /package/{cli/src → src/cli}/utils/config.js +0 -0
  202. /package/{cli/src → src/cli}/utils/markdown.js +0 -0
  203. /package/{cli/src → src/cli}/utils/plugin-config.js +0 -0
  204. /package/{cli/src → src/cli}/utils/render-diff.js +0 -0
  205. /package/src/{utils/circuit-breaker.js → common/circuit.js} +0 -0
  206. /package/src/{utils/edit-diff.js → common/diff.js} +0 -0
  207. /package/src/{utils/event-emitter.js → common/events.js} +0 -0
  208. /package/src/{utils → common}/id.js +0 -0
  209. /package/src/{utils → common}/retry.js +0 -0
  210. /package/src/{core/notification-manager.js → notification/manager.js} +0 -0
  211. /package/src/{core/session-entry.js → session/entry.js} +0 -0
  212. /package/src/{core/storage-manager.js → storage/manager.js} +0 -0
@@ -0,0 +1,645 @@
1
+ # Foliko 重构方案
2
+
3
+ > **项目**:Foliko(简约的插件化 Agent 框架)
4
+ > **源仓库**:`D:\code\vb-agent`
5
+ > **重构目标**:`D:\date\20260624\agent`
6
+ > **状态**:方案已确认,待执行
7
+ > **版本**:v1.0
8
+
9
+ ---
10
+
11
+ ## 目录
12
+
13
+ - [1. 项目背景](#1-项目背景)
14
+ - [2. 现状分析](#2-现状分析)
15
+ - [3. 问题诊断](#3-问题诊断)
16
+ - [4. 重构目标](#4-重构目标)
17
+ - [5. 已确认的关键决策](#5-已确认的关键决策)
18
+ - [6. 目标目录结构](#6-目标目录结构)
19
+ - [7. 核心模块重构细节](#7-核心模块重构细节)
20
+ - [8. 命名与编码规范](#8-命名与编码规范)
21
+ - [9. 公共 API 门面](#9-公共-api-门面)
22
+ - [10. 迁移策略](#10-迁移策略)
23
+ - [11. 风险与缓解](#11-风险与缓解)
24
+ - [12. 度量指标](#12-度量指标)
25
+ - [13. 后续文档](#13-后续文档)
26
+
27
+ ---
28
+
29
+ ## 1. 项目背景
30
+
31
+ Foliko 是一个纯 JavaScript(无 TypeScript)的插件化 Agent 框架,提供:
32
+
33
+ - 极简核心 + 插件扩展机制
34
+ - Vercel AI SDK 集成,支持 Anthropic / OpenAI / DeepSeek / OpenAI-Compatible
35
+ - 工具调用循环(ToolLoopAgent)
36
+ - 技能系统(Skill)、工作流(Workflow)
37
+ - MCP(Model Context Protocol)集成
38
+ - 多会话(Session)与子 Agent(Subagent / Worker)
39
+ - Ambient Agent 模式(持续后台运行)
40
+ - CLI 工具(`foliko chat` / `foliko plugin` / `foliko start` 等)
41
+
42
+ ## 2. 现状分析
43
+
44
+ ### 2.1 规模
45
+
46
+ | 维度 | 数量 |
47
+ |---|---|
48
+ | JS 文件总数 | 111 |
49
+ | 代码总行数 | ~43,530 |
50
+ | `src/core/` | 30 文件 |
51
+ | `src/utils/` | 16 文件 |
52
+ | `plugins/` 顶层 | 30+(仅 2 个有子目录) |
53
+ | `cli/src/` | 17 文件 |
54
+ | 巨型单文件 | framework.js 1422 行、mcp-executor.js 1316 行、memory-plugin.js 1293 行、python-plugin-loader.js 1142 行、workflow-engine.js 1110 行、agent-chat.js 1051 行 |
55
+
56
+ ### 2.2 第三方依赖
57
+
58
+ 详见 `package.json` 核心依赖:AI SDK 生态、MCP SDK、hono、pino、zod、@larksuiteoapi/node-sdk、@chnak/* 系列(QQ/微信 Bot)、@earendil-works/pi-tui 等。
59
+
60
+ ## 3. 问题诊断
61
+
62
+ ### 3.1 架构层
63
+
64
+ 1. **`Framework` 是上帝类**(1422 行,30+ 职责)
65
+ - 子系统管理(PluginManager / ToolRegistry)
66
+ - 三层上下文(3 个独立的 `AsyncLocalStorage`)
67
+ - 三类 Agent 工厂(`createAgent` / `createSubAgent` / `createSessionAgent` / `createWorker`)
68
+ - Worker / Coordinator 协调
69
+ - Session TTL 清理、JSONL 存储
70
+ - Prompt Parts 同步
71
+ - 工作目录 / `.foliko` 目录管理
72
+ - `rescanProject`(114 行,深度耦合 PluginManager / DefaultPlugins / SkillManager)
73
+ - `createFrameworkLogger`(78 行,应在 `logger.js`)
74
+
75
+ 2. **目录职责不清**
76
+ - `src/core/` 同时塞了基础设施(`framework`, `agent`)和次级模块(`context-compressor`, `jsonl-storage`, `session-manager`, `token-counter`, `system-prompt-builder`)
77
+ - `src/utils/` 收容了真正的 utils(`id.js`, `error.js`)和体量不小、明显不该叫 util 的(`data-splitter.js`, `sandbox.js`, `download.js`, `circuit-breaker.js`, `error-boundary.js`)
78
+ - `src/capabilities/` 装了 `skill-manager` 和 `workflow-engine`,但 `mcp-executor` 又在 `src/executors/`,命名风格混乱
79
+
80
+ 3. **上下文概念拆得过散**
81
+ - `context-compressor.js`(958 行)与 `enhanced-context-compressor.js`(重复 / 增强版)
82
+ - `context-manager.js` / `request-context.js` / `session-manager.js` / `session-entry.js` / `chat-session.js` 五个文件交叉引用
83
+
84
+ 4. **Agent 变体过多**
85
+ - `Agent`(主对话)/`Subagent`(轻量子代理)/`WorkerAgent`(Coordinator 模式)/`ChatSession`(消息队列)
86
+ - `coordinator-manager.js` / `coordinator-plugin.js` / `sub-agent-config.js`,一个"子任务"概念衍生出 6 个文件
87
+
88
+ 5. **Plugin 平面化**
89
+ - 30+ 插件全在 `plugins/` 根目录
90
+ - 混合了"系统核心插件"(`ai-plugin`、`tools-plugin`)、"执行器"(`shell-executor-plugin`)、"集成"(`qq-plugin`、`weixin-plugin`)、"功能"(`memory-plugin`、`web-plugin`)四类
91
+
92
+ ### 3.2 工程层
93
+
94
+ 6. **命名风格不统一**
95
+ - `subagent.js` vs `sub-agent-config.js`
96
+ - `framework.js` vs `notification-manager.js`
97
+ - 插件命名:有的 `Plugin` 后缀(`ai-plugin`),有的 `Manager` 后缀(`skill-manager`),有的啥都没有
98
+
99
+ 7. **死代码 / 实验代码混入主干**
100
+ - `cli/src/ui/chat-ui-old.js`(469 行)
101
+ - `framework.js` 中 `createSubAgent` 里有 14 行被注释掉的旧 toolList 构造逻辑
102
+ - 8 个 `examples/test-*.js`(实验)混在示例目录
103
+
104
+ 8. **public API 暴露面不可控**
105
+ - `src/index.js` 只导出 8 个符号
106
+ - 但 `framework` 实例上却有 60+ 公共方法
107
+ - 入口不清晰,新人上手难
108
+
109
+ 9. **配置 / 日志 / 错误处理分散**
110
+ - 日志在 `src/utils/logger.js`,但 `createFrameworkLogger` 又在 `framework.js`
111
+ - 错误有 `error.js` + `error-boundary.js` 两个文件
112
+ - CLI 的 `cli/src/utils/{config,plugin-config}.js` 跟主项目配置分层
113
+
114
+ 10. **没有测试目录**
115
+ - `package.json` 里 `npm test` 都不存在
116
+ - 重构没有安全网
117
+
118
+ ### 3.3 使用层
119
+
120
+ 11. **"使用方法不够简单"具体表现**
121
+ - 跑 demo 需要 4 步:`new Framework` → `loadPlugin(new AIPlugin({...}))` → `framework.createAgent({...})` → `agent.chat(...)`
122
+ - 换模型链路长:`ai-plugin.js` → `provider.js` → `provider-registry.js` → `agent-chat.js` 四处
123
+ - 工具 schema 混用 Zod / JSON Schema,README 不说明
124
+ - CLI 启动要 `.env`,还要单独建 `mcp_config.json` / `agents/*.json` / `plugins/*.json`
125
+
126
+ ## 4. 重构目标
127
+
128
+ 1. **清晰的分层**:核心 / 运行时 / 公共组件 / 插件 / CLI / 示例,各司其职
129
+ 2. **精简的公共 API**:≤ 10 个 `foliko.xxx()` 工厂函数完成 80% 场景
130
+ 3. **单一职责**:每个文件 ≤ 400 行,单个类 ≤ 8 个公共方法
131
+ 4. **插件分类**:核心 / 执行器 / 存储 / 消息 / 观察 / 业务,每个插件自带 README
132
+ 5. **零破坏性迁移**:保留旧导入路径 6~12 个月(带 deprecation warning)
133
+ 6. **可测性**:所有核心模块可独立 mock,关键路径有单元测试
134
+
135
+ ## 5. 已确认的关键决策
136
+
137
+ | 决策项 | 决定 |
138
+ |---|---|
139
+ | 重构后项目位置 | `D:\date\20260624\agent`(当前目录) |
140
+ | Framework 拆分粒度 | 5 个文件:framework / lifecycle / registry / loader + index |
141
+ | 插件目录化 | 全部 30+ 插件按 8 大类迁移 |
142
+ | 测试策略 | 边重构边补 vitest 单测(目标覆盖率 60%) |
143
+ | 源仓库处理 | `D:\code\vb-agent` 保留作只读 mirror,对照参考 |
144
+ | 旧路径兼容 | `src/compat/` 转发 + deprecation warning,保留到下个 major |
145
+
146
+ ## 6. 目标目录结构
147
+
148
+ ```
149
+ foliko/ # 项目根
150
+ ├── package.json
151
+ ├── README.md
152
+ ├── SPEC.md
153
+ ├── CHANGELOG.md
154
+ ├── Dockerfile
155
+ ├── docker-compose.yml
156
+ ├── .env.example
157
+
158
+ ├── bin/ # CLI 入口(薄壳)
159
+ │ └── foliko.js
160
+
161
+ ├── src/ # 框架源码
162
+ │ ├── index.js # 统一公共 API 门面
163
+ │ ├── framework/
164
+ │ │ ├── index.js
165
+ │ │ ├── framework.js # 瘦身后的容器(目标 ~250 行)
166
+ │ │ ├── lifecycle.js # bootstrap / ready / destroy
167
+ │ │ ├── registry.js # 统一注册表
168
+ │ │ └── loader.js # 加载 .foliko 配置
169
+ │ ├── agent/
170
+ │ │ ├── index.js
171
+ │ │ ├── base.js # BaseAgent 公共基类
172
+ │ │ ├── main.js # 主对话 Agent
173
+ │ │ ├── sub.js # 子 Agent
174
+ │ │ ├── worker.js # Coordinator Worker
175
+ │ │ └── prompt.js # SystemPromptBuilder
176
+ │ ├── session/
177
+ │ │ ├── index.js
178
+ │ │ ├── session.js # SessionManager
179
+ │ │ ├── entry.js # JSONL 读写
180
+ │ │ ├── chat.js # ChatSession
181
+ │ │ └── ttl.js # 过期清理
182
+ │ ├── context/
183
+ │ │ ├── index.js
184
+ │ │ ├── request.js # RequestContext
185
+ │ │ ├── session.js # SessionContext
186
+ │ │ ├── agent.js # AgentContext
187
+ │ │ ├── storage.js # AsyncLocalStorage 单例
188
+ │ │ └── compressor.js # 合并后的 Compressor
189
+ │ ├── llm/
190
+ │ │ ├── index.js
191
+ │ │ ├── provider.js # 抽象 Provider
192
+ │ │ ├── registry.js # Provider 注册表
193
+ │ │ ├── streaming.js
194
+ │ │ └── tokens.js # TokenCounter
195
+ │ ├── tool/
196
+ │ │ ├── index.js
197
+ │ │ ├── registry.js # ToolRegistry
198
+ │ │ ├── executor.js # ToolExecutor
199
+ │ │ ├── router.js
200
+ │ │ └── schema.js # Zod/JSON-Schema 适配
201
+ │ ├── plugin/
202
+ │ │ ├── index.js
203
+ │ │ ├── base.js # Plugin 基类
204
+ │ │ ├── manager.js # PluginManager
205
+ │ │ └── loader.js
206
+ │ ├── skills/
207
+ │ │ ├── index.js
208
+ │ │ ├── manager.js # SkillManager
209
+ │ │ ├── workflow.js # WorkflowEngine
210
+ │ │ └── registry.js
211
+ │ ├── mcp/
212
+ │ │ ├── index.js
213
+ │ │ ├── executor.js # MCPExecutor
214
+ │ │ └── client.js
215
+ │ ├── notification/
216
+ │ │ ├── index.js
217
+ │ │ └── manager.js
218
+ │ ├── storage/
219
+ │ │ ├── index.js
220
+ │ │ ├── jsonl.js
221
+ │ │ └── kv.js
222
+ │ ├── common/ # 真正的通用工具
223
+ │ │ ├── logger.js # Logger + createFrameworkLogger
224
+ │ │ ├── events.js # EventEmitter
225
+ │ │ ├── errors.js # 错误类型 + 边界处理(合并)
226
+ │ │ ├── retry.js
227
+ │ │ ├── id.js
228
+ │ │ ├── path.js
229
+ │ │ ├── queue.js
230
+ │ │ ├── circuit.js
231
+ │ │ └── diff.js
232
+ │ ├── config/
233
+ │ │ ├── index.js
234
+ │ │ ├── env.js
235
+ │ │ ├── foliko.js
236
+ │ │ └── plugin-config.js
237
+ │ ├── cli/ # CLI(从 cli/src/ 移过来)
238
+ │ │ ├── index.js
239
+ │ │ ├── runner.js
240
+ │ │ ├── commands/
241
+ │ │ │ ├── chat.js
242
+ │ │ │ ├── list.js
243
+ │ │ │ ├── plugin.js
244
+ │ │ │ └── daemon.js
245
+ │ │ ├── ui/
246
+ │ │ │ ├── chat.js # 合并 chat-ui + chat-ui-old
247
+ │ │ │ └── components/
248
+ │ │ │ ├── footer.js
249
+ │ │ │ ├── status.js
250
+ │ │ │ ├── message-bubble.js
251
+ │ │ │ ├── mention-provider.js
252
+ │ │ │ └── chained-autocomplete.js
253
+ │ │ └── utils/
254
+ │ │ ├── ansi.js
255
+ │ │ ├── markdown.js
256
+ │ │ └── config.js
257
+ │ └── compat/ # 旧路径兼容层
258
+ │ ├── core/
259
+ │ └── ...
260
+
261
+ ├── plugins/ # 内置插件(按职能分组)
262
+ │ ├── README.md
263
+ │ ├── core/
264
+ │ │ ├── default/
265
+ │ │ ├── ai/
266
+ │ │ ├── tool-manager/
267
+ │ │ ├── plugin-manager/
268
+ │ │ ├── session/
269
+ │ │ ├── sub-agent/
270
+ │ │ ├── coordinator/
271
+ │ │ ├── scheduler/
272
+ │ │ ├── skill-manager/
273
+ │ │ ├── workflow/
274
+ │ │ ├── mcp/
275
+ │ │ ├── storage/
276
+ │ │ ├── audit/
277
+ │ │ ├── rules/
278
+ │ │ └── think/
279
+ │ ├── executors/
280
+ │ │ ├── shell/
281
+ │ │ ├── python/
282
+ │ │ ├── extension/
283
+ │ │ └── data-splitter/
284
+ │ ├── io/
285
+ │ │ ├── file-system/
286
+ │ │ ├── web/
287
+ │ │ └── download/
288
+ │ ├── messaging/
289
+ │ │ ├── email/
290
+ │ │ ├── telegram/
291
+ │ │ ├── qq/
292
+ │ │ ├── weixin/
293
+ │ │ └── feishu/
294
+ │ ├── memory/
295
+ │ ├── ambient/
296
+ │ ├── install/
297
+ │ └── trading/
298
+
299
+ ├── examples/ # 整理后的示例
300
+ │ ├── README.md
301
+ │ ├── 01-basic.js
302
+ │ ├── 02-bootstrap.js
303
+ │ ├── 03-custom-tool.js
304
+ │ ├── 04-custom-plugin.js
305
+ │ ├── 05-mcp.js
306
+ │ ├── 06-skills.js
307
+ │ ├── 07-workflow.js
308
+ │ ├── 08-ambient.js
309
+ │ ├── 09-coordinator.js
310
+ │ └── 10-streaming.js
311
+
312
+ ├── docs/
313
+ │ ├── REFACTORING_PLAN.md # 本文档
314
+ │ ├── architecture.md
315
+ │ ├── public-api.md
316
+ │ ├── context-system.md
317
+ │ ├── plugin-dev.md
318
+ │ ├── mcp.md
319
+ │ ├── migration.md
320
+ │ └── ...
321
+
322
+ ├── skills/ # 知识库/工作流(保留原结构)
323
+
324
+ └── tests/ # 新增
325
+ ├── setup.js
326
+ ├── core/
327
+ ├── plugins/
328
+ └── cli/
329
+ ```
330
+
331
+ ## 7. 核心模块重构细节
332
+
333
+ ### 7.1 Framework 拆分
334
+
335
+ 旧 `framework.js`(1422 行)按职责拆 5 个文件:
336
+
337
+ | 新文件 | 行数目标 | 职责 |
338
+ |---|---|---|
339
+ | `framework/framework.js` | ~250 | 容器协调:构造、销毁、事件总线、就绪信号 |
340
+ | `framework/registry.js` | ~200 | 聚合 plugin/tool/command 注册表 |
341
+ | `framework/lifecycle.js` | ~150 | `bootstrap()` / `ready()` / `destroy()` / `setCwd()` / `rescanProject()` |
342
+ | `framework/loader.js` | ~150 | 读取 `.foliko/` 配置并加载默认插件 |
343
+ | `framework/index.js` | ~30 | barrel export |
344
+
345
+ **`rescanProject`(114 行)继续拆**:
346
+ - 把"卸载 keepSet 之外的"逻辑抽到 `plugin/manager.js` 的 `unloadExcept(keepSet)`
347
+ - 把"同步 SkillManager._skillsDirs"抽到 `skills/manager.js` 的 `setSearchDirs()`
348
+
349
+ **Logger 工厂迁移**:`createFrameworkLogger` 整段移到 `common/logger.js`,改成 `Logger.attachTo(framework)` 方法。
350
+
351
+ ### 7.2 三层上下文重整
352
+
353
+ 新 `context/storage.js` 集中所有 `AsyncLocalStorage`:
354
+
355
+ ```js
356
+ // src/context/storage.js
357
+ class ContextStorage {
358
+ constructor() {
359
+ this._request = new AsyncLocalStorage();
360
+ this._session = new AsyncLocalStorage();
361
+ }
362
+ runRequest(ctx, fn) { return this._request.run(ctx, fn); }
363
+ runSession(ctx, fn) { return this._session.run(ctx, fn); }
364
+ getRequest() { return this._request.getStore(); }
365
+ getSession() { return this._session.getStore(); }
366
+ }
367
+ module.exports = new ContextStorage(); // 单例
368
+ ```
369
+
370
+ - `context/compressor.js` 合并 `context-compressor.js`(958 行)+ `enhanced-context-compressor.js`,保留更强的版本,删除旧 export
371
+ - `session/ttl.js` 单独实现 TTL 清理,`framework` 通过组合 `SessionTTL` 引用
372
+
373
+ ### 7.3 Agent 变体统一
374
+
375
+ 让 `MainAgent` / `SubAgent` / `WorkerAgent` 共享一个 `BaseAgent`:
376
+
377
+ ```js
378
+ // src/agent/base.js
379
+ class BaseAgent extends EventEmitter {
380
+ constructor(framework, config) { ... }
381
+ // 公共:chat / chatStream / registerPromptPart
382
+ }
383
+ ```
384
+
385
+ 每个子类的差异通过策略字段注入:
386
+
387
+ | 维度 | MainAgent | SubAgent | WorkerAgent |
388
+ |---|---|---|---|
389
+ | 生命周期 | 常驻 | 单次任务 | 由 Coordinator 回收 |
390
+ | 工具来源 | Framework 全量 | parentTools ∪ 自定义 | 注册到 coordinator |
391
+ | Prompt | 完整 | 角色 + 父 prompt 切片 | 任务描述 |
392
+ | 创建 | `framework.createAgent()` | `framework.createSubAgent()` | `framework.createWorker()` |
393
+
394
+ `framework.createSessionAgent` 本质是"带 sessionId 的 MainAgent",改成 `framework.createAgent({ sessionId })`。
395
+
396
+ ### 7.4 插件目录化
397
+
398
+ 每个插件一个目录,**统一结构**:
399
+
400
+ ```
401
+ plugins/messaging/email/
402
+ ├── index.js # 导出 Plugin 类
403
+ ├── monitor.js
404
+ ├── parser.js
405
+ ├── reply.js
406
+ ├── handlers.js
407
+ ├── constants.js
408
+ ├── utils.js
409
+ └── README.md # 用途、配置项、依赖
410
+ ```
411
+
412
+ `plugins/core/default/` 拆 `default-plugins.js`(735 行):
413
+ - `bootstrap.js` 负责"哪些是默认必装"
414
+ - `config.js` 负责"读取 agent 配置"
415
+ - `index.js` 拼装
416
+
417
+ ### 7.5 LLM 层抽象
418
+
419
+ `llm/provider.js` 提供统一接口:
420
+
421
+ ```js
422
+ class LLMProvider {
423
+ async chat(messages, options) { ... }
424
+ async *stream(messages, options) { ... }
425
+ countTokens(text) { ... }
426
+ }
427
+ ```
428
+
429
+ `ai-plugin` 通过 `provider-registry` 适配多种后端(Anthropic / OpenAI / DeepSeek / OpenAI-Compat),把"如何选 provider"的逻辑从 `agent-chat.js` 移到这里。
430
+
431
+ ### 7.6 CLI 重整
432
+
433
+ - 删除 `chat-ui-old.js`(469 行)
434
+ - 删除 `cli/src/daemon.js`(与 `commands/daemon.js` 重名)
435
+ - `cli/src/` 整目录移到 `src/cli/`
436
+ - 命令分派改成 commander / yargs 等成熟库
437
+
438
+ ## 8. 命名与编码规范
439
+
440
+ | 类别 | 规则 | 示例 |
441
+ |---|---|---|
442
+ | 文件名 | kebab-case | `chat-session.js` |
443
+ | 类名 | PascalCase | `SessionManager` |
444
+ | 公开方法 | camelCase | `createAgent` |
445
+ | 私有方法 | `_camelCase` | `_registerListeners` |
446
+ | 插件目录 | 单数名词 | `plugins/messaging/email/` |
447
+ | 插件入口 | `index.js` | — |
448
+ | 命名空间常量 | UPPER_SNAKE | `LOG_LEVELS` |
449
+ | 测试文件 | `<unit>.test.js` | `framework.test.js` |
450
+ | 临时/实验文件 | 不进 `examples/`,改 `sandbox/` | — |
451
+
452
+ ## 9. 公共 API 门面
453
+
454
+ 新建 `src/index.js`(替换旧的 25 行文件):
455
+
456
+ ```js
457
+ // src/index.js
458
+ 'use strict';
459
+
460
+ const { Framework } = require('./framework');
461
+ const { createAgent } = require('./agent');
462
+ const { bootstrap } = require('./framework/lifecycle');
463
+
464
+ // === 入门三件套 ===
465
+ exports.bootstrap = bootstrap; // 加载 .foliko 配置并启动
466
+ exports.createAgent = createAgent; // 显式构造 Agent
467
+ exports.createApp = createApp; // 构造一个未启动的 Framework
468
+
469
+ // === 工具 ===
470
+ exports.registerTool = ...; // 全局工具快捷注册
471
+ exports.use = use; // app.use(plugin/trait)
472
+
473
+ // === 上下文 ===
474
+ exports.runInSession = runInSession;
475
+ exports.runInRequest = runInRequest;
476
+
477
+ // === 常用插件快捷注册 ===
478
+ exports.withAI = withAI; // 链式 app.use(withAI({...}))
479
+ exports.withShell = withShell;
480
+ exports.withPython = withPython;
481
+
482
+ // === 类型/常量 ===
483
+ exports.z = require('zod');
484
+ exports.LLM = require('./llm'); // Provider 枚举
485
+ ```
486
+
487
+ ### 9.1 "3 行启动"示例
488
+
489
+ ```js
490
+ // examples/01-basic.js
491
+ const foliko = require('foliko');
492
+ const agent = await foliko.bootstrap();
493
+ const reply = await agent.chat('你好');
494
+ ```
495
+
496
+ ```js
497
+ // examples/03-custom-tool.js
498
+ const foliko = require('foliko');
499
+ const { z } = foliko;
500
+
501
+ const app = foliko.createApp()
502
+ .use(foliko.withAI({ provider: 'deepseek', apiKey: 'sk-xxx' }));
503
+ app.tool({
504
+ name: 'sum',
505
+ input: z.object({ a: z.number(), b: z.number() }),
506
+ execute: async ({ a, b }) => ({ result: a + b }),
507
+ });
508
+
509
+ const agent = await app.start();
510
+ const reply = await agent.chat('3 + 5 等于几?');
511
+ ```
512
+
513
+ ## 10. 迁移策略
514
+
515
+ > **原则**:始终保持 `main` 可跑,每一步可单独发布 minor 版本。
516
+
517
+ ### Phase 0:项目初始化与基线(1 周)
518
+
519
+ - 在 `D:\date\20260624\foliko` 初始化 git
520
+ - 从 `D:\code\vb-agent` 同步源码(跳过 `node_modules` / `.git` / `xhs_auth.json` / `system.md`)
521
+ - 加 `vitest` 依赖
522
+ - 写 3 个 smoke test:`framework.createAgent` / `agent.chat` / 工具调用
523
+ - 跑通 `npm start` 确认基线
524
+
525
+ **验收**:3 个 smoke test 全绿,`npm start` 行为与源仓库一致。
526
+
527
+ ### Phase 1:建新目录骨架与 compat 兼容层(半周)
528
+
529
+ - 创建所有新目录占位
530
+ - 新位置放空文件 + `index.js` barrel export
531
+ - `src/compat/` 转发旧路径并加 deprecation warning
532
+ - 验证所有 examples 仍可跑
533
+
534
+ **验收**:旧代码 `require('foliko/src/core/framework')` 仍可工作(带 warning)。
535
+
536
+ ### Phase 2:拆分 common/ 与 config/(1 周)
537
+
538
+ - 迁移 `logger.js`、`errors.js`、`events.js`、`retry.js`、`id.js`、`queue.js`、`circuit.js`、`diff.js` 到 `src/common/`
539
+ - 迁移 `env.js`、`foliko.js`、`plugin-config.js` 到 `src/config/`
540
+ - 改内部引用,旧路径 compat 转发
541
+
542
+ **验收**:`npm start` 行为不变,单元测试覆盖 logger / retry / id。
543
+
544
+ ### Phase 3:重整 context/ 与 session/(1.5 周)
545
+
546
+ - 5 个上下文/会话相关文件按 `src/context/`、`src/session/` 归位
547
+ - 合并 `context-compressor.js` + `enhanced-context-compressor.js`
548
+ - 抽 `ContextStorage` 单例
549
+ - 新加单测覆盖三层隔离
550
+
551
+ **验收**:所有 examples 通过;context 隔离有专门测试。
552
+
553
+ ### Phase 4:拆分 agent/ 为 BaseAgent 体系(1 周)
554
+
555
+ - 提取 `BaseAgent` 公共基类
556
+ - 子类化 `MainAgent` / `SubAgent` / `WorkerAgent`
557
+ - `framework.createAgent` 保持签名,行为通过现有 smoke test
558
+ - `createSessionAgent` 简化为 `createAgent({ sessionId })`
559
+
560
+ **验收**:所有 agent 变体的 smoke test 通过;新增 BaseAgent 单测。
561
+
562
+ ### Phase 5:拆分 framework/ 核心 5 文件(1.5 周)
563
+
564
+ - 1422 行 `framework.js` → 5 个文件
565
+ - `rescanProject` 重构为组合调用
566
+ - `createFrameworkLogger` 移到 `common/logger`
567
+
568
+ **验收**:framework 集成测试通过;`setCwd` / `rescanProject` 路径覆盖。
569
+
570
+ ### Phase 6:LLM / Tool / Plugin 体系抽象(2 周)
571
+
572
+ - 抽象 `LLMProvider` 接口
573
+ - `ai-plugin` 改为基于 `provider-registry`
574
+ - 合并 `provider.js` + `provider-registry.js`
575
+ - 重组 `tool-registry` + `tool-executor` + `tool-router`
576
+ - `plugin` 系统抽 `loader`
577
+
578
+ **验收**:所有 AI 后端切换测试通过;tool 路由有专门测试。
579
+
580
+ ### Phase 7:插件目录化与死代码清理(2 周)
581
+
582
+ - 按 `core / executors / io / messaging / memory / ambient / install / trading` 八大类迁移 30+ 插件
583
+ - 每个插件加 `README.md`(用途、配置、依赖)
584
+ - 删除 `chat-ui-old.js`、`cli/src/daemon.js`、注释老代码
585
+ - 整理 `examples/`:8 个 `test-*.js` 移到 `sandbox/`
586
+
587
+ **验收**:所有插件在新位置加载成功;compat 仍能加载旧路径。
588
+
589
+ ### Phase 8:公共 API 门面 + 文档(1 周)
590
+
591
+ - 实现 `src/index.js` 门面(`bootstrap` / `createAgent` / `createApp` / `withAI` 等)
592
+ - 写 `docs/public-api.md`、`docs/migration.md`、`docs/architecture.md`
593
+ - `compat/` 维护到下一个 major 版本
594
+
595
+ **验收**:examples/01~10 全部基于新门面跑通;migration.md 覆盖所有旧路径。
596
+
597
+ ### 10.1 时间表
598
+
599
+ | Phase | 周期 | 累计 |
600
+ |---|---|---|
601
+ | 0 | 1 周 | 1 周 |
602
+ | 1 | 0.5 周 | 1.5 周 |
603
+ | 2 | 1 周 | 2.5 周 |
604
+ | 3 | 1.5 周 | 4 周 |
605
+ | 4 | 1 周 | 5 周 |
606
+ | 5 | 1.5 周 | 6.5 周 |
607
+ | 6 | 2 周 | 8.5 周 |
608
+ | 7 | 2 周 | 10.5 周 |
609
+ | 8 | 1 周 | 11.5 周 |
610
+
611
+ 总周期 ~10~12 周,可分 3~4 个 milestone 发布。
612
+
613
+ ## 11. 风险与缓解
614
+
615
+ | 风险 | 缓解 |
616
+ |---|---|
617
+ | 行为回归(context / agent 拆分最容易改语义) | Phase 0 起的 smoke test + 每个 Phase 跑全部 example |
618
+ | 插件作者引用了 `plugins/xxx-plugin.js` 路径 | `compat/` 转发 + `migration.md` 列出所有改动 |
619
+ | 单测覆盖不足 | 先 end-to-end 行为锚点,再逐步加单元;先核心后边缘 |
620
+ | 重构与新功能并行 | 重构期间不接大需求;小修小补用 branch 隔离 |
621
+ | Ambient Agent / 邮件等大插件(>500 行)拆分困难 | 单文件插件可保留 `index.js` 主文件,子模块放同目录 `*.js` |
622
+ | 上下文 AsyncLocalStorage 切换引入竞态 | Phase 3 阶段保留新旧两套并跑 1 周再切换默认路径 |
623
+
624
+ ## 12. 度量指标
625
+
626
+ - **代码质量**:单文件 ≤ 400 行;单类公开方法 ≤ 8 个
627
+ - **覆盖率**:核心模块(framework / agent / context / session)≥ 70%
628
+ - **公共 API 稳定性**:Phase 8 后 `src/index.js` 导出符号 ≤ 15 个
629
+ - **可读性**:每个目录有 `README.md` 解释职责
630
+ - **运行时间**:从 `npm install` 到 `npm start` 可用 ≤ 2 分钟(CI 中验证)
631
+
632
+ ## 13. 后续文档
633
+
634
+ 重构过程中会持续输出:
635
+
636
+ - `docs/architecture.md`:整体架构图与数据流
637
+ - `docs/public-api.md`:对外 API 速查
638
+ - `docs/context-system.md`:三层上下文详解
639
+ - `docs/plugin-dev.md`:插件开发指南
640
+ - `docs/mcp.md`:MCP 集成
641
+ - `docs/migration.md`:旧路径 → 新路径迁移对照表
642
+
643
+ ---
644
+
645
+ > **本文件作为重构的权威参考,所有 Phase 执行过程中如发现与方案不一致,须先更新本文件再动代码。**