comate-ui-inspector 0.1.2-alpha.5 → 0.1.2
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 +3 -3
- package/cli.mjs +17 -5
- package/extension/background.js +6 -5
- package/extension/popup.html +9 -4
- package/extension/popup.js +10 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ ui-inspector install # 注册 native host + 个人级 hook,并打印
|
|
|
33
33
|
- **生效域名**:默认已含 `localhost` / `127.0.0.1`;项目域名(如 `https://local.oreateai.com`)自己加,添加时浏览器会弹权限申请,允许后即在该域名注入选取脚本。
|
|
34
34
|
- **传输通路**:
|
|
35
35
|
- `本地(Native Messaging)`——默认,浏览器按需拉起 `host.mjs`,零常驻。
|
|
36
|
-
- `远程(HTTP bridge
|
|
36
|
+
- `远程(HTTP bridge)`——只填**本地端口**(host 固定 127.0.0.1,默认 `8917`),用于远程开发(见下)。
|
|
37
37
|
|
|
38
38
|
## 远程开发(HTTP bridge)
|
|
39
39
|
|
|
@@ -46,7 +46,7 @@ ui-inspector install --remote # --port 默认 8917;跳过无浏览
|
|
|
46
46
|
ui-inspector link <remote-ssh-目标> --port <dev端口>
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
`install --remote` 会打印 MCP 配置(贴进**远程**的 Comate 并 reload),并把 bridge 后台拉起(日志在 `~/.ui-inspector/bridge.log`)。`link` 本质是 `ssh -N -L
|
|
49
|
+
`install --remote` 会打印 MCP 配置(贴进**远程**的 Comate 并 reload),并把 bridge 后台拉起(日志在 `~/.ui-inspector/bridge.log`)。`link` 本质是 `ssh -N -L <本地bridge端口>:127.0.0.1:<远程bridge端口> -L <dev端口>:127.0.0.1:<dev端口> <remote>`,保持前台、Ctrl-C 断开。远程 bridge 端口不必和本地一致:本地用 `--bridge-port`、远程用 `--remote-bridge-port`(默认两者相同);弹窗里填的是**本地**那个端口。
|
|
50
50
|
|
|
51
51
|
链路断了(ssh 掉线 / 远程 bridge 或 dev server 停了)时,先在本地自检:
|
|
52
52
|
|
|
@@ -56,7 +56,7 @@ ui-inspector doctor <remote> --port <dev端口> # 定位断在哪层并打印
|
|
|
56
56
|
|
|
57
57
|
恢复顺序:先确保远程 bridge 活(`ui-inspector bridge` / `install --remote`)→ 再接本地隧道(`ui-inspector link`)→ 再看远程 dev server。
|
|
58
58
|
|
|
59
|
-
本地仍需一次:加载扩展(`chrome://extensions` 选 `extension` 目录),在弹窗把传输切到 `远程(HTTP bridge
|
|
59
|
+
本地仍需一次:加载扩展(`chrome://extensions` 选 `extension` 目录),在弹窗把传输切到 `远程(HTTP bridge)`、填本地端口、加上你的 dev 域名。bridge 只绑 127.0.0.1、不暴露到网络,访问全程走 SSH 转发,所以 https 页面连 `127.0.0.1` 不触发混合内容拦截。
|
|
60
60
|
|
|
61
61
|
## 卸载 / 状态
|
|
62
62
|
|
package/cli.mjs
CHANGED
|
@@ -134,19 +134,28 @@ function install({remote, port}) {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
// 本地笔记本:把远程 bridge 端口 + dev server 端口都转发到本地 127.0.0.1。
|
|
137
|
-
|
|
137
|
+
// 远程 bridge 监听端口可与本地不同:-L <本地bridge端口>:127.0.0.1:<远程bridge端口>。
|
|
138
|
+
function link({remote, devPort, bridgePort, remoteBridgePort}) {
|
|
138
139
|
if (!remote) {
|
|
139
|
-
out(
|
|
140
|
+
out(
|
|
141
|
+
'用法:ui-inspector link <remote-ssh-目标> --port <dev端口> [--bridge-port 8917] [--remote-bridge-port <远程端口>]'
|
|
142
|
+
);
|
|
140
143
|
out('例: ui-inspector link dev-box --port 5173');
|
|
141
144
|
return;
|
|
142
145
|
}
|
|
143
|
-
const
|
|
146
|
+
const rbp = remoteBridgePort || bridgePort;
|
|
147
|
+
const args = ['-N', '-L', `${bridgePort}:127.0.0.1:${rbp}`];
|
|
144
148
|
if (devPort) {
|
|
145
149
|
args.push('-L', `${devPort}:127.0.0.1:${devPort}`);
|
|
146
150
|
}
|
|
147
151
|
args.push(remote);
|
|
148
152
|
out(`转发中(Ctrl-C 断开):ssh ${args.join(' ')}`);
|
|
149
|
-
out(
|
|
153
|
+
out(
|
|
154
|
+
` bridge → 本地 127.0.0.1:${bridgePort} ⇢ 远程 127.0.0.1:${rbp}${devPort ? `;dev → 127.0.0.1:${devPort}` : ''}`
|
|
155
|
+
);
|
|
156
|
+
out(
|
|
157
|
+
` 提示:弹窗里的端口填本地的 ${bridgePort};远程 bridge 需在 ${rbp} 上监听(ui-inspector bridge --port ${rbp})。`
|
|
158
|
+
);
|
|
150
159
|
const child = spawn('ssh', args, {stdio: 'inherit'});
|
|
151
160
|
child.on('exit', code => process.exit(code ?? 0));
|
|
152
161
|
}
|
|
@@ -219,17 +228,20 @@ function parseLink() {
|
|
|
219
228
|
let remote;
|
|
220
229
|
let devPort;
|
|
221
230
|
let bridgePort = '8917';
|
|
231
|
+
let remoteBridgePort;
|
|
222
232
|
for (let i = 0; i < rest.length; i++) {
|
|
223
233
|
const a = rest[i];
|
|
224
234
|
if (a === '--port') {
|
|
225
235
|
devPort = rest[++i];
|
|
226
236
|
} else if (a === '--bridge-port') {
|
|
227
237
|
bridgePort = rest[++i];
|
|
238
|
+
} else if (a === '--remote-bridge-port') {
|
|
239
|
+
remoteBridgePort = rest[++i];
|
|
228
240
|
} else if (!a.startsWith('-')) {
|
|
229
241
|
remote = a;
|
|
230
242
|
}
|
|
231
243
|
}
|
|
232
|
-
return {remote, devPort, bridgePort};
|
|
244
|
+
return {remote, devPort, bridgePort, remoteBridgePort};
|
|
233
245
|
}
|
|
234
246
|
|
|
235
247
|
// 探测本地某端口的 http 可达性(2s 超时)。用 node:http 而非 fetch,兼容 node 18+。
|
package/extension/background.js
CHANGED
|
@@ -4,17 +4,18 @@
|
|
|
4
4
|
* 两件事:
|
|
5
5
|
* 1) 传输适配:把内容脚本的 ingest/state 转发给本地后端。
|
|
6
6
|
* - native(默认,本地开发):chrome.runtime.sendNativeMessage 按需拉起 host.mjs。
|
|
7
|
-
* - http(远程开发):fetch
|
|
7
|
+
* - http(远程开发):fetch http://127.0.0.1:<bridgePort>(/ingest、/state),远程机上跑 bridge/server.mjs。
|
|
8
8
|
* 2) 动态注册内容脚本:目标域名不再硬编码在 manifest,改由弹窗(popup)写入 storage,
|
|
9
9
|
* 这里按配置用 chrome.scripting 注册(MAIN + ISOLATED 两份)。
|
|
10
10
|
*/
|
|
11
11
|
const HOST = 'com.oreate.ui_inspector';
|
|
12
12
|
|
|
13
13
|
// localhost / 127.0.0.1 是通用开发地址,作默认种子;项目专属域名(如 local.oreateai.com)在弹窗里加。
|
|
14
|
+
// 远程模式下扩展永远连本地 SSH 转发出来的 127.0.0.1,host 固定,只需配端口。
|
|
14
15
|
const DEFAULTS = {
|
|
15
16
|
domains: ['http://localhost/*', 'http://127.0.0.1/*'],
|
|
16
17
|
transport: 'native',
|
|
17
|
-
|
|
18
|
+
bridgePort: '8917',
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
function getConfig() {
|
|
@@ -34,8 +35,8 @@ function viaNative(message) {
|
|
|
34
35
|
});
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
async function viaHttp(
|
|
38
|
-
const base =
|
|
38
|
+
async function viaHttp(port, message) {
|
|
39
|
+
const base = `http://127.0.0.1:${port}`;
|
|
39
40
|
try {
|
|
40
41
|
if (message.type === 'ingest') {
|
|
41
42
|
const r = await fetch(`${base}/ingest`, {
|
|
@@ -54,7 +55,7 @@ async function viaHttp(bridgeUrl, message) {
|
|
|
54
55
|
|
|
55
56
|
async function dispatch(message) {
|
|
56
57
|
const cfg = await getConfig();
|
|
57
|
-
return cfg.transport === 'http' ? viaHttp(cfg.
|
|
58
|
+
return cfg.transport === 'http' ? viaHttp(cfg.bridgePort, message) : viaNative(message);
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
|
package/extension/popup.html
CHANGED
|
@@ -142,16 +142,21 @@
|
|
|
142
142
|
class="row"
|
|
143
143
|
style="margin-top: 6px"
|
|
144
144
|
>
|
|
145
|
+
<span style="color: #656d76">127.0.0.1 :</span>
|
|
145
146
|
<input
|
|
146
|
-
id="bridge-
|
|
147
|
+
id="bridge-port"
|
|
147
148
|
type="text"
|
|
148
|
-
|
|
149
|
+
inputmode="numeric"
|
|
150
|
+
placeholder="8917"
|
|
151
|
+
style="max-width: 90px"
|
|
149
152
|
/>
|
|
150
153
|
</div>
|
|
151
154
|
<div class="hint">
|
|
152
|
-
|
|
155
|
+
只填本地端口(host 固定 127.0.0.1)。远程开发:远程跑
|
|
153
156
|
<code>ui-inspector bridge</code>
|
|
154
|
-
,
|
|
157
|
+
,
|
|
158
|
+
<code>ui-inspector link</code>
|
|
159
|
+
把端口转发到本地。
|
|
155
160
|
</div>
|
|
156
161
|
</div>
|
|
157
162
|
</section>
|
package/extension/popup.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const DEFAULTS = {
|
|
3
3
|
domains: ['http://localhost/*', 'http://127.0.0.1/*'],
|
|
4
4
|
transport: 'native',
|
|
5
|
-
|
|
5
|
+
bridgePort: '8917',
|
|
6
6
|
};
|
|
7
7
|
const PROTECTED = new Set(DEFAULTS.domains); // 默认项不可删、不回收权限
|
|
8
8
|
|
|
@@ -106,18 +106,23 @@ function toggleBridge() {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
async function renderTransport() {
|
|
109
|
-
const {transport,
|
|
109
|
+
const {transport, bridgePort} = await getConfig();
|
|
110
110
|
for (const r of document.querySelectorAll('input[name="transport"]')) {
|
|
111
111
|
r.checked = r.value === transport;
|
|
112
112
|
}
|
|
113
|
-
$('bridge-
|
|
113
|
+
$('bridge-port').value = bridgePort;
|
|
114
114
|
toggleBridge();
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
async function saveTransport() {
|
|
118
118
|
const transport = document.querySelector('input[name="transport"]:checked')?.value || 'native';
|
|
119
|
-
const
|
|
120
|
-
|
|
119
|
+
const raw = $('bridge-port').value.trim();
|
|
120
|
+
if (transport === 'http' && !/^\d+$/.test(raw)) {
|
|
121
|
+
msg('端口要是数字', false);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const bridgePort = raw || DEFAULTS.bridgePort;
|
|
125
|
+
await chrome.storage.local.set({transport, bridgePort});
|
|
121
126
|
msg('已保存传输设置');
|
|
122
127
|
}
|
|
123
128
|
|
package/package.json
CHANGED