@creatoria/miniapp-mcp 0.1.3 → 0.2.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 (246) hide show
  1. package/README.md +14 -3
  2. package/dist/app/cli/index.d.ts +6 -0
  3. package/dist/app/cli/index.d.ts.map +1 -0
  4. package/dist/app/cli/index.js +6 -0
  5. package/dist/app/cli/index.js.map +1 -0
  6. package/dist/app/index.d.ts +6 -0
  7. package/dist/app/index.d.ts.map +1 -0
  8. package/dist/app/index.js +6 -0
  9. package/dist/app/index.js.map +1 -0
  10. package/dist/app/server/index.d.ts +7 -0
  11. package/dist/app/server/index.d.ts.map +1 -0
  12. package/dist/app/server/index.js +6 -0
  13. package/dist/app/server/index.js.map +1 -0
  14. package/dist/capabilities/assert/index.d.ts +5 -0
  15. package/dist/capabilities/assert/index.d.ts.map +1 -0
  16. package/dist/capabilities/assert/index.js +5 -0
  17. package/dist/capabilities/assert/index.js.map +1 -0
  18. package/dist/capabilities/automator/index.d.ts +6 -0
  19. package/dist/capabilities/automator/index.d.ts.map +1 -0
  20. package/dist/capabilities/automator/index.js +6 -0
  21. package/dist/capabilities/automator/index.js.map +1 -0
  22. package/dist/capabilities/automator/schemas/close.d.ts +5 -0
  23. package/dist/capabilities/automator/schemas/close.d.ts.map +1 -0
  24. package/dist/capabilities/automator/schemas/close.js +11 -0
  25. package/dist/capabilities/automator/schemas/close.js.map +1 -0
  26. package/dist/capabilities/automator/schemas/connect.d.ts +11 -0
  27. package/dist/capabilities/automator/schemas/connect.d.ts.map +1 -0
  28. package/dist/capabilities/automator/schemas/connect.js +19 -0
  29. package/dist/capabilities/automator/schemas/connect.js.map +1 -0
  30. package/dist/capabilities/automator/schemas/disconnect.d.ts +5 -0
  31. package/dist/capabilities/automator/schemas/disconnect.d.ts.map +1 -0
  32. package/dist/capabilities/automator/schemas/disconnect.js +11 -0
  33. package/dist/capabilities/automator/schemas/disconnect.js.map +1 -0
  34. package/dist/capabilities/automator/schemas/index.d.ts +4 -0
  35. package/dist/capabilities/automator/schemas/index.d.ts.map +1 -0
  36. package/dist/capabilities/automator/schemas/index.js +12 -0
  37. package/dist/capabilities/automator/schemas/index.js.map +1 -0
  38. package/dist/capabilities/automator/schemas/launch.d.ts +17 -0
  39. package/dist/capabilities/automator/schemas/launch.d.ts.map +1 -0
  40. package/dist/capabilities/automator/schemas/launch.js +26 -0
  41. package/dist/capabilities/automator/schemas/launch.js.map +1 -0
  42. package/dist/capabilities/element/index.d.ts +5 -0
  43. package/dist/capabilities/element/index.d.ts.map +1 -0
  44. package/dist/capabilities/element/index.js +5 -0
  45. package/dist/capabilities/element/index.js.map +1 -0
  46. package/dist/capabilities/index.d.ts +15 -0
  47. package/dist/capabilities/index.d.ts.map +1 -0
  48. package/dist/capabilities/index.js +14 -0
  49. package/dist/capabilities/index.js.map +1 -0
  50. package/dist/capabilities/miniprogram/index.d.ts +5 -0
  51. package/dist/capabilities/miniprogram/index.d.ts.map +1 -0
  52. package/dist/capabilities/miniprogram/index.js +5 -0
  53. package/dist/capabilities/miniprogram/index.js.map +1 -0
  54. package/dist/capabilities/network/index.d.ts +5 -0
  55. package/dist/capabilities/network/index.d.ts.map +1 -0
  56. package/dist/capabilities/network/index.js +5 -0
  57. package/dist/capabilities/network/index.js.map +1 -0
  58. package/dist/capabilities/page/index.d.ts +5 -0
  59. package/dist/capabilities/page/index.d.ts.map +1 -0
  60. package/dist/capabilities/page/index.js +5 -0
  61. package/dist/capabilities/page/index.js.map +1 -0
  62. package/dist/capabilities/record/index.d.ts +5 -0
  63. package/dist/capabilities/record/index.d.ts.map +1 -0
  64. package/dist/capabilities/record/index.js +5 -0
  65. package/dist/capabilities/record/index.js.map +1 -0
  66. package/dist/capabilities/schema-registry.d.ts +4 -0
  67. package/dist/capabilities/schema-registry.d.ts.map +1 -0
  68. package/dist/capabilities/schema-registry.js +18 -0
  69. package/dist/capabilities/schema-registry.js.map +1 -0
  70. package/dist/capabilities/schema-types.d.ts +22 -0
  71. package/dist/capabilities/schema-types.d.ts.map +1 -0
  72. package/dist/capabilities/schema-types.js +2 -0
  73. package/dist/capabilities/schema-types.js.map +1 -0
  74. package/dist/capabilities/snapshot/index.d.ts +5 -0
  75. package/dist/capabilities/snapshot/index.d.ts.map +1 -0
  76. package/dist/capabilities/snapshot/index.js +5 -0
  77. package/dist/capabilities/snapshot/index.js.map +1 -0
  78. package/dist/config/loader.js +1 -1
  79. package/dist/config/loader.js.map +1 -1
  80. package/dist/core/element-ref.d.ts +1 -43
  81. package/dist/core/element-ref.d.ts.map +1 -1
  82. package/dist/core/element-ref.js +1 -212
  83. package/dist/core/element-ref.js.map +1 -1
  84. package/dist/core/logger.d.ts +1 -54
  85. package/dist/core/logger.d.ts.map +1 -1
  86. package/dist/core/logger.js +1 -377
  87. package/dist/core/logger.js.map +1 -1
  88. package/dist/core/output.d.ts +1 -20
  89. package/dist/core/output.d.ts.map +1 -1
  90. package/dist/core/output.js +1 -55
  91. package/dist/core/output.js.map +1 -1
  92. package/dist/core/report-generator.d.ts +1 -23
  93. package/dist/core/report-generator.d.ts.map +1 -1
  94. package/dist/core/report-generator.js +1 -211
  95. package/dist/core/report-generator.js.map +1 -1
  96. package/dist/core/session.d.ts +2 -82
  97. package/dist/core/session.d.ts.map +1 -1
  98. package/dist/core/session.js +2 -305
  99. package/dist/core/session.js.map +1 -1
  100. package/dist/core/timeout.d.ts +1 -48
  101. package/dist/core/timeout.d.ts.map +1 -1
  102. package/dist/core/timeout.js +1 -66
  103. package/dist/core/timeout.js.map +1 -1
  104. package/dist/core/tool-logger.d.ts +1 -82
  105. package/dist/core/tool-logger.d.ts.map +1 -1
  106. package/dist/core/tool-logger.js +1 -452
  107. package/dist/core/tool-logger.js.map +1 -1
  108. package/dist/core/validation.d.ts +1 -38
  109. package/dist/core/validation.d.ts.map +1 -1
  110. package/dist/core/validation.js +1 -92
  111. package/dist/core/validation.js.map +1 -1
  112. package/dist/runtime/element/element-ref.d.ts +44 -0
  113. package/dist/runtime/element/element-ref.d.ts.map +1 -0
  114. package/dist/runtime/element/element-ref.js +214 -0
  115. package/dist/runtime/element/element-ref.js.map +1 -0
  116. package/dist/runtime/element/index.d.ts +2 -0
  117. package/dist/runtime/element/index.d.ts.map +1 -0
  118. package/dist/runtime/element/index.js +2 -0
  119. package/dist/runtime/element/index.js.map +1 -0
  120. package/dist/runtime/index.d.ts +10 -0
  121. package/dist/runtime/index.d.ts.map +1 -0
  122. package/dist/runtime/index.js +10 -0
  123. package/dist/runtime/index.js.map +1 -0
  124. package/dist/runtime/logging/index.d.ts +3 -0
  125. package/dist/runtime/logging/index.d.ts.map +1 -0
  126. package/dist/runtime/logging/index.js +3 -0
  127. package/dist/runtime/logging/index.js.map +1 -0
  128. package/dist/runtime/logging/logger.d.ts +55 -0
  129. package/dist/runtime/logging/logger.d.ts.map +1 -0
  130. package/dist/runtime/logging/logger.js +379 -0
  131. package/dist/runtime/logging/logger.js.map +1 -0
  132. package/dist/runtime/logging/tool-logger.d.ts +83 -0
  133. package/dist/runtime/logging/tool-logger.d.ts.map +1 -0
  134. package/dist/runtime/logging/tool-logger.js +454 -0
  135. package/dist/runtime/logging/tool-logger.js.map +1 -0
  136. package/dist/runtime/outputs/index.d.ts +3 -0
  137. package/dist/runtime/outputs/index.d.ts.map +1 -0
  138. package/dist/runtime/outputs/index.js +3 -0
  139. package/dist/runtime/outputs/index.js.map +1 -0
  140. package/dist/runtime/outputs/output-manager.d.ts +12 -0
  141. package/dist/runtime/outputs/output-manager.d.ts.map +1 -0
  142. package/dist/runtime/outputs/output-manager.js +39 -0
  143. package/dist/runtime/outputs/output-manager.js.map +1 -0
  144. package/dist/runtime/outputs/report-generator.d.ts +5 -0
  145. package/dist/runtime/outputs/report-generator.d.ts.map +1 -0
  146. package/dist/runtime/outputs/report-generator.js +175 -0
  147. package/dist/runtime/outputs/report-generator.js.map +1 -0
  148. package/dist/runtime/session/index.d.ts +3 -0
  149. package/dist/runtime/session/index.d.ts.map +1 -0
  150. package/dist/runtime/session/index.js +3 -0
  151. package/dist/runtime/session/index.js.map +1 -0
  152. package/dist/runtime/session/store.d.ts +28 -0
  153. package/dist/runtime/session/store.d.ts.map +1 -0
  154. package/dist/runtime/session/store.js +154 -0
  155. package/dist/runtime/session/store.js.map +1 -0
  156. package/dist/runtime/session/utils/cleanup.d.ts +3 -0
  157. package/dist/runtime/session/utils/cleanup.d.ts.map +1 -0
  158. package/dist/runtime/session/utils/cleanup.js +78 -0
  159. package/dist/runtime/session/utils/cleanup.js.map +1 -0
  160. package/dist/runtime/timeout/index.d.ts +2 -0
  161. package/dist/runtime/timeout/index.d.ts.map +1 -0
  162. package/dist/runtime/timeout/index.js +2 -0
  163. package/dist/runtime/timeout/index.js.map +1 -0
  164. package/dist/runtime/timeout/timeout.d.ts +49 -0
  165. package/dist/runtime/timeout/timeout.d.ts.map +1 -0
  166. package/dist/runtime/timeout/timeout.js +67 -0
  167. package/dist/runtime/timeout/timeout.js.map +1 -0
  168. package/dist/runtime/validation/index.d.ts +2 -0
  169. package/dist/runtime/validation/index.d.ts.map +1 -0
  170. package/dist/runtime/validation/index.js +2 -0
  171. package/dist/runtime/validation/index.js.map +1 -0
  172. package/dist/runtime/validation/validation.d.ts +39 -0
  173. package/dist/runtime/validation/validation.d.ts.map +1 -0
  174. package/dist/runtime/validation/validation.js +93 -0
  175. package/dist/runtime/validation/validation.js.map +1 -0
  176. package/dist/schemas/automator/miniprogram_close.json +12 -0
  177. package/dist/schemas/automator/miniprogram_connect.json +19 -0
  178. package/dist/schemas/automator/miniprogram_disconnect.json +12 -0
  179. package/dist/schemas/automator/miniprogram_launch.json +30 -0
  180. package/dist/server.js +1 -1
  181. package/dist/server.js.map +1 -1
  182. package/dist/tools/index.js +1 -1
  183. package/dist/tools/index.js.map +1 -1
  184. package/dist/tools/miniprogram.d.ts +0 -1
  185. package/dist/tools/miniprogram.d.ts.map +1 -1
  186. package/dist/tools/miniprogram.js +17 -29
  187. package/dist/tools/miniprogram.js.map +1 -1
  188. package/dist/tools/page.js +2 -2
  189. package/dist/tools/page.js.map +1 -1
  190. package/docs/directory-structure-and-code-style-best-practices.md +91 -0
  191. package/docs/migration/README.md +34 -0
  192. package/docs/migration/TC-ALIGN-01-notes.md +35 -0
  193. package/docs/migration/runtime-skeleton.md +50 -0
  194. package/docs/migration/tool-schema-strategy.md +75 -0
  195. package/docs//345/256/214/346/225/264/345/256/236/347/216/260/346/226/271/346/241/210.md +14 -14
  196. package/docs//347/254/254/344/270/200/347/211/210/346/234/254/346/226/271/346/241/210.md +7 -7
  197. package/package.json +4 -2
  198. package/docs/SIMPLE_USAGE.md +0 -210
  199. package/docs/architecture.E-Docs.md +0 -1359
  200. package/docs/architecture.F1.md +0 -720
  201. package/docs/architecture.F2.md +0 -871
  202. package/docs/architecture.F3.md +0 -905
  203. package/docs/architecture.md +0 -90
  204. package/docs/charter.A1.align.yaml +0 -170
  205. package/docs/charter.A2.align.yaml +0 -199
  206. package/docs/charter.A3.align.yaml +0 -242
  207. package/docs/charter.A4.align.yaml +0 -227
  208. package/docs/charter.B1.align.yaml +0 -179
  209. package/docs/charter.B2.align.yaml +0 -200
  210. package/docs/charter.B3.align.yaml +0 -200
  211. package/docs/charter.B4.align.yaml +0 -188
  212. package/docs/charter.C1.align.yaml +0 -190
  213. package/docs/charter.C2.align.yaml +0 -202
  214. package/docs/charter.C3.align.yaml +0 -211
  215. package/docs/charter.C4.align.yaml +0 -263
  216. package/docs/charter.C5.align.yaml +0 -220
  217. package/docs/charter.D1.align.yaml +0 -190
  218. package/docs/charter.D2.align.yaml +0 -234
  219. package/docs/charter.D3.align.yaml +0 -206
  220. package/docs/charter.E-Docs.align.yaml +0 -294
  221. package/docs/charter.F1.align.yaml +0 -193
  222. package/docs/charter.F2.align.yaml +0 -248
  223. package/docs/charter.F3.align.yaml +0 -287
  224. package/docs/charter.G.align.yaml +0 -174
  225. package/docs/charter.align.yaml +0 -111
  226. package/docs/maintenance.md +0 -682
  227. package/docs/playwright-mcp/350/260/203/347/240/224.md +0 -53
  228. package/docs/setup-guide.md +0 -775
  229. package/docs/tasks.A1.atomize.md +0 -296
  230. package/docs/tasks.A2.atomize.md +0 -408
  231. package/docs/tasks.A3.atomize.md +0 -564
  232. package/docs/tasks.A4.atomize.md +0 -496
  233. package/docs/tasks.B1.atomize.md +0 -352
  234. package/docs/tasks.B2.atomize.md +0 -561
  235. package/docs/tasks.B3.atomize.md +0 -508
  236. package/docs/tasks.B4.atomize.md +0 -504
  237. package/docs/tasks.C1.atomize.md +0 -540
  238. package/docs/tasks.C2.atomize.md +0 -665
  239. package/docs/tasks.C3.atomize.md +0 -745
  240. package/docs/tasks.C4.atomize.md +0 -908
  241. package/docs/tasks.C5.atomize.md +0 -755
  242. package/docs/tasks.D1.atomize.md +0 -547
  243. package/docs/tasks.D2.atomize.md +0 -619
  244. package/docs/tasks.D3.atomize.md +0 -790
  245. package/docs/tasks.E-Docs.atomize.md +0 -1204
  246. package/docs/tasks.atomize.md +0 -189
