opensteer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/README.md +156 -0
- package/bin/opensteer.mjs +388 -0
- package/dist/chunk-3H5RRIMZ.js +69 -0
- package/dist/chunk-6L24FEKD.js +9233 -0
- package/dist/chunk-DQIHOUXH.js +61 -0
- package/dist/chunk-L4FHT64T.js +109 -0
- package/dist/chunk-SRJLH34D.js +56 -0
- package/dist/cli/server.cjs +9921 -0
- package/dist/cli/server.d.cts +2 -0
- package/dist/cli/server.d.ts +2 -0
- package/dist/cli/server.js +433 -0
- package/dist/extractor-K5VU7HVC.js +8 -0
- package/dist/index.cjs +9659 -0
- package/dist/index.d.cts +718 -0
- package/dist/index.d.ts +718 -0
- package/dist/index.js +153 -0
- package/dist/resolver-WGFFHW4N.js +7 -0
- package/package.json +82 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Opensteer
|
|
3
|
+
} from "../chunk-6L24FEKD.js";
|
|
4
|
+
import "../chunk-3H5RRIMZ.js";
|
|
5
|
+
|
|
6
|
+
// src/cli/server.ts
|
|
7
|
+
import { createServer } from "net";
|
|
8
|
+
import { writeFileSync, unlinkSync, existsSync } from "fs";
|
|
9
|
+
|
|
10
|
+
// src/cli/paths.ts
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
import { homedir } from "os";
|
|
13
|
+
import { mkdirSync } from "fs";
|
|
14
|
+
function getRuntimeDir() {
|
|
15
|
+
const dir = join(homedir(), ".opensteer");
|
|
16
|
+
mkdirSync(dir, { recursive: true });
|
|
17
|
+
return dir;
|
|
18
|
+
}
|
|
19
|
+
function getSocketPath() {
|
|
20
|
+
return join(getRuntimeDir(), "opensteer.sock");
|
|
21
|
+
}
|
|
22
|
+
function getPidPath() {
|
|
23
|
+
return join(getRuntimeDir(), "opensteer.pid");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/cli/commands.ts
|
|
27
|
+
import { writeFile } from "fs/promises";
|
|
28
|
+
var commands = {
|
|
29
|
+
async navigate(opensteer, args) {
|
|
30
|
+
const url = args.url;
|
|
31
|
+
if (!url) throw new Error("Missing required argument: url");
|
|
32
|
+
await opensteer.goto(url, {
|
|
33
|
+
timeout: args.timeout,
|
|
34
|
+
settleMs: args.settleMs,
|
|
35
|
+
waitUntil: args.waitUntil
|
|
36
|
+
});
|
|
37
|
+
return { url: opensteer.page.url() };
|
|
38
|
+
},
|
|
39
|
+
async back(opensteer) {
|
|
40
|
+
await opensteer.page.goBack();
|
|
41
|
+
return { url: opensteer.page.url() };
|
|
42
|
+
},
|
|
43
|
+
async forward(opensteer) {
|
|
44
|
+
await opensteer.page.goForward();
|
|
45
|
+
return { url: opensteer.page.url() };
|
|
46
|
+
},
|
|
47
|
+
async reload(opensteer) {
|
|
48
|
+
await opensteer.page.reload();
|
|
49
|
+
return { url: opensteer.page.url() };
|
|
50
|
+
},
|
|
51
|
+
async snapshot(opensteer, args) {
|
|
52
|
+
const mode = args.mode || "action";
|
|
53
|
+
const html = await opensteer.snapshot({ mode });
|
|
54
|
+
return { html };
|
|
55
|
+
},
|
|
56
|
+
async state(opensteer) {
|
|
57
|
+
return await opensteer.state();
|
|
58
|
+
},
|
|
59
|
+
async screenshot(opensteer, args) {
|
|
60
|
+
const file = args.file || "screenshot.png";
|
|
61
|
+
const type = file.endsWith(".jpg") || file.endsWith(".jpeg") ? "jpeg" : "png";
|
|
62
|
+
const buffer = await opensteer.screenshot({
|
|
63
|
+
fullPage: args.fullPage,
|
|
64
|
+
type
|
|
65
|
+
});
|
|
66
|
+
await writeFile(file, buffer);
|
|
67
|
+
return { file };
|
|
68
|
+
},
|
|
69
|
+
async click(opensteer, args) {
|
|
70
|
+
return await opensteer.click({
|
|
71
|
+
element: args.element,
|
|
72
|
+
selector: args.selector,
|
|
73
|
+
description: args.description,
|
|
74
|
+
button: args.button,
|
|
75
|
+
clickCount: args.clickCount
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
async dblclick(opensteer, args) {
|
|
79
|
+
return await opensteer.dblclick({
|
|
80
|
+
element: args.element,
|
|
81
|
+
selector: args.selector,
|
|
82
|
+
description: args.description
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
async rightclick(opensteer, args) {
|
|
86
|
+
return await opensteer.rightclick({
|
|
87
|
+
element: args.element,
|
|
88
|
+
selector: args.selector,
|
|
89
|
+
description: args.description
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
async hover(opensteer, args) {
|
|
93
|
+
return await opensteer.hover({
|
|
94
|
+
element: args.element,
|
|
95
|
+
selector: args.selector,
|
|
96
|
+
description: args.description
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
async input(opensteer, args) {
|
|
100
|
+
const text = args.text;
|
|
101
|
+
if (text == null) throw new Error("Missing required argument: text");
|
|
102
|
+
return await opensteer.input({
|
|
103
|
+
element: args.element,
|
|
104
|
+
selector: args.selector,
|
|
105
|
+
description: args.description,
|
|
106
|
+
text,
|
|
107
|
+
clear: args.clear,
|
|
108
|
+
pressEnter: args.pressEnter
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
async select(opensteer, args) {
|
|
112
|
+
return await opensteer.select({
|
|
113
|
+
element: args.element,
|
|
114
|
+
selector: args.selector,
|
|
115
|
+
description: args.description,
|
|
116
|
+
value: args.value,
|
|
117
|
+
label: args.label,
|
|
118
|
+
index: args.index
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
async scroll(opensteer, args) {
|
|
122
|
+
return await opensteer.scroll({
|
|
123
|
+
element: args.element,
|
|
124
|
+
selector: args.selector,
|
|
125
|
+
description: args.description,
|
|
126
|
+
direction: args.direction,
|
|
127
|
+
amount: args.amount
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
async press(opensteer, args) {
|
|
131
|
+
const key = args.key;
|
|
132
|
+
if (!key) throw new Error("Missing required argument: key");
|
|
133
|
+
await opensteer.pressKey(key);
|
|
134
|
+
return { key };
|
|
135
|
+
},
|
|
136
|
+
async type(opensteer, args) {
|
|
137
|
+
const text = args.text;
|
|
138
|
+
if (text == null) throw new Error("Missing required argument: text");
|
|
139
|
+
await opensteer.type(text);
|
|
140
|
+
return { text };
|
|
141
|
+
},
|
|
142
|
+
async "get-text"(opensteer, args) {
|
|
143
|
+
const text = await opensteer.getElementText({
|
|
144
|
+
element: args.element,
|
|
145
|
+
selector: args.selector,
|
|
146
|
+
description: args.description
|
|
147
|
+
});
|
|
148
|
+
return { text };
|
|
149
|
+
},
|
|
150
|
+
async "get-value"(opensteer, args) {
|
|
151
|
+
const value = await opensteer.getElementValue({
|
|
152
|
+
element: args.element,
|
|
153
|
+
selector: args.selector,
|
|
154
|
+
description: args.description
|
|
155
|
+
});
|
|
156
|
+
return { value };
|
|
157
|
+
},
|
|
158
|
+
async "get-attrs"(opensteer, args) {
|
|
159
|
+
const attributes = await opensteer.getElementAttributes({
|
|
160
|
+
element: args.element,
|
|
161
|
+
selector: args.selector,
|
|
162
|
+
description: args.description
|
|
163
|
+
});
|
|
164
|
+
return { attributes };
|
|
165
|
+
},
|
|
166
|
+
async "get-html"(opensteer, args) {
|
|
167
|
+
const html = await opensteer.getHtml(args.selector);
|
|
168
|
+
return { html };
|
|
169
|
+
},
|
|
170
|
+
async tabs(opensteer) {
|
|
171
|
+
const tabs = await opensteer.tabs();
|
|
172
|
+
return { tabs };
|
|
173
|
+
},
|
|
174
|
+
async "tab-new"(opensteer, args) {
|
|
175
|
+
return await opensteer.newTab(args.url);
|
|
176
|
+
},
|
|
177
|
+
async "tab-switch"(opensteer, args) {
|
|
178
|
+
const index = args.index;
|
|
179
|
+
if (index == null) throw new Error("Missing required argument: index");
|
|
180
|
+
await opensteer.switchTab(index);
|
|
181
|
+
return { index };
|
|
182
|
+
},
|
|
183
|
+
async "tab-close"(opensteer, args) {
|
|
184
|
+
await opensteer.closeTab(args.index);
|
|
185
|
+
return {};
|
|
186
|
+
},
|
|
187
|
+
async cookies(opensteer, args) {
|
|
188
|
+
const cookies = await opensteer.getCookies(args.url);
|
|
189
|
+
return { cookies };
|
|
190
|
+
},
|
|
191
|
+
async "cookie-set"(opensteer, args) {
|
|
192
|
+
await opensteer.setCookie({
|
|
193
|
+
name: args.name,
|
|
194
|
+
value: args.value,
|
|
195
|
+
url: args.url,
|
|
196
|
+
domain: args.domain,
|
|
197
|
+
path: args.path,
|
|
198
|
+
expires: args.expires,
|
|
199
|
+
httpOnly: args.httpOnly,
|
|
200
|
+
secure: args.secure,
|
|
201
|
+
sameSite: args.sameSite
|
|
202
|
+
});
|
|
203
|
+
return {};
|
|
204
|
+
},
|
|
205
|
+
async "cookies-clear"(opensteer) {
|
|
206
|
+
await opensteer.clearCookies();
|
|
207
|
+
return {};
|
|
208
|
+
},
|
|
209
|
+
async "cookies-export"(opensteer, args) {
|
|
210
|
+
const file = args.file;
|
|
211
|
+
if (!file) throw new Error("Missing required argument: file");
|
|
212
|
+
await opensteer.exportCookies(file, args.url);
|
|
213
|
+
return { file };
|
|
214
|
+
},
|
|
215
|
+
async "cookies-import"(opensteer, args) {
|
|
216
|
+
const file = args.file;
|
|
217
|
+
if (!file) throw new Error("Missing required argument: file");
|
|
218
|
+
await opensteer.importCookies(file);
|
|
219
|
+
return { file };
|
|
220
|
+
},
|
|
221
|
+
async eval(opensteer, args) {
|
|
222
|
+
const expression = args.expression;
|
|
223
|
+
if (!expression)
|
|
224
|
+
throw new Error("Missing required argument: expression");
|
|
225
|
+
const result = await opensteer.page.evaluate(expression);
|
|
226
|
+
return { result };
|
|
227
|
+
},
|
|
228
|
+
async "wait-for"(opensteer, args) {
|
|
229
|
+
const text = args.text;
|
|
230
|
+
if (!text) throw new Error("Missing required argument: text");
|
|
231
|
+
await opensteer.waitForText(text, {
|
|
232
|
+
timeout: args.timeout
|
|
233
|
+
});
|
|
234
|
+
return { text };
|
|
235
|
+
},
|
|
236
|
+
async "wait-selector"(opensteer, args) {
|
|
237
|
+
const selector = args.selector;
|
|
238
|
+
if (!selector) throw new Error("Missing required argument: selector");
|
|
239
|
+
await opensteer.page.waitForSelector(selector, {
|
|
240
|
+
timeout: args.timeout ?? 3e4
|
|
241
|
+
});
|
|
242
|
+
return { selector };
|
|
243
|
+
},
|
|
244
|
+
async extract(opensteer, args) {
|
|
245
|
+
const schema = args.schema;
|
|
246
|
+
const data = await opensteer.extract({
|
|
247
|
+
schema,
|
|
248
|
+
description: args.description,
|
|
249
|
+
prompt: args.prompt
|
|
250
|
+
});
|
|
251
|
+
return { data };
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
function getCommandHandler(name) {
|
|
255
|
+
return commands[name];
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// src/cli/server.ts
|
|
259
|
+
var instance = null;
|
|
260
|
+
var launchPromise = null;
|
|
261
|
+
var socketPath = getSocketPath();
|
|
262
|
+
var pidPath = getPidPath();
|
|
263
|
+
function cleanup() {
|
|
264
|
+
try {
|
|
265
|
+
unlinkSync(socketPath);
|
|
266
|
+
} catch {
|
|
267
|
+
}
|
|
268
|
+
try {
|
|
269
|
+
unlinkSync(pidPath);
|
|
270
|
+
} catch {
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function sendResponse(socket, response) {
|
|
274
|
+
try {
|
|
275
|
+
socket.write(JSON.stringify(response) + "\n");
|
|
276
|
+
} catch {
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async function handleRequest(request, socket) {
|
|
280
|
+
const { id, command, args } = request;
|
|
281
|
+
if (command === "open") {
|
|
282
|
+
try {
|
|
283
|
+
const url = args.url;
|
|
284
|
+
const headless = args.headless;
|
|
285
|
+
const name = args.name;
|
|
286
|
+
const connectUrl = args["connect-url"];
|
|
287
|
+
const channel = args.channel;
|
|
288
|
+
const profileDir = args["profile-dir"];
|
|
289
|
+
if (!instance) {
|
|
290
|
+
instance = new Opensteer({
|
|
291
|
+
name: name ?? "cli",
|
|
292
|
+
browser: {
|
|
293
|
+
headless: headless ?? false,
|
|
294
|
+
connectUrl,
|
|
295
|
+
channel,
|
|
296
|
+
profileDir
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
launchPromise = instance.launch({
|
|
300
|
+
headless: headless ?? false,
|
|
301
|
+
timeout: connectUrl ? 12e4 : 3e4
|
|
302
|
+
});
|
|
303
|
+
try {
|
|
304
|
+
await launchPromise;
|
|
305
|
+
} catch (err) {
|
|
306
|
+
instance = null;
|
|
307
|
+
throw err;
|
|
308
|
+
} finally {
|
|
309
|
+
launchPromise = null;
|
|
310
|
+
}
|
|
311
|
+
} else if (launchPromise) {
|
|
312
|
+
await launchPromise;
|
|
313
|
+
}
|
|
314
|
+
if (url) {
|
|
315
|
+
await instance.page.goto(url);
|
|
316
|
+
}
|
|
317
|
+
sendResponse(socket, {
|
|
318
|
+
id,
|
|
319
|
+
ok: true,
|
|
320
|
+
result: { url: instance.page.url() }
|
|
321
|
+
});
|
|
322
|
+
} catch (err) {
|
|
323
|
+
sendResponse(socket, {
|
|
324
|
+
id,
|
|
325
|
+
ok: false,
|
|
326
|
+
error: err instanceof Error ? err.message : String(err)
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (command === "close") {
|
|
332
|
+
try {
|
|
333
|
+
if (instance) {
|
|
334
|
+
await instance.close();
|
|
335
|
+
instance = null;
|
|
336
|
+
}
|
|
337
|
+
sendResponse(socket, { id, ok: true, result: {} });
|
|
338
|
+
} catch (err) {
|
|
339
|
+
sendResponse(socket, {
|
|
340
|
+
id,
|
|
341
|
+
ok: false,
|
|
342
|
+
error: err instanceof Error ? err.message : String(err)
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
setTimeout(() => {
|
|
346
|
+
cleanup();
|
|
347
|
+
process.exit(0);
|
|
348
|
+
}, 100);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (command === "ping") {
|
|
352
|
+
sendResponse(socket, { id, ok: true, result: { pong: true } });
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
if (!instance) {
|
|
356
|
+
sendResponse(socket, {
|
|
357
|
+
id,
|
|
358
|
+
ok: false,
|
|
359
|
+
error: "No browser session. Call 'opensteer open' first."
|
|
360
|
+
});
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
const handler = getCommandHandler(command);
|
|
364
|
+
if (!handler) {
|
|
365
|
+
sendResponse(socket, {
|
|
366
|
+
id,
|
|
367
|
+
ok: false,
|
|
368
|
+
error: `Unknown command: ${command}`
|
|
369
|
+
});
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
try {
|
|
373
|
+
const result = await handler(instance, args);
|
|
374
|
+
sendResponse(socket, { id, ok: true, result });
|
|
375
|
+
} catch (err) {
|
|
376
|
+
sendResponse(socket, {
|
|
377
|
+
id,
|
|
378
|
+
ok: false,
|
|
379
|
+
error: err instanceof Error ? err.message : String(err)
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if (existsSync(socketPath)) {
|
|
384
|
+
unlinkSync(socketPath);
|
|
385
|
+
}
|
|
386
|
+
var server = createServer((socket) => {
|
|
387
|
+
let buffer = "";
|
|
388
|
+
socket.on("data", (chunk) => {
|
|
389
|
+
buffer += chunk.toString();
|
|
390
|
+
const lines = buffer.split("\n");
|
|
391
|
+
buffer = lines.pop() || "";
|
|
392
|
+
for (const line of lines) {
|
|
393
|
+
if (!line.trim()) continue;
|
|
394
|
+
try {
|
|
395
|
+
const request = JSON.parse(line);
|
|
396
|
+
handleRequest(request, socket);
|
|
397
|
+
} catch {
|
|
398
|
+
sendResponse(socket, {
|
|
399
|
+
id: 0,
|
|
400
|
+
ok: false,
|
|
401
|
+
error: "Invalid JSON request"
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
socket.on("error", () => {
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
server.listen(socketPath, () => {
|
|
410
|
+
writeFileSync(pidPath, String(process.pid));
|
|
411
|
+
if (process.send) {
|
|
412
|
+
process.send("ready");
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
server.on("error", (err) => {
|
|
416
|
+
console.error("Server error:", err.message);
|
|
417
|
+
cleanup();
|
|
418
|
+
process.exit(1);
|
|
419
|
+
});
|
|
420
|
+
async function shutdown() {
|
|
421
|
+
if (instance) {
|
|
422
|
+
try {
|
|
423
|
+
await instance.close();
|
|
424
|
+
} catch {
|
|
425
|
+
}
|
|
426
|
+
instance = null;
|
|
427
|
+
}
|
|
428
|
+
server.close();
|
|
429
|
+
cleanup();
|
|
430
|
+
process.exit(0);
|
|
431
|
+
}
|
|
432
|
+
process.on("SIGTERM", shutdown);
|
|
433
|
+
process.on("SIGINT", shutdown);
|