@tunnelbox/dsh-tunnelbox 0.1.29 → 0.1.32
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 +2 -3
- package/README.zh-CN.md +1 -2
- package/dist/index.mjs +49 -53
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ Each instance appears separately on the phone by `type=dsh` + its own agentID.
|
|
|
98
98
|
|
|
99
99
|
## Multilingual
|
|
100
100
|
|
|
101
|
-
User-visible output supports 8 languages (`zh-CN` / `zh-TW` / `en-US` / `ja-JP` / `ko-KR` / `fr-FR` / `de-DE` / `es-ES`). Resolution order: `TUNNELBOX_LANG` >
|
|
101
|
+
User-visible output supports 8 languages (`zh-CN` / `zh-TW` / `en-US` / `ja-JP` / `ko-KR` / `fr-FR` / `de-DE` / `es-ES`). Resolution order: `TUNNELBOX_LANG` > system locale > `en-US`.
|
|
102
102
|
|
|
103
103
|
## Troubleshooting
|
|
104
104
|
|
|
@@ -111,8 +111,7 @@ User-visible output supports 8 languages (`zh-CN` / `zh-TW` / `en-US` / `ja-JP`
|
|
|
111
111
|
|
|
112
112
|
## State files
|
|
113
113
|
|
|
114
|
-
- `~/.tunnelbox/remote-state.dsh.json` — agentID
|
|
115
|
-
- `~/.tunnelbox/remote-pairing.json` — latest pairing info
|
|
114
|
+
- `~/.tunnelbox/remote-state.dsh.json` — agentID (+ language)
|
|
116
115
|
- `~/.tunnelbox/tunnelbox.log` — plugin log
|
|
117
116
|
|
|
118
117
|
## Uninstall
|
package/README.zh-CN.md
CHANGED
|
@@ -111,8 +111,7 @@ DSH_HOME=~/.dsh-b DSH_PERMISSION_MODE=danger-full-access dsh --profile tunnelbox
|
|
|
111
111
|
|
|
112
112
|
## 状态文件
|
|
113
113
|
|
|
114
|
-
- `~/.tunnelbox/remote-state.dsh.json` — agentID
|
|
115
|
-
- `~/.tunnelbox/remote-pairing.json` — 最新配对信息
|
|
114
|
+
- `~/.tunnelbox/remote-state.dsh.json` — agentID(+ 语言)
|
|
116
115
|
- `~/.tunnelbox/tunnelbox.log` — 插件日志
|
|
117
116
|
|
|
118
117
|
## 卸载
|
package/dist/index.mjs
CHANGED
|
@@ -208,7 +208,6 @@ var zh_CN_default = {
|
|
|
208
208
|
"perm.promptResource": "opencode \u8BF7\u6C42\u8BBF\u95EE\u8D44\u6E90\uFF1A{list}",
|
|
209
209
|
"perm.promptTool": "opencode \u8BF7\u6C42\u6267\u884C {tool}",
|
|
210
210
|
"qr.codeLabel": "\u914D\u5BF9\u7801",
|
|
211
|
-
"qr.fileWritten": "\u914D\u5BF9\u4FE1\u606F\u5DF2\u5199\u5165: {path}",
|
|
212
211
|
"qr.openHint": "\u6253\u5F00 tunnelbox App\uFF0C\u7528\u300C\u626B\u4E00\u626B\u914D\u5BF9\u300D\u626B\u63CF\u4E0A\u65B9\u4E8C\u7EF4\u7801\uFF0C\u6216\u624B\u52A8\u8F93\u5165\u914D\u5BF9\u7801\u3002",
|
|
213
212
|
"qr.titleNoType": "tunnelbox \u624B\u673A\u914D\u5BF9",
|
|
214
213
|
"qr.titleWithType": "tunnelbox {type} \u624B\u673A\u914D\u5BF9",
|
|
@@ -618,7 +617,6 @@ var zh_TW_default = {
|
|
|
618
617
|
"perm.promptResource": "opencode \u8ACB\u6C42\u5B58\u53D6\u8CC7\u6E90\uFF1A{list}",
|
|
619
618
|
"perm.promptTool": "opencode \u8ACB\u6C42\u57F7\u884C {tool}",
|
|
620
619
|
"qr.codeLabel": "\u914D\u5C0D\u78BC",
|
|
621
|
-
"qr.fileWritten": "\u914D\u5C0D\u8CC7\u8A0A\u5DF2\u5BEB\u5165: {path}",
|
|
622
620
|
"qr.openHint": "\u958B\u555F tunnelbox App\uFF0C\u7528\u300C\u6383\u63CF\u914D\u5C0D\u300D\u6383\u63CF\u4E0A\u65B9 QR Code\uFF0C\u6216\u624B\u52D5\u8F38\u5165\u914D\u5C0D\u78BC\u3002",
|
|
623
621
|
"qr.titleNoType": "tunnelbox \u624B\u6A5F\u914D\u5C0D",
|
|
624
622
|
"qr.titleWithType": "tunnelbox {type} \u624B\u6A5F\u914D\u5C0D",
|
|
@@ -1028,7 +1026,6 @@ var en_US_default = {
|
|
|
1028
1026
|
"perm.promptResource": "opencode requests access to resources: {list}",
|
|
1029
1027
|
"perm.promptTool": "opencode requests to run {tool}",
|
|
1030
1028
|
"qr.codeLabel": "Pairing code",
|
|
1031
|
-
"qr.fileWritten": "Pairing info written to: {path}",
|
|
1032
1029
|
"qr.openHint": "Open the tunnelbox app on your phone and scan the QR code above, or enter the pairing code manually in the app.",
|
|
1033
1030
|
"qr.titleNoType": "tunnelbox phone pairing",
|
|
1034
1031
|
"qr.titleWithType": "tunnelbox {type} phone pairing",
|
|
@@ -1438,7 +1435,6 @@ var ja_JP_default = {
|
|
|
1438
1435
|
"perm.promptResource": "opencode \u304C\u30EA\u30BD\u30FC\u30B9\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u3092\u8981\u6C42: {list}",
|
|
1439
1436
|
"perm.promptTool": "opencode \u304C {tool} \u306E\u5B9F\u884C\u3092\u8981\u6C42",
|
|
1440
1437
|
"qr.codeLabel": "\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9",
|
|
1441
|
-
"qr.fileWritten": "\u30DA\u30A2\u30EA\u30F3\u30B0\u60C5\u5831\u3092\u66F8\u304D\u8FBC\u307F\u307E\u3057\u305F: {path}",
|
|
1442
1438
|
"qr.openHint": "tunnelbox App \u3092\u958B\u304D\u3001\u4E0A\u306E QR \u30B3\u30FC\u30C9\u3092\u30B9\u30AD\u30E3\u30F3\u3059\u308B\u304B\u3001App \u3067\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3092\u624B\u52D5\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
1443
1439
|
"qr.titleNoType": "tunnelbox \u30B9\u30DE\u30DB\u30DA\u30A2\u30EA\u30F3\u30B0",
|
|
1444
1440
|
"qr.titleWithType": "tunnelbox {type} \u30B9\u30DE\u30DB\u30DA\u30A2\u30EA\u30F3\u30B0",
|
|
@@ -1848,7 +1844,6 @@ var ko_KR_default = {
|
|
|
1848
1844
|
"perm.promptResource": "opencode\uAC00 \uB9AC\uC18C\uC2A4 \uC811\uADFC\uC744 \uC694\uCCAD: {list}",
|
|
1849
1845
|
"perm.promptTool": "opencode\uAC00 {tool} \uC2E4\uD589\uC744 \uC694\uCCAD",
|
|
1850
1846
|
"qr.codeLabel": "\uD398\uC5B4\uB9C1 \uCF54\uB4DC",
|
|
1851
|
-
"qr.fileWritten": "\uD398\uC5B4\uB9C1 \uC815\uBCF4\uAC00 \uAE30\uB85D\uB428: {path}",
|
|
1852
1847
|
"qr.openHint": "tunnelbox \uC571\uC744 \uC5F4\uACE0 \uC704 QR \uCF54\uB4DC\uB97C \uC2A4\uCE94\uD558\uAC70\uB098, \uC571\uC5D0\uC11C \uD398\uC5B4\uB9C1 \uCF54\uB4DC\uB97C \uC9C1\uC811 \uC785\uB825\uD558\uC138\uC694.",
|
|
1853
1848
|
"qr.titleNoType": "tunnelbox \uD734\uB300\uD3F0 \uD398\uC5B4\uB9C1",
|
|
1854
1849
|
"qr.titleWithType": "tunnelbox {type} \uD734\uB300\uD3F0 \uD398\uC5B4\uB9C1",
|
|
@@ -2258,7 +2253,6 @@ var fr_FR_default = {
|
|
|
2258
2253
|
"perm.promptResource": "opencode demande l'acc\xE8s aux ressources : {list}",
|
|
2259
2254
|
"perm.promptTool": "opencode demande d'ex\xE9cuter {tool}",
|
|
2260
2255
|
"qr.codeLabel": "Code d'appairage",
|
|
2261
|
-
"qr.fileWritten": "Informations d'appairage \xE9crites dans : {path}",
|
|
2262
2256
|
"qr.openHint": "Ouvrez l'application tunnelbox sur votre t\xE9l\xE9phone et scannez le QR ci-dessus, ou saisissez le code d'appairage manuellement dans l'application.",
|
|
2263
2257
|
"qr.titleNoType": "appairage t\xE9l\xE9phone tunnelbox",
|
|
2264
2258
|
"qr.titleWithType": "appairage t\xE9l\xE9phone tunnelbox {type}",
|
|
@@ -2668,7 +2662,6 @@ var de_DE_default = {
|
|
|
2668
2662
|
"perm.promptResource": "opencode fordert Zugriff auf Ressourcen: {list}",
|
|
2669
2663
|
"perm.promptTool": "opencode fordert die Ausf\xFChrung von {tool} an",
|
|
2670
2664
|
"qr.codeLabel": "Pairing-Code",
|
|
2671
|
-
"qr.fileWritten": "Pairing-Informationen geschrieben in: {path}",
|
|
2672
2665
|
"qr.openHint": "\xD6ffnen Sie die tunnelbox-App auf dem Telefon und scannen Sie den QR-Code oben, oder geben Sie den Pairing-Code manuell in der App ein.",
|
|
2673
2666
|
"qr.titleNoType": "tunnelbox Telefon-Pairing",
|
|
2674
2667
|
"qr.titleWithType": "tunnelbox {type} Telefon-Pairing",
|
|
@@ -3078,7 +3071,6 @@ var es_ES_default = {
|
|
|
3078
3071
|
"perm.promptResource": "opencode solicita acceso a los recursos: {list}",
|
|
3079
3072
|
"perm.promptTool": "opencode solicita ejecutar {tool}",
|
|
3080
3073
|
"qr.codeLabel": "C\xF3digo de emparejamiento",
|
|
3081
|
-
"qr.fileWritten": "Informaci\xF3n de emparejamiento escrita en: {path}",
|
|
3082
3074
|
"qr.openHint": "Abra la aplicaci\xF3n tunnelbox en el tel\xE9fono y escanee el c\xF3digo QR superior, o introduzca el c\xF3digo de emparejamiento manualmente en la aplicaci\xF3n.",
|
|
3083
3075
|
"qr.titleNoType": "emparejamiento de tel\xE9fono tunnelbox",
|
|
3084
3076
|
"qr.titleWithType": "emparejamiento de tel\xE9fono tunnelbox {type}",
|
|
@@ -3523,8 +3515,6 @@ function loadState(type) {
|
|
|
3523
3515
|
if (parsed.agentId && parsed.agentId.length >= 16) {
|
|
3524
3516
|
return {
|
|
3525
3517
|
agentId: parsed.agentId,
|
|
3526
|
-
relayUrl: parsed.relayUrl || "",
|
|
3527
|
-
claimed: parsed.claimed === true,
|
|
3528
3518
|
lang: parsed.lang ? normalizeLang(parsed.lang) : void 0
|
|
3529
3519
|
};
|
|
3530
3520
|
}
|
|
@@ -3535,26 +3525,6 @@ function loadState(type) {
|
|
|
3535
3525
|
return fallback;
|
|
3536
3526
|
}
|
|
3537
3527
|
}
|
|
3538
|
-
function writePairingFile(code, type, lang) {
|
|
3539
|
-
const p = join(baseName(), `remote-pairing${suffix(type)}.txt`);
|
|
3540
|
-
try {
|
|
3541
|
-
mkdirSync(dirname(p), { recursive: true });
|
|
3542
|
-
const label = t(lang ?? resolveLang(), "qr.codeLabel");
|
|
3543
|
-
writeFileSync(p, `${label}: ${code}
|
|
3544
|
-
`, "utf8");
|
|
3545
|
-
} catch {
|
|
3546
|
-
}
|
|
3547
|
-
return p;
|
|
3548
|
-
}
|
|
3549
|
-
function writePairingJson(info, type) {
|
|
3550
|
-
const p = join(baseName(), `remote-pairing${suffix(type)}.json`);
|
|
3551
|
-
try {
|
|
3552
|
-
mkdirSync(dirname(p), { recursive: true });
|
|
3553
|
-
writeFileSync(p, JSON.stringify(info, null, 2), "utf8");
|
|
3554
|
-
} catch {
|
|
3555
|
-
}
|
|
3556
|
-
return p;
|
|
3557
|
-
}
|
|
3558
3528
|
function injectedRelayUrl() {
|
|
3559
3529
|
return "wss://relay.tunnelbox.top" ? "wss://relay.tunnelbox.top".replace(/\/+$/, "") : "";
|
|
3560
3530
|
}
|
|
@@ -3604,7 +3574,6 @@ function padVisual(s, width, align = "left") {
|
|
|
3604
3574
|
}
|
|
3605
3575
|
async function printPairing(code, type, name2, lang) {
|
|
3606
3576
|
const resolved = lang ? normalizeLang(lang) : resolveLang();
|
|
3607
|
-
const file = writePairingFile(code, type, resolved);
|
|
3608
3577
|
const tt = (key, vars) => t(resolved, key, vars);
|
|
3609
3578
|
const title = type ? tt("qr.titleWithType", { type }) : tt("qr.titleNoType");
|
|
3610
3579
|
const codeLine = `${tt("qr.codeLabel")}: ${code}`;
|
|
@@ -3632,7 +3601,6 @@ async function printPairing(code, type, name2, lang) {
|
|
|
3632
3601
|
} catch {
|
|
3633
3602
|
console.log(" " + tt("qr.unavailable"));
|
|
3634
3603
|
}
|
|
3635
|
-
console.log(" " + tt("qr.fileWritten", { path: file }));
|
|
3636
3604
|
console.log("");
|
|
3637
3605
|
}
|
|
3638
3606
|
var DEFAULT_PAGE_SIZE = 20;
|
|
@@ -3986,8 +3954,19 @@ import { join as join2 } from "node:path";
|
|
|
3986
3954
|
function dshHome() {
|
|
3987
3955
|
return process.env.DSH_HOME || join2(homedir2(), ".dsh");
|
|
3988
3956
|
}
|
|
3989
|
-
function
|
|
3990
|
-
|
|
3957
|
+
function headerOf(s) {
|
|
3958
|
+
if (s.header && typeof s.header.id === "string") return s.header;
|
|
3959
|
+
return { id: s.id ?? "", createdAt: s.createdAt ?? 0, cwd: s.cwd };
|
|
3960
|
+
}
|
|
3961
|
+
async function release(h) {
|
|
3962
|
+
const p = h;
|
|
3963
|
+
if (typeof p?.close === "function") {
|
|
3964
|
+
try {
|
|
3965
|
+
await p.close();
|
|
3966
|
+
} catch {
|
|
3967
|
+
}
|
|
3968
|
+
return;
|
|
3969
|
+
}
|
|
3991
3970
|
const d = typeof p?.dispose === "function" ? p.dispose : typeof p?.[Symbol.dispose] === "function" ? p[Symbol.dispose] : void 0;
|
|
3992
3971
|
if (typeof d === "function") {
|
|
3993
3972
|
try {
|
|
@@ -4008,20 +3987,36 @@ function titleOf(events) {
|
|
|
4008
3987
|
return sessionTitle(msgs) || "";
|
|
4009
3988
|
}
|
|
4010
3989
|
async function readSessionEvents(sp, sessionId) {
|
|
3990
|
+
if (typeof sp.open === "function") {
|
|
3991
|
+
const handle = await sp.open(sessionId, "read");
|
|
3992
|
+
try {
|
|
3993
|
+
const result = await handle.read();
|
|
3994
|
+
return [...result.events];
|
|
3995
|
+
} finally {
|
|
3996
|
+
await release(handle);
|
|
3997
|
+
}
|
|
3998
|
+
}
|
|
4011
3999
|
if (typeof sp.inspect === "function") {
|
|
4012
4000
|
const view = await sp.inspect(sessionId);
|
|
4013
4001
|
return [...view.events ?? []];
|
|
4014
4002
|
}
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4003
|
+
if (typeof sp.prepare === "function") {
|
|
4004
|
+
const prep = await sp.prepare(sessionId);
|
|
4005
|
+
try {
|
|
4006
|
+
return [...prep.session.events];
|
|
4007
|
+
} finally {
|
|
4008
|
+
await release(prep);
|
|
4009
|
+
}
|
|
4020
4010
|
}
|
|
4011
|
+
return [];
|
|
4021
4012
|
}
|
|
4022
4013
|
async function sessionExists(sp, sessionId) {
|
|
4014
|
+
if (typeof sp.stat === "function") {
|
|
4015
|
+
const snap = await sp.stat(sessionId).catch(() => void 0);
|
|
4016
|
+
return !!snap;
|
|
4017
|
+
}
|
|
4023
4018
|
const headers = await sp.list().catch(() => []);
|
|
4024
|
-
return headers.some((h) => h.id === sessionId);
|
|
4019
|
+
return headers.some((h) => headerOf(h).id === sessionId);
|
|
4025
4020
|
}
|
|
4026
4021
|
async function sessionInfo(sp, h, t2) {
|
|
4027
4022
|
let events = [];
|
|
@@ -4044,7 +4039,9 @@ async function sessionInfo(sp, h, t2) {
|
|
|
4044
4039
|
async function listSessions(sp, workspace, t2) {
|
|
4045
4040
|
const headers = await sp.list().catch(() => []);
|
|
4046
4041
|
const out = [];
|
|
4047
|
-
for (const
|
|
4042
|
+
for (const raw of headers) {
|
|
4043
|
+
const h = headerOf(raw);
|
|
4044
|
+
if (!h.id) continue;
|
|
4048
4045
|
if (workspace && h.cwd !== workspace) continue;
|
|
4049
4046
|
const s = await sessionInfo(sp, h, t2);
|
|
4050
4047
|
if (s) out.push(s);
|
|
@@ -4054,7 +4051,8 @@ async function listSessions(sp, workspace, t2) {
|
|
|
4054
4051
|
async function listWorkspaces(sp, current) {
|
|
4055
4052
|
const headers = await sp.list().catch(() => []);
|
|
4056
4053
|
const byPath = /* @__PURE__ */ new Map();
|
|
4057
|
-
for (const
|
|
4054
|
+
for (const raw of headers) {
|
|
4055
|
+
const h = headerOf(raw);
|
|
4058
4056
|
const p = h.cwd;
|
|
4059
4057
|
if (!p) continue;
|
|
4060
4058
|
const e = byPath.get(p) ?? { count: 0, updated: 0 };
|
|
@@ -4104,7 +4102,7 @@ function findDir(dir, name2) {
|
|
|
4104
4102
|
}
|
|
4105
4103
|
|
|
4106
4104
|
// src/bridge.ts
|
|
4107
|
-
var VERSION = true ? "0.1.
|
|
4105
|
+
var VERSION = true ? "0.1.32" : "0.0.0-dev";
|
|
4108
4106
|
var AGENT_TYPE = "dsh";
|
|
4109
4107
|
var APPROVAL_TIMEOUT_MS = 12e4;
|
|
4110
4108
|
var ADAPTER_COMMANDS = [
|
|
@@ -4122,7 +4120,7 @@ var TunnelboxBridge = class {
|
|
|
4122
4120
|
}
|
|
4123
4121
|
ws = new RelayClient();
|
|
4124
4122
|
state = loadState(AGENT_TYPE);
|
|
4125
|
-
|
|
4123
|
+
paired = false;
|
|
4126
4124
|
everConnected = false;
|
|
4127
4125
|
relayBase = "";
|
|
4128
4126
|
/** sessionID → 活动 AgentHandle(本进程生命周期)。 */
|
|
@@ -4240,7 +4238,6 @@ ${err.stack}` : ""));
|
|
|
4240
4238
|
timezone: localTimezone()
|
|
4241
4239
|
};
|
|
4242
4240
|
this.send(envelope("agent.info", info));
|
|
4243
|
-
if (!this.claimed) this.send(envelope("pair.create", {}));
|
|
4244
4241
|
}
|
|
4245
4242
|
getSessionPersistence() {
|
|
4246
4243
|
return this.ctx.get("sessionPersistence");
|
|
@@ -4250,17 +4247,17 @@ ${err.stack}` : ""));
|
|
|
4250
4247
|
switch (env.type) {
|
|
4251
4248
|
case "pair.created": {
|
|
4252
4249
|
const code = env.payload.code;
|
|
4253
|
-
writePairingJson({ code, relayUrl: this.relayBase, at: Date.now() }, AGENT_TYPE);
|
|
4254
4250
|
this.log(this.t("adapter.logPairCode", { code }));
|
|
4255
4251
|
void printPairing(code, AGENT_TYPE, hostname(), this.lang);
|
|
4256
4252
|
return;
|
|
4257
4253
|
}
|
|
4258
|
-
case "agent.
|
|
4259
|
-
|
|
4260
|
-
this.
|
|
4261
|
-
|
|
4262
|
-
this.
|
|
4254
|
+
case "agent.status": {
|
|
4255
|
+
const status = env.payload;
|
|
4256
|
+
this.paired = status?.claimed === true;
|
|
4257
|
+
if (this.paired) this.log(this.t("adapter.logClaimed"));
|
|
4258
|
+
else this.send(envelope("pair.create", {}));
|
|
4263
4259
|
return;
|
|
4260
|
+
}
|
|
4264
4261
|
case "agent.revoked":
|
|
4265
4262
|
this.resetIdentity();
|
|
4266
4263
|
return;
|
|
@@ -4947,9 +4944,8 @@ ${err.stack}` : ""));
|
|
|
4947
4944
|
}
|
|
4948
4945
|
resetIdentity() {
|
|
4949
4946
|
this.log(this.t("adapter.logResetIdentity"));
|
|
4950
|
-
this.
|
|
4947
|
+
this.paired = false;
|
|
4951
4948
|
this.state.agentId = randomBytes2(16).toString("hex");
|
|
4952
|
-
this.state.claimed = false;
|
|
4953
4949
|
saveState(this.state, AGENT_TYPE);
|
|
4954
4950
|
this.ws.close();
|
|
4955
4951
|
this.connect(this.relayBase);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tunnelbox/dsh-tunnelbox",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"description": "tunnelbox 的 dsh 原生 Cordis 插件:手机远程驱动 DeepSeek Harness(agent/session/tools/审批/中止)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@deepseek-ai/schemastery": "^3.18.1"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@tunnelbox/core": "0.1.
|
|
39
|
+
"@tunnelbox/core": "0.1.32",
|
|
40
40
|
"@types/node": "^22.0.0",
|
|
41
41
|
"esbuild": "^0.24.0",
|
|
42
42
|
"typescript": "^5.4.5"
|