@cluesmith/codev 2.0.0-rc.60 → 2.0.0-rc.63

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.
Files changed (156) hide show
  1. package/dashboard/dist/assets/index-C7FtNK6Y.css +32 -0
  2. package/dashboard/dist/assets/index-D6VqWAaI.js +131 -0
  3. package/dashboard/dist/assets/index-D6VqWAaI.js.map +1 -0
  4. package/dashboard/dist/index.html +2 -2
  5. package/dist/agent-farm/cli.d.ts.map +1 -1
  6. package/dist/agent-farm/cli.js +75 -50
  7. package/dist/agent-farm/cli.js.map +1 -1
  8. package/dist/agent-farm/commands/architect.d.ts.map +1 -1
  9. package/dist/agent-farm/commands/architect.js +38 -48
  10. package/dist/agent-farm/commands/architect.js.map +1 -1
  11. package/dist/agent-farm/commands/attach.d.ts.map +1 -1
  12. package/dist/agent-farm/commands/attach.js +14 -35
  13. package/dist/agent-farm/commands/attach.js.map +1 -1
  14. package/dist/agent-farm/commands/cleanup.d.ts.map +1 -1
  15. package/dist/agent-farm/commands/cleanup.js +17 -18
  16. package/dist/agent-farm/commands/cleanup.js.map +1 -1
  17. package/dist/agent-farm/commands/consult.d.ts +3 -4
  18. package/dist/agent-farm/commands/consult.d.ts.map +1 -1
  19. package/dist/agent-farm/commands/consult.js +27 -37
  20. package/dist/agent-farm/commands/consult.js.map +1 -1
  21. package/dist/agent-farm/commands/open.d.ts.map +1 -1
  22. package/dist/agent-farm/commands/open.js +19 -36
  23. package/dist/agent-farm/commands/open.js.map +1 -1
  24. package/dist/agent-farm/commands/shell.d.ts +3 -3
  25. package/dist/agent-farm/commands/shell.d.ts.map +1 -1
  26. package/dist/agent-farm/commands/shell.js +33 -78
  27. package/dist/agent-farm/commands/shell.js.map +1 -1
  28. package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
  29. package/dist/agent-farm/commands/spawn.js +113 -90
  30. package/dist/agent-farm/commands/spawn.js.map +1 -1
  31. package/dist/agent-farm/commands/start.d.ts +7 -20
  32. package/dist/agent-farm/commands/start.d.ts.map +1 -1
  33. package/dist/agent-farm/commands/start.js +7 -243
  34. package/dist/agent-farm/commands/start.js.map +1 -1
  35. package/dist/agent-farm/commands/status.d.ts.map +1 -1
  36. package/dist/agent-farm/commands/status.js +22 -29
  37. package/dist/agent-farm/commands/status.js.map +1 -1
  38. package/dist/agent-farm/commands/stop.d.ts.map +1 -1
  39. package/dist/agent-farm/commands/stop.js +43 -172
  40. package/dist/agent-farm/commands/stop.js.map +1 -1
  41. package/dist/agent-farm/commands/tower-cloud.d.ts +47 -0
  42. package/dist/agent-farm/commands/tower-cloud.d.ts.map +1 -0
  43. package/dist/agent-farm/commands/tower-cloud.js +316 -0
  44. package/dist/agent-farm/commands/tower-cloud.js.map +1 -0
  45. package/dist/agent-farm/db/index.d.ts +6 -2
  46. package/dist/agent-farm/db/index.d.ts.map +1 -1
  47. package/dist/agent-farm/db/index.js +56 -31
  48. package/dist/agent-farm/db/index.js.map +1 -1
  49. package/dist/agent-farm/db/migrate.d.ts +0 -4
  50. package/dist/agent-farm/db/migrate.d.ts.map +1 -1
  51. package/dist/agent-farm/db/migrate.js +0 -46
  52. package/dist/agent-farm/db/migrate.js.map +1 -1
  53. package/dist/agent-farm/db/schema.d.ts +3 -3
  54. package/dist/agent-farm/db/schema.d.ts.map +1 -1
  55. package/dist/agent-farm/db/schema.js +3 -17
  56. package/dist/agent-farm/db/schema.js.map +1 -1
  57. package/dist/agent-farm/db/types.d.ts +0 -10
  58. package/dist/agent-farm/db/types.d.ts.map +1 -1
  59. package/dist/agent-farm/db/types.js +0 -8
  60. package/dist/agent-farm/db/types.js.map +1 -1
  61. package/dist/agent-farm/hq-connector.d.ts +1 -1
  62. package/dist/agent-farm/hq-connector.js +1 -1
  63. package/dist/agent-farm/lib/cloud-config.d.ts +46 -0
  64. package/dist/agent-farm/lib/cloud-config.d.ts.map +1 -0
  65. package/dist/agent-farm/lib/cloud-config.js +106 -0
  66. package/dist/agent-farm/lib/cloud-config.js.map +1 -0
  67. package/dist/agent-farm/lib/tower-client.d.ts +7 -5
  68. package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
  69. package/dist/agent-farm/lib/tower-client.js.map +1 -1
  70. package/dist/agent-farm/lib/tunnel-client.d.ts +117 -0
  71. package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -0
  72. package/dist/agent-farm/lib/tunnel-client.js +502 -0
  73. package/dist/agent-farm/lib/tunnel-client.js.map +1 -0
  74. package/dist/agent-farm/servers/tower-server.js +865 -441
  75. package/dist/agent-farm/servers/tower-server.js.map +1 -1
  76. package/dist/agent-farm/state.d.ts +2 -2
  77. package/dist/agent-farm/state.d.ts.map +1 -1
  78. package/dist/agent-farm/state.js +6 -16
  79. package/dist/agent-farm/state.js.map +1 -1
  80. package/dist/agent-farm/types.d.ts +1 -18
  81. package/dist/agent-farm/types.d.ts.map +1 -1
  82. package/dist/agent-farm/utils/config.d.ts +0 -5
  83. package/dist/agent-farm/utils/config.d.ts.map +1 -1
  84. package/dist/agent-farm/utils/config.js +0 -31
  85. package/dist/agent-farm/utils/config.js.map +1 -1
  86. package/dist/agent-farm/utils/file-tabs.d.ts +27 -0
  87. package/dist/agent-farm/utils/file-tabs.d.ts.map +1 -0
  88. package/dist/agent-farm/utils/file-tabs.js +46 -0
  89. package/dist/agent-farm/utils/file-tabs.js.map +1 -0
  90. package/dist/agent-farm/utils/gate-status.d.ts +16 -0
  91. package/dist/agent-farm/utils/gate-status.d.ts.map +1 -0
  92. package/dist/agent-farm/utils/gate-status.js +79 -0
  93. package/dist/agent-farm/utils/gate-status.js.map +1 -0
  94. package/dist/agent-farm/utils/gate-watcher.d.ts +38 -0
  95. package/dist/agent-farm/utils/gate-watcher.d.ts.map +1 -0
  96. package/dist/agent-farm/utils/gate-watcher.js +122 -0
  97. package/dist/agent-farm/utils/gate-watcher.js.map +1 -0
  98. package/dist/agent-farm/utils/index.d.ts +0 -1
  99. package/dist/agent-farm/utils/index.d.ts.map +1 -1
  100. package/dist/agent-farm/utils/index.js +0 -1
  101. package/dist/agent-farm/utils/index.js.map +1 -1
  102. package/dist/agent-farm/utils/notifications.js +1 -1
  103. package/dist/agent-farm/utils/notifications.js.map +1 -1
  104. package/dist/agent-farm/utils/server-utils.d.ts +1 -1
  105. package/dist/agent-farm/utils/server-utils.js +1 -1
  106. package/dist/agent-farm/utils/session.d.ts +10 -0
  107. package/dist/agent-farm/utils/session.d.ts.map +1 -0
  108. package/dist/agent-farm/utils/session.js +12 -0
  109. package/dist/agent-farm/utils/session.js.map +1 -0
  110. package/dist/cli.d.ts.map +1 -1
  111. package/dist/cli.js +2 -0
  112. package/dist/cli.js.map +1 -1
  113. package/dist/commands/adopt.js +1 -1
  114. package/dist/commands/adopt.js.map +1 -1
  115. package/dist/commands/consult/index.d.ts +1 -0
  116. package/dist/commands/consult/index.d.ts.map +1 -1
  117. package/dist/commands/consult/index.js +42 -15
  118. package/dist/commands/consult/index.js.map +1 -1
  119. package/dist/commands/init.js +1 -1
  120. package/dist/commands/init.js.map +1 -1
  121. package/dist/commands/porch/index.d.ts.map +1 -1
  122. package/dist/commands/porch/index.js +35 -12
  123. package/dist/commands/porch/index.js.map +1 -1
  124. package/dist/commands/porch/next.js +15 -5
  125. package/dist/commands/porch/next.js.map +1 -1
  126. package/dist/commands/porch/verdict.d.ts +8 -0
  127. package/dist/commands/porch/verdict.d.ts.map +1 -1
  128. package/dist/commands/porch/verdict.js +13 -0
  129. package/dist/commands/porch/verdict.js.map +1 -1
  130. package/dist/terminal/pty-session.d.ts +2 -0
  131. package/dist/terminal/pty-session.d.ts.map +1 -1
  132. package/dist/terminal/pty-session.js +4 -0
  133. package/dist/terminal/pty-session.js.map +1 -1
  134. package/package.json +1 -1
  135. package/skeleton/.claude/skills/af/SKILL.md +15 -0
  136. package/skeleton/consult-types/impl-review.md +9 -0
  137. package/skeleton/protocols/spir/prompts/review.md +15 -16
  138. package/skeleton/protocols/spir/protocol.json +4 -0
  139. package/skeleton/protocols/spir/templates/review.md +81 -199
  140. package/skeleton/resources/commands/agent-farm.md +38 -2
  141. package/templates/tower.html +7 -150
  142. package/dashboard/dist/assets/index-CXloFYpB.css +0 -32
  143. package/dashboard/dist/assets/index-Ca2fjOJf.js +0 -131
  144. package/dashboard/dist/assets/index-Ca2fjOJf.js.map +0 -1
  145. package/dist/agent-farm/utils/orphan-handler.d.ts +0 -27
  146. package/dist/agent-farm/utils/orphan-handler.d.ts.map +0 -1
  147. package/dist/agent-farm/utils/orphan-handler.js +0 -149
  148. package/dist/agent-farm/utils/orphan-handler.js.map +0 -1
  149. package/dist/agent-farm/utils/port-registry.d.ts +0 -57
  150. package/dist/agent-farm/utils/port-registry.d.ts.map +0 -1
  151. package/dist/agent-farm/utils/port-registry.js +0 -166
  152. package/dist/agent-farm/utils/port-registry.js.map +0 -1
  153. package/dist/agent-farm/utils/terminal-ports.d.ts +0 -18
  154. package/dist/agent-farm/utils/terminal-ports.d.ts.map +0 -1
  155. package/dist/agent-farm/utils/terminal-ports.js +0 -35
  156. package/dist/agent-farm/utils/terminal-ports.js.map +0 -1
