dsh-inner-browser-use 0.11.44 → 0.18.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/README.md +112 -75
- package/README.zh.md +90 -45
- package/client.js +473 -3276
- package/docs/ARCHITECTURE.md +196 -150
- package/docs/BENCH.md +234 -0
- package/docs/COMPATIBILITY.md +72 -102
- package/docs/ROADMAP.md +176 -0
- package/docs/VERIFY.md +131 -415
- package/index.js +230 -1117
- package/locale/en.json +11 -22
- package/locale/zh.json +11 -22
- package/package.json +12 -5
- package/read.js +718 -0
- package/scripts/doctor.mjs +89 -0
- package/sidecar.js +1364 -0
- package/tools.js +1652 -0
- package/docs/upstream/cookie-persistence.md +0 -52
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Report what the sidecar browser is doing right now: whether the Host answers,
|
|
4
|
+
* whether a Chromium is attached, which profile it uses, and whether that
|
|
5
|
+
* profile is outside the Host so logins outlive a restart. Reads only; nothing
|
|
6
|
+
* is started, attached, or closed.
|
|
7
|
+
*
|
|
8
|
+
* node scripts/doctor.mjs
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { execFile } from 'node:child_process'
|
|
12
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
13
|
+
import { homedir } from 'node:os'
|
|
14
|
+
import { join } from 'node:path'
|
|
15
|
+
import { promisify } from 'node:util'
|
|
16
|
+
|
|
17
|
+
const run = promisify(execFile)
|
|
18
|
+
const ROUTE = '/dsh-inner-browser-use'
|
|
19
|
+
const PROFILES = join(homedir(), '.dsh', 'inner-browser-use', 'chrome')
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The Host picks its port each time it starts, so try the asked-for address
|
|
23
|
+
* first and then whatever the running app is listening on.
|
|
24
|
+
* @returns {Promise<string[]>} candidate addresses, without trailing slash.
|
|
25
|
+
*/
|
|
26
|
+
async function addresses() {
|
|
27
|
+
const asked = (process.env.DSH_BRIDGE ?? '').trim().replace(/\/+$/, '')
|
|
28
|
+
const found = asked === '' ? [] : [asked]
|
|
29
|
+
found.push('http://127.0.0.1:60930')
|
|
30
|
+
try {
|
|
31
|
+
const { stdout } = await run('lsof', ['-nP', '-iTCP', '-sTCP:LISTEN', '-a', '-c', 'DeepSeek'], { timeout: 4_000 })
|
|
32
|
+
for (const line of String(stdout).split('\n')) {
|
|
33
|
+
const hit = /127\.0\.0\.1:(\d{4,5})\s/.exec(line)
|
|
34
|
+
if (hit === null) continue
|
|
35
|
+
const address = `http://127.0.0.1:${hit[1]}`
|
|
36
|
+
if (found.includes(address) === false) found.push(address)
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
/* no lsof, or nothing listening: the default address is all that is left */
|
|
40
|
+
}
|
|
41
|
+
return found
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let base = ''
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {string} path - route under this plugin.
|
|
48
|
+
* @returns {Promise<any>} parsed body, or null when no address answers.
|
|
49
|
+
*/
|
|
50
|
+
async function get(path) {
|
|
51
|
+
const tried = base === '' ? await addresses() : [base]
|
|
52
|
+
for (const address of tried) {
|
|
53
|
+
try {
|
|
54
|
+
const response = await fetch(address + path, { signal: AbortSignal.timeout(4_000) })
|
|
55
|
+
if (response.ok !== true) continue
|
|
56
|
+
base = address
|
|
57
|
+
return await response.json()
|
|
58
|
+
} catch {
|
|
59
|
+
/* the next address may be the one this app is on */
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const state = await get(`${ROUTE}/sidecar/state`)
|
|
66
|
+
console.log(`host ${state === null ? `not answering under ${ROUTE}` : base}`)
|
|
67
|
+
if (state === null) {
|
|
68
|
+
console.log(' start the app, or set DSH_BRIDGE to the app address')
|
|
69
|
+
process.exit(0)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log(`browser ${state.alive === true ? `attached, ${state.headless === true ? 'headless' : 'with a window'}` : 'not running'}`)
|
|
73
|
+
const profileDir = join(PROFILES, String(state.profile ?? ''))
|
|
74
|
+
console.log(`profile ${state.profile} in ${profileDir}`)
|
|
75
|
+
console.log(`stored ${existsSync(profileDir) ? 'on disk, so cookies and logins survive a restart' : 'not created yet'}`)
|
|
76
|
+
if (state.alive === true) {
|
|
77
|
+
console.log(`page ${String(state.title ?? '') === '' ? String(state.url ?? '') : state.title}`)
|
|
78
|
+
console.log(`viewers ${state.viewers} | frames ${state.frames} | pointer ${state.pointer === null ? 'none' : `${state.pointer.x},${state.pointer.y}`}`)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const portFile = join(profileDir, 'DevToolsActivePort')
|
|
82
|
+
if (existsSync(portFile)) {
|
|
83
|
+
const [port = '', path = ''] = readFileSync(portFile, 'utf8').trim().split('\n')
|
|
84
|
+
console.log(`control port ${port}, ${path.startsWith('/devtools/') ? 'endpoint file present' : 'endpoint file odd'}`)
|
|
85
|
+
} else {
|
|
86
|
+
console.log('control no DevToolsActivePort yet')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (String(state.error ?? '') !== '') console.log(`error ${state.error}`)
|