dsh-mobile-plugin 0.5.20 → 0.5.22
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 -12
- package/assets/pets/README.md +9 -0
- package/assets/pets/deepy-whale/attention.gif +0 -0
- package/assets/pets/deepy-whale/done.gif +0 -0
- package/assets/pets/deepy-whale/error.gif +0 -0
- package/assets/pets/deepy-whale/idle.gif +0 -0
- package/assets/pets/deepy-whale/pack.json +54 -0
- package/assets/pets/deepy-whale/sleeping.gif +0 -0
- package/assets/pets/deepy-whale/working-3.gif +0 -0
- package/assets/pets/deepy-whale/working.gif +0 -0
- package/extensions/README.md +64 -0
- package/extensions/catalog.json +1 -0
- package/lib/client.js +318 -27
- package/lib/impl.js +21 -1
- package/lib/mobile/approvals.js +22 -2
- package/lib/mobile/cli/acp.js +34 -20
- package/lib/mobile/cli/mobile.js +8 -1
- package/lib/mobile/cli/service.js +151 -10
- package/lib/mobile/extension-catalog.js +244 -0
- package/lib/mobile/local-images.js +10 -5
- package/lib/mobile/monitor.js +5 -2
- package/lib/mobile/pet-tools.js +215 -0
- package/lib/mobile/pets.js +559 -0
- package/lib/mobile/session-flags.js +61 -8
- package/lib/mobile/session-local-image.js +9 -1
- package/lib/mobile/stats-collect.cjs +15 -7
- package/lib/mobile/stats-ledger.cjs +44 -5
- package/lib/mobile/wechat-tools.js +257 -0
- package/lib/mobile/wechat.js +489 -0
- package/lib/panel/index.html +12 -11
- package/lib/relay/pairing-payload.cjs +13 -5
- package/lib/relay/snapshot-auth.js +82 -0
- package/lib/relay/status.js +3 -0
- package/lib/routes/control-plane.js +74 -3
- package/lib/routes/mobile-api.js +54 -1
- package/lib/session-cleanup.cjs +22 -7
- package/lib/sidecar-facade-worker.cjs +8 -0
- package/lib/tailcat/host-process.cjs +266 -0
- package/lib/tailcat/ingress.cjs +98 -0
- package/lib/tailcat/session.cjs +264 -0
- package/lib/tailcat/wiring.cjs +96 -0
- package/package.json +10 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 把直连隧道挂进装配层:回环入口 + 助手会话 + 一条自己的启停 effect。
|
|
5
|
+
*
|
|
6
|
+
* 单独一个文件是因为装配层有行数上限(`test/assembly-layer.test.cjs` 钉着)——那些上限不是
|
|
7
|
+
* 「装配层恰好该多长」,而是「实现不许搬回装配层」。这里的三样东西都是装配动作,实现分别
|
|
8
|
+
* 在 `ingress.cjs` 与 `session.cjs`。
|
|
9
|
+
*
|
|
10
|
+
* 任何一步起不来都只意味着「这台机器没有这条通道」:`mount` 兜住异常并留一行日志,中转与
|
|
11
|
+
* 局域网一行不受影响。
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { createLoopbackIngress } = require('./ingress.cjs');
|
|
15
|
+
const { createTailcatSession } = require('./session.cjs');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {object} options
|
|
19
|
+
* @param {(label: string, fn: Function) => any} options.mount 装配层的兜底挂载
|
|
20
|
+
* @param {(message: string) => void} options.warn 告警出口(拿不到 logger 时为空实现)
|
|
21
|
+
* @param {object} options.state relay.json 那份内存状态(唯一真值)
|
|
22
|
+
* @param {(state: object) => void} options.saveState 落盘
|
|
23
|
+
* @param {() => number} options.lanPortInUse 当前局域网端口(会漂)
|
|
24
|
+
* @param {() => string} options.hostName 电脑名
|
|
25
|
+
* @param {object} options.ctx 插件 ctx(只为 `ctx.effect`)
|
|
26
|
+
* @param {string} options.name 插件名,用于 effect 标签
|
|
27
|
+
* @returns {object|undefined} 会话;起不来就是 undefined(路由与面板按「不可用」处理)
|
|
28
|
+
*/
|
|
29
|
+
function mountTailcat(options) {
|
|
30
|
+
const { mount, warn, state, saveState, lanPortInUse, hostName, ctx, name } = options;
|
|
31
|
+
const ingress = mount('直连隧道入口', () =>
|
|
32
|
+
createLoopbackIngress({ targetPort: () => lanPortInUse(), log: message => warn(message) }),
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 端口是异步拿到的(`listen(0)` 要等 `listening`),所以会话也是异步建好的。
|
|
37
|
+
* 路由和面板在装配阶段就要拿到一个对象,于是对外交的是**门面**:里面那格可能还是空,
|
|
38
|
+
* 调用方问到的就是「暂不可用」,等挂上了自然就通了 —— 不需要谁去等一次 Promise。
|
|
39
|
+
*/
|
|
40
|
+
let session = null;
|
|
41
|
+
const door = {
|
|
42
|
+
status: () => (session ? session.status() : { available: Boolean(ingress), enabled: true, ready: false, address: '', paired: 0, error: 'starting' }),
|
|
43
|
+
openPairingWindow: ttl => (session ? session.openPairingWindow(ttl) : Promise.resolve(null)),
|
|
44
|
+
setAllowed: keys => (session ? session.setAllowed(keys) : false),
|
|
45
|
+
setEnabled: enabled => (session ? session.setEnabled(enabled) : false),
|
|
46
|
+
enroll: publicKey => (session ? session.enroll(publicKey) : Promise.resolve(null)),
|
|
47
|
+
allowedClients: () => (session ? session.allowedClients() : []),
|
|
48
|
+
start: () => (session ? session.start() : undefined),
|
|
49
|
+
stop: () => (session ? session.stop() : Promise.resolve()),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// 启停单独一条命:跟 sidecar 不是一件事,谁挂了都不该带走对方。
|
|
53
|
+
// 关的时候先停助手再关回环门——门是助手唯一的去处,反过来会让最后几条连接瞬间断在门上。
|
|
54
|
+
mount('直连隧道生命周期', () =>
|
|
55
|
+
ctx.effect(() => {
|
|
56
|
+
let closed = false;
|
|
57
|
+
const wiring = ingress
|
|
58
|
+
? Promise.resolve(ingress.start())
|
|
59
|
+
.then(port => {
|
|
60
|
+
if (closed || !port) return;
|
|
61
|
+
session = createTailcatSession({
|
|
62
|
+
readState: () => state,
|
|
63
|
+
writeState: patch => {
|
|
64
|
+
Object.assign(state, patch);
|
|
65
|
+
saveState(state);
|
|
66
|
+
},
|
|
67
|
+
localPort: port,
|
|
68
|
+
hostName,
|
|
69
|
+
log: message => warn(message),
|
|
70
|
+
});
|
|
71
|
+
session.start();
|
|
72
|
+
})
|
|
73
|
+
.catch(error => warn(`直连隧道没有起来:${error && error.message ? error.message : error}`))
|
|
74
|
+
: Promise.resolve();
|
|
75
|
+
return () => {
|
|
76
|
+
closed = true;
|
|
77
|
+
void wiring.then(() => {
|
|
78
|
+
try {
|
|
79
|
+
if (session) session.stop();
|
|
80
|
+
session = null;
|
|
81
|
+
} catch {
|
|
82
|
+
/* 已经在停 */
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
if (ingress) ingress.close();
|
|
86
|
+
} catch {
|
|
87
|
+
/* 已经关了 */
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
}, `${name}: tailcat`),
|
|
92
|
+
);
|
|
93
|
+
return door;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
module.exports = { mountTailcat };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mobile-plugin",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.22",
|
|
4
4
|
"description": "Mobile API (/api/mobile/v1) and relay client for the DSH mobile app — desktop profile build (dsh 0.2.x, peers resolved by the host)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"icon": "./icon.png",
|
|
@@ -42,6 +42,8 @@
|
|
|
42
42
|
"dsh-mobile-credentials",
|
|
43
43
|
"locale/*.json",
|
|
44
44
|
"icon.png",
|
|
45
|
+
"assets/pets/**",
|
|
46
|
+
"extensions/**",
|
|
45
47
|
"README.md"
|
|
46
48
|
],
|
|
47
49
|
"publishConfig": {
|
|
@@ -58,6 +60,13 @@
|
|
|
58
60
|
"qrcode": "1.5.4",
|
|
59
61
|
"ws": "8.18.0"
|
|
60
62
|
},
|
|
63
|
+
"optionalDependencies": {
|
|
64
|
+
"dsh-mobile-tailcat-darwin-arm64": "1.0.0",
|
|
65
|
+
"dsh-mobile-tailcat-darwin-x64": "1.0.0",
|
|
66
|
+
"dsh-mobile-tailcat-linux-arm64": "1.0.0",
|
|
67
|
+
"dsh-mobile-tailcat-linux-x64": "1.0.0",
|
|
68
|
+
"dsh-mobile-tailcat-win32-x64": "1.0.0"
|
|
69
|
+
},
|
|
61
70
|
"peerDependencies": {
|
|
62
71
|
"@deepseek-ai/cordis": ">=4.0.1",
|
|
63
72
|
"@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2 || ^0.2.0-rc.1 || ^0.2.1-rc.2",
|