opensteer 0.1.0 → 0.3.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/bin/opensteer.mjs +187 -28
- package/dist/{chunk-6L24FEKD.js → chunk-2NKR4JZ6.js} +3 -0
- package/dist/cli/server.cjs +57 -45
- package/dist/cli/server.js +26 -17
- package/dist/index.cjs +3 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/bin/opensteer.mjs
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { connect } from 'net'
|
|
4
3
|
import { spawn } from 'child_process'
|
|
5
|
-
import { existsSync, readFileSync,
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
4
|
+
import { existsSync, readFileSync, readdirSync, unlinkSync } from 'fs'
|
|
5
|
+
import { connect } from 'net'
|
|
6
|
+
import { tmpdir } from 'os'
|
|
7
|
+
import { basename, dirname, join } from 'path'
|
|
8
8
|
import { fileURLToPath } from 'url'
|
|
9
9
|
|
|
10
10
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
11
|
-
|
|
12
|
-
const RUNTIME_DIR = join(homedir(), '.opensteer')
|
|
13
|
-
const SOCKET_PATH = join(RUNTIME_DIR, 'opensteer.sock')
|
|
14
|
-
const PID_PATH = join(RUNTIME_DIR, 'opensteer.pid')
|
|
15
11
|
const SERVER_SCRIPT = join(__dirname, '..', 'dist', 'cli', 'server.js')
|
|
16
12
|
|
|
17
13
|
const CONNECT_TIMEOUT = 15000
|
|
18
14
|
const POLL_INTERVAL = 100
|
|
19
15
|
const RESPONSE_TIMEOUT = 120000
|
|
16
|
+
const RUNTIME_PREFIX = 'opensteer-'
|
|
17
|
+
const SOCKET_SUFFIX = '.sock'
|
|
18
|
+
const PID_SUFFIX = '.pid'
|
|
19
|
+
const CLOSE_ALL_REQUEST = { id: 1, command: 'close', args: {} }
|
|
20
20
|
|
|
21
21
|
function parseArgs(argv) {
|
|
22
22
|
const args = argv.slice(2)
|
|
@@ -56,10 +56,51 @@ function parseValue(str) {
|
|
|
56
56
|
return str
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
function sanitizeNamespace(value) {
|
|
60
|
+
const trimmed = String(value || '').trim()
|
|
61
|
+
if (!trimmed || trimmed === '.' || trimmed === '..') {
|
|
62
|
+
return 'default'
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const replaced = trimmed.replace(/[^a-zA-Z0-9_-]+/g, '_')
|
|
66
|
+
const collapsed = replaced.replace(/_+/g, '_')
|
|
67
|
+
const bounded = collapsed.replace(/^_+|_+$/g, '')
|
|
68
|
+
|
|
69
|
+
return bounded || 'default'
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function resolveNamespace(flags) {
|
|
73
|
+
if (flags.name !== undefined && String(flags.name).trim().length > 0) {
|
|
74
|
+
return sanitizeNamespace(String(flags.name))
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (
|
|
78
|
+
typeof process.env.OPENSTEER_NAME === 'string' &&
|
|
79
|
+
process.env.OPENSTEER_NAME.trim().length > 0
|
|
80
|
+
) {
|
|
81
|
+
return sanitizeNamespace(process.env.OPENSTEER_NAME)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const cwdBase = basename(process.cwd())
|
|
85
|
+
if (cwdBase && cwdBase !== '.' && cwdBase !== '/') {
|
|
86
|
+
return sanitizeNamespace(cwdBase)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return 'default'
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function getSocketPath(namespace) {
|
|
93
|
+
return join(tmpdir(), `${RUNTIME_PREFIX}${namespace}${SOCKET_SUFFIX}`)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function getPidPath(namespace) {
|
|
97
|
+
return join(tmpdir(), `${RUNTIME_PREFIX}${namespace}${PID_SUFFIX}`)
|
|
98
|
+
}
|
|
99
|
+
|
|
59
100
|
function buildRequest(command, flags, positional) {
|
|
60
101
|
const id = 1
|
|
61
102
|
const globalFlags = {}
|
|
62
|
-
for (const key of ['
|
|
103
|
+
for (const key of ['headless', 'json', 'connect-url', 'channel', 'profile-dir']) {
|
|
63
104
|
if (key in flags) {
|
|
64
105
|
globalFlags[key] = flags[key]
|
|
65
106
|
delete flags[key]
|
|
@@ -165,38 +206,66 @@ function buildRequest(command, flags, positional) {
|
|
|
165
206
|
return { id, command, args }
|
|
166
207
|
}
|
|
167
208
|
|
|
168
|
-
function
|
|
169
|
-
if (!existsSync(
|
|
209
|
+
function readPid(pidPath) {
|
|
210
|
+
if (!existsSync(pidPath)) {
|
|
211
|
+
return null
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const parsed = Number.parseInt(readFileSync(pidPath, 'utf-8').trim(), 10)
|
|
215
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
216
|
+
return null
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return parsed
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function isPidAlive(pid) {
|
|
170
223
|
try {
|
|
171
|
-
const pid = parseInt(readFileSync(PID_PATH, 'utf-8').trim(), 10)
|
|
172
224
|
process.kill(pid, 0)
|
|
173
225
|
return true
|
|
174
226
|
} catch {
|
|
175
|
-
cleanStaleFiles()
|
|
176
227
|
return false
|
|
177
228
|
}
|
|
178
229
|
}
|
|
179
230
|
|
|
180
|
-
function cleanStaleFiles() {
|
|
231
|
+
function cleanStaleFiles(namespace) {
|
|
181
232
|
try {
|
|
182
|
-
unlinkSync(
|
|
233
|
+
unlinkSync(getSocketPath(namespace))
|
|
183
234
|
} catch { }
|
|
184
235
|
try {
|
|
185
|
-
unlinkSync(
|
|
236
|
+
unlinkSync(getPidPath(namespace))
|
|
186
237
|
} catch { }
|
|
187
238
|
}
|
|
188
239
|
|
|
189
|
-
function
|
|
190
|
-
|
|
240
|
+
function isServerRunning(namespace) {
|
|
241
|
+
const pidPath = getPidPath(namespace)
|
|
242
|
+
const pid = readPid(pidPath)
|
|
243
|
+
if (!pid) {
|
|
244
|
+
cleanStaleFiles(namespace)
|
|
245
|
+
return false
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (!isPidAlive(pid)) {
|
|
249
|
+
cleanStaleFiles(namespace)
|
|
250
|
+
return false
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return existsSync(getSocketPath(namespace))
|
|
254
|
+
}
|
|
191
255
|
|
|
256
|
+
function startServer(namespace) {
|
|
192
257
|
const child = spawn('node', [SERVER_SCRIPT], {
|
|
193
258
|
detached: true,
|
|
194
259
|
stdio: ['ignore', 'ignore', 'ignore'],
|
|
260
|
+
env: {
|
|
261
|
+
...process.env,
|
|
262
|
+
OPENSTEER_NAME: namespace,
|
|
263
|
+
},
|
|
195
264
|
})
|
|
196
265
|
child.unref()
|
|
197
266
|
}
|
|
198
267
|
|
|
199
|
-
function waitForSocket(timeout) {
|
|
268
|
+
function waitForSocket(socketPath, timeout) {
|
|
200
269
|
return new Promise((resolve, reject) => {
|
|
201
270
|
const start = Date.now()
|
|
202
271
|
|
|
@@ -206,7 +275,7 @@ function waitForSocket(timeout) {
|
|
|
206
275
|
return
|
|
207
276
|
}
|
|
208
277
|
|
|
209
|
-
if (existsSync(
|
|
278
|
+
if (existsSync(socketPath)) {
|
|
210
279
|
resolve()
|
|
211
280
|
return
|
|
212
281
|
}
|
|
@@ -218,9 +287,9 @@ function waitForSocket(timeout) {
|
|
|
218
287
|
})
|
|
219
288
|
}
|
|
220
289
|
|
|
221
|
-
function sendCommand(request) {
|
|
290
|
+
function sendCommand(socketPath, request) {
|
|
222
291
|
return new Promise((resolve, reject) => {
|
|
223
|
-
const socket = connect(
|
|
292
|
+
const socket = connect(socketPath)
|
|
224
293
|
let buffer = ''
|
|
225
294
|
let settled = false
|
|
226
295
|
|
|
@@ -270,6 +339,71 @@ function sendCommand(request) {
|
|
|
270
339
|
})
|
|
271
340
|
}
|
|
272
341
|
|
|
342
|
+
function listSessions() {
|
|
343
|
+
const sessions = []
|
|
344
|
+
const entries = readdirSync(tmpdir())
|
|
345
|
+
|
|
346
|
+
for (const entry of entries) {
|
|
347
|
+
if (!entry.startsWith(RUNTIME_PREFIX) || !entry.endsWith(PID_SUFFIX)) {
|
|
348
|
+
continue
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const name = entry.slice(
|
|
352
|
+
RUNTIME_PREFIX.length,
|
|
353
|
+
entry.length - PID_SUFFIX.length
|
|
354
|
+
)
|
|
355
|
+
if (!name) {
|
|
356
|
+
continue
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const pid = readPid(join(tmpdir(), entry))
|
|
360
|
+
if (!pid || !isPidAlive(pid)) {
|
|
361
|
+
cleanStaleFiles(name)
|
|
362
|
+
continue
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
sessions.push({ name, pid })
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
sessions.sort((a, b) => a.name.localeCompare(b.name))
|
|
369
|
+
return sessions
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
async function closeAllSessions() {
|
|
373
|
+
const sessions = listSessions()
|
|
374
|
+
const closed = []
|
|
375
|
+
const failures = []
|
|
376
|
+
|
|
377
|
+
for (const session of sessions) {
|
|
378
|
+
const socketPath = getSocketPath(session.name)
|
|
379
|
+
if (!existsSync(socketPath)) {
|
|
380
|
+
cleanStaleFiles(session.name)
|
|
381
|
+
continue
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
try {
|
|
385
|
+
const response = await sendCommand(socketPath, CLOSE_ALL_REQUEST)
|
|
386
|
+
if (response && response.ok === true) {
|
|
387
|
+
closed.push(session)
|
|
388
|
+
} else {
|
|
389
|
+
failures.push(
|
|
390
|
+
`${session.name}: ${response?.error || 'unknown close error'}`
|
|
391
|
+
)
|
|
392
|
+
}
|
|
393
|
+
} catch (err) {
|
|
394
|
+
failures.push(
|
|
395
|
+
`${session.name}: ${err instanceof Error ? err.message : String(err)}`
|
|
396
|
+
)
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (failures.length > 0) {
|
|
401
|
+
throw new Error(`Failed to close sessions: ${failures.join('; ')}`)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return closed
|
|
405
|
+
}
|
|
406
|
+
|
|
273
407
|
function output(data) {
|
|
274
408
|
process.stdout.write(JSON.stringify(data) + '\n')
|
|
275
409
|
}
|
|
@@ -289,6 +423,10 @@ Navigation:
|
|
|
289
423
|
forward Go forward
|
|
290
424
|
reload Reload page
|
|
291
425
|
close Close browser and server
|
|
426
|
+
close --all Close all active namespace-scoped servers
|
|
427
|
+
|
|
428
|
+
Sessions:
|
|
429
|
+
sessions List active namespace-scoped sessions
|
|
292
430
|
|
|
293
431
|
Observation:
|
|
294
432
|
snapshot [--mode action] Get page snapshot
|
|
@@ -334,7 +472,7 @@ Utility:
|
|
|
334
472
|
extract <schema-json> Extract structured data
|
|
335
473
|
|
|
336
474
|
Global Flags:
|
|
337
|
-
--name <namespace>
|
|
475
|
+
--name <namespace> Session namespace (default: CWD basename or OPENSTEER_NAME)
|
|
338
476
|
--headless Launch browser in headless mode
|
|
339
477
|
--connect-url <url> Connect to a running browser (e.g. http://localhost:9222)
|
|
340
478
|
--channel <browser> Use installed browser (chrome, chrome-beta, msedge)
|
|
@@ -345,6 +483,7 @@ Global Flags:
|
|
|
345
483
|
--help Show this help
|
|
346
484
|
|
|
347
485
|
Environment:
|
|
486
|
+
OPENSTEER_NAME Default session namespace when --name is omitted
|
|
348
487
|
OPENSTEER_MODE Runtime mode: "local" (default) or "remote"
|
|
349
488
|
OPENSTEER_API_KEY Required when remote mode is selected
|
|
350
489
|
OPENSTEER_BASE_URL Override remote control-plane base URL
|
|
@@ -353,24 +492,44 @@ Environment:
|
|
|
353
492
|
|
|
354
493
|
async function main() {
|
|
355
494
|
const { command, flags, positional } = parseArgs(process.argv)
|
|
495
|
+
const namespace = resolveNamespace(flags)
|
|
496
|
+
const socketPath = getSocketPath(namespace)
|
|
497
|
+
|
|
498
|
+
if (command === 'sessions') {
|
|
499
|
+
output({ ok: true, sessions: listSessions() })
|
|
500
|
+
return
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (command === 'close' && flags.all === true) {
|
|
504
|
+
try {
|
|
505
|
+
const closed = await closeAllSessions()
|
|
506
|
+
output({ ok: true, closed })
|
|
507
|
+
} catch (err) {
|
|
508
|
+
error(err instanceof Error ? err.message : 'Failed to close sessions')
|
|
509
|
+
}
|
|
510
|
+
return
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
delete flags.name
|
|
514
|
+
delete flags.all
|
|
356
515
|
const request = buildRequest(command, flags, positional)
|
|
357
516
|
|
|
358
|
-
if (!isServerRunning()) {
|
|
517
|
+
if (!isServerRunning(namespace)) {
|
|
359
518
|
if (!existsSync(SERVER_SCRIPT)) {
|
|
360
519
|
error(
|
|
361
520
|
`Server script not found: ${SERVER_SCRIPT}. Run the build script first.`
|
|
362
521
|
)
|
|
363
522
|
}
|
|
364
|
-
startServer()
|
|
523
|
+
startServer(namespace)
|
|
365
524
|
try {
|
|
366
|
-
await waitForSocket(CONNECT_TIMEOUT)
|
|
525
|
+
await waitForSocket(socketPath, CONNECT_TIMEOUT)
|
|
367
526
|
} catch {
|
|
368
527
|
error('Failed to start server. Check that the build is complete.')
|
|
369
528
|
}
|
|
370
529
|
}
|
|
371
530
|
|
|
372
531
|
try {
|
|
373
|
-
const response = await sendCommand(request)
|
|
532
|
+
const response = await sendCommand(socketPath, request)
|
|
374
533
|
|
|
375
534
|
if (response.ok) {
|
|
376
535
|
output({ ok: true, ...response.result })
|
|
@@ -381,7 +540,7 @@ async function main() {
|
|
|
381
540
|
process.exit(1)
|
|
382
541
|
}
|
|
383
542
|
} catch (err) {
|
|
384
|
-
error(err.message
|
|
543
|
+
error(err instanceof Error ? err.message : 'Connection failed')
|
|
385
544
|
}
|
|
386
545
|
}
|
|
387
546
|
|
|
@@ -7069,6 +7069,9 @@ var Opensteer = class _Opensteer {
|
|
|
7069
7069
|
}
|
|
7070
7070
|
return this.contextRef;
|
|
7071
7071
|
}
|
|
7072
|
+
getRemoteSessionId() {
|
|
7073
|
+
return this.remote?.sessionId ?? null;
|
|
7074
|
+
}
|
|
7072
7075
|
async launch(options = {}) {
|
|
7073
7076
|
if (this.pageRef && !this.ownsBrowser) {
|
|
7074
7077
|
throw new Error(
|
package/dist/cli/server.cjs
CHANGED
|
@@ -35,30 +35,30 @@ function flattenExtractionDataToFieldPlan(data) {
|
|
|
35
35
|
flattenExtractionDataToFieldPlanRecursive(data, "", fields);
|
|
36
36
|
return fields;
|
|
37
37
|
}
|
|
38
|
-
function flattenExtractionDataToFieldPlanRecursive(value,
|
|
38
|
+
function flattenExtractionDataToFieldPlanRecursive(value, prefix2, out) {
|
|
39
39
|
if (value == null) return;
|
|
40
40
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
41
|
-
const key = String(
|
|
41
|
+
const key = String(prefix2 || "").trim();
|
|
42
42
|
if (!key) return;
|
|
43
43
|
out[key] = { element: Math.trunc(value) };
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
46
|
if (typeof value === "string" && value.trim().toUpperCase() === CURRENT_URL_SENTINEL) {
|
|
47
|
-
const key = String(
|
|
47
|
+
const key = String(prefix2 || "").trim();
|
|
48
48
|
if (!key) return;
|
|
49
49
|
out[key] = { source: "current_url" };
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
52
|
const counterLeaf = parseCounterLeafDescriptor(value);
|
|
53
53
|
if (counterLeaf) {
|
|
54
|
-
const key = String(
|
|
54
|
+
const key = String(prefix2 || "").trim();
|
|
55
55
|
if (!key) return;
|
|
56
56
|
out[key] = counterLeaf;
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
if (Array.isArray(value)) {
|
|
60
60
|
for (let i = 0; i < value.length; i++) {
|
|
61
|
-
const nextPrefix =
|
|
61
|
+
const nextPrefix = prefix2 ? `${prefix2}[${i}]` : `[${i}]`;
|
|
62
62
|
flattenExtractionDataToFieldPlanRecursive(value[i], nextPrefix, out);
|
|
63
63
|
}
|
|
64
64
|
return;
|
|
@@ -67,7 +67,7 @@ function flattenExtractionDataToFieldPlanRecursive(value, prefix, out) {
|
|
|
67
67
|
for (const [key, child] of Object.entries(
|
|
68
68
|
value
|
|
69
69
|
)) {
|
|
70
|
-
const nextPrefix =
|
|
70
|
+
const nextPrefix = prefix2 ? `${prefix2}.${key}` : key;
|
|
71
71
|
flattenExtractionDataToFieldPlanRecursive(child, nextPrefix, out);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -103,8 +103,8 @@ var init_extract_field_plan = __esm({
|
|
|
103
103
|
|
|
104
104
|
// src/ai/model.ts
|
|
105
105
|
function resolveProviderInfo(modelStr) {
|
|
106
|
-
for (const [
|
|
107
|
-
if (modelStr.startsWith(
|
|
106
|
+
for (const [prefix2, info] of Object.entries(PROVIDER_MAP)) {
|
|
107
|
+
if (modelStr.startsWith(prefix2)) {
|
|
108
108
|
return info;
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -335,7 +335,7 @@ var init_extractor = __esm({
|
|
|
335
335
|
|
|
336
336
|
// src/cli/server.ts
|
|
337
337
|
var import_net = require("net");
|
|
338
|
-
var
|
|
338
|
+
var import_fs4 = require("fs");
|
|
339
339
|
|
|
340
340
|
// src/opensteer.ts
|
|
341
341
|
var import_crypto2 = require("crypto");
|
|
@@ -817,15 +817,15 @@ function normalizeNamespace(input) {
|
|
|
817
817
|
if (!segments.length) return DEFAULT_NAMESPACE;
|
|
818
818
|
return segments.join("/");
|
|
819
819
|
}
|
|
820
|
-
function resolveNamespaceDir(rootDir,
|
|
820
|
+
function resolveNamespaceDir(rootDir, namespace2) {
|
|
821
821
|
const selectorsRoot = import_path2.default.resolve(rootDir, ".opensteer", "selectors");
|
|
822
|
-
const normalizedNamespace = normalizeNamespace(
|
|
822
|
+
const normalizedNamespace = normalizeNamespace(namespace2);
|
|
823
823
|
const namespaceDir = import_path2.default.resolve(selectorsRoot, normalizedNamespace);
|
|
824
824
|
const relative = import_path2.default.relative(selectorsRoot, namespaceDir);
|
|
825
825
|
if (relative === "" || relative === ".") return namespaceDir;
|
|
826
826
|
if (relative.startsWith("..") || import_path2.default.isAbsolute(relative)) {
|
|
827
827
|
throw new Error(
|
|
828
|
-
`Namespace "${
|
|
828
|
+
`Namespace "${namespace2}" resolves outside selectors root.`
|
|
829
829
|
);
|
|
830
830
|
}
|
|
831
831
|
return namespaceDir;
|
|
@@ -1275,9 +1275,9 @@ function createEmptyRegistry(name) {
|
|
|
1275
1275
|
var LocalSelectorStorage = class {
|
|
1276
1276
|
rootDir;
|
|
1277
1277
|
namespace;
|
|
1278
|
-
constructor(rootDir,
|
|
1278
|
+
constructor(rootDir, namespace2) {
|
|
1279
1279
|
this.rootDir = rootDir;
|
|
1280
|
-
this.namespace = normalizeNamespace(
|
|
1280
|
+
this.namespace = normalizeNamespace(namespace2);
|
|
1281
1281
|
}
|
|
1282
1282
|
getRootDir() {
|
|
1283
1283
|
return this.rootDir;
|
|
@@ -1461,7 +1461,7 @@ function shouldKeepAttributeForPath(name, value, options = {}) {
|
|
|
1461
1461
|
if (key === "c") return false;
|
|
1462
1462
|
if (/^on[a-z]/i.test(key)) return false;
|
|
1463
1463
|
if (ATTRIBUTE_DENY_KEYS.has(key)) return false;
|
|
1464
|
-
if (INTERNAL_ATTR_PREFIXES.some((
|
|
1464
|
+
if (INTERNAL_ATTR_PREFIXES.some((prefix2) => key.startsWith(prefix2)))
|
|
1465
1465
|
return false;
|
|
1466
1466
|
if (options.allowClass === false && key === "class") return false;
|
|
1467
1467
|
if (isMediaTag(options.tag) && VOLATILE_LAZY_LOADING_ATTRS.has(key)) {
|
|
@@ -1711,7 +1711,7 @@ async function buildElementPathFromHandle(handle) {
|
|
|
1711
1711
|
if (/^on[a-z]/i.test(normalized)) return false;
|
|
1712
1712
|
if (ATTRIBUTE_DENY_KEYS2.has(normalized)) return false;
|
|
1713
1713
|
if (INTERNAL_ATTR_PREFIXES2.some(
|
|
1714
|
-
(
|
|
1714
|
+
(prefix2) => normalized.startsWith(prefix2)
|
|
1715
1715
|
)) {
|
|
1716
1716
|
return false;
|
|
1717
1717
|
}
|
|
@@ -5884,12 +5884,12 @@ function isPersistedArrayNode(node) {
|
|
|
5884
5884
|
function isPersistedObjectNode(node) {
|
|
5885
5885
|
return !!node && typeof node === "object" && !Array.isArray(node) && !isPersistedValueNode(node) && !isPersistedSourceNode(node) && !isPersistedArrayNode(node);
|
|
5886
5886
|
}
|
|
5887
|
-
function collectArrayItemFieldDescriptors(node,
|
|
5887
|
+
function collectArrayItemFieldDescriptors(node, prefix2 = "") {
|
|
5888
5888
|
if (isPersistedValueNode(node)) {
|
|
5889
5889
|
return [
|
|
5890
5890
|
{
|
|
5891
5891
|
kind: "path",
|
|
5892
|
-
path:
|
|
5892
|
+
path: prefix2,
|
|
5893
5893
|
selector: {
|
|
5894
5894
|
elementPath: cloneElementPath(node.$path),
|
|
5895
5895
|
attribute: node.attribute
|
|
@@ -5901,7 +5901,7 @@ function collectArrayItemFieldDescriptors(node, prefix = "") {
|
|
|
5901
5901
|
return [
|
|
5902
5902
|
{
|
|
5903
5903
|
kind: "source",
|
|
5904
|
-
path:
|
|
5904
|
+
path: prefix2,
|
|
5905
5905
|
source: "current_url"
|
|
5906
5906
|
}
|
|
5907
5907
|
];
|
|
@@ -5913,7 +5913,7 @@ function collectArrayItemFieldDescriptors(node, prefix = "") {
|
|
|
5913
5913
|
}
|
|
5914
5914
|
const out = [];
|
|
5915
5915
|
for (const [key, child] of Object.entries(node)) {
|
|
5916
|
-
const nextPath = joinDataPath(
|
|
5916
|
+
const nextPath = joinDataPath(prefix2, key);
|
|
5917
5917
|
out.push(...collectArrayItemFieldDescriptors(child, nextPath));
|
|
5918
5918
|
}
|
|
5919
5919
|
return out;
|
|
@@ -6973,7 +6973,7 @@ function withTokenQuery(wsUrl, token) {
|
|
|
6973
6973
|
var import_fs3 = __toESM(require("fs"), 1);
|
|
6974
6974
|
var import_path5 = __toESM(require("path"), 1);
|
|
6975
6975
|
function collectLocalSelectorCacheEntries(storage) {
|
|
6976
|
-
const
|
|
6976
|
+
const namespace2 = storage.getNamespace();
|
|
6977
6977
|
const namespaceDir = storage.getNamespaceDir();
|
|
6978
6978
|
if (!import_fs3.default.existsSync(namespaceDir)) return [];
|
|
6979
6979
|
const entries = [];
|
|
@@ -6994,7 +6994,7 @@ function collectLocalSelectorCacheEntries(storage) {
|
|
|
6994
6994
|
continue;
|
|
6995
6995
|
}
|
|
6996
6996
|
entries.push({
|
|
6997
|
-
namespace,
|
|
6997
|
+
namespace: namespace2,
|
|
6998
6998
|
siteOrigin,
|
|
6999
6999
|
method,
|
|
7000
7000
|
descriptionHash,
|
|
@@ -7403,6 +7403,9 @@ var Opensteer = class _Opensteer {
|
|
|
7403
7403
|
}
|
|
7404
7404
|
return this.contextRef;
|
|
7405
7405
|
}
|
|
7406
|
+
getRemoteSessionId() {
|
|
7407
|
+
return this.remote?.sessionId ?? null;
|
|
7408
|
+
}
|
|
7406
7409
|
async launch(options = {}) {
|
|
7407
7410
|
if (this.pageRef && !this.ownsBrowser) {
|
|
7408
7411
|
throw new Error(
|
|
@@ -9033,9 +9036,9 @@ var Opensteer = class _Opensteer {
|
|
|
9033
9036
|
);
|
|
9034
9037
|
return fields;
|
|
9035
9038
|
}
|
|
9036
|
-
async collectFieldTargetsFromSchemaObject(obj,
|
|
9039
|
+
async collectFieldTargetsFromSchemaObject(obj, prefix2, fields) {
|
|
9037
9040
|
for (const [key, value] of Object.entries(obj)) {
|
|
9038
|
-
const fieldKey =
|
|
9041
|
+
const fieldKey = prefix2 ? `${prefix2}.${key}` : key;
|
|
9039
9042
|
await this.collectFieldTargetsFromValue(fieldKey, value, fields);
|
|
9040
9043
|
}
|
|
9041
9044
|
}
|
|
@@ -9496,19 +9499,16 @@ function getScrollDelta2(options) {
|
|
|
9496
9499
|
}
|
|
9497
9500
|
|
|
9498
9501
|
// src/cli/paths.ts
|
|
9499
|
-
var import_path6 = require("path");
|
|
9500
9502
|
var import_os2 = require("os");
|
|
9501
|
-
var
|
|
9502
|
-
function
|
|
9503
|
-
|
|
9504
|
-
(0, import_fs4.mkdirSync)(dir, { recursive: true });
|
|
9505
|
-
return dir;
|
|
9503
|
+
var import_path6 = require("path");
|
|
9504
|
+
function prefix(namespace2) {
|
|
9505
|
+
return `opensteer-${namespace2}`;
|
|
9506
9506
|
}
|
|
9507
|
-
function getSocketPath() {
|
|
9508
|
-
return (0, import_path6.join)(
|
|
9507
|
+
function getSocketPath(namespace2) {
|
|
9508
|
+
return (0, import_path6.join)((0, import_os2.tmpdir)(), `${prefix(namespace2)}.sock`);
|
|
9509
9509
|
}
|
|
9510
|
-
function getPidPath() {
|
|
9511
|
-
return (0, import_path6.join)(
|
|
9510
|
+
function getPidPath(namespace2) {
|
|
9511
|
+
return (0, import_path6.join)((0, import_os2.tmpdir)(), `${prefix(namespace2)}.pid`);
|
|
9512
9512
|
}
|
|
9513
9513
|
|
|
9514
9514
|
// src/cli/commands.ts
|
|
@@ -9746,15 +9746,20 @@ function getCommandHandler(name) {
|
|
|
9746
9746
|
// src/cli/server.ts
|
|
9747
9747
|
var instance = null;
|
|
9748
9748
|
var launchPromise = null;
|
|
9749
|
-
var
|
|
9750
|
-
|
|
9749
|
+
var namespace = process.env.OPENSTEER_NAME?.trim();
|
|
9750
|
+
if (!namespace) {
|
|
9751
|
+
process.stderr.write("Missing OPENSTEER_NAME environment variable.\n");
|
|
9752
|
+
process.exit(1);
|
|
9753
|
+
}
|
|
9754
|
+
var socketPath = getSocketPath(namespace);
|
|
9755
|
+
var pidPath = getPidPath(namespace);
|
|
9751
9756
|
function cleanup() {
|
|
9752
9757
|
try {
|
|
9753
|
-
(0,
|
|
9758
|
+
(0, import_fs4.unlinkSync)(socketPath);
|
|
9754
9759
|
} catch {
|
|
9755
9760
|
}
|
|
9756
9761
|
try {
|
|
9757
|
-
(0,
|
|
9762
|
+
(0, import_fs4.unlinkSync)(pidPath);
|
|
9758
9763
|
} catch {
|
|
9759
9764
|
}
|
|
9760
9765
|
}
|
|
@@ -9770,13 +9775,12 @@ async function handleRequest(request, socket) {
|
|
|
9770
9775
|
try {
|
|
9771
9776
|
const url = args.url;
|
|
9772
9777
|
const headless = args.headless;
|
|
9773
|
-
const name = args.name;
|
|
9774
9778
|
const connectUrl = args["connect-url"];
|
|
9775
9779
|
const channel = args.channel;
|
|
9776
9780
|
const profileDir = args["profile-dir"];
|
|
9777
9781
|
if (!instance) {
|
|
9778
9782
|
instance = new Opensteer({
|
|
9779
|
-
name:
|
|
9783
|
+
name: namespace,
|
|
9780
9784
|
browser: {
|
|
9781
9785
|
headless: headless ?? false,
|
|
9782
9786
|
connectUrl,
|
|
@@ -9805,7 +9809,11 @@ async function handleRequest(request, socket) {
|
|
|
9805
9809
|
sendResponse(socket, {
|
|
9806
9810
|
id,
|
|
9807
9811
|
ok: true,
|
|
9808
|
-
result: {
|
|
9812
|
+
result: {
|
|
9813
|
+
url: instance.page.url(),
|
|
9814
|
+
sessionId: instance.getRemoteSessionId() ?? void 0,
|
|
9815
|
+
name: namespace
|
|
9816
|
+
}
|
|
9809
9817
|
});
|
|
9810
9818
|
} catch (err) {
|
|
9811
9819
|
sendResponse(socket, {
|
|
@@ -9822,7 +9830,11 @@ async function handleRequest(request, socket) {
|
|
|
9822
9830
|
await instance.close();
|
|
9823
9831
|
instance = null;
|
|
9824
9832
|
}
|
|
9825
|
-
sendResponse(socket, {
|
|
9833
|
+
sendResponse(socket, {
|
|
9834
|
+
id,
|
|
9835
|
+
ok: true,
|
|
9836
|
+
result: { sessionClosed: true }
|
|
9837
|
+
});
|
|
9826
9838
|
} catch (err) {
|
|
9827
9839
|
sendResponse(socket, {
|
|
9828
9840
|
id,
|
|
@@ -9868,8 +9880,8 @@ async function handleRequest(request, socket) {
|
|
|
9868
9880
|
});
|
|
9869
9881
|
}
|
|
9870
9882
|
}
|
|
9871
|
-
if ((0,
|
|
9872
|
-
(0,
|
|
9883
|
+
if ((0, import_fs4.existsSync)(socketPath)) {
|
|
9884
|
+
(0, import_fs4.unlinkSync)(socketPath);
|
|
9873
9885
|
}
|
|
9874
9886
|
var server = (0, import_net.createServer)((socket) => {
|
|
9875
9887
|
let buffer = "";
|
|
@@ -9895,7 +9907,7 @@ var server = (0, import_net.createServer)((socket) => {
|
|
|
9895
9907
|
});
|
|
9896
9908
|
});
|
|
9897
9909
|
server.listen(socketPath, () => {
|
|
9898
|
-
(0,
|
|
9910
|
+
(0, import_fs4.writeFileSync)(pidPath, String(process.pid));
|
|
9899
9911
|
if (process.send) {
|
|
9900
9912
|
process.send("ready");
|
|
9901
9913
|
}
|
package/dist/cli/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Opensteer
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-2NKR4JZ6.js";
|
|
4
4
|
import "../chunk-3H5RRIMZ.js";
|
|
5
5
|
|
|
6
6
|
// src/cli/server.ts
|
|
@@ -8,19 +8,16 @@ import { createServer } from "net";
|
|
|
8
8
|
import { writeFileSync, unlinkSync, existsSync } from "fs";
|
|
9
9
|
|
|
10
10
|
// src/cli/paths.ts
|
|
11
|
+
import { tmpdir } from "os";
|
|
11
12
|
import { join } from "path";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
function getRuntimeDir() {
|
|
15
|
-
const dir = join(homedir(), ".opensteer");
|
|
16
|
-
mkdirSync(dir, { recursive: true });
|
|
17
|
-
return dir;
|
|
13
|
+
function prefix(namespace2) {
|
|
14
|
+
return `opensteer-${namespace2}`;
|
|
18
15
|
}
|
|
19
|
-
function getSocketPath() {
|
|
20
|
-
return join(
|
|
16
|
+
function getSocketPath(namespace2) {
|
|
17
|
+
return join(tmpdir(), `${prefix(namespace2)}.sock`);
|
|
21
18
|
}
|
|
22
|
-
function getPidPath() {
|
|
23
|
-
return join(
|
|
19
|
+
function getPidPath(namespace2) {
|
|
20
|
+
return join(tmpdir(), `${prefix(namespace2)}.pid`);
|
|
24
21
|
}
|
|
25
22
|
|
|
26
23
|
// src/cli/commands.ts
|
|
@@ -258,8 +255,13 @@ function getCommandHandler(name) {
|
|
|
258
255
|
// src/cli/server.ts
|
|
259
256
|
var instance = null;
|
|
260
257
|
var launchPromise = null;
|
|
261
|
-
var
|
|
262
|
-
|
|
258
|
+
var namespace = process.env.OPENSTEER_NAME?.trim();
|
|
259
|
+
if (!namespace) {
|
|
260
|
+
process.stderr.write("Missing OPENSTEER_NAME environment variable.\n");
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
var socketPath = getSocketPath(namespace);
|
|
264
|
+
var pidPath = getPidPath(namespace);
|
|
263
265
|
function cleanup() {
|
|
264
266
|
try {
|
|
265
267
|
unlinkSync(socketPath);
|
|
@@ -282,13 +284,12 @@ async function handleRequest(request, socket) {
|
|
|
282
284
|
try {
|
|
283
285
|
const url = args.url;
|
|
284
286
|
const headless = args.headless;
|
|
285
|
-
const name = args.name;
|
|
286
287
|
const connectUrl = args["connect-url"];
|
|
287
288
|
const channel = args.channel;
|
|
288
289
|
const profileDir = args["profile-dir"];
|
|
289
290
|
if (!instance) {
|
|
290
291
|
instance = new Opensteer({
|
|
291
|
-
name:
|
|
292
|
+
name: namespace,
|
|
292
293
|
browser: {
|
|
293
294
|
headless: headless ?? false,
|
|
294
295
|
connectUrl,
|
|
@@ -317,7 +318,11 @@ async function handleRequest(request, socket) {
|
|
|
317
318
|
sendResponse(socket, {
|
|
318
319
|
id,
|
|
319
320
|
ok: true,
|
|
320
|
-
result: {
|
|
321
|
+
result: {
|
|
322
|
+
url: instance.page.url(),
|
|
323
|
+
sessionId: instance.getRemoteSessionId() ?? void 0,
|
|
324
|
+
name: namespace
|
|
325
|
+
}
|
|
321
326
|
});
|
|
322
327
|
} catch (err) {
|
|
323
328
|
sendResponse(socket, {
|
|
@@ -334,7 +339,11 @@ async function handleRequest(request, socket) {
|
|
|
334
339
|
await instance.close();
|
|
335
340
|
instance = null;
|
|
336
341
|
}
|
|
337
|
-
sendResponse(socket, {
|
|
342
|
+
sendResponse(socket, {
|
|
343
|
+
id,
|
|
344
|
+
ok: true,
|
|
345
|
+
result: { sessionClosed: true }
|
|
346
|
+
});
|
|
338
347
|
} catch (err) {
|
|
339
348
|
sendResponse(socket, {
|
|
340
349
|
id,
|
package/dist/index.cjs
CHANGED
|
@@ -7487,6 +7487,9 @@ var Opensteer = class _Opensteer {
|
|
|
7487
7487
|
}
|
|
7488
7488
|
return this.contextRef;
|
|
7489
7489
|
}
|
|
7490
|
+
getRemoteSessionId() {
|
|
7491
|
+
return this.remote?.sessionId ?? null;
|
|
7492
|
+
}
|
|
7490
7493
|
async launch(options = {}) {
|
|
7491
7494
|
if (this.pageRef && !this.ownsBrowser) {
|
|
7492
7495
|
throw new Error(
|
package/dist/index.d.cts
CHANGED
|
@@ -317,6 +317,7 @@ declare class Opensteer {
|
|
|
317
317
|
private buildActionError;
|
|
318
318
|
get page(): Page;
|
|
319
319
|
get context(): BrowserContext;
|
|
320
|
+
getRemoteSessionId(): string | null;
|
|
320
321
|
launch(options?: LaunchOptions): Promise<void>;
|
|
321
322
|
static from(page: Page, config?: OpensteerConfig): Opensteer;
|
|
322
323
|
close(): Promise<void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -317,6 +317,7 @@ declare class Opensteer {
|
|
|
317
317
|
private buildActionError;
|
|
318
318
|
get page(): Page;
|
|
319
319
|
get context(): BrowserContext;
|
|
320
|
+
getRemoteSessionId(): string | null;
|
|
320
321
|
launch(options?: LaunchOptions): Promise<void>;
|
|
321
322
|
static from(page: Page, config?: OpensteerConfig): Opensteer;
|
|
322
323
|
close(): Promise<void>;
|
package/dist/index.js
CHANGED