@openchambery/web 1.18.4-beta.15 → 1.18.4-beta.17
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/assets/{AssistantView-8uU58vy0.js → AssistantView-DEj25qZ3.js} +1 -1
- package/dist/assets/{ChatContainer-CimpaKcn.js → ChatContainer-Coz-SS4w.js} +4 -4
- package/dist/assets/{DiagramView-euzFXO_O.js → DiagramView-CmfEFwg_.js} +1 -1
- package/dist/assets/{MarkdownRendererImpl-Dit2Ib5h.js → MarkdownRendererImpl-7Fg9WTru.js} +1 -1
- package/dist/assets/{MobileDetailNavigation-BUj1ICFS.js → MobileDetailNavigation-CI7MSgpS.js} +1 -1
- package/dist/assets/{MobileShareBridge-DFHvcf7Q.js → MobileShareBridge-BIRpFBKk.js} +1 -1
- package/dist/assets/{MobileSurface-CDowKkJL.js → MobileSurface-DRuvj5Uf.js} +1 -1
- package/dist/assets/{MultiRunWindow-CvUMhyyj.js → MultiRunWindow-C6rV7M6d.js} +1 -1
- package/dist/assets/{SettingsView-By3I3xXH.js → SettingsView-Bvqyd8l4.js} +1 -1
- package/dist/assets/{SettingsWindow-5n2DvzeP.js → SettingsWindow--7SALc4j.js} +1 -1
- package/dist/assets/{TerminalView-BmycLxLS.js → TerminalView-DPro88qD.js} +1 -1
- package/dist/assets/{ToolOutputDialog-BdhiH4i4.js → ToolOutputDialog-4gg_xtVy.js} +1 -1
- package/dist/assets/{appThemeRegistry-NoIEZNtX.js → appThemeRegistry-DXlrnRjB.js} +2 -2
- package/dist/assets/{context-menu-BOlxzatH.js → context-menu-D5N_flrS.js} +1 -1
- package/dist/assets/{gitApi-q_WNtocg.js → gitApi-BvxR62l4.js} +1 -1
- package/dist/assets/{insertionBoundaries-tokUZ60O.js → insertionBoundaries-BHxoSkD8.js} +1 -1
- package/dist/assets/{main-B5n5utaj.js → main-BppOw9K7.js} +5 -5
- package/dist/assets/{main-D08xX-l9.js → main-afWKObn5.js} +2 -2
- package/dist/assets/{miniChat-S0KGzmRO.js → miniChat-B6Ep95re.js} +2 -2
- package/dist/assets/{mobile-BBGkZDcd.js → mobile-yy3URHhc.js} +2 -2
- package/dist/assets/{multirun-CWuU0fcO.js → multirun-BvjsbaaC.js} +1 -1
- package/dist/assets/{projectMeta-BKC7h4Rl.js → projectMeta-MxbiA5TA.js} +1 -1
- package/dist/assets/{radio-BNOD9XTZ.js → radio-D_JuPpCr.js} +1 -1
- package/dist/assets/{renderElectronMiniChatApp-CNL8yc53.js → renderElectronMiniChatApp-LhlzhAmF.js} +2 -2
- package/dist/assets/{renderMobileApp-DabtxHdO.js → renderMobileApp-kldZMgOn.js} +4 -4
- package/dist/assets/{runtimeConfig-Cfrfl4hH.js → runtimeConfig-D4ipFV0f.js} +1 -1
- package/dist/assets/{runtimeEndpointReset-C1vjUBL_.js → runtimeEndpointReset-CFk9zICh.js} +3 -3
- package/dist/assets/{src-06zk77Ia.css → src-DvNTbMG0.css} +1 -1
- package/dist/assets/{useAppFontEffects-CkLk4g06.js → useAppFontEffects-CvQAqRxq.js} +2 -2
- package/dist/assets/{useDesktopWindowControlsLayout-BSeMY94L.js → useDesktopWindowControlsLayout-TBYw24zS.js} +1 -1
- package/dist/assets/{useEffectiveDirectory-CA1iNlkc.js → useEffectiveDirectory-CfZEUjlu.js} +1 -1
- package/dist/assets/useMobileNavigationStore-Dt-ih9iV.js +475 -0
- package/dist/assets/{useSessionAutoCleanup-LLUYctRd.js → useSessionAutoCleanup-mL1L8rAe.js} +1 -1
- package/dist/assets/{useWorkerHighlightedLines-dTnogsPN.js → useWorkerHighlightedLines-dsHNFaDX.js} +1 -1
- package/dist/index.html +3 -3
- package/dist/mini-chat.html +3 -3
- package/dist/mobile.html +3 -3
- package/package.json +1 -1
- package/server/lib/notifications/DOCUMENTATION.md +2 -1
- package/server/lib/notifications/emitter-runtime.js +78 -1
- package/server/lib/notifications/emitter-runtime.test.js +94 -1
- package/server/lib/scheduled-tasks/DOCUMENTATION.md +4 -1
- package/server/lib/scheduled-tasks/routes.js +51 -8
- package/server/sse-routes.test.js +64 -1
- package/dist/assets/useMobileNavigationStore-DyYYlEY1.js +0 -475
|
@@ -52,8 +52,10 @@ const createMockResponse = () => {
|
|
|
52
52
|
let body = '';
|
|
53
53
|
let flushed = false;
|
|
54
54
|
let bodyFlushCount = 0;
|
|
55
|
+
let destroyed = false;
|
|
56
|
+
let writableEnded = false;
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
const res = {
|
|
57
59
|
on(event, handler) {
|
|
58
60
|
listeners.set(event, handler);
|
|
59
61
|
return this;
|
|
@@ -80,6 +82,9 @@ const createMockResponse = () => {
|
|
|
80
82
|
body += String(chunk);
|
|
81
83
|
return true;
|
|
82
84
|
},
|
|
85
|
+
destroy() {
|
|
86
|
+
destroyed = true;
|
|
87
|
+
},
|
|
83
88
|
status(code) {
|
|
84
89
|
statusCode = code;
|
|
85
90
|
return this;
|
|
@@ -100,7 +105,21 @@ const createMockResponse = () => {
|
|
|
100
105
|
get bodyFlushCount() {
|
|
101
106
|
return bodyFlushCount;
|
|
102
107
|
},
|
|
108
|
+
get destroyed() {
|
|
109
|
+
return destroyed;
|
|
110
|
+
},
|
|
111
|
+
set destroyed(value) {
|
|
112
|
+
destroyed = Boolean(value);
|
|
113
|
+
},
|
|
114
|
+
get writableEnded() {
|
|
115
|
+
return writableEnded;
|
|
116
|
+
},
|
|
117
|
+
set writableEnded(value) {
|
|
118
|
+
writableEnded = Boolean(value);
|
|
119
|
+
},
|
|
103
120
|
};
|
|
121
|
+
|
|
122
|
+
return res;
|
|
104
123
|
};
|
|
105
124
|
|
|
106
125
|
describe('local SSE routes', () => {
|
|
@@ -162,6 +181,7 @@ describe('local SSE routes', () => {
|
|
|
162
181
|
getOpenChamberEventClients: () => clients,
|
|
163
182
|
writeSseEvent(res, payload) {
|
|
164
183
|
res.write(`data: ${JSON.stringify(payload)}\n\n`);
|
|
184
|
+
return true;
|
|
165
185
|
},
|
|
166
186
|
});
|
|
167
187
|
|
|
@@ -183,4 +203,47 @@ describe('local SSE routes', () => {
|
|
|
183
203
|
req.emit('close');
|
|
184
204
|
expect(clients.has(res)).toBe(false);
|
|
185
205
|
});
|
|
206
|
+
|
|
207
|
+
it('evicts half-open OpenChamber SSE clients after consecutive paused heartbeats', () => {
|
|
208
|
+
vi.useFakeTimers();
|
|
209
|
+
const { app, getRoute } = createRouteRegistry();
|
|
210
|
+
const clients = new Set();
|
|
211
|
+
let destroyCount = 0;
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
registerScheduledTaskRoutes(app, {
|
|
215
|
+
getOpenChamberEventClients: () => clients,
|
|
216
|
+
writeSseEvent(res) {
|
|
217
|
+
res.__ssePaused = true;
|
|
218
|
+
return false;
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const handler = getRoute('GET', '/api/openchamber/events');
|
|
223
|
+
const req = createMockRequest();
|
|
224
|
+
const res = createMockResponse();
|
|
225
|
+
res.destroy = () => {
|
|
226
|
+
destroyCount += 1;
|
|
227
|
+
res.destroyed = true;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
handler(req, res);
|
|
231
|
+
expect(clients.has(res)).toBe(true);
|
|
232
|
+
|
|
233
|
+
vi.advanceTimersByTime(25_000);
|
|
234
|
+
expect(clients.has(res)).toBe(true);
|
|
235
|
+
expect(destroyCount).toBe(0);
|
|
236
|
+
|
|
237
|
+
vi.advanceTimersByTime(25_000);
|
|
238
|
+
expect(clients.has(res)).toBe(false);
|
|
239
|
+
expect(destroyCount).toBe(1);
|
|
240
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
241
|
+
|
|
242
|
+
// Idempotent cleanup: a late close must not throw or re-destroy.
|
|
243
|
+
req.emit('close');
|
|
244
|
+
expect(destroyCount).toBe(1);
|
|
245
|
+
} finally {
|
|
246
|
+
vi.useRealTimers();
|
|
247
|
+
}
|
|
248
|
+
});
|
|
186
249
|
});
|