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,203 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PageSession } from '../page-session.js';
|
|
3
|
+
/**
|
|
4
|
+
* WIP gotcha: `Runtime.evaluate` with `awaitPromise:true` does NOT correctly
|
|
5
|
+
* serialize the resolved value of a returned Promise — even `Promise.resolve(42)`
|
|
6
|
+
* comes back as `{}`. So this tool MUST keep the inner expression synchronous.
|
|
7
|
+
* Per-char delay is implemented by issuing one Runtime.evaluate per character
|
|
8
|
+
* from TS land when `delayMs > 0`. When `delayMs === 0`, a single sync IIFE
|
|
9
|
+
* types the whole string in one round-trip.
|
|
10
|
+
*/
|
|
11
|
+
export const typeTextTool = {
|
|
12
|
+
name: 'type_text',
|
|
13
|
+
description: [
|
|
14
|
+
'Type text into the currently focused element (or a selector-targeted one) character-by-character on the inspected iOS WebView page.',
|
|
15
|
+
'NOTE: WIP has no `Input.dispatchKeyEvent`. Each character is simulated via `dispatchEvent(new KeyboardEvent(...))` for `keydown` + `keypress` + `keyup`, with the input value updated and an `input` event between keys. Listeners that read `event.isTrusted` will see `false`; IME / composition events are NOT replayed.',
|
|
16
|
+
'If `selector` is omitted, types into `document.activeElement`. Pass `clearFirst:true` to wipe the field before typing.',
|
|
17
|
+
].join(' '),
|
|
18
|
+
inputSchema: {
|
|
19
|
+
text: z.string().min(1).describe('Text to type, one character at a time.'),
|
|
20
|
+
selector: z
|
|
21
|
+
.string()
|
|
22
|
+
.min(1)
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Optional CSS selector to focus before typing. If omitted uses document.activeElement.'),
|
|
25
|
+
nth: z
|
|
26
|
+
.number()
|
|
27
|
+
.int()
|
|
28
|
+
.min(0)
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('When the selector matches multiple, pick the Nth (0-indexed). Default 0.'),
|
|
31
|
+
clearFirst: z
|
|
32
|
+
.boolean()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe('Clear the field via value setter before typing. Default false.'),
|
|
35
|
+
delayMs: z
|
|
36
|
+
.number()
|
|
37
|
+
.int()
|
|
38
|
+
.min(0)
|
|
39
|
+
.max(500)
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('Delay between characters (default 0). Use small values like 10–30 to mimic human cadence.'),
|
|
42
|
+
waitAfterMs: z
|
|
43
|
+
.number()
|
|
44
|
+
.int()
|
|
45
|
+
.min(0)
|
|
46
|
+
.max(10_000)
|
|
47
|
+
.optional()
|
|
48
|
+
.describe('Block after typing for this long (default 100).'),
|
|
49
|
+
},
|
|
50
|
+
handler: async ({ text, selector, nth = 0, clearFirst = false, delayMs = 0, waitAfterMs = 100, }) => {
|
|
51
|
+
let ps;
|
|
52
|
+
try {
|
|
53
|
+
ps = await PageSession.get();
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
return errorResult(`Unable to attach to a WKWebView page: ${describe(e)}`);
|
|
57
|
+
}
|
|
58
|
+
const selJson = selector !== undefined ? JSON.stringify(selector) : 'null';
|
|
59
|
+
const prelude = `
|
|
60
|
+
(() => {
|
|
61
|
+
let el = null;
|
|
62
|
+
if (${selJson} !== null) {
|
|
63
|
+
const matches = document.querySelectorAll(${selJson});
|
|
64
|
+
if (matches.length === 0) return { ok: false, reason: 'no_match', selector: ${selJson} };
|
|
65
|
+
if (${nth} >= matches.length) return { ok: false, reason: 'nth_out_of_range', found: matches.length };
|
|
66
|
+
el = matches[${nth}];
|
|
67
|
+
} else {
|
|
68
|
+
el = document.activeElement;
|
|
69
|
+
if (!el || el === document.body) return { ok: false, reason: 'no_active_element' };
|
|
70
|
+
}
|
|
71
|
+
const tag = el.tagName.toLowerCase();
|
|
72
|
+
const isInput = tag === 'input' || tag === 'textarea';
|
|
73
|
+
const isCE = el.isContentEditable === true;
|
|
74
|
+
if (!isInput && !isCE) return { ok: false, reason: 'not_typable', tag };
|
|
75
|
+
try { el.focus(); } catch (e) {}
|
|
76
|
+
window.__wdm_type_target = el;
|
|
77
|
+
window.__wdm_type_mode = isInput ? 'input' : 'ce';
|
|
78
|
+
if (${clearFirst}) {
|
|
79
|
+
if (isInput) {
|
|
80
|
+
const proto = tag === 'input' ? HTMLInputElement.prototype : HTMLTextAreaElement.prototype;
|
|
81
|
+
const setter = Object.getOwnPropertyDescriptor(proto, 'value') && Object.getOwnPropertyDescriptor(proto, 'value').set;
|
|
82
|
+
if (setter) setter.call(el, ''); else el.value = '';
|
|
83
|
+
} else {
|
|
84
|
+
el.textContent = '';
|
|
85
|
+
}
|
|
86
|
+
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
87
|
+
}
|
|
88
|
+
return { ok: true, tag, mode: isInput ? 'input-keystroke' : 'contenteditable-keystroke' };
|
|
89
|
+
})()
|
|
90
|
+
`;
|
|
91
|
+
let pre;
|
|
92
|
+
try {
|
|
93
|
+
pre = await ps.session.send('Runtime.evaluate', { expression: prelude, returnByValue: true, awaitPromise: false }, 10_000);
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
return errorResult(`Runtime.evaluate (type_text prelude) failed: ${describe(e)}`);
|
|
97
|
+
}
|
|
98
|
+
const preVal = pre?.result?.value;
|
|
99
|
+
if (!preVal || preVal.ok !== true) {
|
|
100
|
+
return errorResult(`# type_text: failed at prelude\n\n${JSON.stringify(preVal)}`);
|
|
101
|
+
}
|
|
102
|
+
const fastSync = `
|
|
103
|
+
(() => {
|
|
104
|
+
const el = window.__wdm_type_target;
|
|
105
|
+
const isInput = window.__wdm_type_mode === 'input';
|
|
106
|
+
const tag = el.tagName.toLowerCase();
|
|
107
|
+
const setter = isInput
|
|
108
|
+
? (Object.getOwnPropertyDescriptor(tag === 'input' ? HTMLInputElement.prototype : HTMLTextAreaElement.prototype, 'value') || {}).set
|
|
109
|
+
: null;
|
|
110
|
+
const text = ${JSON.stringify(text)};
|
|
111
|
+
for (let i = 0; i < text.length; i++) {
|
|
112
|
+
const ch = text[i];
|
|
113
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key: ch }));
|
|
114
|
+
el.dispatchEvent(new KeyboardEvent('keypress', { bubbles: true, cancelable: true, key: ch }));
|
|
115
|
+
if (isInput) {
|
|
116
|
+
const next = (el.value || '') + ch;
|
|
117
|
+
if (setter) setter.call(el, next); else el.value = next;
|
|
118
|
+
} else {
|
|
119
|
+
el.textContent = (el.textContent || '') + ch;
|
|
120
|
+
}
|
|
121
|
+
el.dispatchEvent(new InputEvent('input', { bubbles: true, data: ch, inputType: 'insertText' }));
|
|
122
|
+
el.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true, cancelable: true, key: ch }));
|
|
123
|
+
}
|
|
124
|
+
el.dispatchEvent(new Event('change', { bubbles: true }));
|
|
125
|
+
const finalValue = isInput ? el.value : el.textContent;
|
|
126
|
+
return { ok: true, chars: text.length, finalLen: (finalValue || '').length };
|
|
127
|
+
})()
|
|
128
|
+
`;
|
|
129
|
+
const perChar = (ch, isLast) => `
|
|
130
|
+
(() => {
|
|
131
|
+
const el = window.__wdm_type_target;
|
|
132
|
+
const isInput = window.__wdm_type_mode === 'input';
|
|
133
|
+
const tag = el.tagName.toLowerCase();
|
|
134
|
+
const setter = isInput
|
|
135
|
+
? (Object.getOwnPropertyDescriptor(tag === 'input' ? HTMLInputElement.prototype : HTMLTextAreaElement.prototype, 'value') || {}).set
|
|
136
|
+
: null;
|
|
137
|
+
const ch = ${JSON.stringify(ch)};
|
|
138
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key: ch }));
|
|
139
|
+
el.dispatchEvent(new KeyboardEvent('keypress', { bubbles: true, cancelable: true, key: ch }));
|
|
140
|
+
if (isInput) {
|
|
141
|
+
const next = (el.value || '') + ch;
|
|
142
|
+
if (setter) setter.call(el, next); else el.value = next;
|
|
143
|
+
} else {
|
|
144
|
+
el.textContent = (el.textContent || '') + ch;
|
|
145
|
+
}
|
|
146
|
+
el.dispatchEvent(new InputEvent('input', { bubbles: true, data: ch, inputType: 'insertText' }));
|
|
147
|
+
el.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true, cancelable: true, key: ch }));
|
|
148
|
+
${isLast ? 'el.dispatchEvent(new Event("change", { bubbles: true }));' : ''}
|
|
149
|
+
const finalValue = isInput ? el.value : el.textContent;
|
|
150
|
+
return { ok: true, finalLen: (finalValue || '').length };
|
|
151
|
+
})()
|
|
152
|
+
`;
|
|
153
|
+
let finalLen = 0;
|
|
154
|
+
try {
|
|
155
|
+
if (delayMs === 0) {
|
|
156
|
+
const r = await ps.session.send('Runtime.evaluate', { expression: fastSync, returnByValue: true, awaitPromise: false }, 15_000);
|
|
157
|
+
const v = r?.result?.value;
|
|
158
|
+
if (!v || v.ok !== true) {
|
|
159
|
+
return errorResult(`# type_text: failed at fast loop\n\n${JSON.stringify(v)}`);
|
|
160
|
+
}
|
|
161
|
+
finalLen = v.finalLen;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
for (let i = 0; i < text.length; i++) {
|
|
165
|
+
const r = await ps.session.send('Runtime.evaluate', { expression: perChar(text[i], i === text.length - 1), returnByValue: true, awaitPromise: false }, 10_000);
|
|
166
|
+
const v = r?.result?.value;
|
|
167
|
+
if (!v || v.ok !== true) {
|
|
168
|
+
return errorResult(`# type_text: failed at char ${i} (${JSON.stringify(text[i])})\n\n${JSON.stringify(v)}`);
|
|
169
|
+
}
|
|
170
|
+
finalLen = v.finalLen;
|
|
171
|
+
if (i < text.length - 1) {
|
|
172
|
+
await new Promise(r => setTimeout(r, delayMs));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
return errorResult(`Runtime.evaluate (type_text loop) failed: ${describe(e)}`);
|
|
179
|
+
}
|
|
180
|
+
if (waitAfterMs > 0) {
|
|
181
|
+
await new Promise(r => setTimeout(r, waitAfterMs));
|
|
182
|
+
}
|
|
183
|
+
return textResult([
|
|
184
|
+
`# type_text ✓`,
|
|
185
|
+
'',
|
|
186
|
+
`tag: \`<${preVal.tag}>\` (mode: ${preVal.mode})`,
|
|
187
|
+
`chars typed: ${text.length}${delayMs > 0 ? ` (per-char, ${delayMs}ms between)` : ' (single sync round-trip)'}`,
|
|
188
|
+
`final field length: ${finalLen}`,
|
|
189
|
+
'',
|
|
190
|
+
'⚠ Synthetic KeyboardEvent sequence — `isTrusted=false`, no IME / composition. For fast bulk assignment use `fill`.',
|
|
191
|
+
].join('\n'));
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
function textResult(text) {
|
|
195
|
+
return { content: [{ type: 'text', text }] };
|
|
196
|
+
}
|
|
197
|
+
function errorResult(text) {
|
|
198
|
+
return { content: [{ type: 'text', text }], isError: true };
|
|
199
|
+
}
|
|
200
|
+
function describe(e) {
|
|
201
|
+
return e instanceof Error ? e.message : String(e);
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=type_text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type_text.js","sourceRoot":"","sources":["../../../src/tools/type_text.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const waitForTool: {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
selector: z.ZodOptional<z.ZodString>;
|
|
7
|
+
text: z.ZodOptional<z.ZodString>;
|
|
8
|
+
expression: z.ZodOptional<z.ZodString>;
|
|
9
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
pollMs: z.ZodOptional<z.ZodNumber>;
|
|
11
|
+
};
|
|
12
|
+
handler: ({ selector, text, expression, timeoutMs, pollMs, }: {
|
|
13
|
+
selector?: string;
|
|
14
|
+
text?: string;
|
|
15
|
+
expression?: string;
|
|
16
|
+
timeoutMs?: number;
|
|
17
|
+
pollMs?: number;
|
|
18
|
+
}) => Promise<{
|
|
19
|
+
content: {
|
|
20
|
+
type: "text";
|
|
21
|
+
text: string;
|
|
22
|
+
}[];
|
|
23
|
+
}>;
|
|
24
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PageSession } from '../page-session.js';
|
|
3
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
4
|
+
const DEFAULT_POLL_MS = 250;
|
|
5
|
+
export const waitForTool = {
|
|
6
|
+
name: 'wait_for',
|
|
7
|
+
description: [
|
|
8
|
+
'Wait for a condition on the inspected iOS WebView page. Polls via `Runtime.evaluate` until the condition is met or timeout.',
|
|
9
|
+
'Modes (exactly one required):',
|
|
10
|
+
' • `selector`: wait for `document.querySelector(selector)` to return non-null',
|
|
11
|
+
' • `text`: wait for `document.body.textContent.includes(text)` to be true',
|
|
12
|
+
' • `expression`: wait for the given JS expression to evaluate truthy',
|
|
13
|
+
].join(' '),
|
|
14
|
+
inputSchema: {
|
|
15
|
+
selector: z.string().min(1).optional().describe('CSS selector to wait for.'),
|
|
16
|
+
text: z.string().min(1).optional().describe('Text substring to appear in document.body.textContent.'),
|
|
17
|
+
expression: z.string().min(1).optional().describe('JS expression — succeeds when truthy.'),
|
|
18
|
+
timeoutMs: z
|
|
19
|
+
.number()
|
|
20
|
+
.int()
|
|
21
|
+
.min(100)
|
|
22
|
+
.max(60_000)
|
|
23
|
+
.optional()
|
|
24
|
+
.describe(`Max time to wait (default ${DEFAULT_TIMEOUT_MS}).`),
|
|
25
|
+
pollMs: z
|
|
26
|
+
.number()
|
|
27
|
+
.int()
|
|
28
|
+
.min(50)
|
|
29
|
+
.max(5_000)
|
|
30
|
+
.optional()
|
|
31
|
+
.describe(`Polling interval (default ${DEFAULT_POLL_MS}).`),
|
|
32
|
+
},
|
|
33
|
+
handler: async ({ selector, text, expression, timeoutMs = DEFAULT_TIMEOUT_MS, pollMs = DEFAULT_POLL_MS, }) => {
|
|
34
|
+
const modes = [selector, text, expression].filter(x => x !== undefined).length;
|
|
35
|
+
if (modes !== 1) {
|
|
36
|
+
return errorResult(`Provide exactly one of: selector / text / expression (got ${modes}).`);
|
|
37
|
+
}
|
|
38
|
+
let ps;
|
|
39
|
+
try {
|
|
40
|
+
ps = await PageSession.get();
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
return errorResult(`Unable to attach to a WKWebView page: ${describe(e)}`);
|
|
44
|
+
}
|
|
45
|
+
let probe;
|
|
46
|
+
let label;
|
|
47
|
+
if (selector !== undefined) {
|
|
48
|
+
probe = `(document.querySelector(${JSON.stringify(selector)}) !== null)`;
|
|
49
|
+
label = `selector \`${selector}\``;
|
|
50
|
+
}
|
|
51
|
+
else if (text !== undefined) {
|
|
52
|
+
probe = `(typeof document.body !== 'undefined' && (document.body.textContent || '').includes(${JSON.stringify(text)}))`;
|
|
53
|
+
label = `text \`${text}\``;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
probe = `Boolean(${expression})`;
|
|
57
|
+
label = `expression \`${expression.length > 60 ? expression.slice(0, 60) + '…' : expression}\``;
|
|
58
|
+
}
|
|
59
|
+
const deadline = Date.now() + timeoutMs;
|
|
60
|
+
let polls = 0;
|
|
61
|
+
while (Date.now() < deadline) {
|
|
62
|
+
polls++;
|
|
63
|
+
try {
|
|
64
|
+
const r = await ps.session.send('Runtime.evaluate', {
|
|
65
|
+
expression: probe,
|
|
66
|
+
returnByValue: true,
|
|
67
|
+
}, Math.max(2_000, pollMs));
|
|
68
|
+
if (r?.result?.value === true) {
|
|
69
|
+
return textResult([
|
|
70
|
+
`# wait_for ✓ ${label}`,
|
|
71
|
+
'',
|
|
72
|
+
`Matched after ${polls} poll(s) / ${Date.now() - (deadline - timeoutMs)}ms (timeout was ${timeoutMs}ms, poll ${pollMs}ms).`,
|
|
73
|
+
].join('\n'));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
return errorResult(`Runtime.evaluate during wait_for failed: ${describe(e)}`);
|
|
78
|
+
}
|
|
79
|
+
await new Promise(r => setTimeout(r, pollMs));
|
|
80
|
+
}
|
|
81
|
+
return errorResult(`# wait_for ✗ ${label} — timed out after ${timeoutMs}ms (${polls} polls)`);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
function textResult(text) {
|
|
85
|
+
return { content: [{ type: 'text', text }] };
|
|
86
|
+
}
|
|
87
|
+
function errorResult(text) {
|
|
88
|
+
return { content: [{ type: 'text', text }], isError: true };
|
|
89
|
+
}
|
|
90
|
+
function describe(e) {
|
|
91
|
+
return e instanceof Error ? e.message : String(e);
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=wait_for.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait_for.js","sourceRoot":"","sources":["../../../src/tools/wait_for.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const wipSendTool: {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
method: z.ZodString;
|
|
7
|
+
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
8
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
9
|
+
previewMaxLen: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
};
|
|
11
|
+
handler: ({ method, params, timeoutMs, previewMaxLen, }: {
|
|
12
|
+
method: string;
|
|
13
|
+
params?: Record<string, unknown>;
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
previewMaxLen?: number;
|
|
16
|
+
}) => Promise<{
|
|
17
|
+
content: {
|
|
18
|
+
type: "text";
|
|
19
|
+
text: string;
|
|
20
|
+
}[];
|
|
21
|
+
}>;
|
|
22
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PageSession } from '../page-session.js';
|
|
3
|
+
export const wipSendTool = {
|
|
4
|
+
name: 'wip_send',
|
|
5
|
+
description: [
|
|
6
|
+
'Escape hatch — send an arbitrary WIP method through the shared PageSession with full envelope wrapping (`Target.sendMessageToTarget`).',
|
|
7
|
+
'Use this to probe new methods, drive Apple-specific domains (`CSS`, `Animation`, `Heap`, `DOMDebugger`, …) not yet wrapped by dedicated tools, or experiment before promoting to a real tool.',
|
|
8
|
+
'Returns the raw `result` payload on success, or a structured error with WIP error code/message.',
|
|
9
|
+
].join(' '),
|
|
10
|
+
inputSchema: {
|
|
11
|
+
method: z
|
|
12
|
+
.string()
|
|
13
|
+
.min(1)
|
|
14
|
+
.describe('WIP method, e.g. `Page.getResourceTree`, `CSS.enable`, `Heap.gc`.'),
|
|
15
|
+
params: z
|
|
16
|
+
.record(z.unknown())
|
|
17
|
+
.optional()
|
|
18
|
+
.describe('Method params object. Omit for parameterless methods.'),
|
|
19
|
+
timeoutMs: z
|
|
20
|
+
.number()
|
|
21
|
+
.int()
|
|
22
|
+
.min(500)
|
|
23
|
+
.max(120_000)
|
|
24
|
+
.optional()
|
|
25
|
+
.describe('Per-call timeout (default 15000).'),
|
|
26
|
+
previewMaxLen: z
|
|
27
|
+
.number()
|
|
28
|
+
.int()
|
|
29
|
+
.min(100)
|
|
30
|
+
.max(500_000)
|
|
31
|
+
.optional()
|
|
32
|
+
.describe('Result JSON truncation cap (default 20000).'),
|
|
33
|
+
},
|
|
34
|
+
handler: async ({ method, params, timeoutMs = 15_000, previewMaxLen = 20_000, }) => {
|
|
35
|
+
let ps;
|
|
36
|
+
try {
|
|
37
|
+
ps = await PageSession.get();
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
return errorResult(`Unable to attach to a WKWebView page: ${describe(e)}`);
|
|
41
|
+
}
|
|
42
|
+
let result;
|
|
43
|
+
try {
|
|
44
|
+
result = await ps.session.send(method, params, timeoutMs);
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
const err = e;
|
|
48
|
+
const code = err.code;
|
|
49
|
+
const tag = code === -32601 ? '❌ NOT_FOUND' : code === -32602 ? '⚠ INVALID_PARAMS' : `⚠ ${code ?? '?'}`;
|
|
50
|
+
return errorResult([
|
|
51
|
+
`# wip_send ${tag} \`${method}\``,
|
|
52
|
+
'',
|
|
53
|
+
`params: ${JSON.stringify(params ?? {})}`,
|
|
54
|
+
'',
|
|
55
|
+
`error: ${err.message ?? describe(e)}`,
|
|
56
|
+
].join('\n'));
|
|
57
|
+
}
|
|
58
|
+
const json = JSON.stringify(result, null, 2) ?? 'null';
|
|
59
|
+
const body = json.length > previewMaxLen ? json.slice(0, previewMaxLen) + `\n… (truncated, full length ${json.length})` : json;
|
|
60
|
+
return textResult([
|
|
61
|
+
`# wip_send ✓ \`${method}\``,
|
|
62
|
+
'',
|
|
63
|
+
`params: ${JSON.stringify(params ?? {})}`,
|
|
64
|
+
'',
|
|
65
|
+
'## result',
|
|
66
|
+
'```json',
|
|
67
|
+
body,
|
|
68
|
+
'```',
|
|
69
|
+
].join('\n'));
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
function textResult(text) {
|
|
73
|
+
return { content: [{ type: 'text', text }] };
|
|
74
|
+
}
|
|
75
|
+
function errorResult(text) {
|
|
76
|
+
return { content: [{ type: 'text', text }], isError: true };
|
|
77
|
+
}
|
|
78
|
+
function describe(e) {
|
|
79
|
+
return e instanceof Error ? e.message : String(e);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=wip_send.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wip_send.js","sourceRoot":"","sources":["../../../src/tools/wip_send.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface ProxyDevice {
|
|
2
|
+
deviceId: string;
|
|
3
|
+
deviceName: string;
|
|
4
|
+
deviceOSVersion?: string;
|
|
5
|
+
url: string;
|
|
6
|
+
}
|
|
7
|
+
export interface DevicePage {
|
|
8
|
+
id: string;
|
|
9
|
+
title: string;
|
|
10
|
+
url: string;
|
|
11
|
+
type?: string;
|
|
12
|
+
webSocketDebuggerUrl: string;
|
|
13
|
+
webkitVersion?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function fetchProxyDevices(deviceListBaseUrl: string): Promise<ProxyDevice[]>;
|
|
17
|
+
export declare function fetchDevicePages(deviceUrl: string): Promise<DevicePage[]>;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal HTTP client for ios_webkit_debug_proxy's HTTP endpoints.
|
|
3
|
+
*
|
|
4
|
+
* Endpoint shapes (verified against v1.9.2 default config `null:9221,:9222-9322`):
|
|
5
|
+
*
|
|
6
|
+
* GET http://127.0.0.1:9221/json → array of devices with `url` pointing to per-device port
|
|
7
|
+
* GET http://127.0.0.1:<devicePort>/json/list → array of inspectable pages on that device
|
|
8
|
+
*
|
|
9
|
+
* The returned `webSocketDebuggerUrl` looks like CDP but frames are Apple WIP (proxy is transport, not translator).
|
|
10
|
+
*/
|
|
11
|
+
import { request as httpRequest } from 'node:http';
|
|
12
|
+
export async function fetchProxyDevices(deviceListBaseUrl) {
|
|
13
|
+
const json = await httpGetJson(stripTrailingSlash(deviceListBaseUrl) + '/json');
|
|
14
|
+
if (!Array.isArray(json))
|
|
15
|
+
return [];
|
|
16
|
+
return json
|
|
17
|
+
.map((entry) => {
|
|
18
|
+
const url = entry.url;
|
|
19
|
+
if (typeof url !== 'string' || url.length === 0)
|
|
20
|
+
return null;
|
|
21
|
+
const r = entry;
|
|
22
|
+
return {
|
|
23
|
+
deviceId: String(r.deviceId ?? 'unknown'),
|
|
24
|
+
deviceName: String(r.deviceName ?? ''),
|
|
25
|
+
deviceOSVersion: typeof r.deviceOSVersion === 'string' ? r.deviceOSVersion : undefined,
|
|
26
|
+
url,
|
|
27
|
+
};
|
|
28
|
+
})
|
|
29
|
+
.filter((d) => d !== null);
|
|
30
|
+
}
|
|
31
|
+
export async function fetchDevicePages(deviceUrl) {
|
|
32
|
+
const baseUrl = normalizeToHttp(deviceUrl);
|
|
33
|
+
const json = await httpGetJson(baseUrl + '/json/list');
|
|
34
|
+
if (!Array.isArray(json))
|
|
35
|
+
return [];
|
|
36
|
+
return json.map((p) => {
|
|
37
|
+
const o = p;
|
|
38
|
+
const wsUrl = typeof o.webSocketDebuggerUrl === 'string' ? o.webSocketDebuggerUrl : '';
|
|
39
|
+
// /json/list response on ios_webkit_debug_proxy v1.9.2 omits `id`;
|
|
40
|
+
// the page id is the trailing segment of `webSocketDebuggerUrl` (e.g. ".../devtools/page/7" → "7").
|
|
41
|
+
const idFromField = typeof o.id === 'string' || typeof o.id === 'number' ? String(o.id) : '';
|
|
42
|
+
const idFromUrl = wsUrl.match(/\/devtools\/page\/([^/?]+)$/)?.[1] ?? '';
|
|
43
|
+
return {
|
|
44
|
+
id: idFromField || idFromUrl,
|
|
45
|
+
title: typeof o.title === 'string' ? o.title : '',
|
|
46
|
+
url: typeof o.url === 'string' ? o.url : '',
|
|
47
|
+
type: typeof o.type === 'string' ? o.type : undefined,
|
|
48
|
+
webSocketDebuggerUrl: wsUrl,
|
|
49
|
+
webkitVersion: typeof o.webkitVersion === 'string' ? o.webkitVersion : undefined,
|
|
50
|
+
description: typeof o.description === 'string' ? o.description : undefined,
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function normalizeToHttp(input) {
|
|
55
|
+
let s = stripTrailingSlash(input);
|
|
56
|
+
if (s.startsWith('ws://'))
|
|
57
|
+
s = 'http://' + s.slice('ws://'.length);
|
|
58
|
+
else if (s.startsWith('wss://'))
|
|
59
|
+
s = 'https://' + s.slice('wss://'.length);
|
|
60
|
+
else if (!/^https?:\/\//.test(s))
|
|
61
|
+
s = 'http://' + s;
|
|
62
|
+
return s;
|
|
63
|
+
}
|
|
64
|
+
function stripTrailingSlash(s) {
|
|
65
|
+
return s.endsWith('/') ? s.slice(0, -1) : s;
|
|
66
|
+
}
|
|
67
|
+
function httpGetJson(urlStr, timeoutMs = 5000) {
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
const url = new URL(urlStr);
|
|
70
|
+
const req = httpRequest({
|
|
71
|
+
hostname: url.hostname,
|
|
72
|
+
port: url.port || 80,
|
|
73
|
+
path: url.pathname + url.search,
|
|
74
|
+
method: 'GET',
|
|
75
|
+
timeout: timeoutMs,
|
|
76
|
+
}, res => {
|
|
77
|
+
const chunks = [];
|
|
78
|
+
res.on('data', c => chunks.push(c));
|
|
79
|
+
res.on('end', () => {
|
|
80
|
+
const body = Buffer.concat(chunks).toString('utf8');
|
|
81
|
+
if ((res.statusCode ?? 0) >= 400) {
|
|
82
|
+
reject(new Error(`HTTP ${res.statusCode} from ${urlStr}: ${body.slice(0, 200)}`));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
resolve(JSON.parse(body));
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
reject(new Error(`Non-JSON response from ${urlStr}: ${body.slice(0, 200)}`));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
req.on('error', reject);
|
|
94
|
+
req.on('timeout', () => req.destroy(new Error(`Timeout (${timeoutMs}ms) fetching ${urlStr}`)));
|
|
95
|
+
req.end();
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=iwdp-http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iwdp-http.js","sourceRoot":"","sources":["../../../src/wip-client/iwdp-http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface WipTargetInfo {
|
|
2
|
+
targetId: string;
|
|
3
|
+
type: string;
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
}
|
|
6
|
+
type EventHandler = (params: unknown) => void;
|
|
7
|
+
export declare class WipSession {
|
|
8
|
+
private ws;
|
|
9
|
+
private nextOuterId;
|
|
10
|
+
private nextInnerId;
|
|
11
|
+
private readonly pending;
|
|
12
|
+
private readonly events;
|
|
13
|
+
private readonly targets;
|
|
14
|
+
private pageTargetId;
|
|
15
|
+
private pageTargetWaiters;
|
|
16
|
+
private closed;
|
|
17
|
+
connect(url: string, timeoutMs?: number): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Wait until a `Target.targetCreated` event with type=page arrives.
|
|
20
|
+
* Resolves immediately if a page target has already been seen.
|
|
21
|
+
*/
|
|
22
|
+
waitForPageTarget(timeoutMs?: number): Promise<WipTargetInfo>;
|
|
23
|
+
/**
|
|
24
|
+
* Send an inner JSON-RPC request to the page target, wrapped in
|
|
25
|
+
* Target.sendMessageToTarget. Resolves with the inner result.
|
|
26
|
+
*/
|
|
27
|
+
send<R = unknown>(method: string, params?: unknown, timeoutMs?: number): Promise<R>;
|
|
28
|
+
sendToTarget<R = unknown>(targetId: string, method: string, params?: unknown, timeoutMs?: number): Promise<R>;
|
|
29
|
+
/**
|
|
30
|
+
* Subscribe to a domain event (e.g. `Console.messageAdded`,
|
|
31
|
+
* `Network.requestWillBeSent`). Handlers receive the inner `params`.
|
|
32
|
+
*/
|
|
33
|
+
on(event: string, handler: EventHandler): () => void;
|
|
34
|
+
close(): void;
|
|
35
|
+
getTargets(): WipTargetInfo[];
|
|
36
|
+
private handleOuter;
|
|
37
|
+
private handleInner;
|
|
38
|
+
private dispatchEvent;
|
|
39
|
+
private handleClose;
|
|
40
|
+
}
|
|
41
|
+
export {};
|