@@ -0,0 +1,502 @@
1
+ /**
2
+ * HTTP/2 Role-Reversal Tunnel Client (Spec 0097 Phase 3, TICK-001)
3
+ *
4
+ * Opens a WebSocket connection to codevos.ai/tunnel, authenticates
5
+ * with JSON messages, then runs an HTTP/2 *server* over the WebSocket
6
+ * stream. codevos.ai acts as the HTTP/2 *client*, sending requests
7
+ * through the tunnel. The tower proxies those requests to localhost.
8
+ *
9
+ * TICK-001: Transport changed from raw TCP/TLS to WebSocket.
10
+ * The H2 role-reversal is transport-agnostic — it works over any duplex stream.
11
+ */
12
+ import http2 from 'node:http2';
13
+ import http from 'node:http';
14
+ import https from 'node:https';
15
+ import { URL } from 'node:url';
16
+ import WebSocket, { createWebSocketStream } from 'ws';
17
+ /** Headers that must be stripped when proxying between HTTP/2 and HTTP/1.1 */
18
+ const HOP_BY_HOP_HEADERS = new Set([
19
+ 'connection',
20
+ 'keep-alive',
21
+ 'proxy-authenticate',
22
+ 'proxy-authorization',
23
+ 'te',
24
+ 'trailers',
25
+ 'transfer-encoding',
26
+ 'upgrade',
27
+ ]);
28
+ /** Paths that are local-only management endpoints — block from tunnel */
29
+ const BLOCKED_PATH_PREFIX = '/api/tunnel/';
30
+ /**
31
+ * Calculate reconnection backoff with exponential increase and jitter.
32
+ * Exported for unit testing.
33
+ *
34
+ * Formula: min(1000 * 2^attempt + random(0, 1000), 60000)
35
+ * After 10 consecutive failures: 300000ms (5 min)
36
+ */
37
+ export function calculateBackoff(attempt, randomFn = Math.random) {
38
+ if (attempt >= 10)
39
+ return 300_000;
40
+ const base = 1000 * Math.pow(2, attempt);
41
+ const jitter = Math.floor(randomFn() * 1000);
42
+ return Math.min(base + jitter, 60_000);
43
+ }
44
+ /**
45
+ * Check if a request path should be blocked from tunnel proxying.
46
+ * Normalizes percent-encoding and collapses dot segments before checking,
47
+ * preventing bypass via encoded slashes (%2F), double dots, etc.
48
+ * Exported for unit testing.
49
+ */
50
+ export function isBlockedPath(path) {
51
+ try {
52
+ // Decode percent-encoding, then resolve dot segments via URL normalization
53
+ const decoded = decodeURIComponent(path);
54
+ // Collapse duplicate slashes and resolve . / .. segments
55
+ const normalized = new URL(decoded, 'http://localhost').pathname;
56
+ return normalized.startsWith(BLOCKED_PATH_PREFIX);
57
+ }
58
+ catch {
59
+ // If decoding fails, check the raw path as a fallback (fail closed)
60
+ return path.startsWith(BLOCKED_PATH_PREFIX);
61
+ }
62
+ }
63
+ /**
64
+ * Filter hop-by-hop headers from a headers object.
65
+ * Returns a new object with only end-to-end headers.
66
+ * Exported for unit testing.
67
+ */
68
+ export function filterHopByHopHeaders(headers) {
69
+ const result = {};
70
+ for (const [key, value] of Object.entries(headers)) {
71
+ if (value !== undefined && !HOP_BY_HOP_HEADERS.has(key.toLowerCase())) {
72
+ result[key] = value;
73
+ }
74
+ }
75
+ return result;
76
+ }
77
+ /**
78
+ * Build the WebSocket tunnel URL from the server URL.
79
+ * https:// → wss://, http:// → ws://
80
+ */
81
+ function buildTunnelWsUrl(serverUrl) {
82
+ const parsed = new URL(serverUrl);
83
+ const wsProtocol = parsed.protocol === 'https:' ? 'wss:' : 'ws:';
84
+ return `${wsProtocol}//${parsed.host}/tunnel`;
85
+ }
86
+ export class TunnelClient {
87
+ options;
88
+ state = 'disconnected';
89
+ connectedAt = null;
90
+ stateListeners = [];
91
+ ws = null;
92
+ wsStream = null;
93
+ h2Server = null;
94
+ h2Session = null;
95
+ reconnectTimer = null;
96
+ consecutiveFailures = 0;
97
+ rateLimitCount = 0;
98
+ destroyed = false;
99
+ constructor(options) {
100
+ this.options = options;
101
+ }
102
+ getState() {
103
+ return this.state;
104
+ }
105
+ getUptime() {
106
+ if (this.state !== 'connected' || this.connectedAt === null)
107
+ return null;
108
+ return Date.now() - this.connectedAt;
109
+ }
110
+ onStateChange(callback) {
111
+ this.stateListeners.push(callback);
112
+ }
113
+ setState(newState) {
114
+ if (this.state === newState)
115
+ return;
116
+ const prev = this.state;
117
+ this.state = newState;
118
+ if (newState === 'connected') {
119
+ this.connectedAt = Date.now();
120
+ this.consecutiveFailures = 0;
121
+ this.rateLimitCount = 0;
122
+ // Push cached metadata on connect
123
+ if (this._pendingMetadata) {
124
+ this.pushMetadataViaHttp(this._pendingMetadata);
125
+ }
126
+ }
127
+ else if (newState === 'disconnected' || newState === 'auth_failed') {
128
+ this.connectedAt = null;
129
+ }
130
+ for (const listener of this.stateListeners) {
131
+ try {
132
+ listener(newState, prev);
133
+ }
134
+ catch {
135
+ // Ignore listener errors
136
+ }
137
+ }
138
+ }
139
+ /**
140
+ * Initiate tunnel connection. Non-blocking — connection happens asynchronously.
141
+ */
142
+ connect() {
143
+ if (this.state === 'connecting' || this.state === 'connected')
144
+ return;
145
+ this.destroyed = false;
146
+ this.clearReconnectTimer();
147
+ this.doConnect();
148
+ }
149
+ /**
150
+ * Gracefully disconnect the tunnel.
151
+ */
152
+ disconnect() {
153
+ this.destroyed = true;
154
+ this.clearReconnectTimer();
155
+ this.cleanup();
156
+ this.setState('disconnected');
157
+ }
158
+ /**
159
+ * Reset the circuit breaker (e.g. after config change).
160
+ * Allows reconnection after auth_failed state.
161
+ */
162
+ resetCircuitBreaker() {
163
+ if (this.state === 'auth_failed') {
164
+ this.destroyed = false;
165
+ this.consecutiveFailures = 0;
166
+ this.rateLimitCount = 0;
167
+ this.setState('disconnected');
168
+ }
169
+ }
170
+ /**
171
+ * Send tower metadata to codevos.ai.
172
+ *
173
+ * Uses a dual mechanism:
174
+ * 1. Caches metadata for `GET /__tower/metadata` (served when codevos.ai H2 client polls)
175
+ * 2. When connected, proactively POSTs to `serverUrl/api/tower/metadata` via HTTPS
176
+ *
177
+ * Call before `connect()` to set initial metadata, or after to update it.
178
+ */
179
+ sendMetadata(metadata) {
180
+ this._pendingMetadata = metadata;
181
+ // Proactively push via HTTPS when connected
182
+ if (this.state === 'connected') {
183
+ this.pushMetadataViaHttp(metadata);
184
+ }
185
+ }
186
+ /** Stored metadata for serving via GET /__tower/metadata */
187
+ _pendingMetadata = null;
188
+ /**
189
+ * Push metadata to codevos.ai via outbound HTTPS POST.
190
+ * Best-effort — failures are silently ignored since codevos.ai
191
+ * can also poll via the H2 tunnel's GET /__tower/metadata handler.
192
+ */
193
+ pushMetadataViaHttp(metadata) {
194
+ try {
195
+ const url = new URL('/api/tower/metadata', this.options.serverUrl);
196
+ const body = JSON.stringify(metadata);
197
+ const isSecure = url.protocol === 'https:';
198
+ const transport = isSecure ? https : http;
199
+ const req = transport.request(url, {
200
+ method: 'POST',
201
+ headers: {
202
+ 'Content-Type': 'application/json',
203
+ 'Authorization': `Bearer ${this.options.apiKey}`,
204
+ 'Content-Length': Buffer.byteLength(body),
205
+ },
206
+ }, (res) => {
207
+ res.resume(); // Drain response
208
+ });
209
+ req.on('error', () => {
210
+ // Best-effort — silently ignore network errors
211
+ });
212
+ req.end(body);
213
+ }
214
+ catch {
215
+ // Ignore URL construction or other errors
216
+ }
217
+ }
218
+ clearReconnectTimer() {
219
+ if (this.reconnectTimer) {
220
+ clearTimeout(this.reconnectTimer);
221
+ this.reconnectTimer = null;
222
+ }
223
+ }
224
+ scheduleReconnect() {
225
+ if (this.destroyed || this.state === 'auth_failed')
226
+ return;
227
+ const delay = calculateBackoff(this.consecutiveFailures);
228
+ this.reconnectTimer = setTimeout(() => {
229
+ this.reconnectTimer = null;
230
+ if (!this.destroyed && this.state !== 'auth_failed') {
231
+ this.doConnect();
232
+ }
233
+ }, delay);
234
+ }
235
+ cleanup() {
236
+ if (this.h2Session && !this.h2Session.destroyed) {
237
+ this.h2Session.destroy();
238
+ }
239
+ this.h2Session = null;
240
+ if (this.h2Server) {
241
+ this.h2Server.close();
242
+ }
243
+ this.h2Server = null;
244
+ if (this.wsStream) {
245
+ this.wsStream.destroy();
246
+ }
247
+ this.wsStream = null;
248
+ if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {
249
+ this.ws.close();
250
+ }
251
+ this.ws = null;
252
+ }
253
+ doConnect() {
254
+ this.setState('connecting');
255
+ const wsUrl = buildTunnelWsUrl(this.options.serverUrl);
256
+ const ws = new WebSocket(wsUrl);
257
+ this.ws = ws;
258
+ ws.on('open', () => {
259
+ this.onWsOpen(ws);
260
+ });
261
+ ws.on('error', (err) => {
262
+ // Ignore events from stale WebSockets (e.g. after disconnect + reconnect)
263
+ if (ws !== this.ws)
264
+ return;
265
+ this.handleConnectionError(err);
266
+ });
267
+ ws.on('close', () => {
268
+ // Ignore events from stale WebSockets (e.g. after disconnect + reconnect)
269
+ if (ws !== this.ws)
270
+ return;
271
+ if (this.state === 'connected' || this.state === 'connecting') {
272
+ this.cleanup();
273
+ this.setState('disconnected');
274
+ this.consecutiveFailures++;
275
+ this.scheduleReconnect();
276
+ }
277
+ });
278
+ }
279
+ onWsOpen(ws) {
280
+ // Send JSON auth message (TICK-001 protocol)
281
+ ws.send(JSON.stringify({ type: 'auth', apiKey: this.options.apiKey }));
282
+ // Wait for auth response
283
+ const onMessage = (data) => {
284
+ ws.removeListener('message', onMessage);
285
+ try {
286
+ const msg = JSON.parse(data.toString());
287
+ if (msg.type === 'auth_ok') {
288
+ this.options.towerId = msg.towerId;
289
+ this.startH2Server(ws);
290
+ }
291
+ else if (msg.type === 'auth_error') {
292
+ this.handleAuthError(msg.reason || 'unknown');
293
+ }
294
+ else {
295
+ this.handleConnectionError(new Error(`Unexpected auth response type: ${msg.type}`));
296
+ }
297
+ }
298
+ catch (err) {
299
+ this.handleConnectionError(new Error(`Invalid auth response: ${data.toString()}`));
300
+ }
301
+ };
302
+ ws.on('message', onMessage);
303
+ }
304
+ handleAuthError(reason) {
305
+ this.cleanup();
306
+ if (reason === 'invalid_api_key') {
307
+ this.setState('auth_failed');
308
+ console.error("Cloud connection failed: API key is invalid or revoked. Run 'af tower register --reauth' to update credentials.");
309
+ // Circuit breaker: don't retry
310
+ return;
311
+ }
312
+ // Transient errors: rate_limited, internal_error, etc.
313
+ this.setState('disconnected');
314
+ if (reason === 'rate_limited') {
315
+ this.rateLimitCount++;
316
+ // First rate limit: 60s. Subsequent: 5 minutes (per spec).
317
+ const delay = this.rateLimitCount <= 1 ? 60_000 : 300_000;
318
+ this.reconnectTimer = setTimeout(() => {
319
+ this.reconnectTimer = null;
320
+ if (!this.destroyed)
321
+ this.doConnect();
322
+ }, delay);
323
+ }
324
+ else {
325
+ this.scheduleReconnect();
326
+ }
327
+ this.consecutiveFailures++;
328
+ }
329
+ handleConnectionError(_err) {
330
+ this.cleanup();
331
+ if (this.state === 'auth_failed')
332
+ return; // Don't override circuit breaker
333
+ this.setState('disconnected');
334
+ this.scheduleReconnect();
335
+ this.consecutiveFailures++;
336
+ }
337
+ startH2Server(ws) {
338
+ // Convert WebSocket to a Node.js duplex stream
339
+ const wsStream = createWebSocketStream(ws);
340
+ this.wsStream = wsStream;
341
+ // Create an HTTP/2 server (plaintext — TLS is handled by the WebSocket layer)
342
+ // Enable extended CONNECT for WebSocket proxying (RFC 8441)
343
+ const h2Server = http2.createServer({
344
+ settings: { enableConnectProtocol: true },
345
+ });
346
+ this.h2Server = h2Server;
347
+ h2Server.on('session', (session) => {
348
+ this.h2Session = session;
349
+ this.setState('connected');
350
+ });
351
+ h2Server.on('stream', (stream, headers) => {
352
+ this.handleH2Stream(stream, headers);
353
+ });
354
+ h2Server.on('error', () => {
355
+ // H2 server error — will be handled by ws close
356
+ });
357
+ // Emit the duplex stream as a connection to the H2 server
358
+ // This is the "role reversal" — the H2 server runs over an outbound WebSocket
359
+ h2Server.emit('connection', wsStream);
360
+ }
361
+ handleH2Stream(stream, headers) {
362
+ const method = headers[':method'];
363
+ const path = headers[':path'];
364
+ const protocol = headers[':protocol'];
365
+ // Check blocklist
366
+ if (path && isBlockedPath(path)) {
367
+ stream.respond({
368
+ ':status': 403,
369
+ 'content-type': 'application/json',
370
+ });
371
+ stream.end(JSON.stringify({ error: 'Forbidden: tunnel management endpoints are local-only' }));
372
+ return;
373
+ }
374
+ // Handle metadata requests from the server
375
+ if (method === 'GET' && path === '/__tower/metadata') {
376
+ stream.respond({
377
+ ':status': 200,
378
+ 'content-type': 'application/json',
379
+ });
380
+ stream.end(JSON.stringify(this._pendingMetadata ?? { projects: [], terminals: [] }));
381
+ return;
382
+ }
383
+ // Handle WebSocket CONNECT (RFC 8441)
384
+ if (method === 'CONNECT' && protocol === 'websocket') {
385
+ this.handleWebSocketConnect(stream, headers);
386
+ return;
387
+ }
388
+ // Regular HTTP proxy
389
+ this.proxyHttpRequest(stream, headers, method, path);
390
+ }
391
+ handleWebSocketConnect(stream, headers) {
392
+ const authority = headers[':authority'] || `localhost:${this.options.localPort}`;
393
+ const path = headers[':path'] || '/';
394
+ // Forward non-hop-by-hop headers from the H2 CONNECT to the local WS upgrade
395
+ const forwardHeaders = {
396
+ 'Upgrade': 'websocket',
397
+ 'Connection': 'Upgrade',
398
+ 'Sec-WebSocket-Version': '13',
399
+ 'Sec-WebSocket-Key': Buffer.from(Math.random().toString()).toString('base64'),
400
+ 'Host': authority,
401
+ };
402
+ for (const [key, value] of Object.entries(headers)) {
403
+ if (key.startsWith(':'))
404
+ continue;
405
+ if (HOP_BY_HOP_HEADERS.has(key.toLowerCase()))
406
+ continue;
407
+ if (key.toLowerCase() === 'host')
408
+ continue; // Already set
409
+ if (value !== undefined) {
410
+ forwardHeaders[key] = value;
411
+ }
412
+ }
413
+ // Make HTTP/1.1 WebSocket upgrade request to localhost
414
+ const wsReq = http.request({
415
+ hostname: 'localhost',
416
+ port: this.options.localPort,
417
+ path,
418
+ method: 'GET',
419
+ headers: forwardHeaders,
420
+ });
421
+ wsReq.on('upgrade', (_res, socket, head) => {
422
+ // Respond 200 to the H2 CONNECT
423
+ stream.respond({ ':status': 200 });
424
+ // If there's buffered data from upgrade, push it
425
+ if (head.length > 0) {
426
+ stream.write(head);
427
+ }
428
+ // Bidirectional pipe
429
+ socket.pipe(stream);
430
+ stream.pipe(socket);
431
+ socket.on('error', () => stream.destroy());
432
+ stream.on('error', () => socket.destroy());
433
+ socket.on('close', () => { if (!stream.destroyed)
434
+ stream.destroy(); });
435
+ stream.on('close', () => { if (!socket.destroyed)
436
+ socket.destroy(); });
437
+ });
438
+ // Handle non-upgrade responses (e.g. 404 for missing terminal)
439
+ wsReq.on('response', (res) => {
440
+ if (!stream.destroyed) {
441
+ stream.respond({ ':status': res.statusCode || 502 });
442
+ res.pipe(stream);
443
+ }
444
+ });
445
+ wsReq.on('error', () => {
446
+ if (!stream.destroyed) {
447
+ stream.respond({ ':status': 502 });
448
+ stream.end();
449
+ }
450
+ });
451
+ wsReq.end();
452
+ }
453
+ proxyHttpRequest(stream, h2Headers, method, path) {
454
+ // Build HTTP/1.1 request headers, filtering H2 pseudo-headers and hop-by-hop
455
+ const reqHeaders = {};
456
+ for (const [key, value] of Object.entries(h2Headers)) {
457
+ if (key.startsWith(':'))
458
+ continue; // Skip H2 pseudo-headers
459
+ if (HOP_BY_HOP_HEADERS.has(key.toLowerCase()))
460
+ continue;
461
+ if (value !== undefined) {
462
+ reqHeaders[key] = value;
463
+ }
464
+ }
465
+ const proxyReq = http.request({
466
+ hostname: 'localhost',
467
+ port: this.options.localPort,
468
+ path,
469
+ method,
470
+ headers: reqHeaders,
471
+ }, (proxyRes) => {
472
+ // Filter hop-by-hop headers from response
473
+ const responseHeaders = {
474
+ ':status': proxyRes.statusCode ?? 500,
475
+ };
476
+ for (const [key, value] of Object.entries(proxyRes.headers)) {
477
+ if (!HOP_BY_HOP_HEADERS.has(key.toLowerCase()) && value !== undefined) {
478
+ responseHeaders[key] = value;
479
+ }
480
+ }
481
+ stream.respond(responseHeaders);
482
+ proxyRes.pipe(stream);
483
+ proxyRes.on('error', () => {
484
+ if (!stream.destroyed)
485
+ stream.destroy();
486
+ });
487
+ });
488
+ proxyReq.on('error', () => {
489
+ if (!stream.destroyed) {
490
+ stream.respond({ ':status': 502 });
491
+ stream.end(JSON.stringify({ error: 'Bad Gateway: local server unavailable' }));
492
+ }
493
+ });
494
+ // Pipe request body
495
+ stream.pipe(proxyReq);
496
+ stream.on('error', () => {
497
+ if (!proxyReq.destroyed)
498
+ proxyReq.destroy();
499
+ });
500
+ }
501
+ }
502
+ //# sourceMappingURL=tunnel-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-client.js","sourceRoot":"","sources":["../../../src/agent-farm/lib/tunnel-client.ts"],"names":[],"mappings":"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"}