@adhdev/session-host-core 1.0.58-rc.1 → 1.0.58-rc.3
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/dist/index.d.mts +32 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.js +75 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +75 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +7 -1
- package/src/ipc.ts +114 -11
package/dist/index.d.mts
CHANGED
|
@@ -538,12 +538,43 @@ interface SessionHostClientOptions {
|
|
|
538
538
|
endpoint?: SessionHostEndpoint;
|
|
539
539
|
appName?: string;
|
|
540
540
|
}
|
|
541
|
+
/**
|
|
542
|
+
* Why an established session-host connection went away.
|
|
543
|
+
* - `error` — socket emitted 'error' (includes ECONNRESET on abrupt host death)
|
|
544
|
+
* - `ended` — peer sent FIN ('end'): the host closed the connection cleanly
|
|
545
|
+
* - `closed` — socket fully closed ('close') without a preceding error/end
|
|
546
|
+
*/
|
|
547
|
+
type SessionHostDisconnectReason = 'error' | 'ended' | 'closed';
|
|
548
|
+
interface SessionHostDisconnectInfo {
|
|
549
|
+
reason: SessionHostDisconnectReason;
|
|
550
|
+
endpointPath: string;
|
|
551
|
+
/** In-flight requests abandoned by this disconnect (they were rejected). */
|
|
552
|
+
pendingRequests: number;
|
|
553
|
+
error?: Error;
|
|
554
|
+
}
|
|
541
555
|
declare class SessionHostClient {
|
|
542
556
|
readonly endpoint: SessionHostEndpoint;
|
|
543
557
|
private socket;
|
|
544
558
|
private requestWaiters;
|
|
545
559
|
private eventListeners;
|
|
560
|
+
private disconnectListeners;
|
|
561
|
+
/** Guards against emitting both an 'error'-path and a 'close'-path disconnect for one socket. */
|
|
562
|
+
private disconnectedSockets;
|
|
546
563
|
constructor(options?: SessionHostClientOptions);
|
|
564
|
+
/**
|
|
565
|
+
* Fires when an established connection to the session host goes away.
|
|
566
|
+
*
|
|
567
|
+
* Before this existed the client registered only 'data' and 'error' handlers,
|
|
568
|
+
* so a *clean* FIN — the host process exiting normally, or dying to an
|
|
569
|
+
* uncaught exception that took the socket down without an error event on our
|
|
570
|
+
* end — ran nothing at all: `this.socket` stayed non-null pointing at a dead
|
|
571
|
+
* socket, in-flight waiters hung to their 30s timeout, and no caller was told.
|
|
572
|
+
* That silence is what let a session-host death present downstream as an
|
|
573
|
+
* unrelated application-level fault (a missing completion marker) instead of
|
|
574
|
+
* "the host is gone".
|
|
575
|
+
*/
|
|
576
|
+
onDisconnect(listener: (info: SessionHostDisconnectInfo) => void): () => void;
|
|
577
|
+
private handleDisconnect;
|
|
547
578
|
connect(): Promise<void>;
|
|
548
579
|
onEvent(listener: (event: SessionHostEvent) => void): () => void;
|
|
549
580
|
request<T = unknown>(request: SessionHostRequest): Promise<SessionHostResponse<T>>;
|
|
@@ -683,4 +714,4 @@ interface SessionHostControlTransport {
|
|
|
683
714
|
*/
|
|
684
715
|
declare function createSessionHostControlPlane(transport: SessionHostControlTransport): SessionHostControlPlane;
|
|
685
716
|
|
|
686
|
-
export { type AcquireWritePayload, type AttachSessionPayload, type ClearSessionBufferPayload, type CreateSessionPayload, DEFAULT_CONFIG_DIR_NAME, DEFAULT_SESSION_RING_BUFFER_MAX_BYTES, type DetachSessionPayload, type ForceDetachClientPayload, type GetHostDiagnosticsPayload, type GetSnapshotPayload, type GetTerminalSnapshotPayload, type PruneDuplicateSessionsPayload, type ReleaseWritePayload, type ResizeSessionPayload, type RestartSessionPayload, type ResumeSessionPayload, SESSION_HOST_SUPPORTED_REQUEST_TYPES, type SendInputPayload, type SendSignalPayload, type SessionAttachedClient, type SessionBufferSnapshot, type SessionClientType, type SessionHostCategory, SessionHostClient, type SessionHostClientOptions, type SessionHostControlPlane, type SessionHostControlTransport, type SessionHostDiagnostics, type SessionHostDuplicateSessionGroup, type SessionHostEndpoint, type SessionHostEndpointOptions, type SessionHostEvent, type SessionHostEventEnvelope, type SessionHostLogEntry, type SessionHostPruneDuplicatesResult, type SessionHostRecord, SessionHostRegistry, type SessionHostRequest, type SessionHostRequestEnvelope, type SessionHostRequestTrace, type SessionHostRequestType, type SessionHostResponse, type SessionHostResponseEnvelope, type SessionHostRuntimeTransition, type SessionHostSurfaceKind, type SessionHostSurfaceRecordLike, type SessionHostWireEnvelope, type SessionLaunchCommand, type SessionLifecycle, type SessionOwnerType, SessionRingBuffer, type SessionRingBufferOptions, type SessionTerminalSnapshot, type SessionTerminalState, type SessionTermination, type SessionTransport, type SessionWriteOwner, type StopSessionPayload, type UpdateSessionMetaPayload, applyTerminalColorEnv, buildRuntimeDisplayName, buildRuntimeKey, canonicalizeInstancePath, classifyTermination, createLineParser, createResponseEnvelope, createSessionHostControlPlane, ensureNodePtySpawnHelperPermissions, formatRuntimeOwner, getDefaultSessionHostEndpoint, getSessionHostRecoveryLabel, getSessionHostSurfaceKind, getWorkspaceLabel, isDefaultInstanceConfigDir, isSessionHostLiveRuntime, isSessionHostRecoverySnapshot, isTerminalRecord, partitionSessionHostDiagnosticsSessions, partitionSessionHostRecords, resolveAttachableRuntimeRecord, resolveInstanceConfigDir, resolveRuntimeRecord, resolveSessionHostIpcKey, sanitizeSpawnEnv, writeEnvelope };
|
|
717
|
+
export { type AcquireWritePayload, type AttachSessionPayload, type ClearSessionBufferPayload, type CreateSessionPayload, DEFAULT_CONFIG_DIR_NAME, DEFAULT_SESSION_RING_BUFFER_MAX_BYTES, type DetachSessionPayload, type ForceDetachClientPayload, type GetHostDiagnosticsPayload, type GetSnapshotPayload, type GetTerminalSnapshotPayload, type PruneDuplicateSessionsPayload, type ReleaseWritePayload, type ResizeSessionPayload, type RestartSessionPayload, type ResumeSessionPayload, SESSION_HOST_SUPPORTED_REQUEST_TYPES, type SendInputPayload, type SendSignalPayload, type SessionAttachedClient, type SessionBufferSnapshot, type SessionClientType, type SessionHostCategory, SessionHostClient, type SessionHostClientOptions, type SessionHostControlPlane, type SessionHostControlTransport, type SessionHostDiagnostics, type SessionHostDisconnectInfo, type SessionHostDisconnectReason, type SessionHostDuplicateSessionGroup, type SessionHostEndpoint, type SessionHostEndpointOptions, type SessionHostEvent, type SessionHostEventEnvelope, type SessionHostLogEntry, type SessionHostPruneDuplicatesResult, type SessionHostRecord, SessionHostRegistry, type SessionHostRequest, type SessionHostRequestEnvelope, type SessionHostRequestTrace, type SessionHostRequestType, type SessionHostResponse, type SessionHostResponseEnvelope, type SessionHostRuntimeTransition, type SessionHostSurfaceKind, type SessionHostSurfaceRecordLike, type SessionHostWireEnvelope, type SessionLaunchCommand, type SessionLifecycle, type SessionOwnerType, SessionRingBuffer, type SessionRingBufferOptions, type SessionTerminalSnapshot, type SessionTerminalState, type SessionTermination, type SessionTransport, type SessionWriteOwner, type StopSessionPayload, type UpdateSessionMetaPayload, applyTerminalColorEnv, buildRuntimeDisplayName, buildRuntimeKey, canonicalizeInstancePath, classifyTermination, createLineParser, createResponseEnvelope, createSessionHostControlPlane, ensureNodePtySpawnHelperPermissions, formatRuntimeOwner, getDefaultSessionHostEndpoint, getSessionHostRecoveryLabel, getSessionHostSurfaceKind, getWorkspaceLabel, isDefaultInstanceConfigDir, isSessionHostLiveRuntime, isSessionHostRecoverySnapshot, isTerminalRecord, partitionSessionHostDiagnosticsSessions, partitionSessionHostRecords, resolveAttachableRuntimeRecord, resolveInstanceConfigDir, resolveRuntimeRecord, resolveSessionHostIpcKey, sanitizeSpawnEnv, writeEnvelope };
|
package/dist/index.d.ts
CHANGED
|
@@ -538,12 +538,43 @@ interface SessionHostClientOptions {
|
|
|
538
538
|
endpoint?: SessionHostEndpoint;
|
|
539
539
|
appName?: string;
|
|
540
540
|
}
|
|
541
|
+
/**
|
|
542
|
+
* Why an established session-host connection went away.
|
|
543
|
+
* - `error` — socket emitted 'error' (includes ECONNRESET on abrupt host death)
|
|
544
|
+
* - `ended` — peer sent FIN ('end'): the host closed the connection cleanly
|
|
545
|
+
* - `closed` — socket fully closed ('close') without a preceding error/end
|
|
546
|
+
*/
|
|
547
|
+
type SessionHostDisconnectReason = 'error' | 'ended' | 'closed';
|
|
548
|
+
interface SessionHostDisconnectInfo {
|
|
549
|
+
reason: SessionHostDisconnectReason;
|
|
550
|
+
endpointPath: string;
|
|
551
|
+
/** In-flight requests abandoned by this disconnect (they were rejected). */
|
|
552
|
+
pendingRequests: number;
|
|
553
|
+
error?: Error;
|
|
554
|
+
}
|
|
541
555
|
declare class SessionHostClient {
|
|
542
556
|
readonly endpoint: SessionHostEndpoint;
|
|
543
557
|
private socket;
|
|
544
558
|
private requestWaiters;
|
|
545
559
|
private eventListeners;
|
|
560
|
+
private disconnectListeners;
|
|
561
|
+
/** Guards against emitting both an 'error'-path and a 'close'-path disconnect for one socket. */
|
|
562
|
+
private disconnectedSockets;
|
|
546
563
|
constructor(options?: SessionHostClientOptions);
|
|
564
|
+
/**
|
|
565
|
+
* Fires when an established connection to the session host goes away.
|
|
566
|
+
*
|
|
567
|
+
* Before this existed the client registered only 'data' and 'error' handlers,
|
|
568
|
+
* so a *clean* FIN — the host process exiting normally, or dying to an
|
|
569
|
+
* uncaught exception that took the socket down without an error event on our
|
|
570
|
+
* end — ran nothing at all: `this.socket` stayed non-null pointing at a dead
|
|
571
|
+
* socket, in-flight waiters hung to their 30s timeout, and no caller was told.
|
|
572
|
+
* That silence is what let a session-host death present downstream as an
|
|
573
|
+
* unrelated application-level fault (a missing completion marker) instead of
|
|
574
|
+
* "the host is gone".
|
|
575
|
+
*/
|
|
576
|
+
onDisconnect(listener: (info: SessionHostDisconnectInfo) => void): () => void;
|
|
577
|
+
private handleDisconnect;
|
|
547
578
|
connect(): Promise<void>;
|
|
548
579
|
onEvent(listener: (event: SessionHostEvent) => void): () => void;
|
|
549
580
|
request<T = unknown>(request: SessionHostRequest): Promise<SessionHostResponse<T>>;
|
|
@@ -683,4 +714,4 @@ interface SessionHostControlTransport {
|
|
|
683
714
|
*/
|
|
684
715
|
declare function createSessionHostControlPlane(transport: SessionHostControlTransport): SessionHostControlPlane;
|
|
685
716
|
|
|
686
|
-
export { type AcquireWritePayload, type AttachSessionPayload, type ClearSessionBufferPayload, type CreateSessionPayload, DEFAULT_CONFIG_DIR_NAME, DEFAULT_SESSION_RING_BUFFER_MAX_BYTES, type DetachSessionPayload, type ForceDetachClientPayload, type GetHostDiagnosticsPayload, type GetSnapshotPayload, type GetTerminalSnapshotPayload, type PruneDuplicateSessionsPayload, type ReleaseWritePayload, type ResizeSessionPayload, type RestartSessionPayload, type ResumeSessionPayload, SESSION_HOST_SUPPORTED_REQUEST_TYPES, type SendInputPayload, type SendSignalPayload, type SessionAttachedClient, type SessionBufferSnapshot, type SessionClientType, type SessionHostCategory, SessionHostClient, type SessionHostClientOptions, type SessionHostControlPlane, type SessionHostControlTransport, type SessionHostDiagnostics, type SessionHostDuplicateSessionGroup, type SessionHostEndpoint, type SessionHostEndpointOptions, type SessionHostEvent, type SessionHostEventEnvelope, type SessionHostLogEntry, type SessionHostPruneDuplicatesResult, type SessionHostRecord, SessionHostRegistry, type SessionHostRequest, type SessionHostRequestEnvelope, type SessionHostRequestTrace, type SessionHostRequestType, type SessionHostResponse, type SessionHostResponseEnvelope, type SessionHostRuntimeTransition, type SessionHostSurfaceKind, type SessionHostSurfaceRecordLike, type SessionHostWireEnvelope, type SessionLaunchCommand, type SessionLifecycle, type SessionOwnerType, SessionRingBuffer, type SessionRingBufferOptions, type SessionTerminalSnapshot, type SessionTerminalState, type SessionTermination, type SessionTransport, type SessionWriteOwner, type StopSessionPayload, type UpdateSessionMetaPayload, applyTerminalColorEnv, buildRuntimeDisplayName, buildRuntimeKey, canonicalizeInstancePath, classifyTermination, createLineParser, createResponseEnvelope, createSessionHostControlPlane, ensureNodePtySpawnHelperPermissions, formatRuntimeOwner, getDefaultSessionHostEndpoint, getSessionHostRecoveryLabel, getSessionHostSurfaceKind, getWorkspaceLabel, isDefaultInstanceConfigDir, isSessionHostLiveRuntime, isSessionHostRecoverySnapshot, isTerminalRecord, partitionSessionHostDiagnosticsSessions, partitionSessionHostRecords, resolveAttachableRuntimeRecord, resolveInstanceConfigDir, resolveRuntimeRecord, resolveSessionHostIpcKey, sanitizeSpawnEnv, writeEnvelope };
|
|
717
|
+
export { type AcquireWritePayload, type AttachSessionPayload, type ClearSessionBufferPayload, type CreateSessionPayload, DEFAULT_CONFIG_DIR_NAME, DEFAULT_SESSION_RING_BUFFER_MAX_BYTES, type DetachSessionPayload, type ForceDetachClientPayload, type GetHostDiagnosticsPayload, type GetSnapshotPayload, type GetTerminalSnapshotPayload, type PruneDuplicateSessionsPayload, type ReleaseWritePayload, type ResizeSessionPayload, type RestartSessionPayload, type ResumeSessionPayload, SESSION_HOST_SUPPORTED_REQUEST_TYPES, type SendInputPayload, type SendSignalPayload, type SessionAttachedClient, type SessionBufferSnapshot, type SessionClientType, type SessionHostCategory, SessionHostClient, type SessionHostClientOptions, type SessionHostControlPlane, type SessionHostControlTransport, type SessionHostDiagnostics, type SessionHostDisconnectInfo, type SessionHostDisconnectReason, type SessionHostDuplicateSessionGroup, type SessionHostEndpoint, type SessionHostEndpointOptions, type SessionHostEvent, type SessionHostEventEnvelope, type SessionHostLogEntry, type SessionHostPruneDuplicatesResult, type SessionHostRecord, SessionHostRegistry, type SessionHostRequest, type SessionHostRequestEnvelope, type SessionHostRequestTrace, type SessionHostRequestType, type SessionHostResponse, type SessionHostResponseEnvelope, type SessionHostRuntimeTransition, type SessionHostSurfaceKind, type SessionHostSurfaceRecordLike, type SessionHostWireEnvelope, type SessionLaunchCommand, type SessionLifecycle, type SessionOwnerType, SessionRingBuffer, type SessionRingBufferOptions, type SessionTerminalSnapshot, type SessionTerminalState, type SessionTermination, type SessionTransport, type SessionWriteOwner, type StopSessionPayload, type UpdateSessionMetaPayload, applyTerminalColorEnv, buildRuntimeDisplayName, buildRuntimeKey, canonicalizeInstancePath, classifyTermination, createLineParser, createResponseEnvelope, createSessionHostControlPlane, ensureNodePtySpawnHelperPermissions, formatRuntimeOwner, getDefaultSessionHostEndpoint, getSessionHostRecoveryLabel, getSessionHostSurfaceKind, getWorkspaceLabel, isDefaultInstanceConfigDir, isSessionHostLiveRuntime, isSessionHostRecoverySnapshot, isTerminalRecord, partitionSessionHostDiagnosticsSessions, partitionSessionHostRecords, resolveAttachableRuntimeRecord, resolveInstanceConfigDir, resolveRuntimeRecord, resolveSessionHostIpcKey, sanitizeSpawnEnv, writeEnvelope };
|
package/dist/index.js
CHANGED
|
@@ -627,14 +627,77 @@ function createLineParser(onEnvelope) {
|
|
|
627
627
|
}
|
|
628
628
|
};
|
|
629
629
|
}
|
|
630
|
+
var establishedSockets = /* @__PURE__ */ new WeakSet();
|
|
630
631
|
var SessionHostClient = class {
|
|
631
632
|
endpoint;
|
|
632
633
|
socket = null;
|
|
633
634
|
requestWaiters = /* @__PURE__ */ new Map();
|
|
634
635
|
eventListeners = /* @__PURE__ */ new Set();
|
|
636
|
+
disconnectListeners = /* @__PURE__ */ new Set();
|
|
637
|
+
/** Guards against emitting both an 'error'-path and a 'close'-path disconnect for one socket. */
|
|
638
|
+
disconnectedSockets = /* @__PURE__ */ new WeakSet();
|
|
635
639
|
constructor(options = {}) {
|
|
636
640
|
this.endpoint = options.endpoint || getDefaultSessionHostEndpoint(options.appName || "adhdev");
|
|
637
641
|
}
|
|
642
|
+
/**
|
|
643
|
+
* Fires when an established connection to the session host goes away.
|
|
644
|
+
*
|
|
645
|
+
* Before this existed the client registered only 'data' and 'error' handlers,
|
|
646
|
+
* so a *clean* FIN — the host process exiting normally, or dying to an
|
|
647
|
+
* uncaught exception that took the socket down without an error event on our
|
|
648
|
+
* end — ran nothing at all: `this.socket` stayed non-null pointing at a dead
|
|
649
|
+
* socket, in-flight waiters hung to their 30s timeout, and no caller was told.
|
|
650
|
+
* That silence is what let a session-host death present downstream as an
|
|
651
|
+
* unrelated application-level fault (a missing completion marker) instead of
|
|
652
|
+
* "the host is gone".
|
|
653
|
+
*/
|
|
654
|
+
onDisconnect(listener) {
|
|
655
|
+
this.disconnectListeners.add(listener);
|
|
656
|
+
return () => {
|
|
657
|
+
this.disconnectListeners.delete(listener);
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
handleDisconnect(socket, reason, error) {
|
|
661
|
+
if (this.disconnectedSockets.has(socket)) return;
|
|
662
|
+
this.disconnectedSockets.add(socket);
|
|
663
|
+
const wasEstablished = establishedSockets.has(socket);
|
|
664
|
+
if (!wasEstablished) {
|
|
665
|
+
if (this.socket === socket) this.socket = null;
|
|
666
|
+
try {
|
|
667
|
+
socket.destroy();
|
|
668
|
+
} catch {
|
|
669
|
+
}
|
|
670
|
+
const failure2 = error || new Error(`Session host connect failed (${this.endpoint.path})`);
|
|
671
|
+
for (const waiter of this.requestWaiters.values()) waiter.reject(failure2);
|
|
672
|
+
this.requestWaiters.clear();
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
const pendingRequests = this.requestWaiters.size;
|
|
676
|
+
const failure = error || new Error(`Session host connection ${reason} (${this.endpoint.path})`);
|
|
677
|
+
for (const waiter of this.requestWaiters.values()) {
|
|
678
|
+
waiter.reject(failure);
|
|
679
|
+
}
|
|
680
|
+
this.requestWaiters.clear();
|
|
681
|
+
if (this.socket === socket) {
|
|
682
|
+
this.socket = null;
|
|
683
|
+
}
|
|
684
|
+
try {
|
|
685
|
+
socket.destroy();
|
|
686
|
+
} catch {
|
|
687
|
+
}
|
|
688
|
+
const info = {
|
|
689
|
+
reason,
|
|
690
|
+
endpointPath: this.endpoint.path,
|
|
691
|
+
pendingRequests,
|
|
692
|
+
error
|
|
693
|
+
};
|
|
694
|
+
for (const listener of this.disconnectListeners) {
|
|
695
|
+
try {
|
|
696
|
+
listener(info);
|
|
697
|
+
} catch {
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
638
701
|
async connect() {
|
|
639
702
|
if (this.socket && !this.socket.destroyed) return;
|
|
640
703
|
if (this.socket) {
|
|
@@ -660,20 +723,19 @@ var SessionHostClient = class {
|
|
|
660
723
|
}
|
|
661
724
|
}));
|
|
662
725
|
socket.on("error", (error) => {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
this.
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
try {
|
|
671
|
-
socket.destroy();
|
|
672
|
-
} catch {
|
|
673
|
-
}
|
|
726
|
+
this.handleDisconnect(socket, "error", error);
|
|
727
|
+
});
|
|
728
|
+
socket.on("close", () => {
|
|
729
|
+
this.handleDisconnect(socket, "closed");
|
|
730
|
+
});
|
|
731
|
+
socket.on("end", () => {
|
|
732
|
+
this.handleDisconnect(socket, "ended");
|
|
674
733
|
});
|
|
675
734
|
await new Promise((resolve3, reject) => {
|
|
676
|
-
socket.once("connect", () =>
|
|
735
|
+
socket.once("connect", () => {
|
|
736
|
+
establishedSockets.add(socket);
|
|
737
|
+
resolve3();
|
|
738
|
+
});
|
|
677
739
|
socket.once("error", reject);
|
|
678
740
|
});
|
|
679
741
|
}
|
|
@@ -715,6 +777,7 @@ var SessionHostClient = class {
|
|
|
715
777
|
if (!this.socket) return;
|
|
716
778
|
const socket = this.socket;
|
|
717
779
|
this.socket = null;
|
|
780
|
+
this.disconnectedSockets.add(socket);
|
|
718
781
|
for (const waiter of this.requestWaiters.values()) {
|
|
719
782
|
waiter.reject(new Error("Session host client closed"));
|
|
720
783
|
}
|