flutter-devtools-mcp 0.3.1

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 (130) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +208 -0
  3. package/README.zh-CN.md +292 -0
  4. package/dist/index.d.ts +3 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +55 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/services/ai-analysis.d.ts +6 -0
  9. package/dist/services/ai-analysis.d.ts.map +1 -0
  10. package/dist/services/ai-analysis.js +728 -0
  11. package/dist/services/ai-analysis.js.map +1 -0
  12. package/dist/services/collect-progress.d.ts +6 -0
  13. package/dist/services/collect-progress.d.ts.map +1 -0
  14. package/dist/services/collect-progress.js +23 -0
  15. package/dist/services/collect-progress.js.map +1 -0
  16. package/dist/services/cpu-profiler-service.d.ts +42 -0
  17. package/dist/services/cpu-profiler-service.d.ts.map +1 -0
  18. package/dist/services/cpu-profiler-service.js +208 -0
  19. package/dist/services/cpu-profiler-service.js.map +1 -0
  20. package/dist/services/cpu-symbol-filter.d.ts +10 -0
  21. package/dist/services/cpu-symbol-filter.d.ts.map +1 -0
  22. package/dist/services/cpu-symbol-filter.js +90 -0
  23. package/dist/services/cpu-symbol-filter.js.map +1 -0
  24. package/dist/services/http-profile-parser.d.ts +4 -0
  25. package/dist/services/http-profile-parser.d.ts.map +1 -0
  26. package/dist/services/http-profile-parser.js +71 -0
  27. package/dist/services/http-profile-parser.js.map +1 -0
  28. package/dist/services/json-parse-aggregate.d.ts +30 -0
  29. package/dist/services/json-parse-aggregate.d.ts.map +1 -0
  30. package/dist/services/json-parse-aggregate.js +155 -0
  31. package/dist/services/json-parse-aggregate.js.map +1 -0
  32. package/dist/services/network-aggregate.d.ts +50 -0
  33. package/dist/services/network-aggregate.d.ts.map +1 -0
  34. package/dist/services/network-aggregate.js +185 -0
  35. package/dist/services/network-aggregate.js.map +1 -0
  36. package/dist/services/network-capture-service.d.ts +50 -0
  37. package/dist/services/network-capture-service.d.ts.map +1 -0
  38. package/dist/services/network-capture-service.js +187 -0
  39. package/dist/services/network-capture-service.js.map +1 -0
  40. package/dist/services/network-capture.d.ts +2 -0
  41. package/dist/services/network-capture.d.ts.map +1 -0
  42. package/dist/services/network-capture.js +2 -0
  43. package/dist/services/network-capture.js.map +1 -0
  44. package/dist/services/performance-session.d.ts +41 -0
  45. package/dist/services/performance-session.d.ts.map +1 -0
  46. package/dist/services/performance-session.js +697 -0
  47. package/dist/services/performance-session.js.map +1 -0
  48. package/dist/services/performance-thresholds.d.ts +17 -0
  49. package/dist/services/performance-thresholds.d.ts.map +1 -0
  50. package/dist/services/performance-thresholds.js +19 -0
  51. package/dist/services/performance-thresholds.js.map +1 -0
  52. package/dist/services/profiler.d.ts +71 -0
  53. package/dist/services/profiler.d.ts.map +1 -0
  54. package/dist/services/profiler.js +314 -0
  55. package/dist/services/profiler.js.map +1 -0
  56. package/dist/services/rebuild-business-resolver.d.ts +24 -0
  57. package/dist/services/rebuild-business-resolver.d.ts.map +1 -0
  58. package/dist/services/rebuild-business-resolver.js +599 -0
  59. package/dist/services/rebuild-business-resolver.js.map +1 -0
  60. package/dist/services/rebuild-tracker-service.d.ts +45 -0
  61. package/dist/services/rebuild-tracker-service.d.ts.map +1 -0
  62. package/dist/services/rebuild-tracker-service.js +196 -0
  63. package/dist/services/rebuild-tracker-service.js.map +1 -0
  64. package/dist/services/session-types.d.ts +240 -0
  65. package/dist/services/session-types.d.ts.map +1 -0
  66. package/dist/services/session-types.js +180 -0
  67. package/dist/services/session-types.js.map +1 -0
  68. package/dist/services/threshold-alerts.d.ts +49 -0
  69. package/dist/services/threshold-alerts.d.ts.map +1 -0
  70. package/dist/services/threshold-alerts.js +258 -0
  71. package/dist/services/threshold-alerts.js.map +1 -0
  72. package/dist/services/timeline-cpu-parser.d.ts +28 -0
  73. package/dist/services/timeline-cpu-parser.d.ts.map +1 -0
  74. package/dist/services/timeline-cpu-parser.js +174 -0
  75. package/dist/services/timeline-cpu-parser.js.map +1 -0
  76. package/dist/services/timeline-extras.d.ts +61 -0
  77. package/dist/services/timeline-extras.d.ts.map +1 -0
  78. package/dist/services/timeline-extras.js +449 -0
  79. package/dist/services/timeline-extras.js.map +1 -0
  80. package/dist/services/vm-service-client.d.ts +123 -0
  81. package/dist/services/vm-service-client.d.ts.map +1 -0
  82. package/dist/services/vm-service-client.js +418 -0
  83. package/dist/services/vm-service-client.js.map +1 -0
  84. package/dist/tools/connection.d.ts +4 -0
  85. package/dist/tools/connection.d.ts.map +1 -0
  86. package/dist/tools/connection.js +127 -0
  87. package/dist/tools/connection.js.map +1 -0
  88. package/dist/tools/debug-actions.d.ts +4 -0
  89. package/dist/tools/debug-actions.d.ts.map +1 -0
  90. package/dist/tools/debug-actions.js +210 -0
  91. package/dist/tools/debug-actions.js.map +1 -0
  92. package/dist/tools/discover.d.ts +4 -0
  93. package/dist/tools/discover.d.ts.map +1 -0
  94. package/dist/tools/discover.js +183 -0
  95. package/dist/tools/discover.js.map +1 -0
  96. package/dist/tools/memory.d.ts +4 -0
  97. package/dist/tools/memory.d.ts.map +1 -0
  98. package/dist/tools/memory.js +145 -0
  99. package/dist/tools/memory.js.map +1 -0
  100. package/dist/tools/network.d.ts +4 -0
  101. package/dist/tools/network.d.ts.map +1 -0
  102. package/dist/tools/network.js +265 -0
  103. package/dist/tools/network.js.map +1 -0
  104. package/dist/tools/performance-session.d.ts +4 -0
  105. package/dist/tools/performance-session.d.ts.map +1 -0
  106. package/dist/tools/performance-session.js +105 -0
  107. package/dist/tools/performance-session.js.map +1 -0
  108. package/dist/tools/profiling.d.ts +5 -0
  109. package/dist/tools/profiling.d.ts.map +1 -0
  110. package/dist/tools/profiling.js +142 -0
  111. package/dist/tools/profiling.js.map +1 -0
  112. package/dist/tools/rebuild-tracker.d.ts +4 -0
  113. package/dist/tools/rebuild-tracker.d.ts.map +1 -0
  114. package/dist/tools/rebuild-tracker.js +228 -0
  115. package/dist/tools/rebuild-tracker.js.map +1 -0
  116. package/dist/tools/snapshot-diff.d.ts +4 -0
  117. package/dist/tools/snapshot-diff.d.ts.map +1 -0
  118. package/dist/tools/snapshot-diff.js +235 -0
  119. package/dist/tools/snapshot-diff.js.map +1 -0
  120. package/dist/tools/widget-tree.d.ts +4 -0
  121. package/dist/tools/widget-tree.d.ts.map +1 -0
  122. package/dist/tools/widget-tree.js +156 -0
  123. package/dist/tools/widget-tree.js.map +1 -0
  124. package/docs/README.md +9 -0
  125. package/docs/performance-audit-requirements.md +403 -0
  126. package/docs/performance-metrics-guide.md +207 -0
  127. package/docs/performance-session-simple-design.md +399 -0
  128. package/examples/app_network_image.dart +242 -0
  129. package/examples/app_network_image_README.md +51 -0
  130. package/package.json +69 -0
