@agentproto/acp 0.1.0-alpha.1 → 0.1.0

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.
@@ -81,6 +81,10 @@ interface SpawnFrame {
81
81
  * line-delimited JSON-RPC.
82
82
  */
83
83
  pty?: boolean;
84
+ /** Initial PTY column width. Ignored when `pty` is false. Default 80. */
85
+ cols?: number;
86
+ /** Initial PTY row height. Ignored when `pty` is false. Default 24. */
87
+ rows?: number;
84
88
  }
85
89
  interface StdinFrame {
86
90
  t: "stdin";
@@ -100,6 +104,103 @@ interface ResizeFrame {
100
104
  cols: number;
101
105
  rows: number;
102
106
  }
107
+ /**
108
+ * Generic HTTP-over-tunnel request (HOST → DAEMON). Lets the host
109
+ * proxy arbitrary HTTP traffic (MCP JSON-RPC today, anything tomorrow)
110
+ * through the daemon's local network stack without exposing a public
111
+ * URL. The daemon forwards to its configured "http upstream" (default:
112
+ * its own gateway on `127.0.0.1:<port>`) and replies with an
113
+ * `HttpResponseFrame` carrying the same `reqId`.
114
+ */
115
+ interface HttpRequestFrame {
116
+ t: "http_request";
117
+ /** Correlates the response. Host-chosen, MUST be unique per inflight request. */
118
+ reqId: string;
119
+ /** HTTP method (GET / POST / PUT / DELETE / PATCH / OPTIONS). */
120
+ method: string;
121
+ /** Path + querystring, e.g. `/mcp` or `/mcp?session=abc`.
122
+ * Daemon prepends its upstream base. Absolute URLs are rejected. */
123
+ path: string;
124
+ /** Forwarded request headers. Hop-by-hop headers (Connection,
125
+ * Keep-Alive, Transfer-Encoding, Upgrade, Proxy-*) MUST be stripped
126
+ * before forwarding; daemon SHOULD also drop them defensively. */
127
+ headers?: Readonly<Record<string, string>>;
128
+ /** Base64-encoded request body. Omitted when no body. */
129
+ body?: string;
130
+ /** Per-request timeout in ms. Daemon SHOULD enforce + reply with
131
+ * `error: { code: "timeout" }` when exceeded. Default 30_000. */
132
+ timeoutMs?: number;
133
+ }
134
+ /**
135
+ * Generic HTTP-over-tunnel response (DAEMON → HOST). Mirrors
136
+ * `HttpRequestFrame` — see its docs.
137
+ *
138
+ * Two-frame protocol:
139
+ * - SHORT RESPONSES (most HTTP): daemon emits a single `http_response`
140
+ * with body inline. The buffered `forwardHttp` resolves directly
141
+ * from this frame.
142
+ * - STREAMED RESPONSES (text/event-stream, long-lived chunked
143
+ * transfers, large downloads): daemon emits `http_response_head`
144
+ * first with status+headers, then one or more `http_response_chunk`
145
+ * frames, the last of which has `end: true`. The streaming
146
+ * `forwardHttpStream` builds a `ReadableStream` from the chunks.
147
+ *
148
+ * Hosts that only support the legacy buffered API can detect the
149
+ * stream protocol by looking for `http_response_head` and either
150
+ * pull the chunks into a buffer (compat) or refuse to handle.
151
+ */
152
+ interface HttpResponseFrame {
153
+ t: "http_response";
154
+ reqId: string;
155
+ /** HTTP status code (e.g. 200, 404, 500). Set even on transport
156
+ * failure (then `error` is also set and status SHOULD be 502/504). */
157
+ status: number;
158
+ headers?: Readonly<Record<string, string>>;
159
+ /** Base64-encoded response body. */
160
+ body?: string;
161
+ /** Set when the daemon failed to complete the upstream call. */
162
+ error?: Readonly<{
163
+ code: string;
164
+ message: string;
165
+ }>;
166
+ }
167
+ /**
168
+ * Streaming HTTP response head (DAEMON → HOST). Sent ONCE per
169
+ * streaming response, before any chunk frames. Carries status +
170
+ * headers so the host can finalize the response shape (e.g. write
171
+ * Content-Type) before any body bytes arrive.
172
+ */
173
+ interface HttpResponseHeadFrame {
174
+ t: "http_response_head";
175
+ reqId: string;
176
+ status: number;
177
+ headers?: Readonly<Record<string, string>>;
178
+ }
179
+ /**
180
+ * Streaming HTTP response body chunk (DAEMON → HOST). Each chunk
181
+ * carries some bytes of the response body. The terminal chunk has
182
+ * `end: true` and MAY include final bytes. An immediate `end: true`
183
+ * with no data signals empty-body close.
184
+ *
185
+ * `error` set on a chunk frame indicates the daemon's upstream
186
+ * failed mid-stream; host SHOULD propagate it as a stream error.
187
+ */
188
+ interface HttpResponseChunkFrame {
189
+ t: "http_response_chunk";
190
+ reqId: string;
191
+ /** Base64-encoded chunk bytes. Omitted on pure end-of-stream
192
+ * markers (those carry `end: true` only). */
193
+ data?: string;
194
+ /** Set on the last chunk. After this frame the host SHOULD ignore
195
+ * any further frames for this reqId. */
196
+ end?: boolean;
197
+ /** Set when the upstream failed mid-stream. Host surfaces this as
198
+ * a stream error and closes the readable. */
199
+ error?: Readonly<{
200
+ code: string;
201
+ message: string;
202
+ }>;
203
+ }
103
204
  interface HelloFrame {
104
205
  t: "hello";
105
206
  version: typeof TUNNEL_VERSION;
@@ -109,6 +210,10 @@ interface HelloFrame {
109
210
  */
110
211
  capabilities: Readonly<{
111
212
  pty: boolean;
213
+ /** Daemon can bridge browser-WS upgrades to its local upstream via
214
+ * `ws_open` / `ws_message` / `ws_close`. Hosts MUST gate
215
+ * `forwardWebSocket()` on this — older daemons ignore the frames. */
216
+ wsForward?: boolean;
112
217
  }>;
113
218
  /** User-friendly daemon label, surfaced in host UIs. */
114
219
  label?: string;
@@ -163,8 +268,99 @@ interface PongFrame {
163
268
  t: "pong";
164
269
  nonce: string;
165
270
  }
166
- type HostToDaemonFrame = SpawnFrame | StdinFrame | KillFrame | ResizeFrame | PingFrame | PongFrame | ErrorFrame;
167
- type DaemonToHostFrame = HelloFrame | SpawnedFrame | StdoutFrame | StderrFrame | ExitFrame | PingFrame | PongFrame | ErrorFrame;
271
+ /**
272
+ * HOST DAEMON. Graceful drain signal sent during host rollover (e.g.
273
+ * Kubernetes preStop). On receipt the daemon SHOULD:
274
+ * 1. Stop accepting new in-flight work where it can.
275
+ * 2. Close the WS cleanly (does not need to wait — host will follow
276
+ * up with a `close(1012, "service_restart")` ~2 s later as a
277
+ * hard backstop).
278
+ * 3. Reconnect IMMEDIATELY without the usual exponential backoff —
279
+ * the host is mid-deploy, the new replica is already listening.
280
+ *
281
+ * Backward-compatible: daemons that don't know the frame just ignore
282
+ * it (parseFrame returns null for unknown types). The host's close
283
+ * then triggers the daemon's normal backoff loop — worst case ~30 s
284
+ * reconnect gap instead of ~2 s with the handler.
285
+ */
286
+ interface ReconnectSoonFrame {
287
+ t: "reconnect_soon";
288
+ /** Hint of how long the host plans to wait before forcing close.
289
+ * Optional — daemons MAY use it to decide whether to finish
290
+ * in-flight work or close immediately. */
291
+ reasonMs?: number;
292
+ }
293
+ /**
294
+ * HOST → DAEMON. Open a WS connection to the daemon's upstream.
295
+ * Path semantics match `HttpRequestFrame` — absolute URLs rejected,
296
+ * daemon prepends its `ws://<upstream>` base. Headers forwarded as-is
297
+ * (cookies are typically NOT forwarded since the daemon's upstream is
298
+ * loopback; cookie passthrough is opt-in via daemon config).
299
+ */
300
+ interface WsOpenFrame {
301
+ t: "ws_open";
302
+ /** Correlates every WS frame in both directions for this connection. */
303
+ reqId: string;
304
+ /** Path + querystring on the daemon-local upstream, e.g.
305
+ * `/sessions/abc/pty?cols=80&rows=24`. */
306
+ path: string;
307
+ /** Headers to set on the upstream WS request. Hop-by-hop headers
308
+ * (Connection, Upgrade, Sec-WebSocket-*) MUST be stripped — the
309
+ * daemon's `ws` client manages those. */
310
+ headers?: Readonly<Record<string, string>>;
311
+ /** Subprotocols requested by the browser; forwarded to upstream. */
312
+ protocols?: readonly string[];
313
+ }
314
+ /**
315
+ * DAEMON → HOST. Result of a `ws_open`. On success the upstream WS is
316
+ * connected and frames can flow. On failure `error` is set; no further
317
+ * frames for this `reqId` will arrive.
318
+ */
319
+ interface WsOpenAckFrame {
320
+ t: "ws_open_ack";
321
+ reqId: string;
322
+ /** HTTP status from the upstream upgrade. 101 on success; 4xx/5xx
323
+ * when the upstream refused the upgrade. */
324
+ status: number;
325
+ /** Selected subprotocol, if any. */
326
+ protocol?: string;
327
+ /** Set when the daemon couldn't open the upstream (DNS failure,
328
+ * refused, timeout). Distinct from a clean upstream-side close,
329
+ * which arrives as `ws_close`. */
330
+ error?: Readonly<{
331
+ code: string;
332
+ message: string;
333
+ }>;
334
+ }
335
+ /**
336
+ * Either direction. One application-level WS frame's payload. Text
337
+ * frames carry UTF-8 bytes (`binary: false`); binary frames carry
338
+ * arbitrary bytes (`binary: true`). The `data` field is base64-encoded
339
+ * either way so the transport stays JSON.
340
+ */
341
+ interface WsMessageFrame {
342
+ t: "ws_message";
343
+ reqId: string;
344
+ /** Base64-encoded WS frame payload. */
345
+ data: string;
346
+ /** True for binary frames; false (or omitted) for text. */
347
+ binary?: boolean;
348
+ }
349
+ /**
350
+ * Either direction. Close the bridged WS connection. Includes the
351
+ * close code (1000 normal, 1006 abnormal, etc.) and optional reason.
352
+ * After sending or receiving this frame, neither side will send
353
+ * further frames for `reqId`.
354
+ */
355
+ interface WsCloseFrame {
356
+ t: "ws_close";
357
+ reqId: string;
358
+ /** WebSocket close code. */
359
+ code: number;
360
+ reason?: string;
361
+ }
362
+ type HostToDaemonFrame = SpawnFrame | StdinFrame | KillFrame | ResizeFrame | HttpRequestFrame | WsOpenFrame | WsMessageFrame | WsCloseFrame | PingFrame | PongFrame | ErrorFrame | ReconnectSoonFrame;
363
+ type DaemonToHostFrame = HelloFrame | SpawnedFrame | StdoutFrame | StderrFrame | ExitFrame | HttpResponseFrame | HttpResponseHeadFrame | HttpResponseChunkFrame | WsOpenAckFrame | WsMessageFrame | WsCloseFrame | PingFrame | PongFrame | ErrorFrame;
168
364
  type TunnelFrame = HostToDaemonFrame | DaemonToHostFrame;
169
365
  /**
170
366
  * Parse a raw WS message into a `TunnelFrame`. Returns null when the
@@ -237,14 +433,113 @@ interface TunnelServerOptions {
237
433
  * everything (useful for tests; never for production).
238
434
  */
239
435
  authorize: (req: SpawnFrame) => SpawnFrame | null | Promise<SpawnFrame | null>;
436
+ /**
437
+ * Upstream HTTP base URL for `http_request` frames. The daemon
438
+ * appends the frame's `path` and forwards. Typically the local
439
+ * gateway address — `http://127.0.0.1:18790`. When omitted, the
440
+ * daemon replies to any `http_request` with
441
+ * `error: { code: "http_upstream_not_configured" }`.
442
+ */
443
+ httpUpstream?: string;
240
444
  /** User-friendly label sent in the hello frame. */
241
445
  label?: string;
242
446
  /**
243
- * Whether this daemon advertises PTY support. v0 always reports
244
- * false PTY allocation needs node-pty (optional dep) and we
245
- * haven't wired that side yet.
447
+ * Whether this daemon advertises PTY support. Set to true only when
448
+ * `spawnPty` is also provided.
246
449
  */
247
450
  pty?: boolean;
451
+ /**
452
+ * Factory for PTY-backed processes. When provided (and `pty: true`),
453
+ * spawn frames with `pty: true` use this instead of node:child_process.
454
+ * Injected from the CLI layer so the ACP package stays native-free.
455
+ */
456
+ spawnPty?: (opts: {
457
+ command: string;
458
+ args: string[];
459
+ cwd?: string;
460
+ env?: Record<string, string>;
461
+ cols: number;
462
+ rows: number;
463
+ }) => PtyProcess;
464
+ /**
465
+ * Optional hook fired once per successful spawn — after authorize
466
+ * passed and the ChildProcess has emitted its `spawn` event.
467
+ * Lets the daemon adopt this child into a higher-level registry
468
+ * (e.g. @agentproto/runtime's sessions registry, AIP-46) so the
469
+ * spawn shows up in /sessions, the LocalDaemonSessionsCard, and
470
+ * the CLI TUI alongside spawns originated locally.
471
+ *
472
+ * The hook is fire-and-forget — the tunnel doesn't await its
473
+ * return. Errors from the hook are swallowed so an observer
474
+ * registry hiccup never breaks the tunnel exchange.
475
+ */
476
+ onChildSpawned?: (info: {
477
+ execId: string;
478
+ child: ChildProcess;
479
+ request: SpawnFrame;
480
+ }) => void;
481
+ /**
482
+ * Optional hook fired when the host sends a `reconnect_soon` frame —
483
+ * graceful drain signal during host rollover. The daemon SHOULD
484
+ * close + reconnect immediately (skipping any backoff) so the new
485
+ * host replica picks it up. Default: ignore (the host follows up
486
+ * with `close(1012)` and the daemon's own reconnect supervisor
487
+ * handles it via normal backoff, ~30 s gap).
488
+ *
489
+ * Implementations typically call into their connection supervisor
490
+ * to mark the next reconnect as "no-backoff" then close the sink.
491
+ * `reasonMs` is the host's hint for how long it will wait before
492
+ * forcing close — daemons MAY use it to drain in-flight RPCs first.
493
+ */
494
+ onReconnectSoon?: (info: {
495
+ reasonMs?: number;
496
+ }) => void;
497
+ /**
498
+ * Factory that dials a WS connection to the local upstream. When
499
+ * provided (and `httpUpstream` is set), the daemon advertises
500
+ * `wsForward` capability and handles `ws_open` frames by piping the
501
+ * upstream WS through the tunnel. Injected so `@agentproto/acp`
502
+ * stays free of a hard `ws` dependency — the CLI provides this
503
+ * factory using its already-pulled-in `ws` package.
504
+ */
505
+ dialUpstreamWs?: (params: {
506
+ url: string;
507
+ protocols?: readonly string[];
508
+ headers?: Readonly<Record<string, string>>;
509
+ }) => Promise<UpstreamWebSocket>;
510
+ }
511
+ /**
512
+ * Minimal upstream WS surface — satisfied by the `ws` library's
513
+ * client socket. Daemons supplying `dialUpstreamWs` resolve into
514
+ * one of these as soon as the WS is OPEN. `protocol` is the
515
+ * subprotocol negotiated by the upstream (empty string when none).
516
+ */
517
+ interface UpstreamWebSocket {
518
+ readonly protocol: string;
519
+ /** Send a frame to the upstream. */
520
+ send(data: Buffer | string, opts: {
521
+ binary: boolean;
522
+ }): void;
523
+ /** Close the upstream connection. */
524
+ close(code?: number, reason?: string): void;
525
+ /** Subscribe to inbound frames. */
526
+ onMessage(handler: (data: Buffer, isBinary: boolean) => void): void;
527
+ /** Subscribe to upstream close. */
528
+ onClose(handler: (code: number, reason: string) => void): void;
529
+ /** Subscribe to transport errors. */
530
+ onError(handler: (err: Error) => void): void;
531
+ }
532
+ /** Minimal PTY process surface — satisfied by node-pty's IPty. */
533
+ interface PtyProcess {
534
+ readonly pid: number;
535
+ write(data: string): void;
536
+ resize(cols: number, rows: number): void;
537
+ kill(signal?: string): void;
538
+ onData(handler: (data: string) => void): void;
539
+ onExit(handler: (event: {
540
+ exitCode: number;
541
+ signal?: number;
542
+ }) => void): void;
248
543
  }
249
544
  interface TunnelServer {
250
545
  /** Currently-live execId → ChildProcess. Read-only diagnostic. */
@@ -269,6 +564,74 @@ declare function createTunnelServer(opts: TunnelServerOptions): TunnelServer;
269
564
  * this with a node:stream.Readable shim.
270
565
  */
271
566
 
567
+ /** Resolved response from `forwardHttp`. Mirrors `HttpResponseFrame`
568
+ * but with the body decoded back to a Buffer for the caller. */
569
+ interface TunnelHttpResponse {
570
+ status: number;
571
+ headers: Readonly<Record<string, string>>;
572
+ body: Buffer;
573
+ /** Set when the daemon failed to complete the upstream call. */
574
+ error?: Readonly<{
575
+ code: string;
576
+ message: string;
577
+ }>;
578
+ }
579
+ /** Resolved response from `forwardHttpStream`. Body is a Web
580
+ * `ReadableStream<Uint8Array>` — consume it to receive chunks as
581
+ * they arrive from the daemon's upstream (SSE, long-poll, NDJSON).
582
+ * The stream closes when the daemon's upstream closes OR an upstream
583
+ * error occurs (surfaced as a stream error on the reader). */
584
+ interface TunnelHttpStreamResponse {
585
+ status: number;
586
+ headers: Readonly<Record<string, string>>;
587
+ body: ReadableStream<Uint8Array>;
588
+ }
589
+ interface TunnelHttpRequest {
590
+ method: string;
591
+ path: string;
592
+ headers?: Readonly<Record<string, string>>;
593
+ body?: Buffer | Uint8Array | string;
594
+ /** Per-request timeout in ms. Default 30_000. */
595
+ timeoutMs?: number;
596
+ }
597
+ interface TunnelWebSocketOpenRequest {
598
+ /** Path + querystring on the daemon-local upstream. Daemon prepends
599
+ * its `ws://<upstream>` base; absolute URLs are rejected. */
600
+ path: string;
601
+ /** Headers forwarded to the upstream upgrade. Hop-by-hop / Sec-* are
602
+ * stripped by the daemon. Cookies are NOT forwarded unless the
603
+ * daemon was started with `--upstream-cookies`. */
604
+ headers?: Readonly<Record<string, string>>;
605
+ /** Subprotocols requested. Echoed in `protocol` on success. */
606
+ protocols?: readonly string[];
607
+ /** How long to wait for the upstream upgrade before erroring. The
608
+ * message stream itself has no timeout (WS lives as long as either
609
+ * end keeps it open). Default 30_000. */
610
+ openTimeoutMs?: number;
611
+ }
612
+ /**
613
+ * Bridged WS connection. Mirrors the surface of a browser WebSocket
614
+ * minus URL/protocol bookkeeping — the host already chose those when
615
+ * calling `forwardWebSocket`. Messages are typed as text (UTF-8 string)
616
+ * or binary (Uint8Array); the bridge preserves the upstream's framing.
617
+ */
618
+ interface TunnelWebSocket {
619
+ /** True until `close` runs in either direction. */
620
+ readonly readyState: "open" | "closing" | "closed";
621
+ /** Selected subprotocol from the upstream's upgrade response, if any. */
622
+ readonly protocol: string | null;
623
+ /** Send a frame to the daemon's upstream. No-op when not open. */
624
+ send(data: string | Uint8Array): void;
625
+ /** Initiate a clean close. Idempotent. */
626
+ close(code?: number, reason?: string): void;
627
+ /** Subscribe to inbound frames. Returns an unsubscribe fn. */
628
+ onMessage(listener: (data: Buffer, isBinary: boolean) => void): () => void;
629
+ /** Subscribe to close. Fires exactly once (after either side closes
630
+ * OR the tunnel itself drops). Returns an unsubscribe fn. */
631
+ onClose(listener: (code: number, reason: string) => void): () => void;
632
+ /** Subscribe to transport-level errors. Closes follow shortly. */
633
+ onError(listener: (err: Error) => void): () => void;
634
+ }
272
635
  interface TunnelClientOptions {
273
636
  sink: FrameSink;
274
637
  /**
@@ -283,6 +646,10 @@ interface TunnelSpawnOptions {
283
646
  env?: Readonly<Record<string, string>>;
284
647
  /** Allocate a PTY on the daemon. Requires `hello.capabilities.pty`. */
285
648
  pty?: boolean;
649
+ /** Initial PTY column width (ignored when `pty` is false). Default 80. */
650
+ cols?: number;
651
+ /** Initial PTY row height (ignored when `pty` is false). Default 24. */
652
+ rows?: number;
286
653
  }
287
654
  /**
288
655
  * Minimal ChildProcess-shaped duck. Covers the surface our ACP arm
@@ -298,6 +665,8 @@ interface TunnelChildProcess {
298
665
  on(event: "exit", listener: (code: number | null, signal: string | null) => void): this;
299
666
  on(event: "error", listener: (err: Error) => void): this;
300
667
  kill(signal?: NodeJS.Signals | number): boolean;
668
+ /** Send a terminal resize to the daemon. No-op if the exec isn't PTY-backed. */
669
+ resize(cols: number, rows: number): void;
301
670
  }
302
671
  interface TunnelClient {
303
672
  /**
@@ -307,6 +676,38 @@ interface TunnelClient {
307
676
  */
308
677
  ready(): Promise<HelloFrame>;
309
678
  spawn(command: string, args: readonly string[], opts?: TunnelSpawnOptions): Promise<TunnelChildProcess>;
679
+ /**
680
+ * Forward an HTTP request through the tunnel to the daemon's
681
+ * configured upstream (typically `http://127.0.0.1:<port>`). The
682
+ * daemon completes the upstream call and replies with the response,
683
+ * which this promise resolves to. Rejects on tunnel-transport
684
+ * failure; the daemon-reported HTTP status (incl. 5xx) is returned
685
+ * in the resolved value.
686
+ *
687
+ * Streaming responses (text/event-stream, NDJSON) are buffered into
688
+ * the returned Buffer. For real streaming, use `forwardHttpStream`.
689
+ */
690
+ forwardHttp(req: TunnelHttpRequest): Promise<TunnelHttpResponse>;
691
+ /**
692
+ * Stream an HTTP response through the tunnel. The promise resolves
693
+ * as soon as the response head (status + headers) arrives — the
694
+ * body chunks then flow through `body` (a ReadableStream) until the
695
+ * daemon's upstream closes. Required for SSE / NDJSON / long-poll
696
+ * upstreams where buffering until the end would defeat the point.
697
+ * For one-shot HTTP, prefer `forwardHttp`.
698
+ */
699
+ forwardHttpStream(req: TunnelHttpRequest): Promise<TunnelHttpStreamResponse>;
700
+ /**
701
+ * Open a bridged WebSocket through the tunnel. The promise resolves
702
+ * once the daemon has completed the upstream upgrade; from that
703
+ * point messages flow via the returned `TunnelWebSocket`.
704
+ *
705
+ * Rejects on:
706
+ * - missing `hello.capabilities.wsForward` — older daemon, no bridge
707
+ * - upstream upgrade failure (4xx/5xx) — `cause` carries the status
708
+ * - timeout waiting for `ws_open_ack`
709
+ */
710
+ forwardWebSocket(req: TunnelWebSocketOpenRequest): Promise<TunnelWebSocket>;
310
711
  close(): Promise<void>;
311
712
  }
312
713
  declare function createTunnelClient(opts: TunnelClientOptions): TunnelClient;
@@ -339,4 +740,4 @@ interface WebSocketLike {
339
740
  }
340
741
  declare function wrapWebSocket(ws: WebSocketLike): FrameSink;
341
742
 
342
- export { type DaemonToHostFrame, type ErrorFrame, type ExitFrame, type FrameSink, type HelloFrame, type HostToDaemonFrame, type KillFrame, type PingFrame, type PongFrame, type ResizeFrame, type SpawnFrame, type SpawnedFrame, type StderrFrame, type StdinFrame, type StdoutFrame, TUNNEL_VERSION, type TunnelChildProcess, type TunnelClient, type TunnelClientOptions, type TunnelFrame, type TunnelServer, type TunnelServerOptions, type TunnelSpawnOptions, type WebSocketLike, createTunnelClient, createTunnelServer, decodeData, encodeData, encodeFrame, parseFrame, wrapWebSocket };
743
+ export { type DaemonToHostFrame, type ErrorFrame, type ExitFrame, type FrameSink, type HelloFrame, type HostToDaemonFrame, type KillFrame, type PingFrame, type PongFrame, type PtyProcess, type ReconnectSoonFrame, type ResizeFrame, type SpawnFrame, type SpawnedFrame, type StderrFrame, type StdinFrame, type StdoutFrame, TUNNEL_VERSION, type TunnelChildProcess, type TunnelClient, type TunnelClientOptions, type TunnelFrame, type TunnelHttpRequest, type TunnelHttpResponse, type TunnelHttpStreamResponse, type TunnelServer, type TunnelServerOptions, type TunnelSpawnOptions, type TunnelWebSocket, type TunnelWebSocketOpenRequest, type UpstreamWebSocket, type WebSocketLike, type WsCloseFrame, type WsMessageFrame, type WsOpenAckFrame, type WsOpenFrame, createTunnelClient, createTunnelServer, decodeData, encodeData, encodeFrame, parseFrame, wrapWebSocket };