mooncat-browser 0.1.0 → 0.2.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/browser-op/backend/browserd.cjs +4 -1
- package/browser-op/extension/server.cjs +3 -2
- package/browser-op/extension/service.cjs +7 -2
- package/browser-op/index.cjs +14 -17
- package/browser-op/webplater/dist/chrome-mv3/chunks/offscreen-JoFB8k4y.js +1 -0
- package/browser-op/webplater/dist/chrome-mv3/manifest.json +1 -1
- package/browser-op/webplater/dist/chrome-mv3/offscreen.html +1 -1
- package/browser-op/webplater/entrypoints/offscreen/main.ts +4 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +363 -85
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +63 -42
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +69 -73
- package/dist/config.js.map +1 -1
- package/dist/instance.d.ts +57 -0
- package/dist/instance.d.ts.map +1 -0
- package/dist/instance.js +128 -0
- package/dist/instance.js.map +1 -0
- package/dist/prepare-extension.d.ts +37 -0
- package/dist/prepare-extension.d.ts.map +1 -0
- package/dist/prepare-extension.js +144 -0
- package/dist/prepare-extension.js.map +1 -0
- package/dist/server.d.ts +40 -23
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +51 -35
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/skills/browser/SKILL.md +37 -14
- package/skills/browser/references/collect.md +4 -2
- package/skills/browser/references/high-risk.md +27 -14
- package/skills/browser/references/probing.md +6 -4
- package/browser-op/webplater/dist/chrome-mv3/chunks/offscreen-CFXYw9Mo.js +0 -1
|
@@ -62,7 +62,10 @@ function getDefaultOp (options = {}) {
|
|
|
62
62
|
}
|
|
63
63
|
const profileRoot = options.profileRoot || process.env.BROWSER_OP_PROFILE_ROOT || getDefaultProfileRoot()
|
|
64
64
|
const userDataDir = options.userDataDir || process.env.BROWSER_OP_USERDATA || null
|
|
65
|
-
|
|
65
|
+
// 多实例 WS 端口:由 wrapper (mooncat-browser) 通过 env 注入本实例的 extensionPort。
|
|
66
|
+
// 不传则 BrowserOp/WebService 内部回退默认 17321(向后兼容)。
|
|
67
|
+
const wsPort = options.wsPort || (process.env.BROWSER_OP_WS_PORT ? Number(process.env.BROWSER_OP_WS_PORT) : null)
|
|
68
|
+
_op = new BrowserOp({ executablePath, profileRoot, userDataDir, wsPort })
|
|
66
69
|
return _op
|
|
67
70
|
}
|
|
68
71
|
|
|
@@ -59,10 +59,11 @@ class WebPluginServer {
|
|
|
59
59
|
|
|
60
60
|
this.wss.on('error', (err) => {
|
|
61
61
|
if (err.message.includes('EADDRINUSE')) {
|
|
62
|
-
//
|
|
62
|
+
// 本端口被占:可能是本实例残留进程,或别的进程占用该端口。
|
|
63
|
+
// 多实例下每个实例有独立 WS 端口,不再有"全局唯一 17321"语义。
|
|
63
64
|
this.info('[web] port %d already in use — EADDRINUSE', port)
|
|
64
65
|
this.wss = null
|
|
65
|
-
reject(new Error(`EADDRINUSE: port ${port} already in use (another
|
|
66
|
+
reject(new Error(`EADDRINUSE: port ${port} already in use (stale process on this port, or another process occupied it)`))
|
|
66
67
|
return
|
|
67
68
|
}
|
|
68
69
|
this.info('[web] server error: %s', err.message)
|
|
@@ -45,8 +45,13 @@ class WebService {
|
|
|
45
45
|
|
|
46
46
|
// ── 生命周期 ──────────────────────────────────────────────
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
/**
|
|
49
|
+
* 启动 WS server(供 WebPlater 扩展 offscreen 回连)。
|
|
50
|
+
* @param {number=} port 实例 WS 端口;不传则用 server 默认(17321,仅向后兼容)。
|
|
51
|
+
* 多实例下由 index.cjs 从 env BROWSER_OP_WS_PORT 透传。
|
|
52
|
+
*/
|
|
53
|
+
async startServer (port) {
|
|
54
|
+
await this.server.start(undefined, port)
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
async stopServer () {
|
package/browser-op/index.cjs
CHANGED
|
@@ -49,6 +49,7 @@ class BrowserOp {
|
|
|
49
49
|
* @param {string} deps.executablePath Chrome 路径(必填)
|
|
50
50
|
* @param {string} deps.profileRoot profile 根目录(检测插件用,可选)
|
|
51
51
|
* @param {string=} deps.userDataDir 显式 userDataDir(不传则 launcher 用 profileRoot/default)
|
|
52
|
+
* @param {number=} deps.wsPort 插件路 WS server 端口(多实例化;不传则用默认 17321)
|
|
52
53
|
* @param {Function=} deps.info 日志函数
|
|
53
54
|
* @param {Function=} deps.errorLog 错误日志函数
|
|
54
55
|
*/
|
|
@@ -59,6 +60,9 @@ class BrowserOp {
|
|
|
59
60
|
this.executablePath = deps.executablePath
|
|
60
61
|
this.profileRoot = deps.profileRoot || null
|
|
61
62
|
this.userDataDirOverride = deps.userDataDir || null
|
|
63
|
+
// 多实例:每个 browserd 在自己的 wsPort 上起 WS server,扩展 offscreen 连本实例端口。
|
|
64
|
+
// 不传时回退默认 17321(向后兼容旧调用方)。
|
|
65
|
+
this.wsPort = deps.wsPort || null
|
|
62
66
|
this.info = deps.info || defaultInfo
|
|
63
67
|
this.errorLog = deps.errorLog || defaultError
|
|
64
68
|
|
|
@@ -109,15 +113,17 @@ class BrowserOp {
|
|
|
109
113
|
let pluginFallbackNotice = null
|
|
110
114
|
|
|
111
115
|
// 启动前:开插件 WS server(插件链路需要;CDP 链路开起来也不碍事,便于 checkRoute)
|
|
112
|
-
//
|
|
116
|
+
// 多实例:用本实例 wsPort(从 env BROWSER_OP_WS_PORT 经 browserd → getDefaultOp → BrowserOp 注入)。
|
|
117
|
+
// 不传则 web.startServer() 内部回退默认 17321。
|
|
113
118
|
if (!this._serverStarted) {
|
|
114
119
|
try {
|
|
115
|
-
await this.web.startServer()
|
|
120
|
+
await this.web.startServer(this.wsPort)
|
|
116
121
|
this._serverStarted = true
|
|
117
122
|
} catch (e) {
|
|
118
123
|
const portBusy = /EADDRINUSE|already in use/.test(e.message)
|
|
124
|
+
const portLabel = this.wsPort || 'default(17321)'
|
|
119
125
|
const message = portBusy
|
|
120
|
-
?
|
|
126
|
+
? `WebPlater WS 端口 ${portLabel} 已被占用(本实例残留进程,或别的进程占用了该端口)。`
|
|
121
127
|
: `WS server 启动失败: ${e.message}`
|
|
122
128
|
if (routeMode === 'extension') {
|
|
123
129
|
return { ok: false, mode: 'extension', notice: { level: 'error', message }, error: message }
|
|
@@ -159,19 +165,10 @@ class BrowserOp {
|
|
|
159
165
|
|
|
160
166
|
// tryPlugin=true → 插件模式启动(无端口)
|
|
161
167
|
if (tryPlugin) {
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
if (reused) {
|
|
167
|
-
this.info('open mode=extension (reused: plugin already connected, skip launch)')
|
|
168
|
-
this.currentMode = 'extension'
|
|
169
|
-
extState.write(userDataDir, { wsPort: extState.DEFAULT_WS_PORT, lastHeartbeatAt: Date.now() })
|
|
170
|
-
globalState.writeGlobal(userDataDir, { profile: 'default' })
|
|
171
|
-
return { ok: true, mode: 'extension', notice: { level: 'info', message: '检测到该 profile 的 Chrome 已开且插件已连接,复用,未重复启动。' } }
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// 没回连 → Chrome 没开, 正常 launch
|
|
168
|
+
// 多实例:本实例在自己的 wsPort 上起 WS server,扩展 offscreen 连本端口。
|
|
169
|
+
// 不再做"先等 2s 看有没有别的 browserd 的 Chrome offscreen 回连"的复用分支——
|
|
170
|
+
// 那基于"17321 全局唯一"假设,多实例下每个实例端口独立,该假设不成立。
|
|
171
|
+
// 直接 launch 本实例的 Chrome(profile 独立),launch 后等自己的 offscreen 回连。
|
|
175
172
|
const result = await this.launcher.launch({
|
|
176
173
|
executablePath: this.executablePath,
|
|
177
174
|
userDataDir,
|
|
@@ -191,7 +188,7 @@ class BrowserOp {
|
|
|
191
188
|
if (alive) {
|
|
192
189
|
this.info('open mode=extension (plugin alive)')
|
|
193
190
|
this.currentMode = 'extension'
|
|
194
|
-
extState.write(userDataDir, { wsPort: extState.DEFAULT_WS_PORT, lastHeartbeatAt: Date.now() })
|
|
191
|
+
extState.write(userDataDir, { wsPort: this.wsPort || extState.DEFAULT_WS_PORT, lastHeartbeatAt: Date.now() })
|
|
195
192
|
globalState.writeGlobal(userDataDir, { profile: 'default' })
|
|
196
193
|
return { ok: true, mode: 'extension', pid: this.launcher.processId, notice: null }
|
|
197
194
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual_wxt-html-plugins-DPbbfBKe.js";const l="__MOONCAT_BROWSER_HOST_WS_URL__",S=1e3,E=2e4;let e=null,s=null,c=null;function d(){(e==null?void 0:e.readyState)===WebSocket.CONNECTING||(e==null?void 0:e.readyState)===WebSocket.OPEN||(e=new WebSocket(l),e.addEventListener("open",()=>{s&&(clearTimeout(s),s=null),console.log("[WebPlater/offscreen] connected to host",l),i({type:"hello",name:"bee-web-plugin"}),_()}),e.addEventListener("message",async t=>{let n;try{n=JSON.parse(String(t.data))}catch{console.error("[WebPlater/offscreen] invalid JSON from host",t.data);return}if(!(!n||n.type!=="command"||typeof n.id!="number"))try{const r=await p(n.id,n.method,n.params??{});u(n.id,{ok:!0,result:r})}catch(r){u(n.id,{ok:!1,error:r instanceof Error?r.message:String(r)})}}),e.addEventListener("close",()=>{console.log("[WebPlater/offscreen] disconnected, reconnecting..."),e=null,f(),y()}),e.addEventListener("error",()=>{e==null||e.close()}))}function i(t){(e==null?void 0:e.readyState)===WebSocket.OPEN&&e.send(JSON.stringify(t))}function u(t,n){const r={id:t,type:"response",...n};i(r)}function p(t,n,r){return new Promise((m,a)=>{chrome.runtime.sendMessage({source:"offscreen-command",id:t,method:n,params:r},g=>{if(chrome.runtime.lastError){a(new Error(chrome.runtime.lastError.message));return}const o=g;if(o&&typeof o=="object"&&o.ok===!1){a(new Error(o.error??"background error"));return}m(o==null?void 0:o.result)})})}function _(){f(),c=setInterval(()=>{i({type:"ping",time:Date.now()})},E)}function f(){c&&(clearInterval(c),c=null)}function y(){s||(s=setTimeout(()=>{s=null,d()},S))}d();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"manifest_version":3,"name":"WebPlater","description":"Generic browser automation bridge — Playwright alternative layer","version":"0.0.1.
|
|
1
|
+
{"manifest_version":3,"name":"WebPlater","description":"Generic browser automation bridge — Playwright alternative layer","version":"0.0.1.2607041709","key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlljeBdeINKB8ouCR6euqG5iegaoSZY3c/uubW1AJoJzoVNyiB8UPzpL98zfWXW5nMF+KTdGa1Vb19sBACMVxO8gXEbxS/gobfqJHddfe0qZpNDEBrM7lwVJtocPb9lYJK3rHASx2VSkRFRPoymaaNDaeEO/uiu9uCG2dut/V00UvUAaeMDM9bwiWxD8aJ5IINRFIk+UniZsPB0kY3tbcmqayGYsjYpwZmU9RXoLSBZjWa8CfFjTNeyPBtLpkj2groQN/Ytk1RWf5AEwAPIahfz/hn2kDOnL1OSNGyQfswL8GuWJZs9h2bvDQMKwCRUQ/iUuqypNQfbin42rpD1kz9QIDAQAB","permissions":["tabs","scripting","cookies","storage","offscreen","webNavigation","downloads"],"host_permissions":["<all_urls>"],"background":{"service_worker":"background.js"},"action":{"default_title":"WebPlater","default_popup":"popup.html"},"content_scripts":[{"matches":["<all_urls>"],"all_frames":true,"run_at":"document_idle","js":["content-scripts/content.js"]}]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<title>WebPlater Offscreen</title>
|
|
6
|
-
<script type="module" crossorigin src="/chunks/offscreen-
|
|
6
|
+
<script type="module" crossorigin src="/chunks/offscreen-JoFB8k4y.js"></script>
|
|
7
7
|
<link rel="modulepreload" crossorigin href="/chunks/_virtual_wxt-html-plugins-DPbbfBKe.js">
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
@@ -34,7 +34,10 @@ interface BackgroundResponse {
|
|
|
34
34
|
error?: string
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
// 占位符:prepare-extension <name> 时会被替换为 ws://127.0.0.1:<extensionPort>。
|
|
38
|
+
// wxt build 保留字符串字面量(minification 只改变量名,不改字符串内容)。
|
|
39
|
+
// 包内 dist 只 build 一次,每个实例复制后由 mooncat-browser prepare-extension 换端口。
|
|
40
|
+
const HOST_WS_URL = '__MOONCAT_BROWSER_HOST_WS_URL__'
|
|
38
41
|
const RECONNECT_DELAY_MS = 1000
|
|
39
42
|
const PING_INTERVAL_MS = 20000
|
|
40
43
|
|
package/dist/cli.d.ts
CHANGED