poke-gate 0.1.6 → 0.1.7
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.
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Publish npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- name: Checkout
|
|
13
|
+
uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Setup Node
|
|
16
|
+
uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: 22
|
|
19
|
+
registry-url: https://registry.npmjs.org
|
|
20
|
+
|
|
21
|
+
- name: Publish
|
|
22
|
+
run: npm publish --access public
|
|
23
|
+
env:
|
|
24
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -251,7 +251,7 @@ class GateService: ObservableObject {
|
|
|
251
251
|
let pipe = Pipe()
|
|
252
252
|
|
|
253
253
|
proc.executableURL = URL(fileURLWithPath: "/bin/zsh")
|
|
254
|
-
proc.arguments = ["-c", "\(npxBin) -y poke-gate --verbose"]
|
|
254
|
+
proc.arguments = ["-c", "\(npxBin) -y poke-gate@latest --verbose"]
|
|
255
255
|
proc.environment = ProcessInfo.processInfo.environment.merging(
|
|
256
256
|
[
|
|
257
257
|
"PATH": fullPath,
|
|
@@ -267,7 +267,7 @@
|
|
|
267
267
|
"@executable_path/../Frameworks",
|
|
268
268
|
);
|
|
269
269
|
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
|
270
|
-
MARKETING_VERSION = 0.1.
|
|
270
|
+
MARKETING_VERSION = 0.1.6;
|
|
271
271
|
PRODUCT_BUNDLE_IDENTIFIER = "dev.fka.Poke-macOS-Gate";
|
|
272
272
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
273
273
|
REGISTER_APP_GROUPS = YES;
|
|
@@ -302,7 +302,7 @@
|
|
|
302
302
|
"@executable_path/../Frameworks",
|
|
303
303
|
);
|
|
304
304
|
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
|
305
|
-
MARKETING_VERSION = 0.1.
|
|
305
|
+
MARKETING_VERSION = 0.1.6;
|
|
306
306
|
PRODUCT_BUNDLE_IDENTIFIER = "dev.fka.Poke-macOS-Gate";
|
|
307
307
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
308
308
|
REGISTER_APP_GROUPS = YES;
|
package/package.json
CHANGED
package/src/app.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { startMcpServer, enableLogging } from "./mcp-server.js";
|
|
2
2
|
import { startTunnel } from "./tunnel.js";
|
|
3
|
-
import { startAgentScheduler } from "./agents.js";
|
|
3
|
+
import { startAgentScheduler, stopAgentScheduler } from "./agents.js";
|
|
4
4
|
import { Poke, isLoggedIn, login, getToken } from "poke";
|
|
5
5
|
|
|
6
6
|
const verbose = process.argv.includes("--verbose") || process.argv.includes("-v");
|
|
@@ -29,7 +29,11 @@ async function ensureAuthenticated() {
|
|
|
29
29
|
return token;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
let currentTunnel = null;
|
|
33
|
+
let reconnectTimer = null;
|
|
34
|
+
let reconnectWatchdog = null;
|
|
35
|
+
|
|
36
|
+
async function connectWithRetry(mcpUrl, token) {
|
|
33
37
|
let attempt = 0;
|
|
34
38
|
const maxDelay = 60_000;
|
|
35
39
|
|
|
@@ -40,19 +44,22 @@ async function connectTunnel(mcpUrl, token) {
|
|
|
40
44
|
try {
|
|
41
45
|
log(attempt > 1 ? `Reconnecting tunnel (attempt ${attempt})…` : "Connecting tunnel to Poke...");
|
|
42
46
|
|
|
43
|
-
await startTunnel({
|
|
47
|
+
const { tunnel } = await startTunnel({
|
|
44
48
|
mcpUrl,
|
|
45
49
|
onEvent: (type, data) => {
|
|
46
50
|
switch (type) {
|
|
47
51
|
case "connected":
|
|
48
52
|
attempt = 0;
|
|
53
|
+
clearTimeout(reconnectWatchdog);
|
|
54
|
+
reconnectWatchdog = null;
|
|
49
55
|
log(`Tunnel connected (${data.connectionId})`);
|
|
50
56
|
log("Ready — your Poke agent can now access this machine.");
|
|
51
57
|
notifyPoke(data.connectionId, token);
|
|
52
58
|
startAgentScheduler();
|
|
53
59
|
break;
|
|
54
60
|
case "disconnected":
|
|
55
|
-
log("Tunnel disconnected.
|
|
61
|
+
log("Tunnel disconnected.");
|
|
62
|
+
scheduleReconnect(mcpUrl, token);
|
|
56
63
|
break;
|
|
57
64
|
case "error":
|
|
58
65
|
log(`Tunnel error: ${data}`);
|
|
@@ -67,7 +74,8 @@ async function connectTunnel(mcpUrl, token) {
|
|
|
67
74
|
},
|
|
68
75
|
});
|
|
69
76
|
|
|
70
|
-
|
|
77
|
+
currentTunnel = tunnel;
|
|
78
|
+
return;
|
|
71
79
|
} catch (err) {
|
|
72
80
|
log(`Tunnel failed: ${err.message}`);
|
|
73
81
|
log(`Retrying in ${Math.round(delay / 1000)}s…`);
|
|
@@ -76,6 +84,24 @@ async function connectTunnel(mcpUrl, token) {
|
|
|
76
84
|
}
|
|
77
85
|
}
|
|
78
86
|
|
|
87
|
+
function scheduleReconnect(mcpUrl, token) {
|
|
88
|
+
if (reconnectWatchdog) return;
|
|
89
|
+
|
|
90
|
+
log("Waiting 15s for automatic reconnect…");
|
|
91
|
+
reconnectWatchdog = setTimeout(async () => {
|
|
92
|
+
reconnectWatchdog = null;
|
|
93
|
+
log("No reconnect after 15s — creating a fresh tunnel.");
|
|
94
|
+
|
|
95
|
+
if (currentTunnel) {
|
|
96
|
+
try { await currentTunnel.stop(); } catch {}
|
|
97
|
+
currentTunnel = null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
stopAgentScheduler();
|
|
101
|
+
await connectWithRetry(mcpUrl, token);
|
|
102
|
+
}, 15_000);
|
|
103
|
+
}
|
|
104
|
+
|
|
79
105
|
async function main() {
|
|
80
106
|
log("poke-gate starting...");
|
|
81
107
|
|
|
@@ -86,7 +112,7 @@ async function main() {
|
|
|
86
112
|
|
|
87
113
|
const mcpUrl = `http://localhost:${port}/mcp`;
|
|
88
114
|
|
|
89
|
-
await
|
|
115
|
+
await connectWithRetry(mcpUrl, token);
|
|
90
116
|
}
|
|
91
117
|
|
|
92
118
|
async function notifyPoke(connectionId, token) {
|