@actana/sdk 0.2.2

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 (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -0
  3. package/dist/core-client.d.ts +616 -0
  4. package/dist/core-client.d.ts.map +1 -0
  5. package/dist/core-client.js +1036 -0
  6. package/dist/core-client.js.map +1 -0
  7. package/dist/core-link-cursor-storage.d.ts +32 -0
  8. package/dist/core-link-cursor-storage.d.ts.map +1 -0
  9. package/dist/core-link-cursor-storage.js +66 -0
  10. package/dist/core-link-cursor-storage.js.map +1 -0
  11. package/dist/core-link-frames.d.ts +1123 -0
  12. package/dist/core-link-frames.d.ts.map +1 -0
  13. package/dist/core-link-frames.js +349 -0
  14. package/dist/core-link-frames.js.map +1 -0
  15. package/dist/core-link-socket.d.ts +54 -0
  16. package/dist/core-link-socket.d.ts.map +1 -0
  17. package/dist/core-link-socket.js +74 -0
  18. package/dist/core-link-socket.js.map +1 -0
  19. package/dist/core-link-transport.d.ts +177 -0
  20. package/dist/core-link-transport.d.ts.map +1 -0
  21. package/dist/core-link-transport.js +432 -0
  22. package/dist/core-link-transport.js.map +1 -0
  23. package/dist/core-registration-blob.d.ts +52 -0
  24. package/dist/core-registration-blob.d.ts.map +1 -0
  25. package/dist/core-registration-blob.js +61 -0
  26. package/dist/core-registration-blob.js.map +1 -0
  27. package/dist/core-session.d.ts +321 -0
  28. package/dist/core-session.d.ts.map +1 -0
  29. package/dist/core-session.js +660 -0
  30. package/dist/core-session.js.map +1 -0
  31. package/dist/durable-core-client.d.ts +172 -0
  32. package/dist/durable-core-client.d.ts.map +1 -0
  33. package/dist/durable-core-client.js +264 -0
  34. package/dist/durable-core-client.js.map +1 -0
  35. package/dist/terminal-screen.d.ts +139 -0
  36. package/dist/terminal-screen.d.ts.map +1 -0
  37. package/dist/terminal-screen.js +807 -0
  38. package/dist/terminal-screen.js.map +1 -0
  39. package/package.json +51 -0
@@ -0,0 +1,177 @@
1
+ import type { CoreLinkEvent, CoreLinkRequestFrame, CoreLinkResponseFrame, CoreLinkStreamFrame } from "./core-link-frames.ts";
2
+ import type { CoreLinkSocketFactory } from "./core-link-socket.ts";
3
+ /** The Core's opening frame on every connection — protocol version, capability. */
4
+ export type CoreLinkReadyFrame = Extract<CoreLinkResponseFrame, {
5
+ type: "ready";
6
+ }>;
7
+ /** One PTY's bytes. Unsolicited; keyed by `ptyId`; carries a `seq`. */
8
+ export type CoreLinkDataFrame = Extract<CoreLinkStreamFrame, {
9
+ type: "data";
10
+ }>;
11
+ /** A PTY's exit. Unsolicited; keyed by `ptyId`. */
12
+ export type CoreLinkExitFrame = Extract<CoreLinkStreamFrame, {
13
+ type: "exit";
14
+ }>;
15
+ /** The Core accepted this connection's bearer. */
16
+ export type CoreLinkAuthOkFrame = Extract<CoreLinkResponseFrame, {
17
+ type: "authOk";
18
+ }>;
19
+ /** The Core refused this connection's bearer, and is about to close the socket. */
20
+ export type CoreLinkAuthErrorFrame = Extract<CoreLinkResponseFrame, {
21
+ type: "authError";
22
+ }>;
23
+ /** Why the Core refused a bearer. */
24
+ export type CoreLinkAuthErrorReason = CoreLinkAuthErrorFrame["reason"];
25
+ /**
26
+ * What a transport tells its owner. Every one is optional and none may throw
27
+ * anything the transport is expected to survive — a listener's failure must not
28
+ * take a connection down, so each is called inside a guard.
29
+ */
30
+ export type CoreLinkTransportHandlers = {
31
+ /** The socket is open. Nothing has been authenticated yet. */
32
+ onOpen?: () => void;
33
+ /**
34
+ * The transport may now be written to: the socket is open and, when a bearer
35
+ * was configured, the Core has accepted it. This is where an owner sends the
36
+ * frames a fresh connection owes — `reclaim`, `subscribe`, a re-subscription
37
+ * — and they go out ahead of whatever the owner had queued.
38
+ */
39
+ onWritable?: () => void;
40
+ /** Frame one, on every connection (see this module's header). */
41
+ onReady?: (frame: CoreLinkReadyFrame) => void;
42
+ /** One PTY's bytes, parsed once, here. */
43
+ onData?: (frame: CoreLinkDataFrame) => void;
44
+ /** One PTY's exit, parsed once, here. */
45
+ onExit?: (frame: CoreLinkExitFrame) => void;
46
+ /** One event off the Core's monotonic log — replayed or live, same frame. */
47
+ onEvent?: (event: CoreLinkEvent) => void;
48
+ /** End of the `subscribe` replay tail; live push resumes after it. */
49
+ onEventsReplayed?: (lastEventId: number) => void;
50
+ onAuthOk?: (frame: CoreLinkAuthOkFrame) => void;
51
+ onAuthError?: (reason: CoreLinkAuthErrorReason) => void;
52
+ /**
53
+ * The socket is gone, with the reason the `error` event carried if it carried
54
+ * one. In-flight requests have already been rejected by the time this runs.
55
+ */
56
+ onClose?: (reason?: string) => void;
57
+ };
58
+ export type CoreLinkHeartbeatOptions = {
59
+ /** Ping cadence. Default {@link DEFAULT_HEARTBEAT_INTERVAL_MS}. */
60
+ intervalMs?: number;
61
+ /** Declare the peer dead after this long with no frame. Default {@link DEFAULT_HEARTBEAT_TIMEOUT_MS}. */
62
+ timeoutMs?: number;
63
+ };
64
+ export type CoreLinkTransportOptions = {
65
+ /** The URL to dial. Reported back on errors; the factory is what opens it. */
66
+ url: string;
67
+ /** How to open the socket. See {@link CoreLinkSocketFactory}. */
68
+ createSocket: CoreLinkSocketFactory;
69
+ /**
70
+ * The signed bearer `{coreId, exp, sig}` from the registration blob (ADR
71
+ * 0002), presented in the `auth` frame the instant the socket opens. Every
72
+ * real Core requires one — there is no trusted transport left to omit it on
73
+ * (ADR 0010). Omitted, the transport is writable as soon as the socket opens,
74
+ * which is the loopback rig and the test.
75
+ */
76
+ bearer?: string | null;
77
+ /**
78
+ * Arm the heartbeat on this connection. Off by default, and deliberately so:
79
+ * a one-shot client that connects, asks and exits has nothing to keep alive,
80
+ * and the durable entry point turns it on because a link that must survive an
81
+ * idle hour is the case it exists for (#129 D6).
82
+ *
83
+ * Only a socket that can actually send a ping participates — see
84
+ * {@link CoreLinkSocket.ping}.
85
+ */
86
+ heartbeat?: CoreLinkHeartbeatOptions | false;
87
+ handlers?: CoreLinkTransportHandlers;
88
+ };
89
+ /**
90
+ * Heartbeat cadence. A remote Core's core link runs over the open internet, so
91
+ * it crosses NATs and stateful firewalls that silently drop idle flows — an
92
+ * agent sitting at its prompt sends nothing for minutes, which is exactly the
93
+ * traffic pattern those boxes reap. Without a heartbeat the drop is invisible:
94
+ * TCP has no keepalive here, so the client keeps believing it is connected,
95
+ * keystrokes are written into a dead socket, and requests hang for their full
96
+ * timeout while the Core happily streams output nobody receives. Pinging every
97
+ * 15s keeps the flow alive AND detects death within one window.
98
+ */
99
+ export declare const DEFAULT_HEARTBEAT_INTERVAL_MS = 15000;
100
+ /** Declare the peer dead after this long with no frame of any kind (3 pings). */
101
+ export declare const DEFAULT_HEARTBEAT_TIMEOUT_MS = 45000;
102
+ /** The message a request rejects with when its socket died before the answer. */
103
+ export declare const CONNECTION_LOST_MESSAGE = "core-link connection lost";
104
+ /**
105
+ * One core-link connection. Constructed open-ended: the socket is dialed
106
+ * immediately, and the handlers passed in are the only way anything gets out of
107
+ * it. Not reusable — a transport is one socket, and a client that wants another
108
+ * builds another.
109
+ */
110
+ export declare class CoreLinkTransport {
111
+ private readonly handlers;
112
+ private readonly bearer;
113
+ private readonly heartbeatOpts;
114
+ private socket;
115
+ private reqSeq;
116
+ private readonly pending;
117
+ private opened;
118
+ private authenticated;
119
+ private disposed;
120
+ /** The reason the socket died, off the `error` event, for the close report. */
121
+ private lastError;
122
+ private ready;
123
+ private heartbeatTimer;
124
+ /** Epoch ms of the last frame received (message OR pong) on this connection. */
125
+ private lastInboundAt;
126
+ /** Injectable clock so a fake-timer test can drive the heartbeat. */
127
+ private readonly now;
128
+ constructor(opts: CoreLinkTransportOptions);
129
+ private wire;
130
+ /** True while this connection can carry a frame — open, and authenticated if it must be. */
131
+ get writable(): boolean;
132
+ /** True once the Core has accepted this connection's bearer. */
133
+ get isAuthenticated(): boolean;
134
+ /** This connection's `ready` frame, or null before it lands. */
135
+ get readyFrame(): CoreLinkReadyFrame | null;
136
+ /**
137
+ * Send a request frame and resolve with the Core's answer — **frames both
138
+ * ways**, errors included, because a router forwarding on behalf of somebody
139
+ * else needs the frame rather than an exception (that is the Panel's shape,
140
+ * and `CoreClient` is what turns a failure frame into a rejection).
141
+ *
142
+ * The `reqId` on the frame passed in is ignored: this transport owns
143
+ * correlation on its own socket and returns the frame carrying the id it
144
+ * assigned. Rejects if the socket dies before the answer arrives; never times
145
+ * out on its own — a deadline is the caller's policy, and the caller above
146
+ * this one has one.
147
+ */
148
+ request(frame: CoreLinkRequestFrame): Promise<CoreLinkResponseFrame>;
149
+ /**
150
+ * Send a frame and forget it. For the frames whose answer is a *stream* rather
151
+ * than a response — `subscribe`, whose reply is the replay tail and the
152
+ * `eventsReplayed` marker — and for the ones nothing waits on by design.
153
+ * Returns the assigned `reqId`, or null when the transport could not take it.
154
+ */
155
+ send(frame: CoreLinkRequestFrame, reqIdPrefix?: string): string | null;
156
+ /** Hang up. Idempotent; fires no `onClose`, because this is not the Core going away. */
157
+ close(): void;
158
+ private nextReqId;
159
+ private write;
160
+ private onMessage;
161
+ private rejectAll;
162
+ /**
163
+ * Arm the heartbeat for a freshly opened socket. Only a transport that can
164
+ * actually send a ping participates; a socket without one is left alone
165
+ * rather than being torn down for failing to answer pings nobody sent.
166
+ */
167
+ private startHeartbeat;
168
+ private stopHeartbeat;
169
+ /**
170
+ * Run an owner's callback. A listener that throws must not take the
171
+ * connection with it — half the callbacks here run inside a socket event, and
172
+ * an exception escaping one of those is an unhandled rejection at best and a
173
+ * connection stuck half-established at worst.
174
+ */
175
+ private guard;
176
+ }
177
+ //# sourceMappingURL=core-link-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-link-transport.d.ts","sourceRoot":"","sources":["../src/core-link-transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,432 @@
1
+ // One core link, from the client's side of it: one socket, one Core.
2
+ //
3
+ // Extracted from the Panel's `PtyCoreLinkClient` (issue 153, #129 D1/D2/D6) —
4
+ // which was `packages/panel/src/server/core-link/client.ts`, deleted in #156 when
5
+ // the Panel moved onto this package, so this is where that code lives now.
6
+ // That class did four separable jobs at once — frame the wire, correlate
7
+ // requests, keep a link alive across drops, and expose a typed API. This module
8
+ // is the first of those two: **the machinery of one connection**, with no
9
+ // opinion about what happens when it ends.
10
+ //
11
+ // Everything that outlives a socket lives above it: `CoreClient` owns the typed
12
+ // methods and the outbound queue, and `DurableCoreClient` owns reconnection.
13
+ // One transport is one socket's whole life, which is what makes the difference
14
+ // between the two entry points a difference in *who re-opens*, rather than two
15
+ // implementations of a wire.
16
+ //
17
+ // Three things about this protocol shape the code below, and each has cost
18
+ // somebody a debugging session:
19
+ //
20
+ // 1. **The Core speaks first, unsolicited.** `ready` is frame one on every
21
+ // connection and answers no request — a transport that treats the first
22
+ // inbound message as a response to something it sent waits forever. It is
23
+ // surfaced as {@link CoreLinkTransportHandlers.onReady}.
24
+ // 2. **`auth` must be the first frame sent**, or the Core answers
25
+ // `not-authenticated` and closes the socket. So nothing else may go out on
26
+ // open: a subscribe, a reclaim, a caller's RPC all queue behind it, and the
27
+ // transport does not report itself {@link CoreLinkTransport.writable} until
28
+ // `authOk` lands.
29
+ // 3. **`data` and `exit` arrive unsolicited too**, carrying a `ptyId` and no
30
+ // `reqId`. They are surfaced as frames, parsed once, here — a caller that
31
+ // re-parses a raw message is a caller that will disagree with this one.
32
+ /**
33
+ * Heartbeat cadence. A remote Core's core link runs over the open internet, so
34
+ * it crosses NATs and stateful firewalls that silently drop idle flows — an
35
+ * agent sitting at its prompt sends nothing for minutes, which is exactly the
36
+ * traffic pattern those boxes reap. Without a heartbeat the drop is invisible:
37
+ * TCP has no keepalive here, so the client keeps believing it is connected,
38
+ * keystrokes are written into a dead socket, and requests hang for their full
39
+ * timeout while the Core happily streams output nobody receives. Pinging every
40
+ * 15s keeps the flow alive AND detects death within one window.
41
+ */
42
+ export const DEFAULT_HEARTBEAT_INTERVAL_MS = 15_000;
43
+ /** Declare the peer dead after this long with no frame of any kind (3 pings). */
44
+ export const DEFAULT_HEARTBEAT_TIMEOUT_MS = 45_000;
45
+ /** The message a request rejects with when its socket died before the answer. */
46
+ export const CONNECTION_LOST_MESSAGE = "core-link connection lost";
47
+ /**
48
+ * One core-link connection. Constructed open-ended: the socket is dialed
49
+ * immediately, and the handlers passed in are the only way anything gets out of
50
+ * it. Not reusable — a transport is one socket, and a client that wants another
51
+ * builds another.
52
+ */
53
+ export class CoreLinkTransport {
54
+ handlers;
55
+ bearer;
56
+ heartbeatOpts;
57
+ socket = null;
58
+ reqSeq = 0;
59
+ pending = new Map();
60
+ opened = false;
61
+ authenticated = false;
62
+ disposed = false;
63
+ /** The reason the socket died, off the `error` event, for the close report. */
64
+ lastError;
65
+ ready = null;
66
+ heartbeatTimer = null;
67
+ /** Epoch ms of the last frame received (message OR pong) on this connection. */
68
+ lastInboundAt = 0;
69
+ /** Injectable clock so a fake-timer test can drive the heartbeat. */
70
+ now = () => Date.now();
71
+ constructor(opts) {
72
+ this.handlers = opts.handlers ?? {};
73
+ this.bearer = opts.bearer ?? null;
74
+ this.heartbeatOpts = opts.heartbeat === false ? null : (opts.heartbeat ?? null);
75
+ let socket;
76
+ try {
77
+ socket = opts.createSocket(opts.url);
78
+ }
79
+ catch (err) {
80
+ // A factory that throws — a malformed URL, a TLS material the runtime
81
+ // refuses — is a connection that closed before it opened, reported on the
82
+ // one channel an owner is already listening to.
83
+ this.disposed = true;
84
+ const reason = err instanceof Error ? err.message : String(err);
85
+ queueMicrotask(() => this.guard(() => this.handlers.onClose?.(reason)));
86
+ return;
87
+ }
88
+ this.socket = socket;
89
+ this.wire(socket);
90
+ }
91
+ wire(socket) {
92
+ socket.on("open", () => {
93
+ if (this.disposed)
94
+ return;
95
+ this.opened = true;
96
+ this.authenticated = false;
97
+ this.startHeartbeat(socket);
98
+ this.guard(() => this.handlers.onOpen?.());
99
+ // The auth frame, first, before anything else this transport or its owner
100
+ // wants to say. See this module's header, trap 2.
101
+ if (this.bearer) {
102
+ this.write({ type: "auth", reqId: this.nextReqId("auth"), bearer: this.bearer });
103
+ }
104
+ else {
105
+ this.guard(() => this.handlers.onWritable?.());
106
+ }
107
+ });
108
+ socket.on("message", (raw) => {
109
+ this.lastInboundAt = this.now();
110
+ this.onMessage(raw);
111
+ });
112
+ // Pong frames prove the peer is alive during an idle stretch. Only the Node
113
+ // `ws` transport surfaces them; a browser WebSocket answers pings in the
114
+ // engine and never tells us, which is why the heartbeat only arms where
115
+ // `ping` exists at all.
116
+ socket.on("pong", () => {
117
+ this.lastInboundAt = this.now();
118
+ });
119
+ socket.on("error", (err) => {
120
+ // The close handler drives everything; errors are ordinary during a Core
121
+ // restart. All that is kept is the reason, so the close report can say
122
+ // something better than "it closed" — a TLS rejection and an
123
+ // ECONNREFUSED both arrive here and then close silently.
124
+ this.lastError = err instanceof Error ? err.message : String(err);
125
+ });
126
+ socket.on("close", () => {
127
+ const wasDisposed = this.disposed;
128
+ this.opened = false;
129
+ this.authenticated = false;
130
+ this.stopHeartbeat();
131
+ // Every request written to this socket can never be answered now, so
132
+ // failing them here is the difference between a caller retrying at once
133
+ // and one waiting out its full timeout first.
134
+ this.rejectAll(CONNECTION_LOST_MESSAGE);
135
+ this.socket = null;
136
+ if (wasDisposed)
137
+ return;
138
+ this.disposed = true;
139
+ this.guard(() => this.handlers.onClose?.(this.lastError));
140
+ });
141
+ }
142
+ /** True while this connection can carry a frame — open, and authenticated if it must be. */
143
+ get writable() {
144
+ return !this.disposed && this.opened && (this.bearer === null || this.authenticated);
145
+ }
146
+ /** True once the Core has accepted this connection's bearer. */
147
+ get isAuthenticated() {
148
+ return this.authenticated;
149
+ }
150
+ /** This connection's `ready` frame, or null before it lands. */
151
+ get readyFrame() {
152
+ return this.ready;
153
+ }
154
+ /**
155
+ * Send a request frame and resolve with the Core's answer — **frames both
156
+ * ways**, errors included, because a router forwarding on behalf of somebody
157
+ * else needs the frame rather than an exception (that is the Panel's shape,
158
+ * and `CoreClient` is what turns a failure frame into a rejection).
159
+ *
160
+ * The `reqId` on the frame passed in is ignored: this transport owns
161
+ * correlation on its own socket and returns the frame carrying the id it
162
+ * assigned. Rejects if the socket dies before the answer arrives; never times
163
+ * out on its own — a deadline is the caller's policy, and the caller above
164
+ * this one has one.
165
+ */
166
+ request(frame) {
167
+ if (!this.writable)
168
+ return Promise.reject(new Error(CONNECTION_LOST_MESSAGE));
169
+ const reqId = this.nextReqId("r");
170
+ return new Promise((resolve, reject) => {
171
+ this.pending.set(reqId, { resolve, reject });
172
+ if (!this.write({ ...frame, reqId })) {
173
+ this.pending.delete(reqId);
174
+ reject(new Error(CONNECTION_LOST_MESSAGE));
175
+ }
176
+ });
177
+ }
178
+ /**
179
+ * Send a frame and forget it. For the frames whose answer is a *stream* rather
180
+ * than a response — `subscribe`, whose reply is the replay tail and the
181
+ * `eventsReplayed` marker — and for the ones nothing waits on by design.
182
+ * Returns the assigned `reqId`, or null when the transport could not take it.
183
+ */
184
+ send(frame, reqIdPrefix = "s") {
185
+ if (!this.writable)
186
+ return null;
187
+ const reqId = this.nextReqId(reqIdPrefix);
188
+ return this.write({ ...frame, reqId }) ? reqId : null;
189
+ }
190
+ /** Hang up. Idempotent; fires no `onClose`, because this is not the Core going away. */
191
+ close() {
192
+ if (this.disposed)
193
+ return;
194
+ this.disposed = true;
195
+ this.stopHeartbeat();
196
+ this.rejectAll("core-link client closed");
197
+ const socket = this.socket;
198
+ this.socket = null;
199
+ this.opened = false;
200
+ this.authenticated = false;
201
+ if (socket) {
202
+ try {
203
+ socket.close();
204
+ }
205
+ catch {
206
+ /* best effort — the socket is going away either way */
207
+ }
208
+ }
209
+ }
210
+ nextReqId(prefix) {
211
+ return `${prefix}${++this.reqSeq}`;
212
+ }
213
+ write(frame) {
214
+ const socket = this.socket;
215
+ if (!socket || !this.opened)
216
+ return false;
217
+ try {
218
+ socket.send(JSON.stringify(frame));
219
+ return true;
220
+ }
221
+ catch {
222
+ // The close handler takes it from here — it is the one place that fails
223
+ // in-flight requests and tells the owner.
224
+ return false;
225
+ }
226
+ }
227
+ onMessage(raw) {
228
+ let msg;
229
+ try {
230
+ msg = JSON.parse(typeof raw === "string" ? raw : String(raw));
231
+ }
232
+ catch {
233
+ return;
234
+ }
235
+ if (!msg || typeof msg.type !== "string")
236
+ return;
237
+ switch (msg.type) {
238
+ // ─── The three unsolicited streams ───
239
+ case "ready": {
240
+ // Kept as the frame rather than picked apart: the version gate and the
241
+ // `multiConnection` capability are both read off it upstairs, and a
242
+ // transport that pre-digested it would have to grow a field per
243
+ // capability the `ready` frame ever gains.
244
+ this.ready = {
245
+ type: "ready",
246
+ version: typeof msg.version === "string" ? msg.version : "",
247
+ ...(msg.multiConnection !== undefined
248
+ ? { multiConnection: msg.multiConnection }
249
+ : {}),
250
+ };
251
+ this.guard(() => this.handlers.onReady?.(this.ready));
252
+ return;
253
+ }
254
+ case "data": {
255
+ const ptyId = typeof msg.ptyId === "string" ? msg.ptyId : "";
256
+ if (!ptyId)
257
+ return;
258
+ const frame = {
259
+ type: "data",
260
+ ptyId,
261
+ data: typeof msg.data === "string" ? msg.data : "",
262
+ seq: typeof msg.seq === "number" ? msg.seq : 0,
263
+ };
264
+ this.guard(() => this.handlers.onData?.(frame));
265
+ return;
266
+ }
267
+ case "exit": {
268
+ const ptyId = typeof msg.ptyId === "string" ? msg.ptyId : "";
269
+ if (!ptyId)
270
+ return;
271
+ const frame = {
272
+ type: "exit",
273
+ ptyId,
274
+ exitCode: typeof msg.exitCode === "number" ? msg.exitCode : 0,
275
+ ...(typeof msg.signal === "number" ? { signal: msg.signal } : {}),
276
+ };
277
+ this.guard(() => this.handlers.onExit?.(frame));
278
+ return;
279
+ }
280
+ // ─── The event log ───
281
+ case "event": {
282
+ const event = parseEvent(msg.event);
283
+ if (!event)
284
+ return;
285
+ this.guard(() => this.handlers.onEvent?.(event));
286
+ return;
287
+ }
288
+ case "eventsReplayed": {
289
+ const lastEventId = typeof msg.lastEventId === "number" ? msg.lastEventId : 0;
290
+ this.guard(() => this.handlers.onEventsReplayed?.(lastEventId));
291
+ return;
292
+ }
293
+ case "subscribeAck":
294
+ // Informational — the event stream and its `eventsReplayed` marker
295
+ // follow, and they are what a subscriber is waiting for.
296
+ return;
297
+ // ─── Bearer auth ───
298
+ case "authOk": {
299
+ this.authenticated = true;
300
+ const frame = {
301
+ type: "authOk",
302
+ reqId: typeof msg.reqId === "string" ? msg.reqId : "",
303
+ coreId: typeof msg.coreId === "string" ? msg.coreId : "",
304
+ exp: typeof msg.exp === "number" ? msg.exp : 0,
305
+ };
306
+ // The owner's turn first: a fresh connection owes the Core a `reclaim`
307
+ // and a `subscribe`, and both must precede whatever requests were
308
+ // waiting for this socket, so the replay tail arrives before the
309
+ // answers to them.
310
+ this.guard(() => this.handlers.onAuthOk?.(frame));
311
+ this.guard(() => this.handlers.onWritable?.());
312
+ return;
313
+ }
314
+ case "authError": {
315
+ const reason = msg.reason === "expired" || msg.reason === "bad-signature" || msg.reason === "malformed"
316
+ ? msg.reason
317
+ : "malformed";
318
+ this.authenticated = false;
319
+ this.guard(() => this.handlers.onAuthError?.(reason));
320
+ // The Core closes the socket right after this frame; the close handler
321
+ // is what reports the connection's end. An expired bearer keeps failing
322
+ // until a reissued blob is pasted — that is the designed "reissuing is a
323
+ // machine-side operation" property (ADR 0003).
324
+ return;
325
+ }
326
+ default:
327
+ break;
328
+ }
329
+ // ─── Everything else is an answer, correlated by reqId ───
330
+ const reqId = typeof msg.reqId === "string" ? msg.reqId : null;
331
+ if (!reqId)
332
+ return;
333
+ const pending = this.pending.get(reqId);
334
+ if (!pending)
335
+ return;
336
+ this.pending.delete(reqId);
337
+ pending.resolve(msg);
338
+ }
339
+ rejectAll(reason) {
340
+ if (this.pending.size === 0)
341
+ return;
342
+ const err = new Error(reason);
343
+ const pending = [...this.pending.values()];
344
+ this.pending.clear();
345
+ for (const p of pending)
346
+ p.reject(err);
347
+ }
348
+ /**
349
+ * Arm the heartbeat for a freshly opened socket. Only a transport that can
350
+ * actually send a ping participates; a socket without one is left alone
351
+ * rather than being torn down for failing to answer pings nobody sent.
352
+ */
353
+ startHeartbeat(socket) {
354
+ this.stopHeartbeat();
355
+ if (!this.heartbeatOpts || !socket.ping)
356
+ return;
357
+ const intervalMs = this.heartbeatOpts.intervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;
358
+ const timeoutMs = this.heartbeatOpts.timeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS;
359
+ this.lastInboundAt = this.now();
360
+ this.heartbeatTimer = setInterval(() => {
361
+ if (this.socket !== socket) {
362
+ this.stopHeartbeat();
363
+ return;
364
+ }
365
+ if (this.now() - this.lastInboundAt > timeoutMs) {
366
+ // Half-open: the peer stopped answering. A graceful close would wait for
367
+ // a FIN that is never coming, so destroy the socket and let the close
368
+ // handler run the ordinary path.
369
+ this.stopHeartbeat();
370
+ try {
371
+ socket.terminate ? socket.terminate() : socket.close();
372
+ }
373
+ catch {
374
+ /* already gone — the close handler still fires */
375
+ }
376
+ return;
377
+ }
378
+ try {
379
+ socket.ping?.();
380
+ }
381
+ catch {
382
+ /* the close handler will take it from here */
383
+ }
384
+ }, intervalMs);
385
+ }
386
+ stopHeartbeat() {
387
+ if (this.heartbeatTimer) {
388
+ clearInterval(this.heartbeatTimer);
389
+ this.heartbeatTimer = null;
390
+ }
391
+ }
392
+ /**
393
+ * Run an owner's callback. A listener that throws must not take the
394
+ * connection with it — half the callbacks here run inside a socket event, and
395
+ * an exception escaping one of those is an unhandled rejection at best and a
396
+ * connection stuck half-established at worst.
397
+ */
398
+ guard(fn) {
399
+ try {
400
+ fn();
401
+ }
402
+ catch {
403
+ /* a listener's failure is not this connection's failure */
404
+ }
405
+ }
406
+ }
407
+ /**
408
+ * Read an `event` frame's payload into a {@link CoreLinkEvent}, or null.
409
+ *
410
+ * Field-by-field rather than a cast, because this is the one frame whose body
411
+ * is a nested object from another process's database: an `eventId` that is
412
+ * missing or zero would silently corrupt the cursor that decides what gets
413
+ * replayed after the next reconnect, so it is the one field whose absence
414
+ * rejects the frame outright.
415
+ */
416
+ function parseEvent(raw) {
417
+ if (!raw || typeof raw !== "object")
418
+ return null;
419
+ const e = raw;
420
+ const eventId = typeof e.eventId === "number" ? e.eventId : NaN;
421
+ if (!Number.isFinite(eventId) || eventId <= 0)
422
+ return null;
423
+ return {
424
+ eventId,
425
+ ts: typeof e.ts === "number" ? e.ts : 0,
426
+ kind: typeof e.kind === "string" ? e.kind : "",
427
+ ptyId: typeof e.ptyId === "string" ? e.ptyId : null,
428
+ taskId: typeof e.taskId === "string" ? e.taskId : null,
429
+ payload: typeof e.payload === "string" ? e.payload : "{}",
430
+ };
431
+ }
432
+ //# sourceMappingURL=core-link-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-link-transport.js","sourceRoot":"","sources":["../src/core-link-transport.ts"],"names":[],"mappings":"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"}