@tianshu-ai/local-bridge 0.6.2 → 0.7.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/app/TianshuBridge.swift +46 -11
- package/dist/connection.js +82 -0
- package/dist/connection.js.map +1 -1
- package/package.json +1 -1
package/app/TianshuBridge.swift
CHANGED
|
@@ -16,8 +16,9 @@ import Foundation
|
|
|
16
16
|
struct Config: Codable {
|
|
17
17
|
var server: String = "ws://localhost:3110/ws"
|
|
18
18
|
var token: String = ""
|
|
19
|
-
var
|
|
20
|
-
var
|
|
19
|
+
var browser: Bool = true // expose browser tools (on by default)
|
|
20
|
+
var engine: String = "own" // "own" | "stealth" (browser sub-option)
|
|
21
|
+
var headless: Bool = false // browser sub-option
|
|
21
22
|
var shell: Bool = false // expose exec + file sync (opt-in)
|
|
22
23
|
var device: String = "" // empty → hostname
|
|
23
24
|
|
|
@@ -91,8 +92,12 @@ final class Bridge {
|
|
|
91
92
|
}
|
|
92
93
|
var args = ["--server", cfg.server]
|
|
93
94
|
if !cfg.token.isEmpty { args += ["--token", cfg.token] }
|
|
94
|
-
if cfg.
|
|
95
|
-
|
|
95
|
+
if cfg.browser {
|
|
96
|
+
if cfg.engine == "stealth" { args += ["--browser-engine", "stealth"] }
|
|
97
|
+
if cfg.headless { args += ["--headless"] }
|
|
98
|
+
} else {
|
|
99
|
+
args += ["--no-browser"]
|
|
100
|
+
}
|
|
96
101
|
if cfg.shell { args += ["--shell"] }
|
|
97
102
|
if !cfg.device.isEmpty { args += ["--device", cfg.device] }
|
|
98
103
|
|
|
@@ -176,9 +181,9 @@ final class AppController: NSObject, NSApplicationDelegate {
|
|
|
176
181
|
menu.addItem(statusMI)
|
|
177
182
|
menu.addItem(NSMenuItem(title: "Server: \(cfg.server)", action: nil, keyEquivalent: ""))
|
|
178
183
|
let eng = cfg.engine == "stealth" ? "stealth" : "own"
|
|
184
|
+
let browserDesc = cfg.browser ? "\(eng)\(cfg.headless ? " (headless)" : "")" : "off"
|
|
185
|
+
menu.addItem(NSMenuItem(title: "Browser: \(browserDesc)", action: nil, keyEquivalent: ""))
|
|
179
186
|
menu.addItem(NSMenuItem(title: "Shell: \(cfg.shell ? "on" : "off")", action: nil, keyEquivalent: ""))
|
|
180
|
-
menu.addItem(NSMenuItem(title: "Browser: \(eng)\(cfg.headless ? " (headless)" : "")",
|
|
181
|
-
action: nil, keyEquivalent: ""))
|
|
182
187
|
menu.addItem(.separator())
|
|
183
188
|
|
|
184
189
|
if bridge.isRunning {
|
|
@@ -218,6 +223,7 @@ final class AppController: NSObject, NSApplicationDelegate {
|
|
|
218
223
|
|
|
219
224
|
private var serverField: NSTextField!
|
|
220
225
|
private var tokenField: NSTextField!
|
|
226
|
+
private var browserCheck: NSButton!
|
|
221
227
|
private var enginePopup: NSPopUpButton!
|
|
222
228
|
private var headlessCheck: NSButton!
|
|
223
229
|
private var shellCheck: NSButton!
|
|
@@ -247,25 +253,41 @@ final class AppController: NSObject, NSApplicationDelegate {
|
|
|
247
253
|
tokenField = NSTextField(frame: NSRect(x: 110, y: 170, width: 250, height: 24))
|
|
248
254
|
tokenField.stringValue = cfg.token; v.addSubview(tokenField)
|
|
249
255
|
|
|
250
|
-
|
|
251
|
-
|
|
256
|
+
// ── Capabilities (Browser + Shell are sibling optional tools) ──
|
|
257
|
+
let capLabel = NSTextField(labelWithString: "Capabilities")
|
|
258
|
+
capLabel.frame = NSRect(x: 16, y: 138, width: 200, height: 18)
|
|
259
|
+
capLabel.font = NSFont.boldSystemFont(ofSize: 12)
|
|
260
|
+
v.addSubview(capLabel)
|
|
261
|
+
|
|
262
|
+
// Browser (top-level toggle) + its sub-options (engine, headless).
|
|
263
|
+
browserCheck = NSButton(checkboxWithTitle: "Browser (control a local browser)",
|
|
264
|
+
target: self, action: #selector(toggleBrowserOptions))
|
|
265
|
+
browserCheck.frame = NSRect(x: 24, y: 116, width: 300, height: 20)
|
|
266
|
+
browserCheck.state = cfg.browser ? .on : .off
|
|
267
|
+
v.addSubview(browserCheck)
|
|
268
|
+
|
|
269
|
+
enginePopup = NSPopUpButton(frame: NSRect(x: 44, y: 88, width: 250, height: 26))
|
|
252
270
|
enginePopup.addItems(withTitles: ["own (your Chrome)", "stealth (CloakBrowser)"])
|
|
253
271
|
enginePopup.selectItem(at: cfg.engine == "stealth" ? 1 : 0)
|
|
254
272
|
v.addSubview(enginePopup)
|
|
255
273
|
|
|
256
274
|
headlessCheck = NSButton(checkboxWithTitle: "Headless (no window)", target: nil, action: nil)
|
|
257
|
-
headlessCheck.frame = NSRect(x:
|
|
275
|
+
headlessCheck.frame = NSRect(x: 44, y: 66, width: 250, height: 20)
|
|
258
276
|
headlessCheck.state = cfg.headless ? .on : .off
|
|
259
277
|
v.addSubview(headlessCheck)
|
|
260
278
|
|
|
279
|
+
// Shell (sibling top-level toggle).
|
|
261
280
|
shellCheck = NSButton(checkboxWithTitle: "Shell (run commands + sync files)", target: nil, action: nil)
|
|
262
|
-
shellCheck.frame = NSRect(x:
|
|
281
|
+
shellCheck.frame = NSRect(x: 24, y: 40, width: 300, height: 20)
|
|
263
282
|
shellCheck.state = cfg.shell ? .on : .off
|
|
264
283
|
shellCheck.toolTip = "Exposes exec + file sync on your machine, jailed to ~/.tianshu_shell. Off by default; enable only for a server you trust."
|
|
265
284
|
v.addSubview(shellCheck)
|
|
266
285
|
|
|
286
|
+
// Grey out browser sub-options when browser is off.
|
|
287
|
+
updateBrowserOptionsEnabled()
|
|
288
|
+
|
|
267
289
|
let save = NSButton(title: "Save & Restart", target: self, action: #selector(saveSettings))
|
|
268
|
-
save.frame = NSRect(x: 200, y:
|
|
290
|
+
save.frame = NSRect(x: 200, y: 8, width: 160, height: 30)
|
|
269
291
|
save.bezelStyle = .rounded
|
|
270
292
|
v.addSubview(save)
|
|
271
293
|
return v
|
|
@@ -275,6 +297,7 @@ final class AppController: NSObject, NSApplicationDelegate {
|
|
|
275
297
|
cfg.server = serverField.stringValue.trimmingCharacters(in: .whitespaces)
|
|
276
298
|
cfg.token = tokenField.stringValue.trimmingCharacters(in: .whitespaces)
|
|
277
299
|
cfg.engine = enginePopup.indexOfSelectedItem == 1 ? "stealth" : "own"
|
|
300
|
+
cfg.browser = browserCheck.state == .on
|
|
278
301
|
cfg.headless = headlessCheck.state == .on
|
|
279
302
|
cfg.shell = shellCheck.state == .on
|
|
280
303
|
cfg.save()
|
|
@@ -307,6 +330,18 @@ final class AppController: NSObject, NSApplicationDelegate {
|
|
|
307
330
|
if let e = params["engine"] { enginePopup.selectItem(at: e == "stealth" ? 1 : 0) }
|
|
308
331
|
if let h = params["headless"] { headlessCheck.state = (h == "1" || h == "true") ? .on : .off }
|
|
309
332
|
if let s = params["shell"] { shellCheck.state = (s == "1" || s == "true") ? .on : .off }
|
|
333
|
+
if let b = params["browser"] { browserCheck.state = (b == "1" || b == "true") ? .on : .off }
|
|
334
|
+
updateBrowserOptionsEnabled()
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Enable/disable the browser sub-options (engine + headless) to
|
|
338
|
+
// reflect the top-level Browser toggle — they're meaningless when
|
|
339
|
+
// browser is off.
|
|
340
|
+
@objc func toggleBrowserOptions() { updateBrowserOptionsEnabled() }
|
|
341
|
+
private func updateBrowserOptionsEnabled() {
|
|
342
|
+
let on = browserCheck?.state == .on
|
|
343
|
+
enginePopup?.isEnabled = on
|
|
344
|
+
headlessCheck?.isEnabled = on
|
|
310
345
|
}
|
|
311
346
|
|
|
312
347
|
private func alert(_ title: String, _ body: String) {
|
package/dist/connection.js
CHANGED
|
@@ -7,6 +7,19 @@ import WebSocket from "ws";
|
|
|
7
7
|
import { MSG, textResult } from "./protocol.js";
|
|
8
8
|
const RECONNECT_BASE_MS = 1000;
|
|
9
9
|
const RECONNECT_MAX_MS = 30_000;
|
|
10
|
+
// Heartbeat: proactively detect "half-open" / silently-dead sockets
|
|
11
|
+
// that never fire a `close` event (Wi-Fi switch, laptop sleep, NAT
|
|
12
|
+
// timeout, server process vanished without a TCP FIN). We send a WS
|
|
13
|
+
// ping every HEARTBEAT_MS; the server auto-replies with pong (RFC
|
|
14
|
+
// default in the `ws` lib). If we go DEAD_AFTER_MS without ANY sign of
|
|
15
|
+
// life (no pong, no message, nothing buffered to send, no tool call in
|
|
16
|
+
// flight) we consider the socket dead and terminate it — that fires
|
|
17
|
+
// `close`, which runs the normal reconnect-with-backoff path.
|
|
18
|
+
const HEARTBEAT_MS = 25_000;
|
|
19
|
+
// A socket is declared dead after ~2.5 missed heartbeats of total
|
|
20
|
+
// silence. Kept comfortably above HEARTBEAT_MS so one slow round-trip
|
|
21
|
+
// doesn't nuke a healthy link.
|
|
22
|
+
const DEAD_AFTER_MS = 65_000;
|
|
10
23
|
export class BridgeConnection {
|
|
11
24
|
opts;
|
|
12
25
|
ws = null;
|
|
@@ -14,6 +27,13 @@ export class BridgeConnection {
|
|
|
14
27
|
attempt = 0;
|
|
15
28
|
toolsByName = new Map();
|
|
16
29
|
log;
|
|
30
|
+
// Liveness tracking. `lastActivityAt` bumps on any inbound frame,
|
|
31
|
+
// pong, or successful send. `inFlight` counts tool calls currently
|
|
32
|
+
// executing — a busy connection is by definition alive + must not be
|
|
33
|
+
// torn down mid-task.
|
|
34
|
+
lastActivityAt = 0;
|
|
35
|
+
inFlight = 0;
|
|
36
|
+
heartbeatTimer = null;
|
|
17
37
|
constructor(opts) {
|
|
18
38
|
this.opts = opts;
|
|
19
39
|
this.log = opts.log ?? ((m) => console.log(m));
|
|
@@ -26,6 +46,7 @@ export class BridgeConnection {
|
|
|
26
46
|
}
|
|
27
47
|
stop() {
|
|
28
48
|
this.closed = true;
|
|
49
|
+
this.stopHeartbeat();
|
|
29
50
|
try {
|
|
30
51
|
this.ws?.send(JSON.stringify({ type: MSG.unregister }));
|
|
31
52
|
}
|
|
@@ -35,6 +56,51 @@ export class BridgeConnection {
|
|
|
35
56
|
this.ws?.close();
|
|
36
57
|
this.ws = null;
|
|
37
58
|
}
|
|
59
|
+
/** Is this connection currently doing work? True while one or more
|
|
60
|
+
* tool calls are executing, or while there are bytes still queued
|
|
61
|
+
* to send (e.g. a large tool result mid-flight). Used by the
|
|
62
|
+
* heartbeat so we never tear down a busy socket. */
|
|
63
|
+
isBusy() {
|
|
64
|
+
return this.inFlight > 0 || (this.ws?.bufferedAmount ?? 0) > 0;
|
|
65
|
+
}
|
|
66
|
+
// ── heartbeat ────────────────────────────────────────────────
|
|
67
|
+
startHeartbeat(ws) {
|
|
68
|
+
this.stopHeartbeat();
|
|
69
|
+
this.heartbeatTimer = setInterval(() => {
|
|
70
|
+
if (this.ws !== ws || ws.readyState !== WebSocket.OPEN)
|
|
71
|
+
return;
|
|
72
|
+
// A busy or recently-active socket is alive by definition —
|
|
73
|
+
// don't judge it dead, just keep pinging.
|
|
74
|
+
const silentFor = Date.now() - this.lastActivityAt;
|
|
75
|
+
if (silentFor >= DEAD_AFTER_MS && !this.isBusy()) {
|
|
76
|
+
this.log(`no response for ${Math.round(silentFor / 1000)}s — assuming dead link, forcing reconnect`);
|
|
77
|
+
// terminate() (not close()) drops a half-open socket
|
|
78
|
+
// immediately; the 'close' handler then runs reconnect.
|
|
79
|
+
try {
|
|
80
|
+
ws.terminate();
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
/* ignore */
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Otherwise probe: server auto-pongs, bumping lastActivityAt.
|
|
88
|
+
try {
|
|
89
|
+
ws.ping();
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
/* ignore — a failed ping surfaces via error/close */
|
|
93
|
+
}
|
|
94
|
+
}, HEARTBEAT_MS);
|
|
95
|
+
// Don't let the heartbeat keep the process alive on its own.
|
|
96
|
+
this.heartbeatTimer.unref?.();
|
|
97
|
+
}
|
|
98
|
+
stopHeartbeat() {
|
|
99
|
+
if (this.heartbeatTimer) {
|
|
100
|
+
clearInterval(this.heartbeatTimer);
|
|
101
|
+
this.heartbeatTimer = null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
38
104
|
connect() {
|
|
39
105
|
const headers = {};
|
|
40
106
|
if (this.opts.token)
|
|
@@ -43,6 +109,7 @@ export class BridgeConnection {
|
|
|
43
109
|
this.ws = ws;
|
|
44
110
|
ws.on("open", () => {
|
|
45
111
|
this.attempt = 0;
|
|
112
|
+
this.lastActivityAt = Date.now();
|
|
46
113
|
this.log(`connected to ${this.opts.server}`);
|
|
47
114
|
const reg = {
|
|
48
115
|
type: MSG.register,
|
|
@@ -51,8 +118,14 @@ export class BridgeConnection {
|
|
|
51
118
|
tools: this.opts.tools.map((t) => t.descriptor),
|
|
52
119
|
};
|
|
53
120
|
ws.send(JSON.stringify(reg));
|
|
121
|
+
this.startHeartbeat(ws);
|
|
122
|
+
});
|
|
123
|
+
// Any pong is a sign of life. (Server auto-pongs our pings.)
|
|
124
|
+
ws.on("pong", () => {
|
|
125
|
+
this.lastActivityAt = Date.now();
|
|
54
126
|
});
|
|
55
127
|
ws.on("message", (raw) => {
|
|
128
|
+
this.lastActivityAt = Date.now();
|
|
56
129
|
let msg;
|
|
57
130
|
try {
|
|
58
131
|
msg = JSON.parse(raw.toString());
|
|
@@ -78,6 +151,7 @@ export class BridgeConnection {
|
|
|
78
151
|
}
|
|
79
152
|
});
|
|
80
153
|
ws.on("close", () => {
|
|
154
|
+
this.stopHeartbeat();
|
|
81
155
|
this.ws = null;
|
|
82
156
|
if (this.closed)
|
|
83
157
|
return;
|
|
@@ -121,6 +195,10 @@ export class BridgeConnection {
|
|
|
121
195
|
this.send({ type: MSG.response, id: req.id, error: { code: -32602, message: `unknown tool: ${params.name}` } });
|
|
122
196
|
return;
|
|
123
197
|
}
|
|
198
|
+
// Mark the connection busy for the duration of the tool call so
|
|
199
|
+
// the heartbeat never tears it down mid-task (a slow tool =
|
|
200
|
+
// silence on the wire, but the link is fine).
|
|
201
|
+
this.inFlight += 1;
|
|
124
202
|
try {
|
|
125
203
|
const result = await tool.run(params.arguments ?? {});
|
|
126
204
|
this.send({ type: MSG.response, id: req.id, result });
|
|
@@ -132,6 +210,10 @@ export class BridgeConnection {
|
|
|
132
210
|
result: textResult(`tool "${params.name}" failed: ${err instanceof Error ? err.message : String(err)}`, true),
|
|
133
211
|
});
|
|
134
212
|
}
|
|
213
|
+
finally {
|
|
214
|
+
this.inFlight = Math.max(0, this.inFlight - 1);
|
|
215
|
+
this.lastActivityAt = Date.now();
|
|
216
|
+
}
|
|
135
217
|
}
|
|
136
218
|
}
|
|
137
219
|
//# sourceMappingURL=connection.js.map
|
package/dist/connection.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,0EAA0E;AAC1E,mEAAmE;AACnE,2DAA2D;AAE3D,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,EAAE,GAAG,EAAE,UAAU,EAAuE,MAAM,eAAe,CAAC;AAWrH,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAC/B,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC,MAAM,OAAO,gBAAgB;
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tianshu-ai/local-bridge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Local bridge for tianshu — dial into a tianshu server over WebSocket and expose your machine's tools (browser, files, shell) to the agent via reverse-MCP.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|