@@ -0,0 +1,49 @@
1
+ import type { NetworkRequestRecord } from "./network-capture-service.js";
2
+ import type { PerformanceSessionResult } from "./session-types.js";
3
+ import { type PerformanceThresholdConfig } from "./performance-thresholds.js";
4
+ import { formatBytesKb, type ParsePathStat } from "./json-parse-aggregate.js";
5
+ export interface LargeImageAlert {
6
+ url: string;
7
+ path: string;
8
+ bytes?: number;
9
+ width?: number;
10
+ height?: number;
11
+ decodeMs?: number;
12
+ httpMs?: number;
13
+ /** 命中哪些阈值,如「体积≥200KB」「解码≥16ms」 */
14
+ triggers: string[];
15
+ source: "timeline" | "http" | "both";
16
+ }
17
+ export interface LargeApiAlert {
18
+ method?: string;
19
+ path: string;
20
+ count: number;
21
+ bytes?: number;
22
+ avgBytes?: number;
23
+ avgParseMs: number;
24
+ totalParseMs: number;
25
+ triggers: string[];
26
+ parseSource?: ParsePathStat["source"];
27
+ }
28
+ export interface ThresholdAlerts {
29
+ config: PerformanceThresholdConfig;
30
+ summary: {
31
+ largeImageHits: number;
32
+ slowDecodeHits: number;
33
+ largeApiHits: number;
34
+ slowParseHits: number;
35
+ };
36
+ largeImages: LargeImageAlert[];
37
+ largeApis: LargeApiAlert[];
38
+ }
39
+ export declare function buildThresholdAlerts(input: {
40
+ requests?: NetworkRequestRecord[];
41
+ imageDecode?: PerformanceSessionResult["imageDecode"];
42
+ parsePaths?: ParsePathStat[];
43
+ dioWorkerCpuMs?: number;
44
+ config?: PerformanceThresholdConfig;
45
+ }): ThresholdAlerts;
46
+ /** 旧 JSON:用 slow / topPaths / topParsePaths / imageDecode 还原超阈值项 */
47
+ export declare function deriveThresholdAlertsFromLegacy(result: PerformanceSessionResult, config?: PerformanceThresholdConfig): ThresholdAlerts;
48
+ export { formatBytesKb };
49
+ //# sourceMappingURL=threshold-alerts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threshold-alerts.d.ts","sourceRoot":"","sources":["../../src/services/threshold-alerts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAGL,aAAa,EAEb,KAAK,aAAa,EACnB,MAAM,2BAA2B,CAAC;AAGnC,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;CACtC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,0BAA0B,CAAC;IACnC,OAAO,EAAE;QACP,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAwDD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,QAAQ,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAClC,WAAW,CAAC,EAAE,wBAAwB,CAAC,aAAa,CAAC,CAAC;IACtD,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,0BAA0B,CAAC;CACrC,GAAG,eAAe,CAiKlB;AAMD,oEAAoE;AACpE,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,wBAAwB,EAChC,MAAM,CAAC,EAAE,0BAA0B,GAClC,eAAe,CA+EjB;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,258 @@
1
+ import { DEFAULT_PERFORMANCE_THRESHOLDS, } from "./performance-thresholds.js";
2
+ import { aggregateParseCostByPath, deriveParseTopFromLegacy, formatBytesKb, isMediaOrStaticAssetUri, } from "./json-parse-aggregate.js";
3
+ import { extractUrlPath } from "./network-aggregate.js";
4
+ function shortUrlPath(uri) {
5
+ try {
6
+ const u = new URL(uri);
7
+ const p = u.pathname + (u.search || "");
8
+ return p.length > 72 ? `${p.slice(0, 69)}...` : p;
9
+ }
10
+ catch {
11
+ return uri.length > 72 ? `${uri.slice(0, 69)}...` : uri;
12
+ }
13
+ }
14
+ function isImageRequest(r) {
15
+ return isMediaOrStaticAssetUri(r.uri);
16
+ }
17
+ function triggerLargeImageBytes(bytes, cfg) {
18
+ if (bytes != null && bytes >= cfg.largeImageBytes) {
19
+ return `体积≥${Math.round(cfg.largeImageBytes / 1024)}KB`;
20
+ }
21
+ return undefined;
22
+ }
23
+ function triggerSlowDecode(ms, cfg) {
24
+ if (ms != null && ms >= cfg.slowImageDecodeMs) {
25
+ return `解码≥${cfg.slowImageDecodeMs}ms`;
26
+ }
27
+ return undefined;
28
+ }
29
+ function triggerLargeApiBytes(bytes, cfg) {
30
+ if (bytes != null && bytes >= cfg.largeApiBytes) {
31
+ return `体积≥${Math.round(cfg.largeApiBytes / 1024)}KB`;
32
+ }
33
+ return undefined;
34
+ }
35
+ function triggerSlowParse(ms, cfg) {
36
+ if (ms != null && ms >= cfg.slowApiParseMs) {
37
+ return `解析≥${cfg.slowApiParseMs}ms`;
38
+ }
39
+ return undefined;
40
+ }
41
+ export function buildThresholdAlerts(input) {
42
+ const cfg = input.config ?? DEFAULT_PERFORMANCE_THRESHOLDS;
43
+ const requests = input.requests ?? [];
44
+ const parsePaths = input.parsePaths ??
45
+ aggregateParseCostByPath(requests, input.dioWorkerCpuMs ?? 0);
46
+ const imageByUrl = new Map();
47
+ for (const r of requests) {
48
+ if (!isImageRequest(r))
49
+ continue;
50
+ const httpMs = r.endTime != null && r.startTime != null
51
+ ? r.endTime - r.startTime
52
+ : undefined;
53
+ const triggers = [];
54
+ const tSize = triggerLargeImageBytes(r.responseSize, cfg);
55
+ if (tSize)
56
+ triggers.push(tSize);
57
+ if (triggers.length === 0)
58
+ continue;
59
+ const url = r.uri;
60
+ const existing = imageByUrl.get(url);
61
+ const item = {
62
+ url,
63
+ path: shortUrlPath(url),
64
+ bytes: r.responseSize ?? existing?.bytes,
65
+ decodeMs: existing?.decodeMs,
66
+ httpMs: httpMs ?? existing?.httpMs,
67
+ width: existing?.width,
68
+ height: existing?.height,
69
+ triggers: [...new Set([...(existing?.triggers ?? []), ...triggers])],
70
+ source: existing?.source === "timeline" ? "both" : "http",
71
+ };
72
+ imageByUrl.set(url, item);
73
+ }
74
+ for (const s of input.imageDecode?.slow ?? []) {
75
+ if (!s.url && s.ms <= 0)
76
+ continue;
77
+ const url = s.url ?? `timeline:${s.name}`;
78
+ const existing = imageByUrl.get(url);
79
+ const triggers = [...(existing?.triggers ?? [])];
80
+ const tDecode = triggerSlowDecode(s.ms, cfg);
81
+ if (tDecode)
82
+ triggers.push(tDecode);
83
+ const tSize = triggerLargeImageBytes(s.bytes, cfg);
84
+ if (tSize)
85
+ triggers.push(tSize);
86
+ if (triggers.length === 0 && s.ms < cfg.slowImageDecodeMs)
87
+ continue;
88
+ const mergedTriggers = triggers.length > 0
89
+ ? [...new Set(triggers)]
90
+ : [triggerSlowDecode(s.ms, cfg)].filter(Boolean);
91
+ imageByUrl.set(url, {
92
+ url: s.url ?? url,
93
+ path: s.url ? shortUrlPath(s.url) : s.name,
94
+ bytes: s.bytes ?? existing?.bytes,
95
+ width: s.width ?? existing?.width,
96
+ height: s.height ?? existing?.height,
97
+ decodeMs: s.ms,
98
+ httpMs: existing?.httpMs,
99
+ triggers: mergedTriggers,
100
+ source: existing?.source === "http" ? "both" : "timeline",
101
+ });
102
+ }
103
+ const largeImages = [...imageByUrl.values()]
104
+ .filter((i) => i.triggers.length > 0)
105
+ .sort((a, b) => (b.decodeMs ?? 0) - (a.decodeMs ?? 0) ||
106
+ (b.bytes ?? 0) - (a.bytes ?? 0) ||
107
+ (b.httpMs ?? 0) - (a.httpMs ?? 0))
108
+ .slice(0, 10);
109
+ const apiByPath = new Map();
110
+ for (const p of parsePaths) {
111
+ const avgBytes = p.totalBytes != null && p.count > 0
112
+ ? Math.round(p.totalBytes / p.count)
113
+ : undefined;
114
+ const triggers = [];
115
+ const tParse = triggerSlowParse(p.avgParseMs, cfg);
116
+ if (tParse)
117
+ triggers.push(tParse);
118
+ const tSize = triggerLargeApiBytes(avgBytes, cfg);
119
+ if (tSize)
120
+ triggers.push(tSize);
121
+ const tTotal = triggerLargeApiBytes(p.totalBytes, cfg);
122
+ if (tTotal && !triggers.includes(tTotal))
123
+ triggers.push(tTotal);
124
+ if (triggers.length === 0)
125
+ continue;
126
+ apiByPath.set(p.path, {
127
+ method: p.method,
128
+ path: p.path,
129
+ count: p.count,
130
+ bytes: p.totalBytes,
131
+ avgBytes,
132
+ avgParseMs: p.avgParseMs,
133
+ totalParseMs: p.totalParseMs,
134
+ triggers,
135
+ parseSource: p.source,
136
+ });
137
+ }
138
+ for (const r of requests) {
139
+ if (isImageRequest(r))
140
+ continue;
141
+ if (!isLikelyApiUri(r.uri))
142
+ continue;
143
+ const path = extractUrlPath(r.uri);
144
+ if (apiByPath.has(path))
145
+ continue;
146
+ const triggers = [];
147
+ const tSize = triggerLargeApiBytes(r.responseSize, cfg);
148
+ if (tSize)
149
+ triggers.push(tSize);
150
+ if (triggers.length === 0)
151
+ continue;
152
+ apiByPath.set(path, {
153
+ method: r.method,
154
+ path,
155
+ count: 1,
156
+ bytes: r.responseSize,
157
+ avgBytes: r.responseSize,
158
+ avgParseMs: 0,
159
+ totalParseMs: 0,
160
+ triggers,
161
+ });
162
+ }
163
+ const largeApis = [...apiByPath.values()]
164
+ .sort((a, b) => b.totalParseMs - a.totalParseMs ||
165
+ (b.avgBytes ?? 0) - (a.avgBytes ?? 0) ||
166
+ b.count - a.count)
167
+ .slice(0, 10);
168
+ const largeImageHits = largeImages.filter((i) => i.triggers.some((t) => t.startsWith("体积"))).length;
169
+ const slowDecodeHits = largeImages.filter((i) => i.triggers.some((t) => t.startsWith("解码"))).length;
170
+ const largeApiHits = largeApis.filter((i) => i.triggers.some((t) => t.startsWith("体积"))).length;
171
+ const slowParseHits = largeApis.filter((i) => i.triggers.some((t) => t.startsWith("解析"))).length;
172
+ return {
173
+ config: cfg,
174
+ summary: {
175
+ largeImageHits,
176
+ slowDecodeHits,
177
+ largeApiHits,
178
+ slowParseHits,
179
+ },
180
+ largeImages,
181
+ largeApis,
182
+ };
183
+ }
184
+ function isLikelyApiUri(uri) {
185
+ return uri.startsWith("http") && !isMediaOrStaticAssetUri(uri);
186
+ }
187
+ /** 旧 JSON:用 slow / topPaths / topParsePaths / imageDecode 还原超阈值项 */
188
+ export function deriveThresholdAlertsFromLegacy(result, config) {
189
+ const cfg = config ?? DEFAULT_PERFORMANCE_THRESHOLDS;
190
+ const parsePaths = result.network.topParsePaths ??
191
+ deriveParseTopFromLegacy({
192
+ topPaths: result.network.topPaths,
193
+ dioWorkerCpuMs: result.dioJsonDecode?.totalWorkerCpuMs,
194
+ });
195
+ const pseudoRequests = [];
196
+ for (const s of result.network.slow ?? []) {
197
+ if (!isMediaOrStaticAssetUri(s.url))
198
+ continue;
199
+ pseudoRequests.push({
200
+ id: s.url,
201
+ method: s.method,
202
+ uri: s.url,
203
+ startTime: 0,
204
+ endTime: s.ms,
205
+ responseSize: undefined,
206
+ });
207
+ }
208
+ for (const p of result.network.topPaths ?? []) {
209
+ if (isMediaOrStaticAssetUri(p.path)) {
210
+ pseudoRequests.push({
211
+ id: p.path,
212
+ method: p.method ?? "GET",
213
+ uri: `https://local${p.path}`,
214
+ startTime: 0,
215
+ responseSize: p.totalBytes,
216
+ });
217
+ }
218
+ }
219
+ const alerts = buildThresholdAlerts({
220
+ requests: pseudoRequests,
221
+ imageDecode: result.imageDecode,
222
+ parsePaths,
223
+ dioWorkerCpuMs: result.dioJsonDecode?.totalWorkerCpuMs,
224
+ config: cfg,
225
+ });
226
+ // slow 图片无 content-length 时:HTTP 极慢也视为「大/慢图片」检测命中
227
+ for (const s of result.network.slow ?? []) {
228
+ if (!isMediaOrStaticAssetUri(s.url))
229
+ continue;
230
+ if (alerts.largeImages.some((i) => i.url === s.url))
231
+ continue;
232
+ if (s.ms < 3000)
233
+ continue;
234
+ let path = s.url;
235
+ try {
236
+ path = shortUrlPath(s.url);
237
+ }
238
+ catch {
239
+ /* keep */
240
+ }
241
+ alerts.largeImages.push({
242
+ url: s.url,
243
+ path,
244
+ httpMs: s.ms,
245
+ triggers: [`HTTP≥3000ms(未测体积,疑似大图/慢网)`],
246
+ source: "http",
247
+ });
248
+ }
249
+ alerts.largeImages.sort((a, b) => (b.decodeMs ?? 0) - (a.decodeMs ?? 0) ||
250
+ (b.httpMs ?? 0) - (a.httpMs ?? 0) ||
251
+ (b.bytes ?? 0) - (a.bytes ?? 0));
252
+ alerts.largeImages.splice(10);
253
+ alerts.summary.largeImageHits = alerts.largeImages.filter((i) => i.triggers.some((t) => t.startsWith("体积") || t.startsWith("HTTP"))).length;
254
+ alerts.summary.slowDecodeHits = alerts.largeImages.filter((i) => i.triggers.some((t) => t.startsWith("解码"))).length;
255
+ return alerts;
256
+ }
257
+ export { formatBytesKb };
258
+ //# sourceMappingURL=threshold-alerts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threshold-alerts.js","sourceRoot":"","sources":["../../src/services/threshold-alerts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { TimelineEvent } from "./vm-service-client.js";
2
+ import { type Severity } from "./session-types.js";
3
+ export interface TimelineCpuEntry {
4
+ name: string;
5
+ file: string;
6
+ selfMs: number;
7
+ pct: number;
8
+ severity: Severity;
9
+ source: "timeline-dart" | "timeline-hotspot";
10
+ }
11
+ /** 从 Timeline 的 Dart build/布局等事件提取带源码路径的 CPU 热点(debug 模式回退) */
12
+ export declare function parseDartTimelineCpu(events: TimelineEvent[], topN: number): TimelineCpuEntry[];
13
+ /** 从 Profiler 聚合热点回退(无文件信息) */
14
+ export declare function parseProfilerHotspots(hotspots: Array<{
15
+ name: string;
16
+ category: string;
17
+ totalDurationMs: number;
18
+ }>, topN: number): TimelineCpuEntry[];
19
+ /** 用 Build/Layout/Paint 阶段统计合成 CPU 条目(最后回退) */
20
+ export declare function parsePhaseCpuFallback(phase: {
21
+ buildCount: number;
22
+ totalBuildTimeMs: number;
23
+ layoutCount: number;
24
+ totalLayoutTimeMs: number;
25
+ paintCount: number;
26
+ totalPaintTimeMs: number;
27
+ }): TimelineCpuEntry[];
28
+ //# sourceMappingURL=timeline-cpu-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-cpu-parser.d.ts","sourceRoot":"","sources":["../../src/services/timeline-cpu-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAIL,KAAK,QAAQ,EACd,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,eAAe,GAAG,kBAAkB,CAAC;CAC9C;AAkFD,+DAA+D;AAC/D,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EAAE,EACvB,IAAI,EAAE,MAAM,GACX,gBAAgB,EAAE,CAyEpB;AAED,+BAA+B;AAC/B,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,KAAK,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC,EACF,IAAI,EAAE,MAAM,GACX,gBAAgB,EAAE,CA+BpB;AAED,+CAA+C;AAC/C,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,GAAG,gBAAgB,EAAE,CAgBrB"}
@@ -0,0 +1,174 @@
1
+ import { isProjectSourceFile, normalizeSourceFile, severityFromPct, } from "./session-types.js";
2
+ const SKIP_EVENT_NAMES = new Set([
3
+ "Frame",
4
+ "Vsync",
5
+ "Animator::BeginFrame",
6
+ "GPURasterizer::Draw",
7
+ ]);
8
+ function readEventLocation(event) {
9
+ const args = event.args ?? {};
10
+ const nested = args.event ?? args;
11
+ const name = nested.name ??
12
+ nested.function ??
13
+ args.name ??
14
+ event.name;
15
+ const file = nested.uri ??
16
+ nested.file ??
17
+ args.uri ??
18
+ args.file ??
19
+ "";
20
+ return { name, file };
21
+ }
22
+ function collectTimedEvents(events) {
23
+ const timed = [];
24
+ for (const event of events) {
25
+ if (event.ph === "X" && event.dur && event.dur > 0) {
26
+ timed.push({
27
+ name: event.name,
28
+ cat: event.cat,
29
+ durUs: event.dur,
30
+ args: event.args,
31
+ });
32
+ }
33
+ }
34
+ // dart:developer Timeline.timeSync 常见为 B/E 对,而非 complete(X)
35
+ const begins = new Map();
36
+ for (const event of events) {
37
+ if (event.ph !== "B")
38
+ continue;
39
+ const key = `${event.name}|${event.pid ?? ""}|${event.tid ?? ""}`;
40
+ const list = begins.get(key) ?? [];
41
+ list.push(event);
42
+ begins.set(key, list);
43
+ }
44
+ for (const event of events) {
45
+ if (event.ph !== "E")
46
+ continue;
47
+ const key = `${event.name}|${event.pid ?? ""}|${event.tid ?? ""}`;
48
+ const list = begins.get(key);
49
+ if (!list?.length)
50
+ continue;
51
+ const begin = list.shift();
52
+ const durUs = event.ts - begin.ts;
53
+ if (durUs > 0) {
54
+ timed.push({
55
+ name: event.name,
56
+ cat: event.cat ?? begin.cat,
57
+ durUs,
58
+ args: event.args ?? begin.args,
59
+ });
60
+ }
61
+ }
62
+ return timed;
63
+ }
64
+ /** 从 Timeline 的 Dart build/布局等事件提取带源码路径的 CPU 热点(debug 模式回退) */
65
+ export function parseDartTimelineCpu(events, topN) {
66
+ const buckets = new Map();
67
+ for (const event of collectTimedEvents(events)) {
68
+ if (SKIP_EVENT_NAMES.has(event.name))
69
+ continue;
70
+ const cat = (event.cat ?? "").toLowerCase();
71
+ const isDart = cat.includes("dart") || cat.includes("flutter");
72
+ const lowerName = event.name.toLowerCase();
73
+ const isBuildPhase = lowerName.includes("build") ||
74
+ lowerName.includes("layout") ||
75
+ lowerName.includes("paint") ||
76
+ lowerName.includes("rebuild");
77
+ const isBusinessNamed = lowerName.includes("business") ||
78
+ lowerName.includes("hotmethod") ||
79
+ lowerName.includes("homepage") ||
80
+ lowerName.includes("ordercard");
81
+ const selfMs = event.durUs / 1000;
82
+ if (selfMs < 0.05 && !isBuildPhase && !isBusinessNamed)
83
+ continue;
84
+ if (!isDart && !isBuildPhase && !isBusinessNamed && selfMs < 1)
85
+ continue;
86
+ const { name, file } = readEventLocation({
87
+ name: event.name,
88
+ cat: event.cat,
89
+ ph: "X",
90
+ ts: 0,
91
+ dur: event.durUs,
92
+ args: event.args,
93
+ });
94
+ const normalizedFile = file ? normalizeSourceFile(file) : "";
95
+ if (normalizedFile && !isProjectSourceFile(normalizedFile) && !isBusinessNamed) {
96
+ continue;
97
+ }
98
+ const displayName = name || event.name;
99
+ const displayFile = normalizedFile && isProjectSourceFile(normalizedFile)
100
+ ? normalizedFile
101
+ : isBusinessNamed
102
+ ? "lib/main.dart"
103
+ : normalizedFile || "lib/main.dart";
104
+ const key = `${displayFile}::${displayName}`;
105
+ const prev = buckets.get(key);
106
+ if (prev) {
107
+ prev.selfMs += selfMs;
108
+ }
109
+ else {
110
+ buckets.set(key, {
111
+ name: displayName,
112
+ file: displayFile,
113
+ selfMs,
114
+ });
115
+ }
116
+ }
117
+ const entries = [...buckets.values()].sort((a, b) => b.selfMs - a.selfMs);
118
+ const total = entries.reduce((s, e) => s + e.selfMs, 0) || 1;
119
+ return entries.slice(0, topN).map((e) => {
120
+ const pct = (e.selfMs / total) * 100;
121
+ return {
122
+ name: e.name,
123
+ file: e.file,
124
+ selfMs: Math.round(e.selfMs * 10) / 10,
125
+ pct: Math.round(pct * 10) / 10,
126
+ severity: severityFromPct(pct),
127
+ source: "timeline-dart",
128
+ };
129
+ });
130
+ }
131
+ /** 从 Profiler 聚合热点回退(无文件信息) */
132
+ export function parseProfilerHotspots(hotspots, topN) {
133
+ const filtered = hotspots
134
+ .filter((h) => h.totalDurationMs > 0.5 &&
135
+ !SKIP_EVENT_NAMES.has(h.name) &&
136
+ !h.name.startsWith("_"))
137
+ .sort((a, b) => b.totalDurationMs - a.totalDurationMs);
138
+ const total = filtered.reduce((s, h) => s + h.totalDurationMs, 0) || 1;
139
+ return filtered.slice(0, topN).map((h) => {
140
+ const pct = (h.totalDurationMs / total) * 100;
141
+ const file = h.name.toLowerCase().includes("build") ||
142
+ h.name.toLowerCase().includes("layout")
143
+ ? "lib/main.dart"
144
+ : h.category.toLowerCase().includes("dart")
145
+ ? "lib/main.dart"
146
+ : "lib/main.dart";
147
+ return {
148
+ name: h.name,
149
+ file,
150
+ selfMs: Math.round(h.totalDurationMs * 10) / 10,
151
+ pct: Math.round(pct * 10) / 10,
152
+ severity: severityFromPct(pct),
153
+ source: "timeline-hotspot",
154
+ };
155
+ });
156
+ }
157
+ /** 用 Build/Layout/Paint 阶段统计合成 CPU 条目(最后回退) */
158
+ export function parsePhaseCpuFallback(phase) {
159
+ const items = [
160
+ { name: "Build", ms: phase.totalBuildTimeMs, count: phase.buildCount },
161
+ { name: "Layout", ms: phase.totalLayoutTimeMs, count: phase.layoutCount },
162
+ { name: "Paint", ms: phase.totalPaintTimeMs, count: phase.paintCount },
163
+ ].filter((i) => i.ms > 0);
164
+ const total = items.reduce((s, i) => s + i.ms, 0) || 1;
165
+ return items.map((i) => ({
166
+ name: `${i.name} (phase aggregate)`,
167
+ file: "lib/main.dart",
168
+ selfMs: Math.round(i.ms * 10) / 10,
169
+ pct: Math.round((i.ms / total) * 1000) / 10,
170
+ severity: severityFromPct((i.ms / total) * 100),
171
+ source: "timeline-hotspot",
172
+ }));
173
+ }
174
+ //# sourceMappingURL=timeline-cpu-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-cpu-parser.js","sourceRoot":"","sources":["../../src/services/timeline-cpu-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import type { TimelineEvent } from "./vm-service-client.js";
2
+ export interface GcPauseEntry {
3
+ name: string;
4
+ ms: number;
5
+ }
6
+ export interface GcStats {
7
+ count: number;
8
+ totalPauseMs: number;
9
+ maxPauseMs: number;
10
+ avgPauseMs: number;
11
+ /** 与掉帧可能相关的长停顿(>8ms)次数 */
12
+ longPauseCount: number;
13
+ /** 最长停顿 Top5(按 ms 降序) */
14
+ topPauses: GcPauseEntry[];
15
+ }
16
+ export interface ImageDecodeEntry {
17
+ name: string;
18
+ ms: number;
19
+ /** 图片 URL(来自 Timeline arguments) */
20
+ url?: string;
21
+ width?: number;
22
+ height?: number;
23
+ /** 原始字节数 */
24
+ bytes?: number;
25
+ }
26
+ export interface ImageDecodeStats {
27
+ count: number;
28
+ totalMs: number;
29
+ maxMs: number;
30
+ slow: ImageDecodeEntry[];
31
+ /** 检测到解码信号但无有效时长(常见于跨 await 的 B/E 丢失) */
32
+ untimedSignals?: number;
33
+ }
34
+ export interface ScrollFpsSegment {
35
+ /** 段起始(相对采集起点,秒) */
36
+ startSec: number;
37
+ endSec: number;
38
+ frames: number;
39
+ fps: number;
40
+ jankCount: number;
41
+ jankPct: number;
42
+ avgMs: number;
43
+ maxMs: number;
44
+ }
45
+ /** 从 Timeline 提取帧耗时序列(ms)及时间戳(micros) */
46
+ export declare function extractFrameTimings(events: TimelineEvent[]): Array<{
47
+ ts: number;
48
+ ms: number;
49
+ }>;
50
+ export declare function parseGcStats(events: TimelineEvent[]): GcStats;
51
+ export declare function parseImageDecodeStats(events: TimelineEvent[], slowThresholdMs?: number): ImageDecodeStats;
52
+ /** 供报告展示:慢解码一行文案 */
53
+ export declare function formatSlowImageDecodeLine(e: ImageDecodeEntry): string;
54
+ /**
55
+ * 将帧序列按固定窗口切成滚动/交互段,计算每段 FPS 与 jank。
56
+ * @param windowSec 窗口秒数,默认 2s
57
+ */
58
+ export declare function parseScrollFpsSegments(events: TimelineEvent[], targetFps: number, windowSec?: number): ScrollFpsSegment[];
59
+ /** 找出 jank 最严重的若干段,供摘要展示 */
60
+ export declare function pickWorstScrollSegments(segments: ScrollFpsSegment[], topN?: number): ScrollFpsSegment[];
61
+ //# sourceMappingURL=timeline-extras.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-extras.d.ts","sourceRoot":"","sources":["../../src/services/timeline-extras.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG5D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,0BAA0B;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,yBAAyB;IACzB,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,oCAAoC;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,gBAAgB,EAAE,CAAC;IACzB,yCAAyC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,oBAAoB;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AA8ED,yCAAyC;AACzC,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EAAE,GACtB,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CA0FnC;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAyD7D;AA2DD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,aAAa,EAAE,EACvB,eAAe,SAAK,GACnB,gBAAgB,CAsIlB;AAED,oBAAoB;AACpB,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAKrE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,aAAa,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,SAAS,SAAI,GACZ,gBAAgB,EAAE,CAuCpB;AAED,4BAA4B;AAC5B,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,gBAAgB,EAAE,EAC5B,IAAI,SAAI,GACP,gBAAgB,EAAE,CAKpB"}