@masons/agent-network 0.5.322 → 0.5.324
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/channel.d.ts.map +1 -1
- package/dist/channel.js +14 -1
- package/dist/conversation-manager.d.ts +2 -2
- package/dist/conversation-manager.d.ts.map +1 -1
- package/dist/conversation-manager.js +6 -6
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +5 -3
- package/dist/runtime-endpoint-client.d.ts.map +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +7 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -11
- package/skills/agent-network/SKILL.md +9 -4
- package/dist/broker/broker-daemon.d.ts +0 -71
- package/dist/broker/broker-daemon.d.ts.map +0 -1
- package/dist/broker/broker-daemon.js +0 -837
- package/dist/broker/claude-code-spawn-driver.d.ts +0 -14
- package/dist/broker/claude-code-spawn-driver.d.ts.map +0 -1
- package/dist/broker/claude-code-spawn-driver.js +0 -39
- package/dist/broker/closed-endpoint-lookup.d.ts +0 -25
- package/dist/broker/closed-endpoint-lookup.d.ts.map +0 -1
- package/dist/broker/closed-endpoint-lookup.js +0 -59
- package/dist/broker/codex-spawn-driver-stub.d.ts +0 -7
- package/dist/broker/codex-spawn-driver-stub.d.ts.map +0 -1
- package/dist/broker/codex-spawn-driver-stub.js +0 -13
- package/dist/broker/connector-ws.d.ts +0 -47
- package/dist/broker/connector-ws.d.ts.map +0 -1
- package/dist/broker/connector-ws.js +0 -60
- package/dist/broker/control-event-dispatcher.d.ts +0 -21
- package/dist/broker/control-event-dispatcher.d.ts.map +0 -1
- package/dist/broker/control-event-dispatcher.js +0 -45
- package/dist/broker/control-event-types.d.ts +0 -28
- package/dist/broker/control-event-types.d.ts.map +0 -1
- package/dist/broker/control-event-types.js +0 -1
- package/dist/broker/correlation-ring.d.ts +0 -10
- package/dist/broker/correlation-ring.d.ts.map +0 -1
- package/dist/broker/correlation-ring.js +0 -32
- package/dist/broker/discovery-file.d.ts +0 -12
- package/dist/broker/discovery-file.d.ts.map +0 -1
- package/dist/broker/discovery-file.js +0 -77
- package/dist/broker/endpoint-registry.d.ts +0 -53
- package/dist/broker/endpoint-registry.d.ts.map +0 -1
- package/dist/broker/endpoint-registry.js +0 -83
- package/dist/broker/endpoint-state-machine.d.ts +0 -40
- package/dist/broker/endpoint-state-machine.d.ts.map +0 -1
- package/dist/broker/endpoint-state-machine.js +0 -92
- package/dist/broker/entry.d.ts +0 -13
- package/dist/broker/entry.d.ts.map +0 -1
- package/dist/broker/entry.js +0 -235
- package/dist/broker/grace-timer.d.ts +0 -9
- package/dist/broker/grace-timer.d.ts.map +0 -1
- package/dist/broker/grace-timer.js +0 -34
- package/dist/broker/ipc-server.d.ts +0 -79
- package/dist/broker/ipc-server.d.ts.map +0 -1
- package/dist/broker/ipc-server.js +0 -263
- package/dist/broker/logger.d.ts +0 -10
- package/dist/broker/logger.d.ts.map +0 -1
- package/dist/broker/logger.js +0 -34
- package/dist/broker/network-presence-changed-event-types.d.ts +0 -8
- package/dist/broker/network-presence-changed-event-types.d.ts.map +0 -1
- package/dist/broker/network-presence-changed-event-types.js +0 -1
- package/dist/broker/network-presence-emitter.d.ts +0 -22
- package/dist/broker/network-presence-emitter.d.ts.map +0 -1
- package/dist/broker/network-presence-emitter.js +0 -150
- package/dist/broker/network-presence.d.ts +0 -31
- package/dist/broker/network-presence.d.ts.map +0 -1
- package/dist/broker/network-presence.js +0 -109
- package/dist/broker/paths.d.ts +0 -11
- package/dist/broker/paths.d.ts.map +0 -1
- package/dist/broker/paths.js +0 -30
- package/dist/broker/plugin-liveness.d.ts +0 -2
- package/dist/broker/plugin-liveness.d.ts.map +0 -1
- package/dist/broker/plugin-liveness.js +0 -15
- package/dist/broker/received-message-correlation-cache.d.ts +0 -23
- package/dist/broker/received-message-correlation-cache.d.ts.map +0 -1
- package/dist/broker/received-message-correlation-cache.js +0 -114
- package/dist/broker/reconnecting-buffer.d.ts +0 -23
- package/dist/broker/reconnecting-buffer.d.ts.map +0 -1
- package/dist/broker/reconnecting-buffer.js +0 -107
- package/dist/broker/routing-table.d.ts +0 -22
- package/dist/broker/routing-table.d.ts.map +0 -1
- package/dist/broker/routing-table.js +0 -35
- package/dist/broker/runtime-endpoint-port.d.ts +0 -20
- package/dist/broker/runtime-endpoint-port.d.ts.map +0 -1
- package/dist/broker/runtime-endpoint-port.js +0 -1
- package/dist/broker/services-event-client.d.ts +0 -21
- package/dist/broker/services-event-client.d.ts.map +0 -1
- package/dist/broker/services-event-client.js +0 -221
- package/dist/broker/spawn-correlation.d.ts +0 -28
- package/dist/broker/spawn-correlation.d.ts.map +0 -1
- package/dist/broker/spawn-correlation.js +0 -77
- package/dist/broker/spawn-driver.d.ts +0 -27
- package/dist/broker/spawn-driver.d.ts.map +0 -1
- package/dist/broker/spawn-driver.js +0 -15
- package/dist/broker/task-hint-handler.d.ts +0 -21
- package/dist/broker/task-hint-handler.d.ts.map +0 -1
- package/dist/broker/task-hint-handler.js +0 -33
- package/dist/broker/transition-state-retry-queue.d.ts +0 -20
- package/dist/broker/transition-state-retry-queue.d.ts.map +0 -1
- package/dist/broker/transition-state-retry-queue.js +0 -48
- package/dist/broker/undispatched-changed-event-types.d.ts +0 -29
- package/dist/broker/undispatched-changed-event-types.d.ts.map +0 -1
- package/dist/broker/undispatched-changed-event-types.js +0 -14
- package/dist/broker/undispatched-emitter.d.ts +0 -22
- package/dist/broker/undispatched-emitter.d.ts.map +0 -1
- package/dist/broker/undispatched-emitter.js +0 -149
- package/dist/broker/undispatched-inbox.d.ts +0 -26
- package/dist/broker/undispatched-inbox.d.ts.map +0 -1
- package/dist/broker/undispatched-inbox.js +0 -53
- package/dist/broker/version-handshake.d.ts +0 -30
- package/dist/broker/version-handshake.d.ts.map +0 -1
- package/dist/broker/version-handshake.js +0 -47
- package/dist/broker-client/broker-client.d.ts +0 -65
- package/dist/broker-client/broker-client.d.ts.map +0 -1
- package/dist/broker-client/broker-client.js +0 -165
- package/dist/broker-client/lazy-spawn.d.ts +0 -18
- package/dist/broker-client/lazy-spawn.d.ts.map +0 -1
- package/dist/broker-client/lazy-spawn.js +0 -61
- package/dist/session-lifecycle.d.ts +0 -89
- package/dist/session-lifecycle.d.ts.map +0 -1
- package/dist/session-lifecycle.js +0 -348
|
@@ -1,348 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session Lifecycle — manages MSTP session state per contact.
|
|
3
|
-
*
|
|
4
|
-
* State machine: idle -> creating -> active -> recreating -> failed.
|
|
5
|
-
* Internal key: MSTP address (not handle) — supports same handle on different Connectors.
|
|
6
|
-
*
|
|
7
|
-
* Responsibilities:
|
|
8
|
-
* - Maps MSTP address to session state (sessionId, status, pending promise)
|
|
9
|
-
* - Auto-creates sessions on demand via ensureSession()
|
|
10
|
-
* - Deduplicates concurrent creates (second caller awaits first's promise)
|
|
11
|
-
* - Registers inbound sessions from remote agents
|
|
12
|
-
* - Invalidates all sessions on transport disconnect
|
|
13
|
-
* - Subscribes to ConnectorClient events: session_created, session_error, session_ended, disconnected
|
|
14
|
-
*
|
|
15
|
-
* @see docs/openclaw/session-abstraction-system-design.md §6.1
|
|
16
|
-
*/
|
|
17
|
-
import createDebug from "debug";
|
|
18
|
-
const dbg = createDebug("agent-network:session-lifecycle");
|
|
19
|
-
// ---------------------------------------------------------------------------
|
|
20
|
-
// Constants
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
const SESSION_CREATE_TIMEOUT_MS = 15_000;
|
|
23
|
-
const MAX_RETRY_COUNT = 1;
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
// SessionLifecycle
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
export class SessionLifecycle {
|
|
28
|
-
client;
|
|
29
|
-
/** Primary map: MSTP address -> session state */
|
|
30
|
-
sessions = new Map();
|
|
31
|
-
/** Reverse index: sessionId -> MSTP address */
|
|
32
|
-
sessionToAddress = new Map();
|
|
33
|
-
/** Configurable timeout for tests */
|
|
34
|
-
timeoutMs = SESSION_CREATE_TIMEOUT_MS;
|
|
35
|
-
constructor(client) {
|
|
36
|
-
this.client = client;
|
|
37
|
-
this.subscribe();
|
|
38
|
-
}
|
|
39
|
-
// -------------------------------------------------------------------------
|
|
40
|
-
// Public API
|
|
41
|
-
// -------------------------------------------------------------------------
|
|
42
|
-
/**
|
|
43
|
-
* Ensure an active session exists for the given address.
|
|
44
|
-
* Returns the sessionId. Creates a new session if none exists.
|
|
45
|
-
* Concurrent callers get the same promise (dedup).
|
|
46
|
-
*/
|
|
47
|
-
ensureSession(address) {
|
|
48
|
-
const state = this.sessions.get(address);
|
|
49
|
-
// Active session — return immediately
|
|
50
|
-
if (state?.status === "active" && state.sessionId) {
|
|
51
|
-
return Promise.resolve(state.sessionId);
|
|
52
|
-
}
|
|
53
|
-
// Creating/recreating — dedup: return existing promise
|
|
54
|
-
if ((state?.status === "creating" || state?.status === "recreating") &&
|
|
55
|
-
state.createPromise) {
|
|
56
|
-
return state.createPromise;
|
|
57
|
-
}
|
|
58
|
-
// Idle, failed, or no state — create new session
|
|
59
|
-
return this.createNewSession(address, state?.retryCount ?? 0);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Get the active sessionId for an address, or null.
|
|
63
|
-
*/
|
|
64
|
-
getSession(address) {
|
|
65
|
-
const state = this.sessions.get(address);
|
|
66
|
-
if (state?.status === "active" && state.sessionId) {
|
|
67
|
-
return state.sessionId;
|
|
68
|
-
}
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Close the session for an address.
|
|
73
|
-
*/
|
|
74
|
-
closeSession(address, reason) {
|
|
75
|
-
const state = this.sessions.get(address);
|
|
76
|
-
if (!state)
|
|
77
|
-
return;
|
|
78
|
-
if (state.sessionId) {
|
|
79
|
-
this.client.endSession(state.sessionId, reason);
|
|
80
|
-
this.sessionToAddress.delete(state.sessionId);
|
|
81
|
-
}
|
|
82
|
-
// Reject any pending create promise
|
|
83
|
-
if (state.createReject) {
|
|
84
|
-
state.createReject(new Error("Session closed by caller"));
|
|
85
|
-
state.createResolve = null;
|
|
86
|
-
state.createReject = null;
|
|
87
|
-
state.createPromise = null;
|
|
88
|
-
}
|
|
89
|
-
this.sessions.delete(address);
|
|
90
|
-
dbg("closeSession address=%s", address);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Register an inbound session (remote initiated).
|
|
94
|
-
*/
|
|
95
|
-
registerInbound(sessionId, address) {
|
|
96
|
-
// If there's an existing session for this address, clean up
|
|
97
|
-
const existing = this.sessions.get(address);
|
|
98
|
-
if (existing?.sessionId && existing.sessionId !== sessionId) {
|
|
99
|
-
this.sessionToAddress.delete(existing.sessionId);
|
|
100
|
-
}
|
|
101
|
-
const state = {
|
|
102
|
-
status: "active",
|
|
103
|
-
sessionId,
|
|
104
|
-
pendingRequestId: null,
|
|
105
|
-
retryCount: 0,
|
|
106
|
-
createPromise: null,
|
|
107
|
-
createResolve: null,
|
|
108
|
-
createReject: null,
|
|
109
|
-
};
|
|
110
|
-
this.sessions.set(address, state);
|
|
111
|
-
this.sessionToAddress.set(sessionId, address);
|
|
112
|
-
dbg("registerInbound sessionId=%s address=%s", sessionId, address);
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Invalidate all sessions. Called on transport disconnect.
|
|
116
|
-
* Conversations are preserved but sessions are cleared.
|
|
117
|
-
*/
|
|
118
|
-
invalidateAll() {
|
|
119
|
-
const count = this.sessions.size;
|
|
120
|
-
for (const [address, state] of this.sessions) {
|
|
121
|
-
// Reject pending creates
|
|
122
|
-
if (state.createReject) {
|
|
123
|
-
state.createReject(new Error("Transport disconnected"));
|
|
124
|
-
state.createResolve = null;
|
|
125
|
-
state.createReject = null;
|
|
126
|
-
state.createPromise = null;
|
|
127
|
-
}
|
|
128
|
-
// Reset to idle — next send() will auto-create
|
|
129
|
-
state.status = "idle";
|
|
130
|
-
state.sessionId = null;
|
|
131
|
-
state.pendingRequestId = null;
|
|
132
|
-
state.retryCount = 0;
|
|
133
|
-
this.sessions.set(address, state);
|
|
134
|
-
}
|
|
135
|
-
this.sessionToAddress.clear();
|
|
136
|
-
dbg("invalidateAll cleared %d sessions", count);
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Reverse lookup: sessionId -> MSTP address.
|
|
140
|
-
*/
|
|
141
|
-
getAddressBySessionId(sessionId) {
|
|
142
|
-
return this.sessionToAddress.get(sessionId);
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Get all session entries (for listing conversations).
|
|
146
|
-
*/
|
|
147
|
-
listSessions() {
|
|
148
|
-
const entries = [];
|
|
149
|
-
for (const [address, state] of this.sessions) {
|
|
150
|
-
entries.push({
|
|
151
|
-
address,
|
|
152
|
-
status: state.status,
|
|
153
|
-
sessionId: state.sessionId,
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
return entries;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Remove a session entry entirely (for endConversation).
|
|
160
|
-
*/
|
|
161
|
-
removeSession(address) {
|
|
162
|
-
const state = this.sessions.get(address);
|
|
163
|
-
if (state?.sessionId) {
|
|
164
|
-
this.sessionToAddress.delete(state.sessionId);
|
|
165
|
-
}
|
|
166
|
-
if (state?.createReject) {
|
|
167
|
-
state.createReject(new Error("Session removed"));
|
|
168
|
-
state.createResolve = null;
|
|
169
|
-
state.createReject = null;
|
|
170
|
-
state.createPromise = null;
|
|
171
|
-
}
|
|
172
|
-
this.sessions.delete(address);
|
|
173
|
-
}
|
|
174
|
-
/** @internal Override timeout for tests. */
|
|
175
|
-
_setTimeoutForTesting(ms) {
|
|
176
|
-
this.timeoutMs = ms;
|
|
177
|
-
}
|
|
178
|
-
/** @internal Reset for test isolation. */
|
|
179
|
-
_resetForTesting() {
|
|
180
|
-
// Reject pending creates silently
|
|
181
|
-
for (const state of this.sessions.values()) {
|
|
182
|
-
if (state.createReject) {
|
|
183
|
-
state.createReject(new Error("Reset for testing"));
|
|
184
|
-
state.createResolve = null;
|
|
185
|
-
state.createReject = null;
|
|
186
|
-
state.createPromise = null;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
this.sessions.clear();
|
|
190
|
-
this.sessionToAddress.clear();
|
|
191
|
-
this.timeoutMs = SESSION_CREATE_TIMEOUT_MS;
|
|
192
|
-
}
|
|
193
|
-
// -------------------------------------------------------------------------
|
|
194
|
-
// Private
|
|
195
|
-
// -------------------------------------------------------------------------
|
|
196
|
-
subscribe() {
|
|
197
|
-
this.client.on("session_created", (event) => {
|
|
198
|
-
this.handleSessionCreated(event.sessionId, event.requestId, event.direction);
|
|
199
|
-
});
|
|
200
|
-
this.client.on("session_error", (sessionId, message) => {
|
|
201
|
-
this.handleSessionError(sessionId, message);
|
|
202
|
-
});
|
|
203
|
-
this.client.on("session_ended", (event) => {
|
|
204
|
-
this.handleSessionEnded(event.sessionId);
|
|
205
|
-
});
|
|
206
|
-
this.client.on("disconnected", () => {
|
|
207
|
-
this.invalidateAll();
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
createNewSession(address, previousRetryCount) {
|
|
211
|
-
const status = previousRetryCount > 0 ? "recreating" : "creating";
|
|
212
|
-
let createResolve = null;
|
|
213
|
-
let createReject = null;
|
|
214
|
-
const createPromise = new Promise((resolve, reject) => {
|
|
215
|
-
createResolve = resolve;
|
|
216
|
-
createReject = reject;
|
|
217
|
-
});
|
|
218
|
-
const { requestId, sent } = this.client.createSession(address);
|
|
219
|
-
if (!sent) {
|
|
220
|
-
const state = {
|
|
221
|
-
status: "failed",
|
|
222
|
-
sessionId: null,
|
|
223
|
-
pendingRequestId: null,
|
|
224
|
-
retryCount: previousRetryCount,
|
|
225
|
-
createPromise: null,
|
|
226
|
-
createResolve: null,
|
|
227
|
-
createReject: null,
|
|
228
|
-
};
|
|
229
|
-
this.sessions.set(address, state);
|
|
230
|
-
return Promise.reject(new Error("Failed to create session: transport unavailable"));
|
|
231
|
-
}
|
|
232
|
-
const state = {
|
|
233
|
-
status,
|
|
234
|
-
sessionId: null,
|
|
235
|
-
pendingRequestId: requestId,
|
|
236
|
-
retryCount: previousRetryCount,
|
|
237
|
-
createPromise,
|
|
238
|
-
createResolve,
|
|
239
|
-
createReject,
|
|
240
|
-
};
|
|
241
|
-
this.sessions.set(address, state);
|
|
242
|
-
// Timeout
|
|
243
|
-
const timer = setTimeout(() => {
|
|
244
|
-
const current = this.sessions.get(address);
|
|
245
|
-
if (current &&
|
|
246
|
-
current.pendingRequestId === requestId &&
|
|
247
|
-
(current.status === "creating" || current.status === "recreating")) {
|
|
248
|
-
dbg("session create timeout address=%s requestId=%s", address, requestId);
|
|
249
|
-
// Can we retry?
|
|
250
|
-
if (current.retryCount < MAX_RETRY_COUNT) {
|
|
251
|
-
// Move to failed, then retry
|
|
252
|
-
current.status = "failed";
|
|
253
|
-
current.retryCount++;
|
|
254
|
-
current.pendingRequestId = null;
|
|
255
|
-
const retryResolve = current.createResolve;
|
|
256
|
-
const retryReject = current.createReject;
|
|
257
|
-
current.createPromise = null;
|
|
258
|
-
current.createResolve = null;
|
|
259
|
-
current.createReject = null;
|
|
260
|
-
this.sessions.set(address, current);
|
|
261
|
-
// Retry: create a new session, pipe result to original promise
|
|
262
|
-
this.createNewSession(address, current.retryCount)
|
|
263
|
-
.then((sessionId) => retryResolve?.(sessionId))
|
|
264
|
-
.catch((err) => retryReject?.(err));
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
// Max retries exhausted
|
|
268
|
-
current.status = "idle";
|
|
269
|
-
current.pendingRequestId = null;
|
|
270
|
-
current.retryCount = 0;
|
|
271
|
-
if (current.createReject) {
|
|
272
|
-
current.createReject(new Error("Session creation timed out. The remote agent may be unavailable."));
|
|
273
|
-
}
|
|
274
|
-
current.createPromise = null;
|
|
275
|
-
current.createResolve = null;
|
|
276
|
-
current.createReject = null;
|
|
277
|
-
this.sessions.set(address, current);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}, this.timeoutMs);
|
|
281
|
-
// Attach cleanup to the promise to clear the timer if resolved early
|
|
282
|
-
createPromise
|
|
283
|
-
.then(() => clearTimeout(timer))
|
|
284
|
-
.catch(() => clearTimeout(timer));
|
|
285
|
-
dbg("createNewSession address=%s requestId=%s status=%s retry=%d", address, requestId, status, previousRetryCount);
|
|
286
|
-
return createPromise;
|
|
287
|
-
}
|
|
288
|
-
handleSessionCreated(sessionId, requestId, direction) {
|
|
289
|
-
// Outbound: match by requestId
|
|
290
|
-
if (direction === "outbound" && requestId) {
|
|
291
|
-
for (const [address, state] of this.sessions) {
|
|
292
|
-
if (state.pendingRequestId === requestId &&
|
|
293
|
-
(state.status === "creating" || state.status === "recreating")) {
|
|
294
|
-
state.status = "active";
|
|
295
|
-
state.sessionId = sessionId;
|
|
296
|
-
state.pendingRequestId = null;
|
|
297
|
-
this.sessionToAddress.set(sessionId, address);
|
|
298
|
-
if (state.createResolve) {
|
|
299
|
-
state.createResolve(sessionId);
|
|
300
|
-
}
|
|
301
|
-
state.createPromise = null;
|
|
302
|
-
state.createResolve = null;
|
|
303
|
-
state.createReject = null;
|
|
304
|
-
dbg("session created (outbound) address=%s sessionId=%s", address, sessionId);
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
// Inbound sessions are registered externally via registerInbound()
|
|
310
|
-
// from the channel adapter (which has the metadata to derive the address).
|
|
311
|
-
// We don't handle inbound SESSION_CREATED here.
|
|
312
|
-
}
|
|
313
|
-
handleSessionEnded(sessionId) {
|
|
314
|
-
const address = this.sessionToAddress.get(sessionId);
|
|
315
|
-
if (!address)
|
|
316
|
-
return;
|
|
317
|
-
const state = this.sessions.get(address);
|
|
318
|
-
if (!state)
|
|
319
|
-
return;
|
|
320
|
-
// Only clear if this session is the current one
|
|
321
|
-
if (state.sessionId === sessionId) {
|
|
322
|
-
state.status = "idle";
|
|
323
|
-
state.sessionId = null;
|
|
324
|
-
dbg("session ended address=%s sessionId=%s", address, sessionId);
|
|
325
|
-
}
|
|
326
|
-
this.sessionToAddress.delete(sessionId);
|
|
327
|
-
}
|
|
328
|
-
handleSessionError(sessionId, message) {
|
|
329
|
-
const address = this.sessionToAddress.get(sessionId);
|
|
330
|
-
if (!address)
|
|
331
|
-
return;
|
|
332
|
-
const state = this.sessions.get(address);
|
|
333
|
-
if (!state)
|
|
334
|
-
return;
|
|
335
|
-
dbg("session error address=%s sessionId=%s message=%s", address, sessionId, message);
|
|
336
|
-
// Session error on active session — mark for auto-recreate on next send().
|
|
337
|
-
// Reset retryCount to 0: this is a new failure context (transport error),
|
|
338
|
-
// not a continuation of a creation timeout. The next ensureSession() gets
|
|
339
|
-
// a fresh retry budget.
|
|
340
|
-
if (state.status === "active") {
|
|
341
|
-
this.sessionToAddress.delete(sessionId);
|
|
342
|
-
state.status = "idle";
|
|
343
|
-
state.sessionId = null;
|
|
344
|
-
state.retryCount = 0;
|
|
345
|
-
dbg("auto-recreate queued address=%s", address);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
}
|