@@ -1,905 +0,0 @@
1
- # Architecture: F3 - 会话报告生成
2
-
3
- ## 文档信息
4
- - **项目**: creatoria-miniapp-mcp
5
- - **阶段**: F - 可观测性与产物输出
6
- - **任务**: F3 - 会话报告生成(JSON/Markdown 汇总)
7
- - **作者**: ClaudeCode
8
- - **日期**: 2025-10-03
9
- - **版本**: 1.0
10
-
11
- ## 目录
12
- 1. [系统概述](#1-系统概述)
13
- 2. [架构设计](#2-架构设计)
14
- 3. [详细设计](#3-详细设计)
15
- 4. [接口设计](#4-接口设计)
16
- 5. [数据模型](#5-数据模型)
17
- 6. [错误处理](#6-错误处理)
18
- 7. [性能考量](#7-性能考量)
19
- 8. [安全性](#8-安全性)
20
- 9. [测试策略](#9-测试策略)
21
-
22
- ---
23
-
24
- ## 1. 系统概述
25
-
26
- ### 1.1 背景
27
- 自动化测试执行后,开发者需要查看执行结果、成功率、失败原因等信息。F3 任务实现会话级别的报告生成,将所有工具调用汇总为结构化报告(JSON)和可读报告(Markdown),便于分析和分享。
28
-
29
- ### 1.2 目标
30
- - **会话汇总**:自动收集所有工具调用记录
31
- - **双格式输出**:JSON(机器可读)+ Markdown(人类可读)
32
- - **失败追踪**:关联 F2 快照路径
33
- - **性能分析**:提供耗时统计和性能指标
34
-
35
- ### 1.3 关键约束
36
- - 依赖 F1 日志系统(ToolLogger)
37
- - 依赖 F2 快照路径格式
38
- - 默认禁用(显式启用)
39
- - Fire-and-forget 模式(不阻塞关闭)
40
-
41
- ---
42
-
43
- ## 2. 架构设计
44
-
45
- ### 2.1 C4 模型
46
-
47
- #### Level 1: 系统上下文图
48
- ```
49
- ┌─────────────────────────────────────────────────────────────────┐
50
- │ │
51
- │ MCP Client (Claude) │
52
- │ │
53
- └────────────────────────┬────────────────────────────────────────┘
54
- │ MCP Protocol
55
- │ (stdio transport)
56
- v
57
- ┌─────────────────────────────────────────────────────────────────┐
58
- │ │
59
- │ MCP Server (miniapp-mcp) │
60
- │ │
61
- │ ┌─────────────────────────────────────────────────────────┐ │
62
- │ │ Session Report Generator (F3) │ │
63
- │ │ - Collects tool call records │ │
64
- │ │ - Generates JSON/Markdown reports on session close │ │
65
- │ │ - Links to F2 failure snapshots │ │
66
- │ └─────────────────────────────────────────────────────────┘ │
67
- │ │ │
68
- └─────────────────────────┼────────────────────────────────────────┘
69
-
70
- v
71
- ┌───────────────────────┐
72
- │ File System │
73
- │ .mcp-artifacts/ │
74
- │ report.json │
75
- │ report.md │
76
- └───────────────────────┘
77
- ```
78
-
79
- #### Level 2: 容器图
80
- ```
81
- ┌──────────────────────────────────────────────────────────────────────┐
82
- │ MCP Server Process │
83
- │ │
84
- │ ┌────────────────┐ ┌────────────────┐ ┌─────────────────┐ │
85
- │ │ ToolLogger │────>│ ReportCollector│────>│ ReportGenerator │ │
86
- │ │ (F1) │ │ │ │ │ │
87
- │ │ - wrap() │ │ - record() │ │ - generateJSON()│ │
88
- │ │ - log calls │ │ - aggregate() │ │ - generateMD() │ │
89
- │ └────────────────┘ └────────────────┘ └─────────────────┘ │
90
- │ │ │ │ │
91
- │ │ │ v │
92
- │ v v ┌─────────────────┐ │
93
- │ ┌────────────────┐ ┌────────────────┐ │ OutputManager │ │
94
- │ │ SessionState │ │ SessionState │ │ │ │
95
- │ │ - reportData │<────│ - reportData │ │ - writeFile() │ │
96
- │ │ .toolCalls[] │ │ .toolCalls[] │ └─────────────────┘ │
97
- │ └────────────────┘ └────────────────┘ │
98
- └──────────────────────────────────────────────────────────────────────┘
99
-
100
- v
101
- ┌─────────────────────────────┐
102
- │ Artifacts Directory │
103
- │ │
104
- │ {sessionId}/ │
105
- │ ├─ report.json │
106
- │ ├─ report.md │
107
- │ └─ failures/ │
108
- └─────────────────────────────┘
109
- ```
110
-
111
- #### Level 3: 组件图
112
- ```
113
- ┌──────────────────────────────────────────────────────────────────────┐
114
- │ ToolLogger (F1) │
115
- │ │
116
- │ wrap(toolName, handler) { │
117
- │ const startTime = Date.now() │
118
- │ │
119
- │ try { │
120
- │ const result = await handler(session, args) │
121
- │ const duration = Date.now() - startTime │
122
- │ │
123
- │ // F3: Record successful call │
124
- │ if (session.reportData) { │
125
- │ session.reportData.toolCalls.push({ │
126
- │ timestamp, toolName, duration, success: true, result │
127
- │ }) │
128
- │ } │
129
- │ │
130
- │ return result │
131
- │ } catch (error) { │
132
- │ const duration = Date.now() - startTime │
133
- │ │
134
- │ // F3: Record failed call │
135
- │ if (session.reportData) { │
136
- │ session.reportData.toolCalls.push({ │
137
- │ timestamp, toolName, duration, success: false, │
138
- │ error: { message, snapshotPath } │
139
- │ }) │
140
- │ } │
141
- │ │
142
- │ throw error │
143
- │ } │
144
- │ } │
145
- └──────────────────────────────────────────────────────────────────────┘
146
-
147
- ┌──────────────────────────────────────────────────────────────────────┐
148
- │ SessionStore.dispose() │
149
- │ │
150
- │ async dispose() { │
151
- │ // Close all sessions │
152
- │ for (const sessionId of this.sessions.keys()) { │
153
- │ const session = this.sessions.get(sessionId) │
154
- │ │
155
- │ // F3: Generate report before cleanup │
156
- │ if (session.reportData && config.enableSessionReport) { │
157
- │ void generateSessionReport(session).catch(err => { │
158
- │ logger.warn('Report generation failed', err) │
159
- │ }) │
160
- │ } │
161
- │ │
162
- │ await this.delete(sessionId) │
163
- │ } │
164
- │ } │
165
- └──────────────────────────────────────────────────────────────────────┘
166
-
167
- ┌──────────────────────────────────────────────────────────────────────┐
168
- │ ReportGenerator │
169
- │ │
170
- │ async generateSessionReport(session: SessionState) { │
171
- │ const { reportData, sessionId, outputManager } = session │
172
- │ │
173
- │ // 1. Calculate summary statistics │
174
- │ const summary = calculateSummary(reportData.toolCalls) │
175
- │ │
176
- │ // 2. Extract failures │
177
- │ const failures = reportData.toolCalls │
178
- │ .filter(call => !call.success) │
179
- │ .map(call => ({ │
180
- │ toolName: call.toolName, │
181
- │ timestamp: call.timestamp, │
182
- │ error: call.error.message, │
183
- │ snapshotPath: call.error.snapshotPath │
184
- │ })) │
185
- │ │
186
- │ // 3. Generate JSON report │
187
- │ const jsonReport = { │
188
- │ sessionId, │
189
- │ startTime: reportData.startTime, │
190
- │ endTime: reportData.endTime, │
191
- │ duration: reportData.endTime - reportData.startTime, │
192
- │ summary, │
193
- │ toolCalls: reportData.toolCalls.map(sanitizeCall), │
194
- │ failures │
195
- │ } │
196
- │ │
197
- │ await outputManager.writeFile( │
198
- │ 'report.json', │
199
- │ JSON.stringify(jsonReport, null, 2) │
200
- │ ) │
201
- │ │
202
- │ // 4. Generate Markdown report │
203
- │ const mdReport = generateMarkdown(jsonReport) │
204
- │ await outputManager.writeFile('report.md', mdReport) │
205
- │ │
206
- │ logger.info('Session report generated', { │
207
- │ sessionId, │
208
- │ totalCalls: summary.totalCalls, │
209
- │ successRate: summary.successRate │
210
- │ }) │
211
- │ } │
212
- └──────────────────────────────────────────────────────────────────────┘
213
- ```
214
-
215
- ### 2.2 数据流图
216
-
217
- ```
218
- ┌───────────────┐
219
- │ Tool Call │
220
- │ Execution │
221
- └───────┬───────┘
222
-
223
- v
224
- ┌─────────────┐
225
- │ ToolLogger │
226
- │ .wrap() │
227
- └─────┬───────┘
228
-
229
- v
230
- ┌────────────────────────┐
231
- │ Record to │
232
- │ session.reportData │
233
- │ .toolCalls.push() │
234
- └────────┬───────────────┘
235
-
236
- │ (Continue accumulating)
237
- v
238
- ┌────────────────────────┐
239
- │ Session Close │
240
- │ (dispose triggered) │
241
- └────────┬───────────────┘
242
-
243
- v
244
- ┌────────────────────────────┐
245
- │ config.enableSession │
246
- │ Report === true? │
247
- └───────┬────────────────────┘
248
-
249
- YES │
250
- v
251
- ┌────────────────────────────┐
252
- │ generateSessionReport() │
253
- │ (async, fire-and-forget) │
254
- └───────┬────────────────────┘
255
-
256
- │ ┌─ Calculate summary stats
257
- │ │ (total, success, fail, avg duration)
258
- │ │
259
- │ ├─ Extract failures with snapshot links
260
- │ │
261
- │ ├─ Generate JSON report
262
- │ │ └─ Write to report.json
263
- │ │
264
- │ └─ Generate Markdown report
265
- │ └─ Write to report.md
266
-
267
- v
268
- ┌────────────────────────────┐
269
- │ Report files saved │
270
- │ - report.json │
271
- │ - report.md │
272
- └────────────────────────────┘
273
- ```
274
-
275
- ---
276
-
277
- ## 3. 详细设计
278
-
279
- ### 3.1 数据收集流程
280
-
281
- **初始化** (Session 创建时):
282
- ```typescript
283
- // src/core/session.ts
284
- session = {
285
- sessionId,
286
- // ... existing fields
287
- reportData: config.enableSessionReport ? {
288
- toolCalls: [],
289
- startTime: new Date(),
290
- } : undefined,
291
- }
292
- ```
293
-
294
- **记录工具调用** (ToolLogger.wrap):
295
- ```typescript
296
- // src/core/tool-logger.ts
297
- private recordToolCall(
298
- session: SessionState,
299
- toolName: string,
300
- duration: number,
301
- success: boolean,
302
- resultOrError: any
303
- ): void {
304
- if (!session.reportData) return // Feature disabled
305
-
306
- const record: ToolCallRecord = {
307
- timestamp: new Date(),
308
- toolName,
309
- duration,
310
- success,
311
- }
312
-
313
- if (success) {
314
- record.result = this.sanitizeResult(resultOrError)
315
- } else {
316
- const error = resultOrError as Error
317
- record.error = {
318
- message: error.message,
319
- snapshotPath: this.extractSnapshotPath(session, toolName),
320
- }
321
- }
322
-
323
- session.reportData.toolCalls.push(record)
324
-
325
- // Memory protection: limit to 1000 records
326
- if (session.reportData.toolCalls.length > 1000) {
327
- session.reportData.toolCalls.shift() // Remove oldest
328
- this.logger?.warn('Report data limit reached, oldest record dropped')
329
- }
330
- }
331
- ```
332
-
333
- **提取快照路径**:
334
- ```typescript
335
- private extractSnapshotPath(
336
- session: SessionState,
337
- toolName: string
338
- ): string | undefined {
339
- // Check if F2 snapshot was created
340
- const sanitizedToolName = toolName.replace(/[^a-zA-Z0-9_-]/g, '_')
341
- const pattern = new RegExp(`failures/${sanitizedToolName}-.*`)
342
-
343
- // Search recent logger output for snapshot path
344
- // (Alternative: ToolLogger could cache last snapshot path)
345
- return undefined // Simplified for now
346
- }
347
- ```
348
-
349
- ### 3.2 报告生成流程
350
-
351
- **触发时机** (Session 关闭):
352
- ```typescript
353
- // src/core/session.ts
354
- async dispose(): Promise<void> {
355
- const sessions = Array.from(this.sessions.values())
356
-
357
- for (const session of sessions) {
358
- // F3: Generate report before cleanup
359
- if (session.reportData && this.config?.enableSessionReport) {
360
- session.reportData.endTime = new Date()
361
-
362
- void generateSessionReport(session, this.config).catch((error) => {
363
- console.error(`Failed to generate report for ${session.sessionId}:`, error)
364
- })
365
- }
366
-
367
- await this.delete(session.sessionId)
368
- }
369
- }
370
- ```
371
-
372
- **报告生成器**:
373
- ```typescript
374
- // src/core/report-generator.ts
375
- export async function generateSessionReport(
376
- session: SessionState,
377
- config: ServerConfig
378
- ): Promise<void> {
379
- const { sessionId, reportData, outputManager } = session
380
-
381
- if (!reportData || !outputManager) {
382
- throw new Error('Missing report data or output manager')
383
- }
384
-
385
- // 1. Calculate summary
386
- const summary = calculateSummary(reportData.toolCalls)
387
-
388
- // 2. Extract failures
389
- const failures = reportData.toolCalls
390
- .filter((call) => !call.success)
391
- .map((call) => ({
392
- toolName: call.toolName,
393
- timestamp: call.timestamp.toISOString(),
394
- error: call.error?.message || 'Unknown error',
395
- snapshotPath: call.error?.snapshotPath,
396
- }))
397
-
398
- // 3. Build JSON report
399
- const jsonReport: SessionReport = {
400
- sessionId,
401
- startTime: reportData.startTime.toISOString(),
402
- endTime: reportData.endTime!.toISOString(),
403
- duration: reportData.endTime!.getTime() - reportData.startTime.getTime(),
404
- summary,
405
- toolCalls: reportData.toolCalls,
406
- failures,
407
- }
408
-
409
- // 4. Write JSON
410
- await outputManager.writeFile(
411
- 'report.json',
412
- Buffer.from(JSON.stringify(jsonReport, null, 2))
413
- )
414
-
415
- // 5. Generate and write Markdown
416
- const markdown = generateMarkdownReport(jsonReport)
417
- await outputManager.writeFile('report.md', Buffer.from(markdown))
418
-
419
- console.error(`Session report generated: ${sessionId}`)
420
- }
421
- ```
422
-
423
- ### 3.3 Markdown 生成
424
-
425
- ```typescript
426
- function generateMarkdownReport(report: SessionReport): string {
427
- const duration = formatDuration(report.duration)
428
- const successRate = ((report.summary.successRate * 100).toFixed(1))
429
-
430
- let md = `# Session Report: ${report.sessionId}\n\n`
431
-
432
- // Summary section
433
- md += `## Summary\n`
434
- md += `- **Duration**: ${duration}\n`
435
- md += `- **Total Calls**: ${report.summary.totalCalls}\n`
436
- md += `- **Success Rate**: ${successRate}% (${report.summary.successCount}/${report.summary.totalCalls})\n`
437
- md += `- **Average Duration**: ${formatDuration(report.summary.avgDuration)}\n\n`
438
-
439
- // Tool statistics table
440
- md += `## Tool Call Statistics\n`
441
- md += formatToolStatistics(report.toolCalls)
442
- md += `\n\n`
443
-
444
- // Failures section
445
- if (report.failures.length > 0) {
446
- md += `## Failures\n`
447
- report.failures.forEach((failure, index) => {
448
- md += `### ${index + 1}. ${failure.toolName}\n`
449
- md += `- **Time**: ${failure.timestamp}\n`
450
- md += `- **Error**: ${failure.error}\n`
451
- if (failure.snapshotPath) {
452
- md += `- **Snapshot**: [${failure.snapshotPath}](${failure.snapshotPath})\n`
453
- }
454
- md += `\n`
455
- })
456
- }
457
-
458
- // Timeline (last 20 calls)
459
- md += `## Timeline (Last 20 Calls)\n`
460
- md += formatTimeline(report.toolCalls.slice(-20))
461
-
462
- return md
463
- }
464
- ```
465
-
466
- ---
467
-
468
- ## 4. 接口设计
469
-
470
- ### 4.1 类型定义
471
-
472
- ```typescript
473
- // src/types.ts
474
-
475
- /**
476
- * Tool call record for session report
477
- */
478
- export interface ToolCallRecord {
479
- timestamp: Date
480
- toolName: string
481
- duration: number // milliseconds
482
- success: boolean
483
- result?: any // Sanitized result (success case)
484
- error?: {
485
- message: string
486
- snapshotPath?: string // Link to F2 failure snapshot
487
- }
488
- }
489
-
490
- /**
491
- * Report data collected during session
492
- */
493
- export interface ReportData {
494
- toolCalls: ToolCallRecord[]
495
- startTime: Date
496
- endTime?: Date
497
- }
498
-
499
- /**
500
- * Session report (JSON format)
501
- */
502
- export interface SessionReport {
503
- sessionId: string
504
- startTime: string // ISO 8601
505
- endTime: string // ISO 8601
506
- duration: number // milliseconds
507
- summary: {
508
- totalCalls: number
509
- successCount: number
510
- failureCount: number
511
- successRate: number // 0-1
512
- avgDuration: number // milliseconds
513
- maxDuration: number
514
- minDuration: number
515
- }
516
- toolCalls: ToolCallRecord[]
517
- failures: Array<{
518
- toolName: string
519
- timestamp: string
520
- error: string
521
- snapshotPath?: string
522
- }>
523
- }
524
-
525
- /**
526
- * Server config extension
527
- */
528
- export interface ServerConfig {
529
- // ... existing fields
530
- enableSessionReport?: boolean // Enable session report generation (default: false)
531
- }
532
- ```
533
-
534
- ### 4.2 公开 API
535
-
536
- ```typescript
537
- // src/core/report-generator.ts
538
-
539
- /**
540
- * Generate session report (JSON + Markdown)
541
- */
542
- export async function generateSessionReport(
543
- session: SessionState,
544
- config: ServerConfig
545
- ): Promise<void>
546
-
547
- /**
548
- * Calculate summary statistics
549
- */
550
- export function calculateSummary(toolCalls: ToolCallRecord[]): SessionReport['summary']
551
-
552
- /**
553
- * Generate Markdown report from JSON report
554
- */
555
- export function generateMarkdownReport(report: SessionReport): string
556
- ```
557
-
558
- ---
559
-
560
- ## 5. 数据模型
561
-
562
- ### 5.1 SessionState 扩展
563
-
564
- ```typescript
565
- export interface SessionState {
566
- sessionId: string
567
- // ... existing fields
568
- reportData?: ReportData // 🆕 Report collection
569
- }
570
- ```
571
-
572
- ### 5.2 ToolCallRecord 结构
573
-
574
- ```typescript
575
- interface ToolCallRecord {
576
- timestamp: Date // When the tool was called
577
- toolName: string // Tool identifier
578
- duration: number // Execution time in ms
579
- success: boolean // true = success, false = error
580
- result?: any // Sanitized result (success)
581
- error?: { // Error details (failure)
582
- message: string // Error message
583
- snapshotPath?: string // Relative path to F2 snapshot
584
- }
585
- }
586
- ```
587
-
588
- **大小估算**:
589
- - 每条记录约 200-500 bytes (含脱敏数据)
590
- - 1000 条记录约 200-500 KB
591
- - 内存限制:单会话最多 1000 条记录
592
-
593
- ### 5.3 JSON Schema
594
-
595
- ```json
596
- {
597
- "$schema": "http://json-schema.org/draft-07/schema#",
598
- "type": "object",
599
- "required": ["sessionId", "startTime", "endTime", "duration", "summary", "toolCalls", "failures"],
600
- "properties": {
601
- "sessionId": { "type": "string" },
602
- "startTime": { "type": "string", "format": "date-time" },
603
- "endTime": { "type": "string", "format": "date-time" },
604
- "duration": { "type": "number", "minimum": 0 },
605
- "summary": {
606
- "type": "object",
607
- "required": ["totalCalls", "successCount", "failureCount", "successRate", "avgDuration", "maxDuration", "minDuration"],
608
- "properties": {
609
- "totalCalls": { "type": "integer", "minimum": 0 },
610
- "successCount": { "type": "integer", "minimum": 0 },
611
- "failureCount": { "type": "integer", "minimum": 0 },
612
- "successRate": { "type": "number", "minimum": 0, "maximum": 1 },
613
- "avgDuration": { "type": "number", "minimum": 0 },
614
- "maxDuration": { "type": "number", "minimum": 0 },
615
- "minDuration": { "type": "number", "minimum": 0 }
616
- }
617
- },
618
- "toolCalls": {
619
- "type": "array",
620
- "items": {
621
- "type": "object",
622
- "required": ["timestamp", "toolName", "duration", "success"],
623
- "properties": {
624
- "timestamp": { "type": "string", "format": "date-time" },
625
- "toolName": { "type": "string" },
626
- "duration": { "type": "number", "minimum": 0 },
627
- "success": { "type": "boolean" },
628
- "result": {},
629
- "error": {
630
- "type": "object",
631
- "properties": {
632
- "message": { "type": "string" },
633
- "snapshotPath": { "type": "string" }
634
- }
635
- }
636
- }
637
- }
638
- },
639
- "failures": {
640
- "type": "array",
641
- "items": {
642
- "type": "object",
643
- "required": ["toolName", "timestamp", "error"],
644
- "properties": {
645
- "toolName": { "type": "string" },
646
- "timestamp": { "type": "string", "format": "date-time" },
647
- "error": { "type": "string" },
648
- "snapshotPath": { "type": "string" }
649
- }
650
- }
651
- }
652
- }
653
- }
654
- ```
655
-
656
- ---
657
-
658
- ## 6. 错误处理
659
-
660
- ### 6.1 报告生成失败
661
-
662
- ```typescript
663
- // Fire-and-forget pattern
664
- void generateSessionReport(session, config).catch((error) => {
665
- console.error(`Failed to generate report: ${error.message}`)
666
- // Don't block session closure
667
- })
668
- ```
669
-
670
- **错误类型**:
671
- 1. **文件写入失败** (ENOSPC, EACCES)
672
- - 记录到日志
673
- - 继续会话关闭
674
-
675
- 2. **数据序列化失败** (循环引用)
676
- - 使用 try-catch 包裹 JSON.stringify
677
- - 返回错误占位符
678
-
679
- 3. **内存不足**
680
- - 限制 toolCalls 数组大小
681
- - 自动丢弃最早记录
682
-
683
- ### 6.2 数据收集失败
684
-
685
- ```typescript
686
- // src/core/tool-logger.ts
687
- try {
688
- this.recordToolCall(session, toolName, duration, success, result)
689
- } catch (error) {
690
- // Don't fail the tool call due to reporting issues
691
- this.logger?.warn('Failed to record tool call', { error })
692
- }
693
- ```
694
-
695
- ---
696
-
697
- ## 7. 性能考量
698
-
699
- ### 7.1 内存管理
700
-
701
- **限制策略**:
702
- ```typescript
703
- const MAX_TOOL_CALLS = 1000
704
-
705
- if (session.reportData.toolCalls.length >= MAX_TOOL_CALLS) {
706
- session.reportData.toolCalls.shift() // FIFO
707
- logger.warn('Report data limit reached')
708
- }
709
- ```
710
-
711
- **内存占用估算**:
712
- - 每条记录: 200-500 bytes
713
- - 1000 条记录: 200-500 KB
714
- - 可接受范围(相比会话其他数据)
715
-
716
- ### 7.2 生成性能
717
-
718
- **优化措施**:
719
- 1. **Fire-and-forget**: 不阻塞会话关闭
720
- 2. **流式写入**: 对大型报告使用流式写入
721
- 3. **延迟序列化**: 仅在生成时序列化
722
-
723
- **性能目标**:
724
- - 报告生成耗时 < 200ms (1000 条记录)
725
- - 不影响会话关闭速度
726
-
727
- ---
728
-
729
- ## 8. 安全性
730
-
731
- ### 8.1 数据脱敏
732
-
733
- **复用 F1 逻辑**:
734
- ```typescript
735
- record.result = this.sanitizeResult(result)
736
- record.args = this.sanitizeArgs(args)
737
- ```
738
-
739
- **脱敏规则**:
740
- - 移除敏感字段 (password, token, apiKey, etc.)
741
- - 截断大字符串 (>1KB)
742
- - 处理循环引用
743
-
744
- ### 8.2 文件权限
745
-
746
- **报告文件位置**:
747
- ```
748
- .mcp-artifacts/{sessionId}/
749
- ├─ report.json (644)
750
- └─ report.md (644)
751
- ```
752
-
753
- **注意事项**:
754
- - 报告文件可能包含业务敏感信息
755
- - 建议在 .gitignore 中排除 .mcp-artifacts/
756
- - 文档提醒用户注意报告文件的访问控制
757
-
758
- ---
759
-
760
- ## 9. 测试策略
761
-
762
- ### 9.1 单元测试
763
-
764
- **数据收集测试**:
765
- ```typescript
766
- it('should record successful tool call', async () => {
767
- const session = createMockSession({ enableSessionReport: true })
768
- const toolLogger = new ToolLogger(mockLogger, config)
769
- const handler = jest.fn().mockResolvedValue({ success: true })
770
-
771
- const wrapped = toolLogger.wrap('test_tool', handler)
772
- await wrapped(session, { arg: 'value' })
773
-
774
- expect(session.reportData.toolCalls).toHaveLength(1)
775
- expect(session.reportData.toolCalls[0]).toMatchObject({
776
- toolName: 'test_tool',
777
- success: true,
778
- duration: expect.any(Number),
779
- })
780
- })
781
- ```
782
-
783
- **报告生成测试**:
784
- ```typescript
785
- it('should generate valid JSON report', async () => {
786
- const session = createSessionWithMockData()
787
- await generateSessionReport(session, config)
788
-
789
- const reportPath = join(session.outputDir, 'report.json')
790
- const content = await readFile(reportPath, 'utf-8')
791
- const report = JSON.parse(content)
792
-
793
- expect(report).toMatchSchema(SessionReportSchema)
794
- expect(report.summary.totalCalls).toBe(10)
795
- expect(report.summary.successRate).toBeCloseTo(0.8)
796
- })
797
- ```
798
-
799
- ### 9.2 集成测试
800
-
801
- **端到端流程**:
802
- ```typescript
803
- it('should generate report on session close', async () => {
804
- const sessionStore = new SessionStore({ enableSessionReport: true })
805
- const session = sessionStore.getOrCreate('test-session')
806
-
807
- // Execute some tools
808
- await executeMockToolCalls(session, 10) // 8 success, 2 fail
809
-
810
- // Close session
811
- await sessionStore.dispose()
812
-
813
- // Verify report files exist
814
- const reportJsonPath = join(session.outputDir, 'report.json')
815
- const reportMdPath = join(session.outputDir, 'report.md')
816
-
817
- expect(await fileExists(reportJsonPath)).toBe(true)
818
- expect(await fileExists(reportMdPath)).toBe(true)
819
-
820
- // Verify content
821
- const report = JSON.parse(await readFile(reportJsonPath, 'utf-8'))
822
- expect(report.summary.totalCalls).toBe(10)
823
- expect(report.summary.failureCount).toBe(2)
824
- })
825
- ```
826
-
827
- ### 9.3 性能测试
828
-
829
- ```typescript
830
- it('should handle 1000 tool calls efficiently', async () => {
831
- const session = createMockSession({ enableSessionReport: true })
832
-
833
- const startTime = Date.now()
834
- for (let i = 0; i < 1000; i++) {
835
- recordToolCall(session, 'test_tool', 100, true, {})
836
- }
837
- const duration = Date.now() - startTime
838
-
839
- expect(duration).toBeLessThan(100) // <100ms for 1000 records
840
- expect(session.reportData.toolCalls).toHaveLength(1000)
841
- })
842
- ```
843
-
844
- ---
845
-
846
- ## 附录
847
-
848
- ### A. Markdown 示例输出
849
-
850
- ```markdown
851
- # Session Report: test-session-abc123
852
-
853
- ## Summary
854
- - **Duration**: 15m 30s
855
- - **Total Calls**: 50
856
- - **Success Rate**: 94.0% (47/50)
857
- - **Average Duration**: 1.5s
858
-
859
- ## Tool Call Statistics
860
- | Tool Name | Calls | Success | Failure | Avg Duration |
861
- |-----------|-------|---------|---------|--------------|
862
- | miniprogram_launch | 1 | 1 | 0 | 3.0s |
863
- | page_navigate | 5 | 5 | 0 | 0.8s |
864
- | element_click | 10 | 8 | 2 | 0.5s |
865
- | element_input | 8 | 8 | 0 | 0.3s |
866
- | assert_exists | 15 | 15 | 0 | 0.2s |
867
- | snapshot_page | 3 | 3 | 0 | 1.2s |
868
-
869
- ## Failures
870
- ### 1. element_click
871
- - **Time**: 2025-10-03T06:05:10.123Z
872
- - **Error**: Element not found: #submit-button
873
- - **Snapshot**: [failures/element_click-2025-10-03_06-05-10-123Z](failures/element_click-2025-10-03_06-05-10-123Z)
874
-
875
- ### 2. element_click
876
- - **Time**: 2025-10-03T06:12:45.789Z
877
- - **Error**: Element is not clickable
878
- - **Snapshot**: [failures/element_click-2025-10-03_06-12-45-789Z](failures/element_click-2025-10-03_06-12-45-789Z)
879
-
880
- ## Timeline (Last 20 Calls)
881
- | Time | Tool | Status | Duration |
882
- |------|------|--------|----------|
883
- | 06:00:05 | miniprogram_launch | ✅ | 3.0s |
884
- | 06:00:08 | page_navigate | ✅ | 0.8s |
885
- | 06:01:15 | element_input | ✅ | 0.3s |
886
- | 06:05:10 | element_click | ❌ | 0.5s |
887
- | ... | ... | ... | ... |
888
- ```
889
-
890
- ### B. 配置示例
891
-
892
- ```typescript
893
- // Enable session report
894
- const server = new Server({
895
- enableSessionReport: true, // 🆕 Generate report.json and report.md
896
- enableFailureSnapshot: true, // F2 integration
897
- logLevel: 'info',
898
- })
899
- ```
900
-
901
- ---
902
-
903
- **文档版本**: 1.0
904
- **最后更新**: 2025-10-03
905
- **作者**: ClaudeCode