@ank1015/llm-extension 0.0.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.
- package/README.md +214 -0
- package/dist/chrome/background.js +244 -0
- package/dist/chrome/manifest.json +23 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/native/host-wrapper.sh +11 -0
- package/dist/native/host.d.ts +2 -0
- package/dist/native/host.d.ts.map +1 -0
- package/dist/native/host.js +21 -0
- package/dist/native/host.js.map +1 -0
- package/dist/native/server.d.ts +28 -0
- package/dist/native/server.d.ts.map +1 -0
- package/dist/native/server.js +112 -0
- package/dist/native/server.js.map +1 -0
- package/dist/native/stdio.d.ts +21 -0
- package/dist/native/stdio.d.ts.map +1 -0
- package/dist/native/stdio.js +94 -0
- package/dist/native/stdio.js.map +1 -0
- package/dist/protocol/constants.d.ts +26 -0
- package/dist/protocol/constants.d.ts.map +1 -0
- package/dist/protocol/constants.js +26 -0
- package/dist/protocol/constants.js.map +1 -0
- package/dist/protocol/types.d.ts +39 -0
- package/dist/protocol/types.d.ts.map +1 -0
- package/dist/protocol/types.js +3 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/sdk/action/diff.d.ts +7 -0
- package/dist/sdk/action/diff.d.ts.map +1 -0
- package/dist/sdk/action/diff.js +54 -0
- package/dist/sdk/action/diff.js.map +1 -0
- package/dist/sdk/action/helpers.d.ts +23 -0
- package/dist/sdk/action/helpers.d.ts.map +1 -0
- package/dist/sdk/action/helpers.js +93 -0
- package/dist/sdk/action/helpers.js.map +1 -0
- package/dist/sdk/action/index.d.ts +6 -0
- package/dist/sdk/action/index.d.ts.map +1 -0
- package/dist/sdk/action/index.js +4 -0
- package/dist/sdk/action/index.js.map +1 -0
- package/dist/sdk/action/script.d.ts +4 -0
- package/dist/sdk/action/script.d.ts.map +1 -0
- package/dist/sdk/action/script.js +359 -0
- package/dist/sdk/action/script.js.map +1 -0
- package/dist/sdk/action/types.d.ts +47 -0
- package/dist/sdk/action/types.d.ts.map +1 -0
- package/dist/sdk/action/types.js +2 -0
- package/dist/sdk/action/types.js.map +1 -0
- package/dist/sdk/client.d.ts +42 -0
- package/dist/sdk/client.d.ts.map +1 -0
- package/dist/sdk/client.js +118 -0
- package/dist/sdk/client.js.map +1 -0
- package/dist/sdk/connect.d.ts +29 -0
- package/dist/sdk/connect.d.ts.map +1 -0
- package/dist/sdk/connect.js +99 -0
- package/dist/sdk/connect.js.map +1 -0
- package/dist/sdk/index.d.ts +17 -0
- package/dist/sdk/index.d.ts.map +1 -0
- package/dist/sdk/index.js +19 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sdk/observe/helpers.d.ts +16 -0
- package/dist/sdk/observe/helpers.d.ts.map +1 -0
- package/dist/sdk/observe/helpers.js +278 -0
- package/dist/sdk/observe/helpers.js.map +1 -0
- package/dist/sdk/observe/index.d.ts +6 -0
- package/dist/sdk/observe/index.d.ts.map +1 -0
- package/dist/sdk/observe/index.js +4 -0
- package/dist/sdk/observe/index.js.map +1 -0
- package/dist/sdk/observe/script.d.ts +7 -0
- package/dist/sdk/observe/script.d.ts.map +1 -0
- package/dist/sdk/observe/script.js +680 -0
- package/dist/sdk/observe/script.js.map +1 -0
- package/dist/sdk/observe/storage.d.ts +39 -0
- package/dist/sdk/observe/storage.d.ts.map +1 -0
- package/dist/sdk/observe/storage.js +83 -0
- package/dist/sdk/observe/storage.js.map +1 -0
- package/dist/sdk/observe/types.d.ts +140 -0
- package/dist/sdk/observe/types.d.ts.map +1 -0
- package/dist/sdk/observe/types.js +2 -0
- package/dist/sdk/observe/types.js.map +1 -0
- package/dist/sdk/window.d.ts +97 -0
- package/dist/sdk/window.d.ts.map +1 -0
- package/dist/sdk/window.js +795 -0
- package/dist/sdk/window.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
function isObject(value) {
|
|
2
|
+
return typeof value === 'object' && value !== null;
|
|
3
|
+
}
|
|
4
|
+
export function buildActionScript(payload) {
|
|
5
|
+
const serializedPayload = JSON.stringify(payload);
|
|
6
|
+
return `
|
|
7
|
+
(() => {
|
|
8
|
+
const payload = ${serializedPayload};
|
|
9
|
+
|
|
10
|
+
const normalizeText = (value, maxLength = 180) => {
|
|
11
|
+
if (typeof value !== 'string') return '';
|
|
12
|
+
const compact = value.replace(/\\s+/g, ' ').trim();
|
|
13
|
+
if (!compact) return '';
|
|
14
|
+
if (compact.length <= maxLength) return compact;
|
|
15
|
+
return compact.slice(0, Math.max(1, maxLength - 3)) + '...';
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const result = (success, action, message, selectorUsed) => ({
|
|
19
|
+
success,
|
|
20
|
+
action,
|
|
21
|
+
message,
|
|
22
|
+
selectorUsed: selectorUsed || '',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const resolveElement = (selectors) => {
|
|
26
|
+
if (!Array.isArray(selectors)) {
|
|
27
|
+
return { element: null, selectorUsed: '' };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
for (const selector of selectors) {
|
|
31
|
+
if (typeof selector !== 'string' || !selector.trim()) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const element = document.querySelector(selector);
|
|
37
|
+
if (element) {
|
|
38
|
+
return {
|
|
39
|
+
element,
|
|
40
|
+
selectorUsed: selector,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
} catch {
|
|
44
|
+
// Ignore invalid selectors and keep trying.
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return { element: null, selectorUsed: '' };
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const focusElement = (element) => {
|
|
52
|
+
if (typeof element.focus === 'function') {
|
|
53
|
+
element.focus();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const scrollIntoView = (element, behavior = 'auto') => {
|
|
58
|
+
if (typeof element.scrollIntoView === 'function') {
|
|
59
|
+
element.scrollIntoView({ block: 'center', inline: 'nearest', behavior });
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const dispatchInputEvents = (element) => {
|
|
64
|
+
element.dispatchEvent(new Event('input', { bubbles: true, cancelable: true }));
|
|
65
|
+
element.dispatchEvent(new Event('change', { bubbles: true, cancelable: true }));
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const isContentEditable = (element) => {
|
|
69
|
+
if (!element) return false;
|
|
70
|
+
if (element.isContentEditable) return true;
|
|
71
|
+
const attr =
|
|
72
|
+
typeof element.getAttribute === 'function' ? element.getAttribute('contenteditable') : null;
|
|
73
|
+
if (typeof attr !== 'string') return false;
|
|
74
|
+
const normalized = attr.trim().toLowerCase();
|
|
75
|
+
return normalized === '' || normalized === 'true' || normalized === 'plaintext-only';
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const getTypeableElement = (element) => {
|
|
79
|
+
if (!element) return null;
|
|
80
|
+
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
|
|
81
|
+
return element;
|
|
82
|
+
}
|
|
83
|
+
if (isContentEditable(element)) {
|
|
84
|
+
return element;
|
|
85
|
+
}
|
|
86
|
+
const nested = element.querySelector(
|
|
87
|
+
'input:not([type="hidden"]), textarea, [contenteditable], [role="textbox"], [role="searchbox"], [role="combobox"]'
|
|
88
|
+
);
|
|
89
|
+
if (!nested) return null;
|
|
90
|
+
if (nested instanceof HTMLInputElement || nested instanceof HTMLTextAreaElement) return nested;
|
|
91
|
+
if (isContentEditable(nested)) return nested;
|
|
92
|
+
return null;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const setInputValue = (element, value) => {
|
|
96
|
+
const prototype = Object.getPrototypeOf(element);
|
|
97
|
+
const descriptor =
|
|
98
|
+
Object.getOwnPropertyDescriptor(prototype, 'value') ||
|
|
99
|
+
Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value') ||
|
|
100
|
+
Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value');
|
|
101
|
+
|
|
102
|
+
if (descriptor && typeof descriptor.set === 'function') {
|
|
103
|
+
descriptor.set.call(element, value);
|
|
104
|
+
} else {
|
|
105
|
+
element.value = value;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const clickElement = (element) => {
|
|
110
|
+
focusElement(element);
|
|
111
|
+
element.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true, cancelable: true }));
|
|
112
|
+
element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true }));
|
|
113
|
+
element.dispatchEvent(new MouseEvent('pointerup', { bubbles: true, cancelable: true }));
|
|
114
|
+
element.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true }));
|
|
115
|
+
if (typeof element.click === 'function') {
|
|
116
|
+
element.click();
|
|
117
|
+
} else {
|
|
118
|
+
element.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const hoverElement = (element) => {
|
|
123
|
+
element.dispatchEvent(new MouseEvent('pointerover', { bubbles: true, cancelable: true }));
|
|
124
|
+
element.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, cancelable: true }));
|
|
125
|
+
element.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true, cancelable: true }));
|
|
126
|
+
element.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, cancelable: true }));
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const pressEnter = (element) => {
|
|
130
|
+
focusElement(element);
|
|
131
|
+
const eventInit = {
|
|
132
|
+
key: 'Enter',
|
|
133
|
+
code: 'Enter',
|
|
134
|
+
keyCode: 13,
|
|
135
|
+
which: 13,
|
|
136
|
+
bubbles: true,
|
|
137
|
+
cancelable: true,
|
|
138
|
+
};
|
|
139
|
+
element.dispatchEvent(new KeyboardEvent('keydown', eventInit));
|
|
140
|
+
element.dispatchEvent(new KeyboardEvent('keypress', eventInit));
|
|
141
|
+
element.dispatchEvent(new KeyboardEvent('keyup', eventInit));
|
|
142
|
+
|
|
143
|
+
const form = typeof element.closest === 'function' ? element.closest('form') : null;
|
|
144
|
+
if (form && typeof form.requestSubmit === 'function') {
|
|
145
|
+
form.requestSubmit();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const action = payload.action;
|
|
150
|
+
const resolved = resolveElement(payload.selectors || []);
|
|
151
|
+
const element = resolved.element;
|
|
152
|
+
const selectorUsed = resolved.selectorUsed;
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
if (action === 'scroll') {
|
|
156
|
+
if (element) {
|
|
157
|
+
scrollIntoView(element, payload.scroll?.behavior || 'auto');
|
|
158
|
+
return result(true, action, 'Scrolled target into view', selectorUsed);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (payload.scroll && payload.scroll.to) {
|
|
162
|
+
const behavior = payload.scroll.behavior || 'auto';
|
|
163
|
+
if (payload.scroll.to === 'top') {
|
|
164
|
+
window.scrollTo({ top: 0, behavior });
|
|
165
|
+
return result(true, action, 'Scrolled page to top', '');
|
|
166
|
+
}
|
|
167
|
+
if (payload.scroll.to === 'bottom') {
|
|
168
|
+
window.scrollTo({
|
|
169
|
+
top: Math.max(0, document.documentElement.scrollHeight - window.innerHeight),
|
|
170
|
+
behavior,
|
|
171
|
+
});
|
|
172
|
+
return result(true, action, 'Scrolled page to bottom', '');
|
|
173
|
+
}
|
|
174
|
+
if (payload.scroll.to === 'left') {
|
|
175
|
+
window.scrollTo({ left: 0, behavior });
|
|
176
|
+
return result(true, action, 'Scrolled page to left edge', '');
|
|
177
|
+
}
|
|
178
|
+
if (payload.scroll.to === 'right') {
|
|
179
|
+
window.scrollTo({
|
|
180
|
+
left: Math.max(0, document.documentElement.scrollWidth - window.innerWidth),
|
|
181
|
+
behavior,
|
|
182
|
+
});
|
|
183
|
+
return result(true, action, 'Scrolled page to right edge', '');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const x = typeof payload.scroll?.x === 'number' ? payload.scroll.x : 0;
|
|
188
|
+
const y =
|
|
189
|
+
typeof payload.scroll?.y === 'number' ? payload.scroll.y : Math.round(window.innerHeight * 0.8);
|
|
190
|
+
window.scrollBy({
|
|
191
|
+
left: x,
|
|
192
|
+
top: y,
|
|
193
|
+
behavior: payload.scroll?.behavior || 'auto',
|
|
194
|
+
});
|
|
195
|
+
return result(true, action, 'Scrolled page', '');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (!element) {
|
|
199
|
+
return result(false, action, 'Target element not found', '');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
scrollIntoView(element, 'auto');
|
|
203
|
+
|
|
204
|
+
if (action === 'focus') {
|
|
205
|
+
focusElement(element);
|
|
206
|
+
const active = document.activeElement;
|
|
207
|
+
const focused = active === element || element.contains(active);
|
|
208
|
+
return result(focused, action, focused ? 'Focused target element' : 'Focus had no effect', selectorUsed);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (action === 'hover') {
|
|
212
|
+
hoverElement(element);
|
|
213
|
+
return result(true, action, 'Hovered target element', selectorUsed);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (action === 'click') {
|
|
217
|
+
clickElement(element);
|
|
218
|
+
return result(true, action, 'Clicked target element', selectorUsed);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (action === 'pressEnter') {
|
|
222
|
+
pressEnter(element);
|
|
223
|
+
return result(true, action, 'Pressed Enter on target element', selectorUsed);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (action === 'toggle') {
|
|
227
|
+
const type = normalizeText(element.getAttribute('type') || '', 40).toLowerCase();
|
|
228
|
+
if (type === 'checkbox' || type === 'radio') {
|
|
229
|
+
clickElement(element);
|
|
230
|
+
return result(true, action, 'Toggled input', selectorUsed);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (element.getAttribute('aria-pressed') !== null) {
|
|
234
|
+
clickElement(element);
|
|
235
|
+
return result(true, action, 'Toggled aria-pressed control', selectorUsed);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return result(false, action, 'Toggle requires checkbox, radio, or aria-pressed control', selectorUsed);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (action === 'clear') {
|
|
242
|
+
const typeable = getTypeableElement(element);
|
|
243
|
+
if (!typeable) {
|
|
244
|
+
return result(false, action, 'Clear requires an editable target', selectorUsed);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
focusElement(typeable);
|
|
248
|
+
if (isContentEditable(typeable)) {
|
|
249
|
+
typeable.textContent = '';
|
|
250
|
+
dispatchInputEvents(typeable);
|
|
251
|
+
return result(true, action, 'Cleared editable target', selectorUsed);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
setInputValue(typeable, '');
|
|
255
|
+
dispatchInputEvents(typeable);
|
|
256
|
+
return result(true, action, 'Cleared input value', selectorUsed);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (action === 'type') {
|
|
260
|
+
if (typeof payload.value !== 'string') {
|
|
261
|
+
return result(false, action, 'Type requires a string value', selectorUsed);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const typeable = getTypeableElement(element);
|
|
265
|
+
if (!typeable) {
|
|
266
|
+
return result(false, action, 'Type requires an editable target', selectorUsed);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
focusElement(typeable);
|
|
270
|
+
const clearBeforeType = payload.clearBeforeType !== false;
|
|
271
|
+
const value = payload.value;
|
|
272
|
+
|
|
273
|
+
if (isContentEditable(typeable)) {
|
|
274
|
+
const previous = typeof typeable.textContent === 'string' ? typeable.textContent : '';
|
|
275
|
+
typeable.textContent = clearBeforeType ? value : previous + value;
|
|
276
|
+
dispatchInputEvents(typeable);
|
|
277
|
+
} else {
|
|
278
|
+
const previous = typeof typeable.value === 'string' ? typeable.value : '';
|
|
279
|
+
setInputValue(typeable, clearBeforeType ? value : previous + value);
|
|
280
|
+
dispatchInputEvents(typeable);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (payload.pressEnter) {
|
|
284
|
+
pressEnter(typeable);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return result(
|
|
288
|
+
true,
|
|
289
|
+
action,
|
|
290
|
+
payload.pressEnter ? 'Typed into target and pressed Enter' : 'Typed into target',
|
|
291
|
+
selectorUsed
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (action === 'select') {
|
|
296
|
+
if (typeof payload.value !== 'string') {
|
|
297
|
+
return result(false, action, 'Select requires a string value', selectorUsed);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const selectElement =
|
|
301
|
+
element instanceof HTMLSelectElement
|
|
302
|
+
? element
|
|
303
|
+
: element.querySelector('select');
|
|
304
|
+
|
|
305
|
+
if (!(selectElement instanceof HTMLSelectElement)) {
|
|
306
|
+
return result(false, action, 'Select requires a <select> target', selectorUsed);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const value = payload.value;
|
|
310
|
+
const normalized = normalizeText(value, 180).toLowerCase();
|
|
311
|
+
const matched =
|
|
312
|
+
Array.from(selectElement.options).find((option) => option.value === value) ||
|
|
313
|
+
Array.from(selectElement.options).find(
|
|
314
|
+
(option) => normalizeText(option.textContent || '', 180).toLowerCase() === normalized
|
|
315
|
+
) ||
|
|
316
|
+
Array.from(selectElement.options).find((option) =>
|
|
317
|
+
normalizeText(option.textContent || '', 180).toLowerCase().includes(normalized)
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
if (!matched) {
|
|
321
|
+
return result(false, action, 'No matching select option found', selectorUsed);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
selectElement.value = matched.value;
|
|
325
|
+
dispatchInputEvents(selectElement);
|
|
326
|
+
|
|
327
|
+
return result(true, action, 'Selected option', selectorUsed);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return result(false, action, 'Unsupported action type', selectorUsed);
|
|
331
|
+
} catch (error) {
|
|
332
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
333
|
+
return result(false, action, message, selectorUsed);
|
|
334
|
+
}
|
|
335
|
+
})()
|
|
336
|
+
`.trim();
|
|
337
|
+
}
|
|
338
|
+
export function parseActionExecutionResult(raw) {
|
|
339
|
+
if (!isObject(raw)) {
|
|
340
|
+
throw new Error('Action returned an invalid payload');
|
|
341
|
+
}
|
|
342
|
+
const success = raw.success;
|
|
343
|
+
const action = raw.action;
|
|
344
|
+
const message = raw.message;
|
|
345
|
+
const selectorUsed = raw.selectorUsed;
|
|
346
|
+
if (typeof success !== 'boolean' || typeof action !== 'string' || typeof message !== 'string') {
|
|
347
|
+
throw new Error('Action payload is missing required fields');
|
|
348
|
+
}
|
|
349
|
+
const parsed = {
|
|
350
|
+
success,
|
|
351
|
+
action,
|
|
352
|
+
message,
|
|
353
|
+
};
|
|
354
|
+
if (typeof selectorUsed === 'string') {
|
|
355
|
+
parsed.selectorUsed = selectorUsed;
|
|
356
|
+
}
|
|
357
|
+
return parsed;
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=script.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script.js","sourceRoot":"","sources":["../../../src/sdk/action/script.ts"],"names":[],"mappings":"AAEA,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAkC;IAClE,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAElD,OAAO;;oBAEW,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwUpC,CAAC,IAAI,EAAE,CAAC;AACT,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,GAAY;IACrD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IAC5B,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAC1B,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IAC5B,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;IAEtC,IAAI,OAAO,OAAO,KAAK,SAAS,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC9F,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,MAAM,GAAgC;QAC1C,OAAO;QACP,MAAM;QACN,OAAO;KACR,CAAC;IAEF,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;IACrC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ObserveLocator } from '../observe/types.js';
|
|
2
|
+
export interface WindowActionOptions {
|
|
3
|
+
tabId?: number;
|
|
4
|
+
timeoutMs?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface WindowTypeOptions extends WindowActionOptions {
|
|
7
|
+
clearBeforeType?: boolean;
|
|
8
|
+
pressEnter?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export type WindowScrollBehavior = 'auto' | 'smooth';
|
|
11
|
+
export interface WindowScrollOptions extends WindowActionOptions {
|
|
12
|
+
targetId?: string;
|
|
13
|
+
x?: number;
|
|
14
|
+
y?: number;
|
|
15
|
+
to?: 'top' | 'bottom' | 'left' | 'right';
|
|
16
|
+
behavior?: WindowScrollBehavior;
|
|
17
|
+
}
|
|
18
|
+
export type WindowTargetActionType = 'click' | 'hover' | 'focus' | 'pressEnter' | 'clear' | 'type' | 'select' | 'toggle';
|
|
19
|
+
export interface WindowObservedActionTarget {
|
|
20
|
+
id: string;
|
|
21
|
+
tag: string;
|
|
22
|
+
role: string;
|
|
23
|
+
name: string;
|
|
24
|
+
href?: string;
|
|
25
|
+
locator: ObserveLocator;
|
|
26
|
+
actions: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface WindowActionScriptPayload {
|
|
29
|
+
action: WindowTargetActionType | 'scroll';
|
|
30
|
+
selectors: string[];
|
|
31
|
+
value?: string;
|
|
32
|
+
clearBeforeType?: boolean;
|
|
33
|
+
pressEnter?: boolean;
|
|
34
|
+
scroll?: {
|
|
35
|
+
x?: number;
|
|
36
|
+
y?: number;
|
|
37
|
+
to?: 'top' | 'bottom' | 'left' | 'right';
|
|
38
|
+
behavior?: WindowScrollBehavior;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export interface WindowActionExecutionResult {
|
|
42
|
+
success: boolean;
|
|
43
|
+
action: string;
|
|
44
|
+
message: string;
|
|
45
|
+
selectorUsed?: string;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/sdk/action/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAErD,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,EAAE,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACzC,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED,MAAM,MAAM,sBAAsB,GAC9B,OAAO,GACP,OAAO,GACP,OAAO,GACP,YAAY,GACZ,OAAO,GACP,MAAM,GACN,QAAQ,GACR,QAAQ,CAAC;AAEb,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,cAAc,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,sBAAsB,GAAG,QAAQ,CAAC;IAC1C,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE;QACP,CAAC,CAAC,EAAE,MAAM,CAAC;QACX,CAAC,CAAC,EAAE,MAAM,CAAC;QACX,EAAE,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;QACzC,QAAQ,CAAC,EAAE,oBAAoB,CAAC;KACjC,CAAC;CACH;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/sdk/action/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Readable, Writable } from 'node:stream';
|
|
2
|
+
export interface ChromeClientOptions {
|
|
3
|
+
input?: Readable;
|
|
4
|
+
output?: Writable;
|
|
5
|
+
maxIncomingMessageSizeBytes?: number;
|
|
6
|
+
maxOutgoingMessageSizeBytes?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* RPC client for calling Chrome APIs over native messaging.
|
|
10
|
+
*
|
|
11
|
+
* Sends call/subscribe/unsubscribe messages to Chrome and routes
|
|
12
|
+
* incoming result/error/event responses to the correct handlers.
|
|
13
|
+
*/
|
|
14
|
+
export declare class ChromeClient {
|
|
15
|
+
private input;
|
|
16
|
+
private output;
|
|
17
|
+
private pendingCalls;
|
|
18
|
+
private eventCallbacks;
|
|
19
|
+
private closed;
|
|
20
|
+
private maxIncomingMessageSizeBytes;
|
|
21
|
+
private maxOutgoingMessageSizeBytes;
|
|
22
|
+
constructor(opts?: ChromeClientOptions);
|
|
23
|
+
/** Call a Chrome API method and wait for the result. */
|
|
24
|
+
call(method: string, ...args: unknown[]): Promise<unknown>;
|
|
25
|
+
/**
|
|
26
|
+
* Subscribe to a Chrome event. Returns an unsubscribe function.
|
|
27
|
+
*
|
|
28
|
+
* The callback is invoked with the event arguments array each time
|
|
29
|
+
* the Chrome event fires.
|
|
30
|
+
*/
|
|
31
|
+
subscribe(event: string, callback: (data: unknown) => void): () => void;
|
|
32
|
+
/**
|
|
33
|
+
* Start the read loop. Runs until stdin closes (EOF).
|
|
34
|
+
*
|
|
35
|
+
* Must be running for `call()` and `subscribe()` to receive responses.
|
|
36
|
+
* The returned promise resolves on clean disconnect, rejects on read errors.
|
|
37
|
+
*/
|
|
38
|
+
run(): Promise<void>;
|
|
39
|
+
private send;
|
|
40
|
+
private cleanup;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/sdk/client.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC;AAOD;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,2BAA2B,CAAS;IAC5C,OAAO,CAAC,2BAA2B,CAAS;gBAEhC,IAAI,CAAC,EAAE,mBAAmB;IAOtC,wDAAwD;IAClD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAahE;;;;;OAKG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAevE;;;;;OAKG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAkD1B,OAAO,CAAC,IAAI;IAMZ,OAAO,CAAC,OAAO;CAQhB"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { readMessageWithOptions, writeMessageWithOptions } from '../native/stdio.js';
|
|
3
|
+
import { MAX_MESSAGE_SIZE_BYTES } from '../protocol/constants.js';
|
|
4
|
+
/**
|
|
5
|
+
* RPC client for calling Chrome APIs over native messaging.
|
|
6
|
+
*
|
|
7
|
+
* Sends call/subscribe/unsubscribe messages to Chrome and routes
|
|
8
|
+
* incoming result/error/event responses to the correct handlers.
|
|
9
|
+
*/
|
|
10
|
+
export class ChromeClient {
|
|
11
|
+
input;
|
|
12
|
+
output;
|
|
13
|
+
pendingCalls = new Map();
|
|
14
|
+
eventCallbacks = new Map();
|
|
15
|
+
closed = false;
|
|
16
|
+
maxIncomingMessageSizeBytes;
|
|
17
|
+
maxOutgoingMessageSizeBytes;
|
|
18
|
+
constructor(opts) {
|
|
19
|
+
this.input = opts?.input;
|
|
20
|
+
this.output = opts?.output;
|
|
21
|
+
this.maxIncomingMessageSizeBytes = opts?.maxIncomingMessageSizeBytes ?? MAX_MESSAGE_SIZE_BYTES;
|
|
22
|
+
this.maxOutgoingMessageSizeBytes = opts?.maxOutgoingMessageSizeBytes ?? MAX_MESSAGE_SIZE_BYTES;
|
|
23
|
+
}
|
|
24
|
+
/** Call a Chrome API method and wait for the result. */
|
|
25
|
+
async call(method, ...args) {
|
|
26
|
+
if (this.closed) {
|
|
27
|
+
throw new Error('ChromeClient connection is closed');
|
|
28
|
+
}
|
|
29
|
+
const id = randomUUID();
|
|
30
|
+
this.send({ id, type: 'call', method, args });
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
this.pendingCalls.set(id, { resolve, reject });
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Subscribe to a Chrome event. Returns an unsubscribe function.
|
|
37
|
+
*
|
|
38
|
+
* The callback is invoked with the event arguments array each time
|
|
39
|
+
* the Chrome event fires.
|
|
40
|
+
*/
|
|
41
|
+
subscribe(event, callback) {
|
|
42
|
+
if (this.closed) {
|
|
43
|
+
throw new Error('ChromeClient connection is closed');
|
|
44
|
+
}
|
|
45
|
+
const id = randomUUID();
|
|
46
|
+
this.send({ id, type: 'subscribe', event });
|
|
47
|
+
this.eventCallbacks.set(id, callback);
|
|
48
|
+
return () => {
|
|
49
|
+
this.send({ id, type: 'unsubscribe' });
|
|
50
|
+
this.eventCallbacks.delete(id);
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Start the read loop. Runs until stdin closes (EOF).
|
|
55
|
+
*
|
|
56
|
+
* Must be running for `call()` and `subscribe()` to receive responses.
|
|
57
|
+
* The returned promise resolves on clean disconnect, rejects on read errors.
|
|
58
|
+
*/
|
|
59
|
+
async run() {
|
|
60
|
+
while (true) {
|
|
61
|
+
let message;
|
|
62
|
+
try {
|
|
63
|
+
message = await readMessageWithOptions(this.input, {
|
|
64
|
+
maxMessageSizeBytes: this.maxIncomingMessageSizeBytes,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
this.cleanup(error instanceof Error ? error : new Error(String(error)));
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
if (message === null) {
|
|
72
|
+
this.cleanup(new Error('Connection closed'));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
switch (message.type) {
|
|
76
|
+
case 'result': {
|
|
77
|
+
const pending = this.pendingCalls.get(message.id);
|
|
78
|
+
if (pending) {
|
|
79
|
+
this.pendingCalls.delete(message.id);
|
|
80
|
+
pending.resolve(message.data);
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case 'error': {
|
|
85
|
+
const pending = this.pendingCalls.get(message.id);
|
|
86
|
+
if (pending) {
|
|
87
|
+
this.pendingCalls.delete(message.id);
|
|
88
|
+
pending.reject(new Error(message.error));
|
|
89
|
+
}
|
|
90
|
+
// If error was for a subscription setup, clean it up
|
|
91
|
+
if (this.eventCallbacks.has(message.id)) {
|
|
92
|
+
this.eventCallbacks.delete(message.id);
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
case 'event': {
|
|
97
|
+
const callback = this.eventCallbacks.get(message.id);
|
|
98
|
+
callback?.(message.data);
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
send(message) {
|
|
105
|
+
writeMessageWithOptions(message, this.output, {
|
|
106
|
+
maxMessageSizeBytes: this.maxOutgoingMessageSizeBytes,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
cleanup(error) {
|
|
110
|
+
this.closed = true;
|
|
111
|
+
for (const [, pending] of this.pendingCalls) {
|
|
112
|
+
pending.reject(error);
|
|
113
|
+
}
|
|
114
|
+
this.pendingCalls.clear();
|
|
115
|
+
this.eventCallbacks.clear();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/sdk/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ChromeClient } from './client.js';
|
|
2
|
+
export interface ConnectOptions {
|
|
3
|
+
port?: number;
|
|
4
|
+
host?: string;
|
|
5
|
+
/** Launch Chrome automatically if connection fails. Default: false */
|
|
6
|
+
launch?: boolean;
|
|
7
|
+
/** Max ms to wait for Chrome + native host to be ready. Default: 30000 */
|
|
8
|
+
launchTimeout?: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Connect to the Chrome RPC server over TCP.
|
|
12
|
+
*
|
|
13
|
+
* Returns a ChromeClient with the same `call()` and `subscribe()` API
|
|
14
|
+
* as the native host uses directly. The connection is multiplexed —
|
|
15
|
+
* multiple calls and subscriptions can be in-flight simultaneously.
|
|
16
|
+
*
|
|
17
|
+
* When `launch: true` is set, Chrome will be opened automatically
|
|
18
|
+
* if the connection fails, then retried until the native host is ready.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { connect } from '@ank1015/llm-extension';
|
|
23
|
+
*
|
|
24
|
+
* const chrome = await connect({ launch: true });
|
|
25
|
+
* const tabs = await chrome.call('tabs.query', { active: true });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function connect(opts?: ConnectOptions): Promise<ChromeClient>;
|
|
29
|
+
//# sourceMappingURL=connect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/sdk/connect.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,OAAO,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAgC1E"}
|