@adhdev/session-host-core 1.0.82-rc.26 → 1.0.82-rc.29
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 +33 -3
- package/dist/index.d.ts +33 -3
- package/dist/index.js +115 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +114 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +4 -0
- package/src/ipc.ts +112 -12
- package/src/types.ts +11 -0
package/dist/index.mjs
CHANGED
|
@@ -16,6 +16,7 @@ var SESSION_HOST_SUPPORTED_REQUEST_TYPES = [
|
|
|
16
16
|
"send_input",
|
|
17
17
|
"resize_session",
|
|
18
18
|
"stop_session",
|
|
19
|
+
"stop_mesh_writer",
|
|
19
20
|
"delete_session",
|
|
20
21
|
"resume_session",
|
|
21
22
|
"acquire_write",
|
|
@@ -746,6 +747,19 @@ function disconnectSessionHostClients(endpoint, error) {
|
|
|
746
747
|
}
|
|
747
748
|
}
|
|
748
749
|
}
|
|
750
|
+
function findConnectedSessionHostClient(endpoint) {
|
|
751
|
+
for (const ref of activeClientRefs) {
|
|
752
|
+
const client = ref.deref();
|
|
753
|
+
if (!client) {
|
|
754
|
+
activeClientRefs.delete(ref);
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
if ((!endpoint || client.endpoint.path === endpoint.path) && client.isConnected()) {
|
|
758
|
+
return client;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
return null;
|
|
762
|
+
}
|
|
749
763
|
var SessionHostClient = class {
|
|
750
764
|
endpoint;
|
|
751
765
|
socket = null;
|
|
@@ -763,11 +777,17 @@ var SessionHostClient = class {
|
|
|
763
777
|
if (typeof options.requestTimeoutMs === "number" && options.requestTimeoutMs > 0) {
|
|
764
778
|
this.requestTimeoutMs = options.requestTimeoutMs;
|
|
765
779
|
}
|
|
766
|
-
activeClientRefs.add(new WeakRef(this));
|
|
780
|
+
if (options.registerAsShared !== false) activeClientRefs.add(new WeakRef(this));
|
|
767
781
|
}
|
|
768
782
|
static disconnectClients(endpoint, error) {
|
|
769
783
|
disconnectSessionHostClients(endpoint, error);
|
|
770
784
|
}
|
|
785
|
+
static findConnectedClient(endpoint) {
|
|
786
|
+
return findConnectedSessionHostClient(endpoint);
|
|
787
|
+
}
|
|
788
|
+
isConnected() {
|
|
789
|
+
return Boolean(this.socket && !this.socket.destroyed && establishedSockets.has(this.socket));
|
|
790
|
+
}
|
|
771
791
|
/**
|
|
772
792
|
* Fires when an established connection to the session host goes away.
|
|
773
793
|
*
|
|
@@ -829,18 +849,32 @@ var SessionHostClient = class {
|
|
|
829
849
|
}
|
|
830
850
|
}
|
|
831
851
|
}
|
|
832
|
-
sendRawRequestOnSocket(socket, request) {
|
|
852
|
+
sendRawRequestOnSocket(socket, request, timeoutMs = this.requestTimeoutMs) {
|
|
833
853
|
const requestId = generateUUID();
|
|
834
854
|
const envelope = {
|
|
835
855
|
kind: "request",
|
|
836
856
|
requestId,
|
|
837
857
|
request
|
|
838
858
|
};
|
|
839
|
-
const timeoutMs = this.requestTimeoutMs > 0 ? this.requestTimeoutMs : 3e4;
|
|
840
859
|
const timeoutLabel = timeoutMs % 1e3 === 0 ? `${timeoutMs / 1e3}s` : `${timeoutMs}ms`;
|
|
860
|
+
const startedAt = Date.now();
|
|
861
|
+
const startedMonotonicAt = performance.now();
|
|
841
862
|
return new Promise((resolve3, reject) => {
|
|
842
863
|
const timeout = setTimeout(() => {
|
|
843
|
-
const
|
|
864
|
+
const actualElapsedMs = Math.max(0, Math.round(performance.now() - startedMonotonicAt));
|
|
865
|
+
const wallElapsedMs = Math.max(0, Date.now() - startedAt);
|
|
866
|
+
const observerLagMs = Math.max(0, actualElapsedMs - timeoutMs);
|
|
867
|
+
const timeoutError = Object.assign(
|
|
868
|
+
new Error(`Session host request timed out after ${timeoutLabel} (${request.type})`),
|
|
869
|
+
{
|
|
870
|
+
code: "SESSION_HOST_REQUEST_TIMEOUT",
|
|
871
|
+
requestType: request.type,
|
|
872
|
+
scheduledTimeoutMs: timeoutMs,
|
|
873
|
+
actualElapsedMs,
|
|
874
|
+
wallElapsedMs,
|
|
875
|
+
observerLagMs
|
|
876
|
+
}
|
|
877
|
+
);
|
|
844
878
|
if (this.socket === socket) {
|
|
845
879
|
this.disconnect(timeoutError);
|
|
846
880
|
} else {
|
|
@@ -866,7 +900,7 @@ var SessionHostClient = class {
|
|
|
866
900
|
socket.write(serializeEnvelope(envelope));
|
|
867
901
|
});
|
|
868
902
|
}
|
|
869
|
-
async connect() {
|
|
903
|
+
async connect(timeoutMs = this.requestTimeoutMs) {
|
|
870
904
|
if (this.socket && !this.socket.destroyed) {
|
|
871
905
|
if (this.connectPromise) await this.connectPromise;
|
|
872
906
|
return;
|
|
@@ -914,11 +948,44 @@ var SessionHostClient = class {
|
|
|
914
948
|
});
|
|
915
949
|
const connectTask = (async () => {
|
|
916
950
|
await new Promise((resolve3, reject) => {
|
|
917
|
-
|
|
951
|
+
const cleanup = () => {
|
|
952
|
+
clearTimeout(timer);
|
|
953
|
+
socket.off("connect", connected);
|
|
954
|
+
socket.off("error", failed);
|
|
955
|
+
socket.off("close", closed);
|
|
956
|
+
};
|
|
957
|
+
const connected = () => {
|
|
958
|
+
cleanup();
|
|
918
959
|
establishedSockets.add(socket);
|
|
919
960
|
resolve3();
|
|
920
|
-
}
|
|
921
|
-
|
|
961
|
+
};
|
|
962
|
+
const failed = (error) => {
|
|
963
|
+
cleanup();
|
|
964
|
+
reject(error);
|
|
965
|
+
};
|
|
966
|
+
const closed = () => failed(new Error("Session host connection closed before connect"));
|
|
967
|
+
const connectStartedAt = Date.now();
|
|
968
|
+
const connectStartedMonotonicAt = performance.now();
|
|
969
|
+
const timer = setTimeout(() => {
|
|
970
|
+
const actualElapsedMs = Math.max(0, Math.round(performance.now() - connectStartedMonotonicAt));
|
|
971
|
+
const wallElapsedMs = Math.max(0, Date.now() - connectStartedAt);
|
|
972
|
+
const observerLagMs = Math.max(0, actualElapsedMs - timeoutMs);
|
|
973
|
+
const error = Object.assign(
|
|
974
|
+
new Error(`Session host connect timed out after ${timeoutMs}ms`),
|
|
975
|
+
{
|
|
976
|
+
code: "SESSION_HOST_CONNECT_TIMEOUT",
|
|
977
|
+
scheduledTimeoutMs: timeoutMs,
|
|
978
|
+
actualElapsedMs,
|
|
979
|
+
wallElapsedMs,
|
|
980
|
+
observerLagMs
|
|
981
|
+
}
|
|
982
|
+
);
|
|
983
|
+
failed(error);
|
|
984
|
+
if (this.socket === socket) this.disconnect(error);
|
|
985
|
+
}, timeoutMs);
|
|
986
|
+
socket.once("connect", connected);
|
|
987
|
+
socket.once("error", failed);
|
|
988
|
+
socket.once("close", closed);
|
|
922
989
|
});
|
|
923
990
|
if (this.attachedSessions.size > 0 && this.socket === socket && !socket.destroyed) {
|
|
924
991
|
for (const [sessionId, sub] of [...this.attachedSessions.entries()]) {
|
|
@@ -948,11 +1015,46 @@ var SessionHostClient = class {
|
|
|
948
1015
|
this.eventListeners.delete(listener);
|
|
949
1016
|
};
|
|
950
1017
|
}
|
|
951
|
-
async request(request) {
|
|
952
|
-
|
|
1018
|
+
async request(request, options = {}) {
|
|
1019
|
+
const timeoutMs = Math.max(1, options.timeoutMs ?? this.requestTimeoutMs);
|
|
1020
|
+
const deadline = Date.now() + timeoutMs;
|
|
1021
|
+
const alreadyConnected = this.isConnected() && !this.connectPromise;
|
|
1022
|
+
if (options.timeoutMs !== void 0) {
|
|
1023
|
+
let timer;
|
|
1024
|
+
const raceStartedAt = Date.now();
|
|
1025
|
+
const raceStartedMonotonicAt = performance.now();
|
|
1026
|
+
try {
|
|
1027
|
+
await Promise.race([
|
|
1028
|
+
this.connect(timeoutMs),
|
|
1029
|
+
new Promise((_resolve, reject) => {
|
|
1030
|
+
timer = setTimeout(() => {
|
|
1031
|
+
const actualElapsedMs = Math.max(0, Math.round(performance.now() - raceStartedMonotonicAt));
|
|
1032
|
+
const wallElapsedMs = Math.max(0, Date.now() - raceStartedAt);
|
|
1033
|
+
const observerLagMs = Math.max(0, actualElapsedMs - timeoutMs);
|
|
1034
|
+
const error = Object.assign(
|
|
1035
|
+
new Error(`Session host connect timed out after ${timeoutMs}ms`),
|
|
1036
|
+
{
|
|
1037
|
+
code: "SESSION_HOST_CONNECT_TIMEOUT",
|
|
1038
|
+
scheduledTimeoutMs: timeoutMs,
|
|
1039
|
+
actualElapsedMs,
|
|
1040
|
+
wallElapsedMs,
|
|
1041
|
+
observerLagMs
|
|
1042
|
+
}
|
|
1043
|
+
);
|
|
1044
|
+
reject(error);
|
|
1045
|
+
this.disconnect(error);
|
|
1046
|
+
}, timeoutMs);
|
|
1047
|
+
})
|
|
1048
|
+
]);
|
|
1049
|
+
} finally {
|
|
1050
|
+
if (timer) clearTimeout(timer);
|
|
1051
|
+
}
|
|
1052
|
+
} else {
|
|
1053
|
+
await this.connect(timeoutMs);
|
|
1054
|
+
}
|
|
953
1055
|
const requestSocket = this.socket;
|
|
954
1056
|
if (!requestSocket) throw new Error("Session host socket unavailable");
|
|
955
|
-
const response = await this.sendRawRequestOnSocket(requestSocket, request);
|
|
1057
|
+
const response = await this.sendRawRequestOnSocket(requestSocket, request, options.timeoutMs === void 0 || alreadyConnected ? timeoutMs : Math.max(1, deadline - Date.now()));
|
|
956
1058
|
if (response.success) {
|
|
957
1059
|
if (request.type === "attach_session") {
|
|
958
1060
|
this.attachedSessions.set(request.payload.sessionId, {
|
|
@@ -1212,6 +1314,7 @@ export {
|
|
|
1212
1314
|
createSessionHostControlPlane,
|
|
1213
1315
|
disconnectSessionHostClients,
|
|
1214
1316
|
ensureNodePtySpawnHelperPermissions,
|
|
1317
|
+
findConnectedSessionHostClient,
|
|
1215
1318
|
formatRuntimeOwner,
|
|
1216
1319
|
getDefaultSessionHostEndpoint,
|
|
1217
1320
|
getSessionHostRecoveryLabel,
|