@linkshell/gateway 0.5.3 → 0.6.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/Dockerfile +8 -22
- package/README.md +102 -44
- package/dist/gateway/src/accounts.js.map +1 -0
- package/dist/gateway/src/index.d.ts +4 -1
- package/dist/gateway/src/index.js +4 -863
- package/dist/gateway/src/index.js.map +1 -1
- package/dist/gateway/src/main.js +57 -0
- package/dist/gateway/src/main.js.map +1 -0
- package/dist/gateway/src/rate-limit.d.ts +32 -0
- package/dist/gateway/src/rate-limit.js +106 -0
- package/dist/gateway/src/rate-limit.js.map +1 -0
- package/dist/gateway/src/relay.d.ts +84 -5
- package/dist/gateway/src/relay.js +402 -529
- package/dist/gateway/src/relay.js.map +1 -1
- package/dist/gateway/src/serve.d.ts +34 -0
- package/dist/gateway/src/serve.js +115 -0
- package/dist/gateway/src/serve.js.map +1 -0
- package/dist/{gateway-v2 → gateway}/src/store.d.ts +5 -0
- package/dist/{gateway-v2 → gateway}/src/store.js +7 -0
- package/dist/gateway/src/store.js.map +1 -0
- package/dist/gateway/src/subscription.d.ts +18 -0
- package/dist/gateway/src/subscription.js +46 -0
- package/dist/gateway/src/subscription.js.map +1 -0
- package/dist/gateway/tsconfig.tsbuildinfo +1 -1
- package/dist/wire/src/direct.d.ts +22 -0
- package/dist/wire/src/direct.js +37 -0
- package/dist/wire/src/direct.js.map +1 -0
- package/dist/wire/src/index.d.ts +1 -0
- package/dist/wire/src/index.js +1 -0
- package/dist/wire/src/index.js.map +1 -1
- package/dist/wire/src/model.d.ts +287 -6
- package/dist/wire/src/model.js +33 -0
- package/dist/wire/src/model.js.map +1 -1
- package/dist/wire/src/relay.d.ts +8 -8
- package/dist/wire/src/rpc.d.ts +1780 -44
- package/dist/wire/src/rpc.js +48 -3
- package/dist/wire/src/rpc.js.map +1 -1
- package/dist/wire/src/updates.d.ts +356 -0
- package/dist/wire/src/updates.js +11 -1
- package/dist/wire/src/updates.js.map +1 -1
- package/package.json +13 -13
- package/src/accounts.ts +32 -0
- package/src/index.ts +4 -997
- package/src/main.ts +65 -0
- package/src/rate-limit.ts +114 -0
- package/src/relay.ts +435 -620
- package/src/serve.ts +142 -0
- package/src/store.ts +135 -0
- package/src/subscription.ts +51 -0
- package/dist/gateway/src/auth-middleware.d.ts +0 -44
- package/dist/gateway/src/auth-middleware.js +0 -204
- package/dist/gateway/src/auth-middleware.js.map +0 -1
- package/dist/gateway/src/cors.d.ts +0 -2
- package/dist/gateway/src/cors.js +0 -7
- package/dist/gateway/src/cors.js.map +0 -1
- package/dist/gateway/src/embedded.d.ts +0 -21
- package/dist/gateway/src/embedded.js +0 -438
- package/dist/gateway/src/embedded.js.map +0 -1
- package/dist/gateway/src/host-auth.d.ts +0 -32
- package/dist/gateway/src/host-auth.js +0 -78
- package/dist/gateway/src/host-auth.js.map +0 -1
- package/dist/gateway/src/pairings.d.ts +0 -38
- package/dist/gateway/src/pairings.js +0 -119
- package/dist/gateway/src/pairings.js.map +0 -1
- package/dist/gateway/src/presence.d.ts +0 -28
- package/dist/gateway/src/presence.js +0 -92
- package/dist/gateway/src/presence.js.map +0 -1
- package/dist/gateway/src/sessions.d.ts +0 -113
- package/dist/gateway/src/sessions.js +0 -352
- package/dist/gateway/src/sessions.js.map +0 -1
- package/dist/gateway/src/state-store.d.ts +0 -21
- package/dist/gateway/src/state-store.js +0 -103
- package/dist/gateway/src/state-store.js.map +0 -1
- package/dist/gateway/src/static-web.d.ts +0 -15
- package/dist/gateway/src/static-web.js +0 -129
- package/dist/gateway/src/static-web.js.map +0 -1
- package/dist/gateway/src/tokens.d.ts +0 -19
- package/dist/gateway/src/tokens.js +0 -151
- package/dist/gateway/src/tokens.js.map +0 -1
- package/dist/gateway/src/tunnel.d.ts +0 -61
- package/dist/gateway/src/tunnel.js +0 -576
- package/dist/gateway/src/tunnel.js.map +0 -1
- package/dist/gateway-v2/src/accounts.js.map +0 -1
- package/dist/gateway-v2/src/index.d.ts +0 -3
- package/dist/gateway-v2/src/index.js +0 -4
- package/dist/gateway-v2/src/index.js.map +0 -1
- package/dist/gateway-v2/src/main.js +0 -17
- package/dist/gateway-v2/src/main.js.map +0 -1
- package/dist/gateway-v2/src/server.d.ts +0 -84
- package/dist/gateway-v2/src/server.js +0 -426
- package/dist/gateway-v2/src/server.js.map +0 -1
- package/dist/gateway-v2/src/store.js.map +0 -1
- package/dist/shared-protocol/src/index.d.ts +0 -17029
- package/dist/shared-protocol/src/index.js +0 -1064
- package/dist/shared-protocol/src/index.js.map +0 -1
- package/src/auth-middleware.ts +0 -266
- package/src/cors.ts +0 -8
- package/src/embedded.ts +0 -526
- package/src/host-auth.ts +0 -88
- package/src/pairings.ts +0 -133
- package/src/presence.ts +0 -118
- package/src/sessions.ts +0 -432
- package/src/state-store.ts +0 -140
- package/src/static-web.ts +0 -133
- package/src/tokens.ts +0 -159
- package/src/tunnel.ts +0 -644
- /package/dist/{gateway-v2 → gateway}/src/accounts.d.ts +0 -0
- /package/dist/{gateway-v2 → gateway}/src/accounts.js +0 -0
- /package/dist/{gateway-v2 → gateway}/src/main.d.ts +0 -0
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
const OUTPUT_BUFFER_CAPACITY = 200;
|
|
2
|
-
const OUTPUT_BUFFER_MAX_BYTES = 8 * 1024 * 1024; // 8MB per terminal buffer
|
|
3
|
-
const AGENT_REPLAY_CAPACITY = 80;
|
|
4
|
-
const HOST_RECONNECT_WINDOW = 60_000; // 60s
|
|
5
|
-
const CLEANUP_INTERVAL = 30_000;
|
|
6
|
-
/** Approximate the wire byte size of an envelope for buffer accounting. */
|
|
7
|
-
function approxEnvelopeBytes(envelope) {
|
|
8
|
-
const data = envelope.payload?.data;
|
|
9
|
-
if (typeof data === "string")
|
|
10
|
-
return data.length;
|
|
11
|
-
try {
|
|
12
|
-
return JSON.stringify(envelope).length;
|
|
13
|
-
}
|
|
14
|
-
catch {
|
|
15
|
-
return 0;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
export class SessionManager {
|
|
19
|
-
sessions = new Map();
|
|
20
|
-
cleanupTimer;
|
|
21
|
-
/** Fired when host liveness or visible agent summary fields change. */
|
|
22
|
-
onPresenceChange;
|
|
23
|
-
constructor() {
|
|
24
|
-
this.cleanupTimer = setInterval(() => this.cleanup(), CLEANUP_INTERVAL);
|
|
25
|
-
}
|
|
26
|
-
emitPresence(session) {
|
|
27
|
-
this.onPresenceChange?.(session);
|
|
28
|
-
}
|
|
29
|
-
getOrCreate(sessionId) {
|
|
30
|
-
let session = this.sessions.get(sessionId);
|
|
31
|
-
if (!session) {
|
|
32
|
-
session = {
|
|
33
|
-
id: sessionId,
|
|
34
|
-
state: "active",
|
|
35
|
-
host: undefined,
|
|
36
|
-
clients: new Map(),
|
|
37
|
-
controllerId: undefined,
|
|
38
|
-
lastActivity: Date.now(),
|
|
39
|
-
createdAt: Date.now(),
|
|
40
|
-
outputBuffers: new Map(),
|
|
41
|
-
outputBufferBytes: new Map(),
|
|
42
|
-
lastStatusByTerminal: new Map(),
|
|
43
|
-
hostDisconnectedAt: undefined,
|
|
44
|
-
provider: undefined,
|
|
45
|
-
machineId: undefined,
|
|
46
|
-
hostname: undefined,
|
|
47
|
-
platform: undefined,
|
|
48
|
-
cwd: undefined,
|
|
49
|
-
projectName: undefined,
|
|
50
|
-
userId: undefined,
|
|
51
|
-
agentStatus: undefined,
|
|
52
|
-
agentProvider: undefined,
|
|
53
|
-
agentConversationId: undefined,
|
|
54
|
-
agentTitle: undefined,
|
|
55
|
-
agentDetail: undefined,
|
|
56
|
-
agentLastActivity: undefined,
|
|
57
|
-
agentUsage: undefined,
|
|
58
|
-
agentUsageReport: undefined,
|
|
59
|
-
lastAgentSnapshot: undefined,
|
|
60
|
-
agentReplay: [],
|
|
61
|
-
};
|
|
62
|
-
this.sessions.set(sessionId, session);
|
|
63
|
-
}
|
|
64
|
-
return session;
|
|
65
|
-
}
|
|
66
|
-
get(sessionId) {
|
|
67
|
-
return this.sessions.get(sessionId);
|
|
68
|
-
}
|
|
69
|
-
setHost(sessionId, device) {
|
|
70
|
-
const session = this.getOrCreate(sessionId);
|
|
71
|
-
session.host = device;
|
|
72
|
-
session.state = "active";
|
|
73
|
-
session.hostDisconnectedAt = undefined;
|
|
74
|
-
session.lastActivity = Date.now();
|
|
75
|
-
this.emitPresence(session);
|
|
76
|
-
}
|
|
77
|
-
addClient(sessionId, device) {
|
|
78
|
-
const session = this.getOrCreate(sessionId);
|
|
79
|
-
session.clients.set(device.deviceId, device);
|
|
80
|
-
if (!session.controllerId) {
|
|
81
|
-
session.controllerId = device.deviceId;
|
|
82
|
-
}
|
|
83
|
-
session.lastActivity = Date.now();
|
|
84
|
-
}
|
|
85
|
-
removeHost(sessionId) {
|
|
86
|
-
const session = this.sessions.get(sessionId);
|
|
87
|
-
if (!session)
|
|
88
|
-
return undefined;
|
|
89
|
-
session.host = undefined;
|
|
90
|
-
session.state = "host_disconnected";
|
|
91
|
-
session.hostDisconnectedAt = Date.now();
|
|
92
|
-
this.emitPresence(session);
|
|
93
|
-
return { clients: session.clients };
|
|
94
|
-
}
|
|
95
|
-
removeClient(sessionId, deviceId) {
|
|
96
|
-
const session = this.sessions.get(sessionId);
|
|
97
|
-
if (!session)
|
|
98
|
-
return;
|
|
99
|
-
session.clients.delete(deviceId);
|
|
100
|
-
if (session.controllerId === deviceId) {
|
|
101
|
-
// Transfer control to next client or clear
|
|
102
|
-
const next = session.clients.keys().next();
|
|
103
|
-
session.controllerId = next.done ? undefined : next.value;
|
|
104
|
-
}
|
|
105
|
-
this.maybeDelete(sessionId);
|
|
106
|
-
}
|
|
107
|
-
/** Force-delete a session: disconnect host + all clients, remove from map. */
|
|
108
|
-
forceDelete(sessionId) {
|
|
109
|
-
const session = this.sessions.get(sessionId);
|
|
110
|
-
if (!session)
|
|
111
|
-
return false;
|
|
112
|
-
if (session.host) {
|
|
113
|
-
try {
|
|
114
|
-
session.host.socket.close(1000, "session deleted");
|
|
115
|
-
}
|
|
116
|
-
catch { }
|
|
117
|
-
}
|
|
118
|
-
for (const [, client] of session.clients) {
|
|
119
|
-
try {
|
|
120
|
-
client.socket.close(1000, "session deleted");
|
|
121
|
-
}
|
|
122
|
-
catch { }
|
|
123
|
-
}
|
|
124
|
-
this.sessions.delete(sessionId);
|
|
125
|
-
return true;
|
|
126
|
-
}
|
|
127
|
-
bufferOutput(sessionId, envelope) {
|
|
128
|
-
const session = this.sessions.get(sessionId);
|
|
129
|
-
if (!session)
|
|
130
|
-
return;
|
|
131
|
-
const tid = envelope.terminalId ?? "default";
|
|
132
|
-
let buf = session.outputBuffers.get(tid);
|
|
133
|
-
if (!buf) {
|
|
134
|
-
buf = [];
|
|
135
|
-
session.outputBuffers.set(tid, buf);
|
|
136
|
-
session.outputBufferBytes.set(tid, 0);
|
|
137
|
-
}
|
|
138
|
-
buf.push(envelope);
|
|
139
|
-
let bytes = (session.outputBufferBytes.get(tid) ?? 0) + approxEnvelopeBytes(envelope);
|
|
140
|
-
// Evict oldest until under BOTH the count cap and the byte cap, so a
|
|
141
|
-
// malicious/abnormal host can't pin unbounded memory via large frames.
|
|
142
|
-
while (buf.length > OUTPUT_BUFFER_CAPACITY ||
|
|
143
|
-
(bytes > OUTPUT_BUFFER_MAX_BYTES && buf.length > 1)) {
|
|
144
|
-
const removed = buf.shift();
|
|
145
|
-
if (removed)
|
|
146
|
-
bytes -= approxEnvelopeBytes(removed);
|
|
147
|
-
}
|
|
148
|
-
session.outputBufferBytes.set(tid, Math.max(0, bytes));
|
|
149
|
-
session.lastActivity = Date.now();
|
|
150
|
-
}
|
|
151
|
-
cacheStatus(sessionId, envelope) {
|
|
152
|
-
const session = this.sessions.get(sessionId);
|
|
153
|
-
if (!session)
|
|
154
|
-
return;
|
|
155
|
-
const tid = envelope.terminalId ?? "default";
|
|
156
|
-
session.lastStatusByTerminal.set(tid, envelope);
|
|
157
|
-
session.lastActivity = Date.now();
|
|
158
|
-
}
|
|
159
|
-
getStatusReplay(sessionId) {
|
|
160
|
-
const session = this.sessions.get(sessionId);
|
|
161
|
-
if (!session)
|
|
162
|
-
return [];
|
|
163
|
-
return [...session.lastStatusByTerminal.values()];
|
|
164
|
-
}
|
|
165
|
-
getReplayFrom(sessionId, afterSeqByTerminal, fallbackAfterSeq = -1) {
|
|
166
|
-
const session = this.sessions.get(sessionId);
|
|
167
|
-
if (!session)
|
|
168
|
-
return [];
|
|
169
|
-
const result = [];
|
|
170
|
-
for (const [terminalId, buf] of session.outputBuffers) {
|
|
171
|
-
const afterSeq = afterSeqByTerminal[terminalId] ?? fallbackAfterSeq;
|
|
172
|
-
for (const e of buf) {
|
|
173
|
-
if (e.seq !== undefined && e.seq > afterSeq)
|
|
174
|
-
result.push(e);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return result.sort((a, b) => {
|
|
178
|
-
const at = Date.parse(a.timestamp);
|
|
179
|
-
const bt = Date.parse(b.timestamp);
|
|
180
|
-
if (!Number.isNaN(at) && !Number.isNaN(bt) && at !== bt)
|
|
181
|
-
return at - bt;
|
|
182
|
-
return (a.seq ?? 0) - (b.seq ?? 0);
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
claimControl(sessionId, deviceId) {
|
|
186
|
-
const session = this.sessions.get(sessionId);
|
|
187
|
-
if (!session)
|
|
188
|
-
return false;
|
|
189
|
-
// Always allow takeover – last claimer wins
|
|
190
|
-
session.controllerId = deviceId;
|
|
191
|
-
return true;
|
|
192
|
-
}
|
|
193
|
-
releaseControl(sessionId, deviceId) {
|
|
194
|
-
const session = this.sessions.get(sessionId);
|
|
195
|
-
if (!session)
|
|
196
|
-
return false;
|
|
197
|
-
if (session.controllerId !== deviceId)
|
|
198
|
-
return false;
|
|
199
|
-
session.controllerId = undefined;
|
|
200
|
-
return true;
|
|
201
|
-
}
|
|
202
|
-
terminate(sessionId) {
|
|
203
|
-
const session = this.sessions.get(sessionId);
|
|
204
|
-
if (!session)
|
|
205
|
-
return;
|
|
206
|
-
session.state = "terminated";
|
|
207
|
-
}
|
|
208
|
-
listActive() {
|
|
209
|
-
return [...this.sessions.values()].filter((s) => s.state !== "terminated");
|
|
210
|
-
}
|
|
211
|
-
getSummary(sessionId) {
|
|
212
|
-
const session = this.sessions.get(sessionId);
|
|
213
|
-
if (!session)
|
|
214
|
-
return undefined;
|
|
215
|
-
return {
|
|
216
|
-
id: session.id,
|
|
217
|
-
state: session.state,
|
|
218
|
-
hasHost: !!session.host &&
|
|
219
|
-
session.host.socket.readyState === session.host.socket.OPEN,
|
|
220
|
-
clientCount: session.clients.size,
|
|
221
|
-
controllerId: session.controllerId ?? null,
|
|
222
|
-
lastActivity: session.lastActivity,
|
|
223
|
-
createdAt: session.createdAt,
|
|
224
|
-
bufferSize: [...session.outputBuffers.values()].reduce((sum, buf) => sum + buf.length, 0),
|
|
225
|
-
provider: session.provider ?? null,
|
|
226
|
-
machineId: session.machineId ?? null,
|
|
227
|
-
hostname: session.hostname ?? null,
|
|
228
|
-
platform: session.platform ?? null,
|
|
229
|
-
cwd: session.cwd ?? null,
|
|
230
|
-
projectName: session.projectName ?? null,
|
|
231
|
-
userId: session.userId ?? null,
|
|
232
|
-
agentStatus: session.agentStatus ?? null,
|
|
233
|
-
agentProvider: session.agentProvider ?? null,
|
|
234
|
-
agentConversationId: session.agentConversationId ?? null,
|
|
235
|
-
agentTitle: session.agentTitle ?? null,
|
|
236
|
-
agentDetail: session.agentDetail ?? null,
|
|
237
|
-
agentLastActivity: session.agentLastActivity ?? null,
|
|
238
|
-
agentUsage: session.agentUsage ?? null,
|
|
239
|
-
agentUsageReport: session.agentUsageReport ?? null,
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
cacheAgentSummary(sessionId, summary) {
|
|
243
|
-
const session = this.sessions.get(sessionId);
|
|
244
|
-
if (!session)
|
|
245
|
-
return false;
|
|
246
|
-
const prev = {
|
|
247
|
-
status: session.agentStatus,
|
|
248
|
-
provider: session.agentProvider,
|
|
249
|
-
conversationId: session.agentConversationId,
|
|
250
|
-
title: session.agentTitle,
|
|
251
|
-
detail: session.agentDetail,
|
|
252
|
-
};
|
|
253
|
-
if (summary.status)
|
|
254
|
-
session.agentStatus = summary.status;
|
|
255
|
-
if (summary.provider !== undefined)
|
|
256
|
-
session.agentProvider = summary.provider ?? undefined;
|
|
257
|
-
if (summary.conversationId !== undefined)
|
|
258
|
-
session.agentConversationId = summary.conversationId ?? undefined;
|
|
259
|
-
if (summary.title !== undefined)
|
|
260
|
-
session.agentTitle = summary.title ?? undefined;
|
|
261
|
-
if (summary.detail !== undefined) {
|
|
262
|
-
session.agentDetail = summary.detail ?? undefined;
|
|
263
|
-
}
|
|
264
|
-
else if (summary.status && summary.status !== "waiting_permission") {
|
|
265
|
-
// Permission lines are only meaningful while waiting. A running/idle
|
|
266
|
-
// status without a new preview must not keep "运行命令 · …" around.
|
|
267
|
-
session.agentDetail = undefined;
|
|
268
|
-
}
|
|
269
|
-
if (summary.lastActivity !== undefined)
|
|
270
|
-
session.agentLastActivity = summary.lastActivity ?? undefined;
|
|
271
|
-
if (summary.usage !== undefined)
|
|
272
|
-
session.agentUsage = summary.usage ?? undefined;
|
|
273
|
-
session.lastActivity = Date.now();
|
|
274
|
-
const changed = prev.status !== session.agentStatus ||
|
|
275
|
-
prev.provider !== session.agentProvider ||
|
|
276
|
-
prev.conversationId !== session.agentConversationId ||
|
|
277
|
-
prev.title !== session.agentTitle ||
|
|
278
|
-
prev.detail !== session.agentDetail;
|
|
279
|
-
if (changed)
|
|
280
|
-
this.emitPresence(session);
|
|
281
|
-
return changed;
|
|
282
|
-
}
|
|
283
|
-
bufferAgentEnvelope(sessionId, envelope) {
|
|
284
|
-
const session = this.sessions.get(sessionId);
|
|
285
|
-
if (!session)
|
|
286
|
-
return;
|
|
287
|
-
if (envelope.type === "agent.v2.snapshot") {
|
|
288
|
-
session.lastAgentSnapshot = envelope;
|
|
289
|
-
session.agentReplay = [];
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
session.agentReplay.push(envelope);
|
|
293
|
-
if (session.agentReplay.length > AGENT_REPLAY_CAPACITY) {
|
|
294
|
-
session.agentReplay.splice(0, session.agentReplay.length - AGENT_REPLAY_CAPACITY);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
getAgentReplay(sessionId) {
|
|
298
|
-
const session = this.sessions.get(sessionId);
|
|
299
|
-
if (!session)
|
|
300
|
-
return [];
|
|
301
|
-
return [
|
|
302
|
-
...(session.lastAgentSnapshot ? [session.lastAgentSnapshot] : []),
|
|
303
|
-
...session.agentReplay,
|
|
304
|
-
];
|
|
305
|
-
}
|
|
306
|
-
setMetadata(sessionId, provider, machineId, hostname, platform, cwd, projectName) {
|
|
307
|
-
const session = this.sessions.get(sessionId);
|
|
308
|
-
if (!session)
|
|
309
|
-
return;
|
|
310
|
-
if (provider)
|
|
311
|
-
session.provider = provider;
|
|
312
|
-
if (machineId)
|
|
313
|
-
session.machineId = machineId;
|
|
314
|
-
if (hostname)
|
|
315
|
-
session.hostname = hostname;
|
|
316
|
-
if (platform)
|
|
317
|
-
session.platform = platform;
|
|
318
|
-
if (cwd)
|
|
319
|
-
session.cwd = cwd;
|
|
320
|
-
if (projectName)
|
|
321
|
-
session.projectName = projectName;
|
|
322
|
-
}
|
|
323
|
-
maybeDelete(sessionId) {
|
|
324
|
-
const session = this.sessions.get(sessionId);
|
|
325
|
-
if (!session)
|
|
326
|
-
return;
|
|
327
|
-
if (!session.host && session.clients.size === 0) {
|
|
328
|
-
this.sessions.delete(sessionId);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
cleanup() {
|
|
332
|
-
const now = Date.now();
|
|
333
|
-
for (const [id, session] of this.sessions) {
|
|
334
|
-
// Remove sessions where host disconnected and window expired
|
|
335
|
-
if (session.state === "host_disconnected" &&
|
|
336
|
-
session.hostDisconnectedAt &&
|
|
337
|
-
now - session.hostDisconnectedAt > HOST_RECONNECT_WINDOW) {
|
|
338
|
-
session.state = "terminated";
|
|
339
|
-
}
|
|
340
|
-
// Clean up terminated sessions with no connections
|
|
341
|
-
if (session.state === "terminated" &&
|
|
342
|
-
!session.host &&
|
|
343
|
-
session.clients.size === 0) {
|
|
344
|
-
this.sessions.delete(id);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
destroy() {
|
|
349
|
-
clearInterval(this.cleanupTimer);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
//# sourceMappingURL=sessions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../../src/sessions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export interface StoredTokenRecord {
|
|
2
|
-
token: string;
|
|
3
|
-
sessionIds: string[];
|
|
4
|
-
createdAt: number;
|
|
5
|
-
lastUsedAt: number;
|
|
6
|
-
}
|
|
7
|
-
export interface StoredPairingRecord {
|
|
8
|
-
sessionId: string;
|
|
9
|
-
pairingCode: string;
|
|
10
|
-
expiresAt: number;
|
|
11
|
-
claimed: boolean;
|
|
12
|
-
}
|
|
13
|
-
export interface GatewayStateStore {
|
|
14
|
-
loadTokens(): Promise<StoredTokenRecord[]>;
|
|
15
|
-
saveToken(record: StoredTokenRecord): Promise<void>;
|
|
16
|
-
deleteToken(token: string): Promise<void>;
|
|
17
|
-
loadPairings(): Promise<StoredPairingRecord[]>;
|
|
18
|
-
savePairing(record: StoredPairingRecord): Promise<void>;
|
|
19
|
-
deletePairing(pairingCode: string): Promise<void>;
|
|
20
|
-
}
|
|
21
|
-
export declare function createSupabaseStateStore(): GatewayStateStore | undefined;
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
const TOKEN_TABLE = process.env.SUPABASE_GATEWAY_TOKEN_TABLE ?? "linkshell_gateway_tokens";
|
|
2
|
-
const PAIRING_TABLE = process.env.SUPABASE_GATEWAY_PAIRING_TABLE ?? "linkshell_gateway_pairings";
|
|
3
|
-
const STORE_TIMEOUT_MS = Number(process.env.SUPABASE_STATE_TIMEOUT_MS ?? 3_000);
|
|
4
|
-
function msToIso(ms) {
|
|
5
|
-
return new Date(ms).toISOString();
|
|
6
|
-
}
|
|
7
|
-
function isoToMs(value) {
|
|
8
|
-
if (typeof value !== "string")
|
|
9
|
-
return Date.now();
|
|
10
|
-
const parsed = Date.parse(value);
|
|
11
|
-
return Number.isNaN(parsed) ? Date.now() : parsed;
|
|
12
|
-
}
|
|
13
|
-
export function createSupabaseStateStore() {
|
|
14
|
-
const url = process.env.SUPABASE_URL?.replace(/\/+$/, "");
|
|
15
|
-
const key = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_ANON_KEY;
|
|
16
|
-
if (!url || !key)
|
|
17
|
-
return undefined;
|
|
18
|
-
const headers = {
|
|
19
|
-
apikey: key,
|
|
20
|
-
Authorization: `Bearer ${key}`,
|
|
21
|
-
"Content-Type": "application/json",
|
|
22
|
-
};
|
|
23
|
-
async function request(path, init) {
|
|
24
|
-
const res = await fetch(`${url}/rest/v1/${path}`, {
|
|
25
|
-
...init,
|
|
26
|
-
signal: init?.signal ?? AbortSignal.timeout(STORE_TIMEOUT_MS),
|
|
27
|
-
headers: {
|
|
28
|
-
...headers,
|
|
29
|
-
...(init?.headers ?? {}),
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
if (!res.ok) {
|
|
33
|
-
const body = await res.text().catch(() => "");
|
|
34
|
-
throw new Error(`Supabase state store ${res.status}: ${body || res.statusText}`);
|
|
35
|
-
}
|
|
36
|
-
if (res.status === 204)
|
|
37
|
-
return undefined;
|
|
38
|
-
// Writes (POST upsert / DELETE) can return 2xx with an EMPTY body depending
|
|
39
|
-
// on PostgREST's Prefer handling — calling res.json() on that throws
|
|
40
|
-
// "Unexpected end of JSON input". Read as text and only parse when non-empty
|
|
41
|
-
// so writes resolve to undefined cleanly; reads (SELECT) always return a
|
|
42
|
-
// JSON array ("[]" at minimum), so they still parse.
|
|
43
|
-
const text = await res.text();
|
|
44
|
-
if (!text.trim())
|
|
45
|
-
return undefined;
|
|
46
|
-
return JSON.parse(text);
|
|
47
|
-
}
|
|
48
|
-
return {
|
|
49
|
-
async loadTokens() {
|
|
50
|
-
const rows = await request(`${TOKEN_TABLE}?select=token,session_ids,created_at,last_used_at`);
|
|
51
|
-
return rows.map((row) => ({
|
|
52
|
-
token: String(row.token ?? ""),
|
|
53
|
-
sessionIds: Array.isArray(row.session_ids)
|
|
54
|
-
? row.session_ids.map(String)
|
|
55
|
-
: [],
|
|
56
|
-
createdAt: isoToMs(row.created_at),
|
|
57
|
-
lastUsedAt: isoToMs(row.last_used_at),
|
|
58
|
-
})).filter((record) => record.token);
|
|
59
|
-
},
|
|
60
|
-
async saveToken(record) {
|
|
61
|
-
await request(`${TOKEN_TABLE}?on_conflict=token`, {
|
|
62
|
-
method: "POST",
|
|
63
|
-
headers: { Prefer: "return=minimal,resolution=merge-duplicates" },
|
|
64
|
-
body: JSON.stringify({
|
|
65
|
-
token: record.token,
|
|
66
|
-
session_ids: record.sessionIds,
|
|
67
|
-
created_at: msToIso(record.createdAt),
|
|
68
|
-
last_used_at: msToIso(record.lastUsedAt),
|
|
69
|
-
}),
|
|
70
|
-
});
|
|
71
|
-
},
|
|
72
|
-
async deleteToken(token) {
|
|
73
|
-
await request(`${TOKEN_TABLE}?token=eq.${encodeURIComponent(token)}`, {
|
|
74
|
-
method: "DELETE",
|
|
75
|
-
});
|
|
76
|
-
},
|
|
77
|
-
async loadPairings() {
|
|
78
|
-
const rows = await request(`${PAIRING_TABLE}?select=pairing_code,session_id,expires_at,claimed`);
|
|
79
|
-
return rows.map((row) => ({
|
|
80
|
-
pairingCode: String(row.pairing_code ?? ""),
|
|
81
|
-
sessionId: String(row.session_id ?? ""),
|
|
82
|
-
expiresAt: isoToMs(row.expires_at),
|
|
83
|
-
claimed: row.claimed === true,
|
|
84
|
-
})).filter((record) => record.pairingCode && record.sessionId);
|
|
85
|
-
},
|
|
86
|
-
async savePairing(record) {
|
|
87
|
-
await request(`${PAIRING_TABLE}?on_conflict=pairing_code`, {
|
|
88
|
-
method: "POST",
|
|
89
|
-
headers: { Prefer: "return=minimal,resolution=merge-duplicates" },
|
|
90
|
-
body: JSON.stringify({
|
|
91
|
-
pairing_code: record.pairingCode,
|
|
92
|
-
session_id: record.sessionId,
|
|
93
|
-
expires_at: msToIso(record.expiresAt),
|
|
94
|
-
claimed: record.claimed,
|
|
95
|
-
}),
|
|
96
|
-
});
|
|
97
|
-
},
|
|
98
|
-
async deletePairing(pairingCode) {
|
|
99
|
-
await request(`${PAIRING_TABLE}?pairing_code=eq.${encodeURIComponent(pairingCode)}`, { method: "DELETE" });
|
|
100
|
-
},
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
//# sourceMappingURL=state-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"state-store.js","sourceRoot":"","sources":["../../../src/state-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
-
export declare function webEnabled(): boolean;
|
|
3
|
-
export declare function webDistPath(): string;
|
|
4
|
-
/**
|
|
5
|
-
* Try to serve a concrete web asset without the SPA fallback. This lets the
|
|
6
|
-
* gateway protect its own built assets before tunnel cookie fallback handles a
|
|
7
|
-
* previewed app's absolute assets such as "/assets/app.css".
|
|
8
|
-
*/
|
|
9
|
-
export declare function serveWebAsset(req: IncomingMessage, res: ServerResponse): Promise<boolean>;
|
|
10
|
-
/**
|
|
11
|
-
* Try to serve a GET/HEAD request from the web dist. Returns true if handled.
|
|
12
|
-
* Place AFTER all API routes so it never shadows them. Unmatched non-asset
|
|
13
|
-
* paths fall back to index.html (SPA client-side routing).
|
|
14
|
-
*/
|
|
15
|
-
export declare function serveWeb(req: IncomingMessage, res: ServerResponse): Promise<boolean>;
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { stat, readFile } from "node:fs/promises";
|
|
3
|
-
import { resolve, join, extname, normalize } from "node:path";
|
|
4
|
-
// Serves the built web-dashboard SPA from the gateway, so a single deployment
|
|
5
|
-
// (and single origin) hosts both the API/WebSocket and the UI. The web is
|
|
6
|
-
// optional: if WEB_DIST doesn't exist (e.g. local dev using the Vite dev
|
|
7
|
-
// server), the gateway runs API-only and this is a no-op.
|
|
8
|
-
const WEB_DIST = process.env.WEB_DIST ?? resolve(process.cwd(), "web");
|
|
9
|
-
const hasWeb = existsSync(join(WEB_DIST, "index.html"));
|
|
10
|
-
const CONTENT_TYPES = {
|
|
11
|
-
".html": "text/html; charset=utf-8",
|
|
12
|
-
".js": "text/javascript; charset=utf-8",
|
|
13
|
-
".mjs": "text/javascript; charset=utf-8",
|
|
14
|
-
".css": "text/css; charset=utf-8",
|
|
15
|
-
".json": "application/json; charset=utf-8",
|
|
16
|
-
".svg": "image/svg+xml",
|
|
17
|
-
".png": "image/png",
|
|
18
|
-
".jpg": "image/jpeg",
|
|
19
|
-
".jpeg": "image/jpeg",
|
|
20
|
-
".gif": "image/gif",
|
|
21
|
-
".ico": "image/x-icon",
|
|
22
|
-
".webp": "image/webp",
|
|
23
|
-
".woff": "font/woff",
|
|
24
|
-
".woff2": "font/woff2",
|
|
25
|
-
".ttf": "font/ttf",
|
|
26
|
-
".map": "application/json; charset=utf-8",
|
|
27
|
-
".txt": "text/plain; charset=utf-8",
|
|
28
|
-
};
|
|
29
|
-
export function webEnabled() {
|
|
30
|
-
return hasWeb;
|
|
31
|
-
}
|
|
32
|
-
export function webDistPath() {
|
|
33
|
-
return WEB_DIST;
|
|
34
|
-
}
|
|
35
|
-
async function resolveWebFile(pathname, allowSpaFallback) {
|
|
36
|
-
// Path-traversal guard: normalize, then confine to WEB_DIST.
|
|
37
|
-
const candidate = resolve(WEB_DIST, "." + normalize(pathname));
|
|
38
|
-
const inRoot = candidate === WEB_DIST || candidate.startsWith(WEB_DIST + "/");
|
|
39
|
-
let filePath = null;
|
|
40
|
-
if (inRoot && pathname !== "/") {
|
|
41
|
-
try {
|
|
42
|
-
const s = await stat(candidate);
|
|
43
|
-
if (s.isFile())
|
|
44
|
-
filePath = candidate;
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
// not a real file
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
// SPA fallback: serve index.html for "/" and for any path without a file
|
|
51
|
-
// extension (a client-side route). Missing assets (with an extension) 404.
|
|
52
|
-
if (!filePath) {
|
|
53
|
-
if (allowSpaFallback && (pathname === "/" || extname(pathname) === "")) {
|
|
54
|
-
filePath = join(WEB_DIST, "index.html");
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
return null; // let the caller 404/proxy the missing asset
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return filePath;
|
|
61
|
-
}
|
|
62
|
-
async function serveWebFile(req, res, filePath) {
|
|
63
|
-
try {
|
|
64
|
-
const ext = extname(filePath).toLowerCase();
|
|
65
|
-
const type = CONTENT_TYPES[ext] ?? "application/octet-stream";
|
|
66
|
-
res.setHeader("Content-Type", type);
|
|
67
|
-
// Hashed assets (Vite emits content-hashed filenames) can cache hard;
|
|
68
|
-
// index.html must never be cached so deploys take effect immediately.
|
|
69
|
-
if (filePath.endsWith("index.html")) {
|
|
70
|
-
res.setHeader("Cache-Control", "no-cache");
|
|
71
|
-
// lsh_tunnel is an HttpOnly helper cookie for preview subresources. Older
|
|
72
|
-
// builds used Path=/, so stale values are still sent to the LinkShell app
|
|
73
|
-
// shell and even /ws handshakes. Clear it whenever the real app document
|
|
74
|
-
// is served; /tunnel/... responses will set a fresh value when preview is
|
|
75
|
-
// actually opened.
|
|
76
|
-
res.setHeader("Set-Cookie", "lsh_tunnel=; Path=/; Max-Age=0; HttpOnly; SameSite=Lax");
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
80
|
-
}
|
|
81
|
-
if (req.method === "HEAD") {
|
|
82
|
-
res.writeHead(200);
|
|
83
|
-
res.end();
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
const body = await readFile(filePath);
|
|
87
|
-
res.writeHead(200);
|
|
88
|
-
res.end(body);
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Try to serve a concrete web asset without the SPA fallback. This lets the
|
|
97
|
-
* gateway protect its own built assets before tunnel cookie fallback handles a
|
|
98
|
-
* previewed app's absolute assets such as "/assets/app.css".
|
|
99
|
-
*/
|
|
100
|
-
export async function serveWebAsset(req, res) {
|
|
101
|
-
if (!hasWeb)
|
|
102
|
-
return false;
|
|
103
|
-
if (req.method !== "GET" && req.method !== "HEAD")
|
|
104
|
-
return false;
|
|
105
|
-
const url = new URL(req.url ?? "/", "http://localhost");
|
|
106
|
-
const pathname = decodeURIComponent(url.pathname);
|
|
107
|
-
const filePath = await resolveWebFile(pathname, false);
|
|
108
|
-
if (!filePath)
|
|
109
|
-
return false;
|
|
110
|
-
return serveWebFile(req, res, filePath);
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Try to serve a GET/HEAD request from the web dist. Returns true if handled.
|
|
114
|
-
* Place AFTER all API routes so it never shadows them. Unmatched non-asset
|
|
115
|
-
* paths fall back to index.html (SPA client-side routing).
|
|
116
|
-
*/
|
|
117
|
-
export async function serveWeb(req, res) {
|
|
118
|
-
if (!hasWeb)
|
|
119
|
-
return false;
|
|
120
|
-
if (req.method !== "GET" && req.method !== "HEAD")
|
|
121
|
-
return false;
|
|
122
|
-
const url = new URL(req.url ?? "/", "http://localhost");
|
|
123
|
-
const pathname = decodeURIComponent(url.pathname);
|
|
124
|
-
const filePath = await resolveWebFile(pathname, true);
|
|
125
|
-
if (!filePath)
|
|
126
|
-
return false;
|
|
127
|
-
return serveWebFile(req, res, filePath);
|
|
128
|
-
}
|
|
129
|
-
//# sourceMappingURL=static-web.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static-web.js","sourceRoot":"","sources":["../../../src/static-web.ts"],"names":[],"mappings":"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"}
|