ios-webkit-mcp 0.18.3
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.
- package/CONTRIBUTING.md +61 -0
- package/LICENSE +202 -0
- package/NOTICE +16 -0
- package/README.md +187 -0
- package/build/src/bin/ios-webkit-mcp.d.ts +2 -0
- package/build/src/bin/ios-webkit-mcp.js +14 -0
- package/build/src/bin/ios-webkit-mcp.js.map +1 -0
- package/build/src/capability.d.ts +61 -0
- package/build/src/capability.js +146 -0
- package/build/src/capability.js.map +1 -0
- package/build/src/index.d.ts +1 -0
- package/build/src/index.js +2 -0
- package/build/src/index.js.map +1 -0
- package/build/src/page-session.d.ts +108 -0
- package/build/src/page-session.js +331 -0
- package/build/src/page-session.js.map +1 -0
- package/build/src/server.d.ts +11 -0
- package/build/src/server.js +144 -0
- package/build/src/server.js.map +1 -0
- package/build/src/tools/analyze_performance.d.ts +40 -0
- package/build/src/tools/analyze_performance.js +112 -0
- package/build/src/tools/analyze_performance.js.map +1 -0
- package/build/src/tools/breakpoints.d.ts +80 -0
- package/build/src/tools/breakpoints.js +167 -0
- package/build/src/tools/breakpoints.js.map +1 -0
- package/build/src/tools/clear_console.d.ts +11 -0
- package/build/src/tools/clear_console.js +32 -0
- package/build/src/tools/clear_console.js.map +1 -0
- package/build/src/tools/click.d.ts +20 -0
- package/build/src/tools/click.js +88 -0
- package/build/src/tools/click.js.map +1 -0
- package/build/src/tools/debug_element.d.ts +36 -0
- package/build/src/tools/debug_element.js +66 -0
- package/build/src/tools/debug_element.js.map +1 -0
- package/build/src/tools/debugger.d.ts +44 -0
- package/build/src/tools/debugger.js +117 -0
- package/build/src/tools/debugger.js.map +1 -0
- package/build/src/tools/delete_cookie.d.ts +18 -0
- package/build/src/tools/delete_cookie.js +33 -0
- package/build/src/tools/delete_cookie.js.map +1 -0
- package/build/src/tools/drag.d.ts +40 -0
- package/build/src/tools/drag.js +202 -0
- package/build/src/tools/drag.js.map +1 -0
- package/build/src/tools/evaluate_script.d.ts +24 -0
- package/build/src/tools/evaluate_script.js +172 -0
- package/build/src/tools/evaluate_script.js.map +1 -0
- package/build/src/tools/fill.d.ts +22 -0
- package/build/src/tools/fill.js +104 -0
- package/build/src/tools/fill.js.map +1 -0
- package/build/src/tools/fill_form.d.ts +34 -0
- package/build/src/tools/fill_form.js +110 -0
- package/build/src/tools/fill_form.js.map +1 -0
- package/build/src/tools/gc_heap.d.ts +16 -0
- package/build/src/tools/gc_heap.js +66 -0
- package/build/src/tools/gc_heap.js.map +1 -0
- package/build/src/tools/get_capability_snapshot.d.ts +17 -0
- package/build/src/tools/get_capability_snapshot.js +50 -0
- package/build/src/tools/get_capability_snapshot.js.map +1 -0
- package/build/src/tools/get_console_message.d.ts +18 -0
- package/build/src/tools/get_console_message.js +92 -0
- package/build/src/tools/get_console_message.js.map +1 -0
- package/build/src/tools/get_cookies.d.ts +20 -0
- package/build/src/tools/get_cookies.js +59 -0
- package/build/src/tools/get_cookies.js.map +1 -0
- package/build/src/tools/get_event_listeners.d.ts +29 -0
- package/build/src/tools/get_event_listeners.js +129 -0
- package/build/src/tools/get_event_listeners.js.map +1 -0
- package/build/src/tools/get_network_request.d.ts +22 -0
- package/build/src/tools/get_network_request.js +121 -0
- package/build/src/tools/get_network_request.js.map +1 -0
- package/build/src/tools/get_performance_metrics.d.ts +27 -0
- package/build/src/tools/get_performance_metrics.js +185 -0
- package/build/src/tools/get_performance_metrics.js.map +1 -0
- package/build/src/tools/get_resource_tree.d.ts +18 -0
- package/build/src/tools/get_resource_tree.js +82 -0
- package/build/src/tools/get_resource_tree.js.map +1 -0
- package/build/src/tools/handle_dialog.d.ts +39 -0
- package/build/src/tools/handle_dialog.js +182 -0
- package/build/src/tools/handle_dialog.js.map +1 -0
- package/build/src/tools/highlight_node.d.ts +41 -0
- package/build/src/tools/highlight_node.js +95 -0
- package/build/src/tools/highlight_node.js.map +1 -0
- package/build/src/tools/hover.d.ts +20 -0
- package/build/src/tools/hover.js +89 -0
- package/build/src/tools/hover.js.map +1 -0
- package/build/src/tools/intercept.d.ts +81 -0
- package/build/src/tools/intercept.js +161 -0
- package/build/src/tools/intercept.js.map +1 -0
- package/build/src/tools/list_console_messages.d.ts +20 -0
- package/build/src/tools/list_console_messages.js +105 -0
- package/build/src/tools/list_console_messages.js.map +1 -0
- package/build/src/tools/list_indexeddb.d.ts +16 -0
- package/build/src/tools/list_indexeddb.js +55 -0
- package/build/src/tools/list_indexeddb.js.map +1 -0
- package/build/src/tools/list_network_requests.d.ts +25 -0
- package/build/src/tools/list_network_requests.js +108 -0
- package/build/src/tools/list_network_requests.js.map +1 -0
- package/build/src/tools/list_pages.d.ts +17 -0
- package/build/src/tools/list_pages.js +113 -0
- package/build/src/tools/list_pages.js.map +1 -0
- package/build/src/tools/navigate_page.d.ts +18 -0
- package/build/src/tools/navigate_page.js +73 -0
- package/build/src/tools/navigate_page.js.map +1 -0
- package/build/src/tools/network_runtime.d.ts +51 -0
- package/build/src/tools/network_runtime.js +101 -0
- package/build/src/tools/network_runtime.js.map +1 -0
- package/build/src/tools/press_key.d.ts +32 -0
- package/build/src/tools/press_key.js +108 -0
- package/build/src/tools/press_key.js.map +1 -0
- package/build/src/tools/query_dom_node.d.ts +22 -0
- package/build/src/tools/query_dom_node.js +103 -0
- package/build/src/tools/query_dom_node.js.map +1 -0
- package/build/src/tools/record_cpu_profile.d.ts +38 -0
- package/build/src/tools/record_cpu_profile.js +174 -0
- package/build/src/tools/record_cpu_profile.js.map +1 -0
- package/build/src/tools/record_memory_tracking.d.ts +32 -0
- package/build/src/tools/record_memory_tracking.js +103 -0
- package/build/src/tools/record_memory_tracking.js.map +1 -0
- package/build/src/tools/record_timeline.d.ts +20 -0
- package/build/src/tools/record_timeline.js +110 -0
- package/build/src/tools/record_timeline.js.map +1 -0
- package/build/src/tools/reload_page.d.ts +18 -0
- package/build/src/tools/reload_page.js +59 -0
- package/build/src/tools/reload_page.js.map +1 -0
- package/build/src/tools/select_page.d.ts +18 -0
- package/build/src/tools/select_page.js +54 -0
- package/build/src/tools/select_page.js.map +1 -0
- package/build/src/tools/set_extra_http_headers.d.ts +16 -0
- package/build/src/tools/set_extra_http_headers.js +55 -0
- package/build/src/tools/set_extra_http_headers.js.map +1 -0
- package/build/src/tools/set_init_script.d.ts +16 -0
- package/build/src/tools/set_init_script.js +43 -0
- package/build/src/tools/set_init_script.js.map +1 -0
- package/build/src/tools/set_outer_html.d.ts +18 -0
- package/build/src/tools/set_outer_html.js +52 -0
- package/build/src/tools/set_outer_html.js.map +1 -0
- package/build/src/tools/set_user_agent.d.ts +40 -0
- package/build/src/tools/set_user_agent.js +83 -0
- package/build/src/tools/set_user_agent.js.map +1 -0
- package/build/src/tools/summarize_console_errors.d.ts +40 -0
- package/build/src/tools/summarize_console_errors.js +131 -0
- package/build/src/tools/summarize_console_errors.js.map +1 -0
- package/build/src/tools/take_memory_snapshot.d.ts +18 -0
- package/build/src/tools/take_memory_snapshot.js +88 -0
- package/build/src/tools/take_memory_snapshot.js.map +1 -0
- package/build/src/tools/take_node_screenshot.d.ts +29 -0
- package/build/src/tools/take_node_screenshot.js +57 -0
- package/build/src/tools/take_node_screenshot.js.map +1 -0
- package/build/src/tools/take_screenshot.d.ts +51 -0
- package/build/src/tools/take_screenshot.js +108 -0
- package/build/src/tools/take_screenshot.js.map +1 -0
- package/build/src/tools/take_snapshot.d.ts +22 -0
- package/build/src/tools/take_snapshot.js +142 -0
- package/build/src/tools/take_snapshot.js.map +1 -0
- package/build/src/tools/type_text.d.ts +34 -0
- package/build/src/tools/type_text.js +203 -0
- package/build/src/tools/type_text.js.map +1 -0
- package/build/src/tools/wait_for.d.ts +24 -0
- package/build/src/tools/wait_for.js +93 -0
- package/build/src/tools/wait_for.js.map +1 -0
- package/build/src/tools/wip_send.d.ts +22 -0
- package/build/src/tools/wip_send.js +81 -0
- package/build/src/tools/wip_send.js.map +1 -0
- package/build/src/wip-client/iwdp-http.d.ts +17 -0
- package/build/src/wip-client/iwdp-http.js +98 -0
- package/build/src/wip-client/iwdp-http.js.map +1 -0
- package/build/src/wip-client/ws-session.d.ts +41 -0
- package/build/src/wip-client/ws-session.js +290 -0
- package/build/src/wip-client/ws-session.js.map +1 -0
- package/docs/spec.md +689 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query_dom_node.js","sourceRoot":"","sources":["../../../src/tools/query_dom_node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAOjD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE;QACX,iIAAiI;QACjI,+KAA+K;QAC/K,0JAA0J;KAC3J,CAAC,IAAI,CAAC,GAAG,CAAC;IAEX,WAAW,EAAE;QACX,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QAC9D,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;aACtB,QAAQ,EAAE;aACV,QAAQ,CAAC,4FAA4F,CAAC;QACzG,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,GAAG,CAAC;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,mDAAmD,CAAC;QAChE,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,GAAG,CAAC;aACR,GAAG,CAAC,OAAO,CAAC;aACZ,QAAQ,EAAE;aACV,QAAQ,CAAC,mDAAmD,CAAC;KACjE;IAED,OAAO,EAAE,KAAK,EAAE,EACd,QAAQ,EACR,IAAI,GAAG,OAAO,EACd,UAAU,GAAG,EAAE,EACf,aAAa,GAAG,KAAK,GACqE,EAAE,EAAE;QAC9F,IAAI,EAAe,CAAC;QACpB,IAAI,CAAC;YACH,EAAE,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,yCAAyC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7E,CAAC;QAED,IAAI,MAAc,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAe,iBAAiB,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YACzF,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;QAC3B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,2BAA2B,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,OAAO,GAAa,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAc,mBAAmB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,CAAC;gBACxG,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACnB,OAAO,UAAU,CAAC,sCAAsC,QAAQ,IAAI,CAAC,CAAC;gBACxE,CAAC;gBACD,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAe,sBAAsB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,CAAC;gBAC5G,OAAO,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,oBAAoB,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/F,CAAC;QAED,MAAM,KAAK,GAAa;YACtB,wBAAwB,QAAQ,YAAY,IAAI,GAAG;YACnD,EAAE;YACF,YAAY,OAAO,CAAC,MAAM,GAAG,IAAI,KAAK,KAAK,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,eAAe,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAClH,EAAE;SACH,CAAC;QAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;YAC3B,IAAI,IAAY,CAAC;YACjB,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAiB,kBAAkB,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC;gBACxF,IAAI,GAAG,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC;YAC3B,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,2BAA2B,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACnF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACf,SAAS;YACX,CAAC;YACD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,aAAa;gBAC3C,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,GAAG,+BAA+B,IAAI,CAAC,MAAM,GAAG;gBAC9E,CAAC,CAAC,IAAI,CAAC;YACT,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,MAAM,IAAI,CAAC,MAAM,QAAQ,CAAC,CAAC;YACpE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QAED,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC,CAAC;CACF,CAAC;AAEF,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC;AACD,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACvE,CAAC;AACD,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `record_cpu_profile` (batch-13 Must) — record an Apple WIP CPU profile.
|
|
3
|
+
*
|
|
4
|
+
* Composes WIP `CPUProfiler.startTracking` + `CPUProfiler.stopTracking` +
|
|
5
|
+
* `ScriptProfiler.startTracking(includeSamples=true)` + `ScriptProfiler.stopTracking`
|
|
6
|
+
* for `durationMs`, plus the lightweight `Runtime.evaluate` `performance.memory`
|
|
7
|
+
* delta as a coarse memory hint. Apple WIP does not return a single normalized
|
|
8
|
+
* profile blob — it streams `*.trackingUpdate` events ending with a `*.trackingComplete`
|
|
9
|
+
* payload that carries the actual samples.
|
|
10
|
+
*
|
|
11
|
+
* Probe-confirmed (capability matrix v2, 2026-05-17):
|
|
12
|
+
* - CPUProfiler.startTracking / stopTracking ✅
|
|
13
|
+
* - ScriptProfiler.startTracking({includeSamples:true}) / stopTracking ✅
|
|
14
|
+
*
|
|
15
|
+
* The output summarizes hottest call sites by sample count + samples/total
|
|
16
|
+
* ratio. We don't ship a full v8-style flamegraph yet (Apple's sample format
|
|
17
|
+
* is union-typed); batch-14 will compose with `analyze_performance`.
|
|
18
|
+
*/
|
|
19
|
+
import { z } from 'zod';
|
|
20
|
+
export declare const recordCpuProfileTool: {
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
inputSchema: {
|
|
24
|
+
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
25
|
+
topN: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
includeAnonymous: z.ZodOptional<z.ZodBoolean>;
|
|
27
|
+
};
|
|
28
|
+
handler: ({ durationMs, topN, includeAnonymous, }: {
|
|
29
|
+
durationMs?: number;
|
|
30
|
+
topN?: number;
|
|
31
|
+
includeAnonymous?: boolean;
|
|
32
|
+
}) => Promise<{
|
|
33
|
+
content: {
|
|
34
|
+
type: "text";
|
|
35
|
+
text: string;
|
|
36
|
+
}[];
|
|
37
|
+
}>;
|
|
38
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `record_cpu_profile` (batch-13 Must) — record an Apple WIP CPU profile.
|
|
3
|
+
*
|
|
4
|
+
* Composes WIP `CPUProfiler.startTracking` + `CPUProfiler.stopTracking` +
|
|
5
|
+
* `ScriptProfiler.startTracking(includeSamples=true)` + `ScriptProfiler.stopTracking`
|
|
6
|
+
* for `durationMs`, plus the lightweight `Runtime.evaluate` `performance.memory`
|
|
7
|
+
* delta as a coarse memory hint. Apple WIP does not return a single normalized
|
|
8
|
+
* profile blob — it streams `*.trackingUpdate` events ending with a `*.trackingComplete`
|
|
9
|
+
* payload that carries the actual samples.
|
|
10
|
+
*
|
|
11
|
+
* Probe-confirmed (capability matrix v2, 2026-05-17):
|
|
12
|
+
* - CPUProfiler.startTracking / stopTracking ✅
|
|
13
|
+
* - ScriptProfiler.startTracking({includeSamples:true}) / stopTracking ✅
|
|
14
|
+
*
|
|
15
|
+
* The output summarizes hottest call sites by sample count + samples/total
|
|
16
|
+
* ratio. We don't ship a full v8-style flamegraph yet (Apple's sample format
|
|
17
|
+
* is union-typed); batch-14 will compose with `analyze_performance`.
|
|
18
|
+
*/
|
|
19
|
+
import { z } from 'zod';
|
|
20
|
+
import { PageSession } from '../page-session.js';
|
|
21
|
+
export const recordCpuProfileTool = {
|
|
22
|
+
name: 'record_cpu_profile',
|
|
23
|
+
description: [
|
|
24
|
+
'Record a CPU profile for a fixed duration on the inspected iOS WebView page using Apple WIP `CPUProfiler.startTracking` + `ScriptProfiler.startTracking({includeSamples:true})` (✅ probe 2026-05-17).',
|
|
25
|
+
'WIP does NOT expose CDP `Profiler.takePreciseCoverage` — instead samples stream as `ScriptProfiler.trackingUpdate` events. The tool subscribes, runs for `durationMs`, then aggregates samples into hottest call-frame summary.',
|
|
26
|
+
'Pair with `record_timeline` for cross-axis timing breakdown (timeline = wall-clock events; cpu profile = stack-sampled hot paths).',
|
|
27
|
+
].join(' '),
|
|
28
|
+
inputSchema: {
|
|
29
|
+
durationMs: z
|
|
30
|
+
.number()
|
|
31
|
+
.int()
|
|
32
|
+
.min(200)
|
|
33
|
+
.max(60_000)
|
|
34
|
+
.optional()
|
|
35
|
+
.describe('How long to record (default 3000).'),
|
|
36
|
+
topN: z
|
|
37
|
+
.number()
|
|
38
|
+
.int()
|
|
39
|
+
.min(1)
|
|
40
|
+
.max(200)
|
|
41
|
+
.optional()
|
|
42
|
+
.describe('Top-N hottest call frames returned (default 20).'),
|
|
43
|
+
includeAnonymous: z
|
|
44
|
+
.boolean()
|
|
45
|
+
.optional()
|
|
46
|
+
.describe('Include frames with empty functionName (anonymous closures). Default true.'),
|
|
47
|
+
},
|
|
48
|
+
handler: async ({ durationMs = 3_000, topN = 20, includeAnonymous = true, }) => {
|
|
49
|
+
let ps;
|
|
50
|
+
try {
|
|
51
|
+
ps = await PageSession.get();
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
return errorResult(`Unable to attach: ${describe(e)}`);
|
|
55
|
+
}
|
|
56
|
+
const samples = [];
|
|
57
|
+
const unsubscribers = [];
|
|
58
|
+
unsubscribers.push(ps.session.on('ScriptProfiler.trackingUpdate', (p) => {
|
|
59
|
+
const params = p;
|
|
60
|
+
const stacks = params?.event?.samples?.stackTraces ?? params?.samples;
|
|
61
|
+
if (Array.isArray(stacks))
|
|
62
|
+
for (const s of stacks)
|
|
63
|
+
samples.push(s);
|
|
64
|
+
}));
|
|
65
|
+
unsubscribers.push(ps.session.on('ScriptProfiler.trackingComplete', (p) => {
|
|
66
|
+
const params = p;
|
|
67
|
+
const stacks = params?.samples ?? params?.event?.samples?.stackTraces;
|
|
68
|
+
if (Array.isArray(stacks))
|
|
69
|
+
for (const s of stacks)
|
|
70
|
+
samples.push(s);
|
|
71
|
+
}));
|
|
72
|
+
let memBefore;
|
|
73
|
+
try {
|
|
74
|
+
const r = await ps.session.send('Runtime.evaluate', { expression: '({jsHeapSizeUsed: performance.memory?.usedJSHeapSize, jsHeapSizeLimit: performance.memory?.jsHeapSizeLimit})', returnByValue: true }, 5_000);
|
|
75
|
+
memBefore = r.result?.value;
|
|
76
|
+
}
|
|
77
|
+
catch { /* not all WebKits expose performance.memory */ }
|
|
78
|
+
try {
|
|
79
|
+
await ps.session.send('CPUProfiler.startTracking', undefined, 5_000);
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
unsubscribers.forEach(u => u());
|
|
83
|
+
return errorResult(`CPUProfiler.startTracking failed: ${describe(e)}`);
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
await ps.session.send('ScriptProfiler.startTracking', { includeSamples: true }, 5_000);
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
try {
|
|
90
|
+
await ps.session.send('CPUProfiler.stopTracking', undefined, 5_000);
|
|
91
|
+
}
|
|
92
|
+
catch { /* best-effort */ }
|
|
93
|
+
unsubscribers.forEach(u => u());
|
|
94
|
+
return errorResult(`ScriptProfiler.startTracking failed: ${describe(e)}`);
|
|
95
|
+
}
|
|
96
|
+
await new Promise(r => setTimeout(r, durationMs));
|
|
97
|
+
try {
|
|
98
|
+
await ps.session.send('ScriptProfiler.stopTracking', undefined, 10_000);
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
unsubscribers.forEach(u => u());
|
|
102
|
+
return errorResult(`ScriptProfiler.stopTracking failed: ${describe(e)}`);
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
await ps.session.send('CPUProfiler.stopTracking', undefined, 10_000);
|
|
106
|
+
}
|
|
107
|
+
catch { /* best-effort tail */ }
|
|
108
|
+
// Allow tail trackingComplete events to drain.
|
|
109
|
+
await new Promise(r => setTimeout(r, 200));
|
|
110
|
+
unsubscribers.forEach(u => u());
|
|
111
|
+
let memAfter;
|
|
112
|
+
try {
|
|
113
|
+
const r = await ps.session.send('Runtime.evaluate', { expression: '({jsHeapSizeUsed: performance.memory?.usedJSHeapSize, jsHeapSizeLimit: performance.memory?.jsHeapSizeLimit})', returnByValue: true }, 5_000);
|
|
114
|
+
memAfter = r.result?.value;
|
|
115
|
+
}
|
|
116
|
+
catch { /* skip */ }
|
|
117
|
+
// Aggregate frames.
|
|
118
|
+
const frameCount = new Map();
|
|
119
|
+
for (const sample of samples) {
|
|
120
|
+
const top = sample.stackTrace?.callFrames?.[0];
|
|
121
|
+
if (!top)
|
|
122
|
+
continue;
|
|
123
|
+
const key = `${top.functionName ?? '<anon>'} ${top.url ?? ''}:${top.lineNumber ?? '?'}`;
|
|
124
|
+
if (!includeAnonymous && (!top.functionName || top.functionName === ''))
|
|
125
|
+
continue;
|
|
126
|
+
const cur = frameCount.get(key) ?? { count: 0, topSample: top };
|
|
127
|
+
cur.count += 1;
|
|
128
|
+
frameCount.set(key, cur);
|
|
129
|
+
}
|
|
130
|
+
const totalSamples = samples.length;
|
|
131
|
+
const top = [...frameCount.entries()]
|
|
132
|
+
.sort((a, b) => b[1].count - a[1].count)
|
|
133
|
+
.slice(0, topN);
|
|
134
|
+
const lines = [
|
|
135
|
+
`# record_cpu_profile ✓ ${durationMs}ms`,
|
|
136
|
+
'',
|
|
137
|
+
`Samples captured: ${totalSamples}`,
|
|
138
|
+
`Unique top-of-stack frames: ${frameCount.size}`,
|
|
139
|
+
];
|
|
140
|
+
if (memBefore && memAfter && typeof memBefore.jsHeapSizeUsed === 'number' && typeof memAfter.jsHeapSizeUsed === 'number') {
|
|
141
|
+
const delta = memAfter.jsHeapSizeUsed - memBefore.jsHeapSizeUsed;
|
|
142
|
+
lines.push(`JS heap delta: ${(delta / 1024 / 1024).toFixed(2)} MB (${memBefore.jsHeapSizeUsed} → ${memAfter.jsHeapSizeUsed} bytes)`);
|
|
143
|
+
}
|
|
144
|
+
if (totalSamples === 0) {
|
|
145
|
+
lines.push('');
|
|
146
|
+
lines.push('⚠ No samples captured. Possible causes:');
|
|
147
|
+
lines.push('- Page idle during recording — interact with it (scroll / tap) and re-record.');
|
|
148
|
+
lines.push('- ScriptProfiler.trackingUpdate event schema differs on this iOS build — file a probe issue.');
|
|
149
|
+
lines.push('- includeSamples=true unsupported (rare, capability matrix says ✅).');
|
|
150
|
+
}
|
|
151
|
+
else if (top.length > 0) {
|
|
152
|
+
lines.push('');
|
|
153
|
+
lines.push(`## Top ${top.length} hottest frames`);
|
|
154
|
+
lines.push('| samples | % | function | source |');
|
|
155
|
+
lines.push('|---|---|---|---|');
|
|
156
|
+
for (const [key, { count, topSample }] of top) {
|
|
157
|
+
const pct = ((count / totalSamples) * 100).toFixed(1);
|
|
158
|
+
const fn = topSample?.functionName || '<anonymous>';
|
|
159
|
+
const src = topSample?.url
|
|
160
|
+
? `${topSample.url}:${topSample.lineNumber ?? '?'}:${topSample.columnNumber ?? '?'}`
|
|
161
|
+
: '(no source)';
|
|
162
|
+
lines.push(`| ${count} | ${pct}% | \`${fn}\` | ${src.replace(/\|/g, '\\|')} |`);
|
|
163
|
+
void key;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
lines.push('');
|
|
167
|
+
lines.push('⚠ Apple WIP CPU sample format is union-typed across iOS builds. If samples look empty or mis-attributed, set `WDM_WS_DEBUG=1` to dump raw `ScriptProfiler.trackingUpdate` payloads to stderr for schema inspection.');
|
|
168
|
+
return textResult(lines.join('\n'));
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
function textResult(text) { return { content: [{ type: 'text', text }] }; }
|
|
172
|
+
function errorResult(text) { return { content: [{ type: 'text', text }], isError: true }; }
|
|
173
|
+
function describe(e) { return e instanceof Error ? e.message : String(e); }
|
|
174
|
+
//# sourceMappingURL=record_cpu_profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record_cpu_profile.js","sourceRoot":"","sources":["../../../src/tools/record_cpu_profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `record_memory_tracking` (batch-14, soft-promoted from "推到 batch-14 nice")
|
|
3
|
+
*
|
|
4
|
+
* Pairs with `record_cpu_profile` to form the "性能三件套路线图" foundation
|
|
5
|
+
* (cross-review v2.0.1 codex). Different signal:
|
|
6
|
+
* - `record_cpu_profile` → who (which JS function) is hot
|
|
7
|
+
* - `record_memory_tracking` → what (jsHeap / images / layers) is using memory
|
|
8
|
+
* - `record_timeline` → when (frame events) on the wall clock
|
|
9
|
+
*
|
|
10
|
+
* WIP: `Memory.startTracking` + `Memory.stopTracking` + `Memory.trackingUpdate`
|
|
11
|
+
* events (probe-confirmed 2026-05-17).
|
|
12
|
+
*
|
|
13
|
+
* Apple's `Memory.trackingUpdate` payload contains a `categories` array
|
|
14
|
+
* carrying per-bucket sizes (JavaScript / Images / Layers / Page / Other).
|
|
15
|
+
* We sample the latest per category, then return delta vs initial sample.
|
|
16
|
+
*/
|
|
17
|
+
import { z } from 'zod';
|
|
18
|
+
export declare const recordMemoryTrackingTool: {
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
inputSchema: {
|
|
22
|
+
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
23
|
+
};
|
|
24
|
+
handler: ({ durationMs }: {
|
|
25
|
+
durationMs?: number;
|
|
26
|
+
}) => Promise<{
|
|
27
|
+
content: {
|
|
28
|
+
type: "text";
|
|
29
|
+
text: string;
|
|
30
|
+
}[];
|
|
31
|
+
}>;
|
|
32
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `record_memory_tracking` (batch-14, soft-promoted from "推到 batch-14 nice")
|
|
3
|
+
*
|
|
4
|
+
* Pairs with `record_cpu_profile` to form the "性能三件套路线图" foundation
|
|
5
|
+
* (cross-review v2.0.1 codex). Different signal:
|
|
6
|
+
* - `record_cpu_profile` → who (which JS function) is hot
|
|
7
|
+
* - `record_memory_tracking` → what (jsHeap / images / layers) is using memory
|
|
8
|
+
* - `record_timeline` → when (frame events) on the wall clock
|
|
9
|
+
*
|
|
10
|
+
* WIP: `Memory.startTracking` + `Memory.stopTracking` + `Memory.trackingUpdate`
|
|
11
|
+
* events (probe-confirmed 2026-05-17).
|
|
12
|
+
*
|
|
13
|
+
* Apple's `Memory.trackingUpdate` payload contains a `categories` array
|
|
14
|
+
* carrying per-bucket sizes (JavaScript / Images / Layers / Page / Other).
|
|
15
|
+
* We sample the latest per category, then return delta vs initial sample.
|
|
16
|
+
*/
|
|
17
|
+
import { z } from 'zod';
|
|
18
|
+
import { PageSession } from '../page-session.js';
|
|
19
|
+
export const recordMemoryTrackingTool = {
|
|
20
|
+
name: 'record_memory_tracking',
|
|
21
|
+
description: [
|
|
22
|
+
'Record an Apple WIP Memory tracking sample for a fixed duration on the inspected iOS WebView page.',
|
|
23
|
+
'Subscribes to `Memory.trackingUpdate` events between `Memory.startTracking` and `Memory.stopTracking` (probe-confirmed 2026-05-17).',
|
|
24
|
+
'Returns per-category memory size delta (JavaScript / Images / Layers / Page / Other) so the AI can answer "which bucket grew during this interaction?".',
|
|
25
|
+
'Pair with `record_cpu_profile` (hot functions) and `record_timeline` (frame events) for the performance三件套.',
|
|
26
|
+
].join(' '),
|
|
27
|
+
inputSchema: {
|
|
28
|
+
durationMs: z
|
|
29
|
+
.number()
|
|
30
|
+
.int()
|
|
31
|
+
.min(200)
|
|
32
|
+
.max(60_000)
|
|
33
|
+
.optional()
|
|
34
|
+
.describe('How long to track (default 3000).'),
|
|
35
|
+
},
|
|
36
|
+
handler: async ({ durationMs = 3_000 }) => {
|
|
37
|
+
let ps;
|
|
38
|
+
try {
|
|
39
|
+
ps = await PageSession.get();
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
return errorResult(`Unable to attach: ${describe(e)}`);
|
|
43
|
+
}
|
|
44
|
+
const samples = [];
|
|
45
|
+
const unsubscribers = [];
|
|
46
|
+
unsubscribers.push(ps.session.on('Memory.trackingUpdate', (p) => {
|
|
47
|
+
const params = p;
|
|
48
|
+
const evt = params?.event ?? params?.sample ?? params;
|
|
49
|
+
if (evt && Array.isArray(evt.categories))
|
|
50
|
+
samples.push(evt);
|
|
51
|
+
}));
|
|
52
|
+
unsubscribers.push(ps.session.on('Memory.trackingComplete', () => { }));
|
|
53
|
+
try {
|
|
54
|
+
await ps.session.send('Memory.startTracking', undefined, 5_000);
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
unsubscribers.forEach(u => u());
|
|
58
|
+
return errorResult(`Memory.startTracking failed: ${describe(e)}`);
|
|
59
|
+
}
|
|
60
|
+
await new Promise(r => setTimeout(r, durationMs));
|
|
61
|
+
try {
|
|
62
|
+
await ps.session.send('Memory.stopTracking', undefined, 10_000);
|
|
63
|
+
}
|
|
64
|
+
catch { /* best-effort */ }
|
|
65
|
+
await new Promise(r => setTimeout(r, 200)); // let trackingComplete drain
|
|
66
|
+
unsubscribers.forEach(u => u());
|
|
67
|
+
if (samples.length === 0) {
|
|
68
|
+
return textResult(`# record_memory_tracking ✓ ${durationMs}ms\n\n` +
|
|
69
|
+
'No `Memory.trackingUpdate` events received. The page may have produced no allocation deltas during the window — interact with it (scroll / load images / open detail view) and re-record. Schema may also differ on this iOS build; set WDM_WS_DEBUG=1 to see raw event payloads.');
|
|
70
|
+
}
|
|
71
|
+
const first = samples[0];
|
|
72
|
+
const last = samples[samples.length - 1];
|
|
73
|
+
const lookup = (s, type) => s.categories?.find(c => c.type === type)?.size ?? 0;
|
|
74
|
+
const cats = new Set();
|
|
75
|
+
for (const s of samples)
|
|
76
|
+
for (const c of s.categories ?? [])
|
|
77
|
+
if (c.type)
|
|
78
|
+
cats.add(c.type);
|
|
79
|
+
const lines = [
|
|
80
|
+
`# record_memory_tracking ✓ ${durationMs}ms`,
|
|
81
|
+
'',
|
|
82
|
+
`Samples: ${samples.length}`,
|
|
83
|
+
`First @ ${first.timestamp ?? 'unknown'} → Last @ ${last.timestamp ?? 'unknown'}`,
|
|
84
|
+
'',
|
|
85
|
+
'| category | first (MB) | last (MB) | delta (MB) | delta % |',
|
|
86
|
+
'|---|---|---|---|---|',
|
|
87
|
+
];
|
|
88
|
+
for (const t of [...cats].sort()) {
|
|
89
|
+
const a = lookup(first, t);
|
|
90
|
+
const b = lookup(last, t);
|
|
91
|
+
const delta = b - a;
|
|
92
|
+
const pct = a > 0 ? `${((delta / a) * 100).toFixed(1)}%` : '—';
|
|
93
|
+
lines.push(`| ${t} | ${(a / 1024 / 1024).toFixed(2)} | ${(b / 1024 / 1024).toFixed(2)} | ${(delta / 1024 / 1024).toFixed(2)} | ${pct} |`);
|
|
94
|
+
}
|
|
95
|
+
lines.push('');
|
|
96
|
+
lines.push('⚠ Apple WIP `Memory.trackingUpdate` event schema is union-typed across iOS builds. If categories look empty or mis-attributed, dump raw with WDM_WS_DEBUG=1 and file a probe.');
|
|
97
|
+
return textResult(lines.join('\n'));
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
function textResult(text) { return { content: [{ type: 'text', text }] }; }
|
|
101
|
+
function errorResult(text) { return { content: [{ type: 'text', text }], isError: true }; }
|
|
102
|
+
function describe(e) { return e instanceof Error ? e.message : String(e); }
|
|
103
|
+
//# sourceMappingURL=record_memory_tracking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record_memory_tracking.js","sourceRoot":"","sources":["../../../src/tools/record_memory_tracking.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const recordTimelineTool: {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
topN: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
eventTypeFilter: z.ZodOptional<z.ZodString>;
|
|
9
|
+
};
|
|
10
|
+
handler: ({ durationMs, topN, eventTypeFilter, }: {
|
|
11
|
+
durationMs?: number;
|
|
12
|
+
topN?: number;
|
|
13
|
+
eventTypeFilter?: string;
|
|
14
|
+
}) => Promise<{
|
|
15
|
+
content: {
|
|
16
|
+
type: "text";
|
|
17
|
+
text: string;
|
|
18
|
+
}[];
|
|
19
|
+
}>;
|
|
20
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PageSession } from '../page-session.js';
|
|
3
|
+
export const recordTimelineTool = {
|
|
4
|
+
name: 'record_timeline',
|
|
5
|
+
description: [
|
|
6
|
+
'Record an Apple WIP Timeline trace for a fixed duration on the inspected iOS WebView page.',
|
|
7
|
+
'WIP exposes `Timeline.start` / `Timeline.stop` + `Timeline.eventRecorded` events (probe-confirmed 2026-05-16). This is the Apple equivalent of CDP `Tracing.*` — captures rendering / scripting / layout / paint events while the timeline is active.',
|
|
8
|
+
'The tool subscribes to events, calls `Timeline.start`, waits `durationMs`, then `Timeline.stop` and returns aggregated event counts + top-N hottest entries by duration.',
|
|
9
|
+
].join(' '),
|
|
10
|
+
inputSchema: {
|
|
11
|
+
durationMs: z
|
|
12
|
+
.number()
|
|
13
|
+
.int()
|
|
14
|
+
.min(100)
|
|
15
|
+
.max(60_000)
|
|
16
|
+
.optional()
|
|
17
|
+
.describe('How long to record (default 3000).'),
|
|
18
|
+
topN: z
|
|
19
|
+
.number()
|
|
20
|
+
.int()
|
|
21
|
+
.min(1)
|
|
22
|
+
.max(200)
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Top-N hottest events (by duration) returned (default 20).'),
|
|
25
|
+
eventTypeFilter: z
|
|
26
|
+
.string()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Case-insensitive substring filter on event type (e.g. "script", "layout", "paint").'),
|
|
29
|
+
},
|
|
30
|
+
handler: async ({ durationMs = 3_000, topN = 20, eventTypeFilter, }) => {
|
|
31
|
+
let ps;
|
|
32
|
+
try {
|
|
33
|
+
ps = await PageSession.get();
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
return errorResult(`Unable to attach: ${describe(e)}`);
|
|
37
|
+
}
|
|
38
|
+
const events = [];
|
|
39
|
+
const unsubscribe = ps.session.on('Timeline.eventRecorded', (p) => {
|
|
40
|
+
const params = p;
|
|
41
|
+
if (params?.record)
|
|
42
|
+
events.push(params.record);
|
|
43
|
+
});
|
|
44
|
+
try {
|
|
45
|
+
await ps.session.send('Timeline.start', undefined, 10_000);
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
unsubscribe();
|
|
49
|
+
return errorResult(`Timeline.start failed: ${describe(e)}`);
|
|
50
|
+
}
|
|
51
|
+
await new Promise(r => setTimeout(r, durationMs));
|
|
52
|
+
try {
|
|
53
|
+
await ps.session.send('Timeline.stop', undefined, 10_000);
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
unsubscribe();
|
|
57
|
+
return errorResult(`Timeline.stop failed: ${describe(e)}`);
|
|
58
|
+
}
|
|
59
|
+
// Allow tail events to drain.
|
|
60
|
+
await new Promise(r => setTimeout(r, 100));
|
|
61
|
+
unsubscribe();
|
|
62
|
+
let kept = events;
|
|
63
|
+
if (eventTypeFilter) {
|
|
64
|
+
const n = eventTypeFilter.toLowerCase();
|
|
65
|
+
kept = kept.filter(e => (e.type || '').toLowerCase().includes(n));
|
|
66
|
+
}
|
|
67
|
+
const byType = new Map();
|
|
68
|
+
for (const e of kept)
|
|
69
|
+
byType.set(e.type, (byType.get(e.type) ?? 0) + 1);
|
|
70
|
+
const typeRows = [...byType.entries()].sort((a, b) => b[1] - a[1]);
|
|
71
|
+
const withDuration = kept
|
|
72
|
+
.filter(e => typeof e.startTime === 'number' && typeof e.endTime === 'number')
|
|
73
|
+
.map(e => ({ ...e, _dur: e.endTime - e.startTime }))
|
|
74
|
+
.sort((a, b) => b._dur - a._dur)
|
|
75
|
+
.slice(0, topN);
|
|
76
|
+
const lines = [
|
|
77
|
+
`# record_timeline ✓ ${durationMs}ms recorded`,
|
|
78
|
+
'',
|
|
79
|
+
`Total events: ${events.length}${eventTypeFilter ? ` (${kept.length} after filter "${eventTypeFilter}")` : ''}`,
|
|
80
|
+
'',
|
|
81
|
+
];
|
|
82
|
+
if (typeRows.length > 0) {
|
|
83
|
+
lines.push('## events by type');
|
|
84
|
+
typeRows.slice(0, 30).forEach(([t, n]) => lines.push(`- ${t}: ${n}`));
|
|
85
|
+
if (typeRows.length > 30)
|
|
86
|
+
lines.push(`- … ${typeRows.length - 30} more types`);
|
|
87
|
+
}
|
|
88
|
+
if (withDuration.length > 0) {
|
|
89
|
+
lines.push('');
|
|
90
|
+
lines.push(`## top ${withDuration.length} hottest events`);
|
|
91
|
+
lines.push('| dur (ms) | type | startTime | data |');
|
|
92
|
+
lines.push('|---|---|---|---|');
|
|
93
|
+
for (const e of withDuration) {
|
|
94
|
+
const data = e.data ? JSON.stringify(e.data).slice(0, 80) : '';
|
|
95
|
+
lines.push(`| ${e._dur.toFixed(2)} | ${e.type} | ${e.startTime.toFixed(2)} | ${data.replace(/\|/g, '\\|')} |`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else if (kept.length > 0) {
|
|
99
|
+
lines.push('');
|
|
100
|
+
lines.push('(no events with start/end timestamps for hottest ranking)');
|
|
101
|
+
}
|
|
102
|
+
lines.push('');
|
|
103
|
+
lines.push('⚠ Apple WIP `Timeline` semantically maps to CDP `Tracing` but the event schema differs. Common types: `RenderingFrame` / `ScheduleStyleRecalculation` / `Paint` / `Layout` / `EvaluateScript` / `FunctionCall` / `TimerFire`.');
|
|
104
|
+
return textResult(lines.join('\n'));
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
function textResult(text) { return { content: [{ type: 'text', text }] }; }
|
|
108
|
+
function errorResult(text) { return { content: [{ type: 'text', text }], isError: true }; }
|
|
109
|
+
function describe(e) { return e instanceof Error ? e.message : String(e); }
|
|
110
|
+
//# sourceMappingURL=record_timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record_timeline.js","sourceRoot":"","sources":["../../../src/tools/record_timeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const reloadPageTool: {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
ignoreCache: z.ZodOptional<z.ZodBoolean>;
|
|
7
|
+
waitAfterMs: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
};
|
|
9
|
+
handler: ({ ignoreCache, waitAfterMs, }: {
|
|
10
|
+
ignoreCache?: boolean;
|
|
11
|
+
waitAfterMs?: number;
|
|
12
|
+
}) => Promise<{
|
|
13
|
+
content: {
|
|
14
|
+
type: "text";
|
|
15
|
+
text: string;
|
|
16
|
+
}[];
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PageSession } from '../page-session.js';
|
|
3
|
+
export const reloadPageTool = {
|
|
4
|
+
name: 'reload_page',
|
|
5
|
+
description: [
|
|
6
|
+
'Reload the inspected iOS WebView page via WIP `Page.reload`.',
|
|
7
|
+
'`Page.reload` is one of the few `Page.*` methods present on WIP (verified 2026-05-16 probe). Cache mode is honored by WebKit.',
|
|
8
|
+
'Side effect: console + network buffers are NOT cleared automatically (they\'re per-attach not per-navigation). Call `select_page` to do that explicitly.',
|
|
9
|
+
].join(' '),
|
|
10
|
+
inputSchema: {
|
|
11
|
+
ignoreCache: z
|
|
12
|
+
.boolean()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe('Bypass cache (equivalent to hard reload). Default false.'),
|
|
15
|
+
waitAfterMs: z
|
|
16
|
+
.number()
|
|
17
|
+
.int()
|
|
18
|
+
.min(0)
|
|
19
|
+
.max(60_000)
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Block after issuing reload for this long (default 500). Use `wait_for` for stronger sync to a specific selector.'),
|
|
22
|
+
},
|
|
23
|
+
handler: async ({ ignoreCache = false, waitAfterMs = 500, }) => {
|
|
24
|
+
let ps;
|
|
25
|
+
try {
|
|
26
|
+
ps = await PageSession.get();
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
return errorResult(`Unable to attach to a WKWebView page: ${describe(e)}`);
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
await ps.session.send('Page.reload', { ignoreCache }, 10_000);
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
return errorResult(`Page.reload failed: ${describe(e)}`);
|
|
36
|
+
}
|
|
37
|
+
if (waitAfterMs > 0) {
|
|
38
|
+
await new Promise(r => setTimeout(r, waitAfterMs));
|
|
39
|
+
}
|
|
40
|
+
return textResult([
|
|
41
|
+
`# reload_page ✓`,
|
|
42
|
+
'',
|
|
43
|
+
`ignoreCache: ${ignoreCache}`,
|
|
44
|
+
`Waited ${waitAfterMs}ms after issuing reload.`,
|
|
45
|
+
'',
|
|
46
|
+
'⚠ Console/Network buffers retain pre-reload entries. Use `select_page` (same pageId) to reattach + reset, or filter by timestamp on the next read.',
|
|
47
|
+
].join('\n'));
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
function textResult(text) {
|
|
51
|
+
return { content: [{ type: 'text', text }] };
|
|
52
|
+
}
|
|
53
|
+
function errorResult(text) {
|
|
54
|
+
return { content: [{ type: 'text', text }], isError: true };
|
|
55
|
+
}
|
|
56
|
+
function describe(e) {
|
|
57
|
+
return e instanceof Error ? e.message : String(e);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=reload_page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reload_page.js","sourceRoot":"","sources":["../../../src/tools/reload_page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE;QACX,8DAA8D;QAC9D,+HAA+H;QAC/H,0JAA0J;KAC3J,CAAC,IAAI,CAAC,GAAG,CAAC;IAEX,WAAW,EAAE;QACX,WAAW,EAAE,CAAC;aACX,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,0DAA0D,CAAC;QACvE,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,MAAM,CAAC;aACX,QAAQ,EAAE;aACV,QAAQ,CAAC,kHAAkH,CAAC;KAChI;IAED,OAAO,EAAE,KAAK,EAAE,EACd,WAAW,GAAG,KAAK,EACnB,WAAW,GAAG,GAAG,GAC+B,EAAE,EAAE;QACpD,IAAI,EAAe,CAAC;QACpB,IAAI,CAAC;YACH,EAAE,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,yCAAyC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7E,CAAC;QAED,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,uBAAuB,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,UAAU,CACf;YACE,iBAAiB;YACjB,EAAE;YACF,gBAAgB,WAAW,EAAE;YAC7B,UAAU,WAAW,0BAA0B;YAC/C,EAAE;YACF,oJAAoJ;SACrJ,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC;AACD,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACvE,CAAC;AACD,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const selectPageTool: {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
pageId: z.ZodString;
|
|
7
|
+
proxyDeviceListUrl: z.ZodOptional<z.ZodString>;
|
|
8
|
+
};
|
|
9
|
+
handler: ({ pageId, proxyDeviceListUrl, }: {
|
|
10
|
+
pageId: string;
|
|
11
|
+
proxyDeviceListUrl?: string;
|
|
12
|
+
}) => Promise<{
|
|
13
|
+
content: {
|
|
14
|
+
type: "text";
|
|
15
|
+
text: string;
|
|
16
|
+
}[];
|
|
17
|
+
}>;
|
|
18
|
+
};
|