@floegence/floeterm-terminal-web 0.5.23 → 0.6.0
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/README.md +21 -1
- package/dist/core/PagedTerminalOutputCoordinator.js +3 -4
- package/dist/core/PagedTerminalOutputCoordinator.js.map +1 -1
- package/dist/core/TerminalCore.d.ts +3 -0
- package/dist/core/TerminalCore.d.ts.map +1 -1
- package/dist/core/TerminalCore.js +121 -35
- package/dist/core/TerminalCore.js.map +1 -1
- package/dist/core/TerminalInputBridge.d.ts +17 -7
- package/dist/core/TerminalInputBridge.d.ts.map +1 -1
- package/dist/core/TerminalInputBridge.js +78 -73
- package/dist/core/TerminalInputBridge.js.map +1 -1
- package/dist/core/TerminalOutputPipeline.js +2 -2
- package/dist/core/TerminalOutputPipeline.js.map +1 -1
- package/dist/entries/live.d.ts +7 -0
- package/dist/entries/live.d.ts.map +1 -0
- package/dist/entries/live.js +4 -0
- package/dist/entries/live.js.map +1 -0
- package/dist/fabric/BeamtermFabricRenderer.d.ts +11 -4
- package/dist/fabric/BeamtermFabricRenderer.d.ts.map +1 -1
- package/dist/fabric/BeamtermFabricRenderer.js +259 -47
- package/dist/fabric/BeamtermFabricRenderer.js.map +1 -1
- package/dist/fabric/TerminalFabricCoordinator.d.ts +1 -1
- package/dist/fabric/TerminalFabricCoordinator.d.ts.map +1 -1
- package/dist/fabric/TerminalFabricCoordinator.js +4 -7
- package/dist/fabric/TerminalFabricCoordinator.js.map +1 -1
- package/dist/fabric/TerminalLiveFabric.d.ts +3 -43
- package/dist/fabric/TerminalLiveFabric.d.ts.map +1 -1
- package/dist/fabric/TerminalLiveFabric.js +3 -97
- package/dist/fabric/TerminalLiveFabric.js.map +1 -1
- package/dist/fabric/types.d.ts +41 -3
- package/dist/fabric/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/BeamtermResourceLoader.d.ts +1 -1
- package/dist/internal/BeamtermResourceLoader.d.ts.map +1 -1
- package/dist/internal/BeamtermResourceLoader.js +1 -1
- package/dist/internal/BeamtermResourceLoader.js.map +1 -1
- package/dist/internal/SequenceBuffer.d.ts +7 -11
- package/dist/internal/SequenceBuffer.d.ts.map +1 -1
- package/dist/internal/SequenceBuffer.js +52 -103
- package/dist/internal/SequenceBuffer.js.map +1 -1
- package/dist/live/client.d.ts +62 -0
- package/dist/live/client.d.ts.map +1 -0
- package/dist/live/client.js +326 -0
- package/dist/live/client.js.map +1 -0
- package/dist/live/codec.d.ts +97 -0
- package/dist/live/codec.d.ts.map +1 -0
- package/dist/live/codec.js +386 -0
- package/dist/live/codec.js.map +1 -0
- package/dist/live/transport.d.ts +37 -0
- package/dist/live/transport.d.ts.map +1 -0
- package/dist/live/transport.js +194 -0
- package/dist/live/transport.js.map +1 -0
- package/dist/manager/TerminalInstanceController.d.ts +11 -0
- package/dist/manager/TerminalInstanceController.d.ts.map +1 -1
- package/dist/manager/TerminalInstanceController.js +265 -38
- package/dist/manager/TerminalInstanceController.js.map +1 -1
- package/dist/types.d.ts +41 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/live/transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,9 @@ export declare class FrameworkNeutralTerminalInstanceController implements Termi
|
|
|
8
8
|
private terminalCore;
|
|
9
9
|
private isInitializing;
|
|
10
10
|
private terminalDataUnsubscribe;
|
|
11
|
+
private terminalGeometryUnsubscribe;
|
|
12
|
+
private lastGeometryGeneration;
|
|
13
|
+
private pendingGeometryEvents;
|
|
11
14
|
private sequenceBuffer;
|
|
12
15
|
private replayCompleteReceived;
|
|
13
16
|
private isReplayActive;
|
|
@@ -17,6 +20,8 @@ export declare class FrameworkNeutralTerminalInstanceController implements Termi
|
|
|
17
20
|
private connectionState;
|
|
18
21
|
private connectionError;
|
|
19
22
|
private retryCount;
|
|
23
|
+
private connectGeneration;
|
|
24
|
+
private resizeGeneration;
|
|
20
25
|
private retryTimeout;
|
|
21
26
|
private initializationAbortController;
|
|
22
27
|
private queueRetryTimeout;
|
|
@@ -26,6 +31,9 @@ export declare class FrameworkNeutralTerminalInstanceController implements Termi
|
|
|
26
31
|
private isProcessing;
|
|
27
32
|
private queueGeneration;
|
|
28
33
|
private flushRaf;
|
|
34
|
+
private flushMicrotaskScheduled;
|
|
35
|
+
private flushMicrotaskGeneration;
|
|
36
|
+
private immediateFlushEligible;
|
|
29
37
|
private disposed;
|
|
30
38
|
readonly actions: TerminalManagerActions;
|
|
31
39
|
constructor(options: TerminalInstanceOptions);
|
|
@@ -59,10 +67,13 @@ export declare class FrameworkNeutralTerminalInstanceController implements Termi
|
|
|
59
67
|
private scheduleInitialize;
|
|
60
68
|
private initializeTerminal;
|
|
61
69
|
private connectToSession;
|
|
70
|
+
private recoverAtomicHistory;
|
|
62
71
|
private scheduleConnectionRetry;
|
|
63
72
|
private clearRetryTimeout;
|
|
64
73
|
private clearQueueRetryTimeout;
|
|
65
74
|
private subscribeToTerminalData;
|
|
75
|
+
private subscribeToTerminalGeometry;
|
|
76
|
+
private applyPendingGeometryEvents;
|
|
66
77
|
private reinitialize;
|
|
67
78
|
}
|
|
68
79
|
export declare const createTerminalInstance: (options: TerminalInstanceOptions) => TerminalInstanceController;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalInstanceController.d.ts","sourceRoot":"","sources":["../../src/manager/TerminalInstanceController.ts"],"names":[],"mappings":"AAMA,OAAO,EAKL,KAAK,4BAA4B,EAGjC,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"TerminalInstanceController.d.ts","sourceRoot":"","sources":["../../src/manager/TerminalInstanceController.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,8 +15,11 @@ var ConnectionState;
|
|
|
15
15
|
ConnectionState["FAILED"] = "failed";
|
|
16
16
|
ConnectionState["ABORTED"] = "aborted";
|
|
17
17
|
})(ConnectionState || (ConnectionState = {}));
|
|
18
|
-
const MAX_WRITE_BATCH_CHUNKS =
|
|
19
|
-
const MAX_WRITE_BATCH_BYTES =
|
|
18
|
+
const MAX_WRITE_BATCH_CHUNKS = 2048;
|
|
19
|
+
const MAX_WRITE_BATCH_BYTES = 512 * 1024;
|
|
20
|
+
const MAX_IMMEDIATE_LIVE_BATCH_BYTES = 256;
|
|
21
|
+
const isAtomicTransport = (transport) => (typeof transport.attachWithHistoryBoundary === 'function'
|
|
22
|
+
&& typeof transport.historyPage === 'function');
|
|
20
23
|
const createDefaultScheduler = () => ({
|
|
21
24
|
requestFrame: callback => {
|
|
22
25
|
if (typeof requestAnimationFrame === 'function') {
|
|
@@ -41,6 +44,9 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
41
44
|
this.terminalCore = null;
|
|
42
45
|
this.isInitializing = false;
|
|
43
46
|
this.terminalDataUnsubscribe = null;
|
|
47
|
+
this.terminalGeometryUnsubscribe = null;
|
|
48
|
+
this.lastGeometryGeneration = 0;
|
|
49
|
+
this.pendingGeometryEvents = [];
|
|
44
50
|
this.sequenceBuffer = new SequenceBuffer();
|
|
45
51
|
this.replayCompleteReceived = false;
|
|
46
52
|
this.isReplayActive = false;
|
|
@@ -50,6 +56,8 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
50
56
|
this.connectionState = ConnectionState.IDLE;
|
|
51
57
|
this.connectionError = null;
|
|
52
58
|
this.retryCount = 0;
|
|
59
|
+
this.connectGeneration = 0;
|
|
60
|
+
this.resizeGeneration = 0;
|
|
53
61
|
this.retryTimeout = null;
|
|
54
62
|
this.initializationAbortController = null;
|
|
55
63
|
this.queueRetryTimeout = null;
|
|
@@ -63,6 +71,9 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
63
71
|
this.isProcessing = false;
|
|
64
72
|
this.queueGeneration = 0;
|
|
65
73
|
this.flushRaf = null;
|
|
74
|
+
this.flushMicrotaskScheduled = false;
|
|
75
|
+
this.flushMicrotaskGeneration = 0;
|
|
76
|
+
this.immediateFlushEligible = false;
|
|
66
77
|
this.disposed = false;
|
|
67
78
|
this.actions = {
|
|
68
79
|
write: data => {
|
|
@@ -114,6 +125,7 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
114
125
|
this.updateState({ state: newState });
|
|
115
126
|
};
|
|
116
127
|
this.handleResize = async (size) => {
|
|
128
|
+
const resizeGeneration = this.resizeGeneration;
|
|
117
129
|
this.dimensions = size;
|
|
118
130
|
this.updateState({ dimensions: size });
|
|
119
131
|
this.options.onResize?.(size.cols, size.rows);
|
|
@@ -121,10 +133,16 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
121
133
|
if (!sessionId) {
|
|
122
134
|
return;
|
|
123
135
|
}
|
|
136
|
+
if (isAtomicTransport(this.options.transport) && this.connectionState !== ConnectionState.CONNECTED) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
124
139
|
try {
|
|
125
140
|
await this.options.transport.resize(sessionId, size.cols, size.rows);
|
|
126
141
|
}
|
|
127
142
|
catch (error) {
|
|
143
|
+
if (this.disposed || resizeGeneration !== this.resizeGeneration) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
128
146
|
this.logger.warn('[TerminalInstanceController] Resize request failed', { error });
|
|
129
147
|
}
|
|
130
148
|
};
|
|
@@ -136,6 +154,7 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
136
154
|
this.logger = options.logger ?? createConsoleLogger();
|
|
137
155
|
this.scheduler = options.scheduler ?? createDefaultScheduler();
|
|
138
156
|
this.subscribeToTerminalData();
|
|
157
|
+
this.subscribeToTerminalGeometry();
|
|
139
158
|
}
|
|
140
159
|
get connection() {
|
|
141
160
|
return computeConnectionState(this.createConnectionState());
|
|
@@ -158,6 +177,7 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
158
177
|
return;
|
|
159
178
|
}
|
|
160
179
|
this.disposed = true;
|
|
180
|
+
this.connectGeneration += 1;
|
|
161
181
|
this.initializationAbortController?.abort();
|
|
162
182
|
this.initializationAbortController = null;
|
|
163
183
|
this.clearRetryTimeout();
|
|
@@ -165,6 +185,8 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
165
185
|
this.cancelDataQueueFlush();
|
|
166
186
|
this.terminalDataUnsubscribe?.();
|
|
167
187
|
this.terminalDataUnsubscribe = null;
|
|
188
|
+
this.terminalGeometryUnsubscribe?.();
|
|
189
|
+
this.terminalGeometryUnsubscribe = null;
|
|
168
190
|
this.cleanupTerminal();
|
|
169
191
|
this.updateState({ state: TerminalState.DISPOSED });
|
|
170
192
|
this.listeners.clear();
|
|
@@ -179,6 +201,7 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
179
201
|
const previousFontSize = this.options.fontSize;
|
|
180
202
|
const previousFontFamily = this.options.config?.fontFamily;
|
|
181
203
|
const previousPresentationScale = this.options.presentationScale;
|
|
204
|
+
const previousSharedGeometry = Boolean(this.options.config?.responsive?.reportHostDimensionsWithFixedGrid);
|
|
182
205
|
this.options = {
|
|
183
206
|
...this.options,
|
|
184
207
|
...options,
|
|
@@ -187,11 +210,20 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
187
210
|
if (options.sessionId !== undefined && options.sessionId !== previousSessionId) {
|
|
188
211
|
this.resetSessionState();
|
|
189
212
|
this.subscribeToTerminalData();
|
|
213
|
+
this.subscribeToTerminalGeometry();
|
|
190
214
|
if (this.terminalCore) {
|
|
191
215
|
void this.reinitialize();
|
|
192
216
|
}
|
|
193
217
|
return;
|
|
194
218
|
}
|
|
219
|
+
const nextSharedGeometry = Boolean(this.options.config?.responsive?.reportHostDimensionsWithFixedGrid);
|
|
220
|
+
if (previousSharedGeometry !== nextSharedGeometry) {
|
|
221
|
+
this.lastGeometryGeneration = 0;
|
|
222
|
+
this.pendingGeometryEvents = [];
|
|
223
|
+
if (!nextSharedGeometry)
|
|
224
|
+
this.terminalCore?.setFixedDimensions(null);
|
|
225
|
+
this.subscribeToTerminalGeometry();
|
|
226
|
+
}
|
|
195
227
|
if (options.isActive !== undefined && options.isActive !== previousIsActive) {
|
|
196
228
|
if (this.options.isActive) {
|
|
197
229
|
this.scheduleInitialize();
|
|
@@ -269,6 +301,7 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
269
301
|
connect: () => void this.connectToSession(),
|
|
270
302
|
disconnect: () => {
|
|
271
303
|
this.clearRetryTimeout();
|
|
304
|
+
this.connectGeneration += 1;
|
|
272
305
|
this.setConnectionState(ConnectionState.ABORTED);
|
|
273
306
|
},
|
|
274
307
|
retry: () => {
|
|
@@ -283,10 +316,14 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
283
316
|
}
|
|
284
317
|
resetSessionState() {
|
|
285
318
|
this.queueGeneration += 1;
|
|
319
|
+
this.connectGeneration += 1;
|
|
286
320
|
this.sequenceBuffer.reset(1);
|
|
287
321
|
this.replayCompleteReceived = false;
|
|
288
322
|
this.isReplayActive = false;
|
|
289
323
|
this.lastAppliedSequence = 0;
|
|
324
|
+
this.lastGeometryGeneration = 0;
|
|
325
|
+
this.pendingGeometryEvents = [];
|
|
326
|
+
this.terminalCore?.setFixedDimensions(null);
|
|
290
327
|
this.dataQueue = [];
|
|
291
328
|
this.isProcessing = false;
|
|
292
329
|
this.cancelDataQueueFlush();
|
|
@@ -303,6 +340,7 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
303
340
|
}
|
|
304
341
|
this.options.transport.sendInput(sessionId, data).catch(error => {
|
|
305
342
|
this.logger.warn('[TerminalInstanceController] sendInput failed', { error });
|
|
343
|
+
this.handleError(error instanceof Error ? error : new Error(String(error)));
|
|
306
344
|
});
|
|
307
345
|
}
|
|
308
346
|
scheduleFocus() {
|
|
@@ -316,6 +354,7 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
316
354
|
});
|
|
317
355
|
}
|
|
318
356
|
cleanupTerminal() {
|
|
357
|
+
this.resizeGeneration += 1;
|
|
319
358
|
this.initializationAbortController?.abort();
|
|
320
359
|
this.initializationAbortController = null;
|
|
321
360
|
this.isInitializing = false;
|
|
@@ -337,10 +376,12 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
337
376
|
this.setLoading('ready', '');
|
|
338
377
|
this.scheduleFocus();
|
|
339
378
|
}
|
|
340
|
-
scheduleDataQueueFlush() {
|
|
379
|
+
scheduleDataQueueFlush(allowImmediate = false) {
|
|
341
380
|
if (this.flushRaf !== null) {
|
|
381
|
+
this.immediateFlushEligible = false;
|
|
342
382
|
return;
|
|
343
383
|
}
|
|
384
|
+
this.immediateFlushEligible = allowImmediate;
|
|
344
385
|
const generation = this.queueGeneration;
|
|
345
386
|
this.flushRaf = this.scheduler.requestFrame(() => {
|
|
346
387
|
this.flushRaf = null;
|
|
@@ -349,8 +390,32 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
349
390
|
}
|
|
350
391
|
void this.processDataQueue();
|
|
351
392
|
});
|
|
393
|
+
if (!allowImmediate || this.isReplayActive || this.flushMicrotaskScheduled) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
this.flushMicrotaskScheduled = true;
|
|
397
|
+
const microtaskGeneration = ++this.flushMicrotaskGeneration;
|
|
398
|
+
queueMicrotask(() => {
|
|
399
|
+
if (microtaskGeneration !== this.flushMicrotaskGeneration) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
this.flushMicrotaskScheduled = false;
|
|
403
|
+
if (this.disposed || this.queueGeneration !== generation || this.isReplayActive || this.isProcessing) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (!this.immediateFlushEligible
|
|
407
|
+
|| this.dataQueue.length !== 1
|
|
408
|
+
|| this.dataQueue[0].data.byteLength > MAX_IMMEDIATE_LIVE_BATCH_BYTES) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
this.cancelDataQueueFlush();
|
|
412
|
+
void this.processDataQueue();
|
|
413
|
+
});
|
|
352
414
|
}
|
|
353
415
|
cancelDataQueueFlush() {
|
|
416
|
+
this.immediateFlushEligible = false;
|
|
417
|
+
this.flushMicrotaskScheduled = false;
|
|
418
|
+
this.flushMicrotaskGeneration += 1;
|
|
354
419
|
if (this.flushRaf === null) {
|
|
355
420
|
return;
|
|
356
421
|
}
|
|
@@ -359,9 +424,12 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
359
424
|
}
|
|
360
425
|
async processDataQueue() {
|
|
361
426
|
const generation = this.queueGeneration;
|
|
362
|
-
if (this.isProcessing || !this.terminalCore
|
|
427
|
+
if (this.isProcessing || !this.terminalCore) {
|
|
363
428
|
return;
|
|
364
429
|
}
|
|
430
|
+
this.applyPendingGeometryEvents();
|
|
431
|
+
if (this.dataQueue.length === 0)
|
|
432
|
+
return;
|
|
365
433
|
const terminalState = this.terminalCore.getState();
|
|
366
434
|
if (terminalState !== TerminalState.READY && terminalState !== TerminalState.CONNECTED) {
|
|
367
435
|
this.clearQueueRetryTimeout();
|
|
@@ -378,22 +446,31 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
378
446
|
try {
|
|
379
447
|
let batchLength = 0;
|
|
380
448
|
let batchBytes = 0;
|
|
449
|
+
const geometryBoundary = this.pendingGeometryEvents[0]?.outputSequenceBoundary;
|
|
381
450
|
for (const chunk of this.dataQueue) {
|
|
382
451
|
if (batchLength >= MAX_WRITE_BATCH_CHUNKS) {
|
|
383
452
|
break;
|
|
384
453
|
}
|
|
454
|
+
if (geometryBoundary !== undefined
|
|
455
|
+
&& chunk.sequence > 0
|
|
456
|
+
&& chunk.sequence > geometryBoundary) {
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
385
459
|
if (batchLength > 0 && batchBytes + chunk.data.byteLength > MAX_WRITE_BATCH_BYTES) {
|
|
386
460
|
break;
|
|
387
461
|
}
|
|
388
462
|
batchLength += 1;
|
|
389
463
|
batchBytes += chunk.data.byteLength;
|
|
390
464
|
}
|
|
391
|
-
|
|
465
|
+
if (batchLength === 0) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
const batch = this.dataQueue.splice(0, batchLength);
|
|
392
469
|
if (this.queueGeneration !== generation) {
|
|
393
470
|
return;
|
|
394
471
|
}
|
|
395
472
|
const payload = batch.length === 1 ? batch[0].data : concatChunks(batch.map(chunk => chunk.data));
|
|
396
|
-
this.terminalCore.
|
|
473
|
+
this.terminalCore.writeFrame(payload);
|
|
397
474
|
for (const chunk of batch) {
|
|
398
475
|
if (this.queueGeneration !== generation) {
|
|
399
476
|
return;
|
|
@@ -402,6 +479,7 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
402
479
|
this.lastAppliedSequence = chunk.sequence;
|
|
403
480
|
}
|
|
404
481
|
}
|
|
482
|
+
this.applyPendingGeometryEvents();
|
|
405
483
|
}
|
|
406
484
|
finally {
|
|
407
485
|
this.isProcessing = false;
|
|
@@ -413,7 +491,7 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
413
491
|
}
|
|
414
492
|
}
|
|
415
493
|
}
|
|
416
|
-
addChunkToQueue(chunk) {
|
|
494
|
+
addChunkToQueue(chunk, allowImmediate = false) {
|
|
417
495
|
if (chunk.sequence > 0 && chunk.sequence <= this.lastAppliedSequence) {
|
|
418
496
|
return;
|
|
419
497
|
}
|
|
@@ -421,9 +499,10 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
421
499
|
if (ready.length === 0) {
|
|
422
500
|
return;
|
|
423
501
|
}
|
|
502
|
+
const queueWasEmpty = this.dataQueue.length === 0;
|
|
424
503
|
this.dataQueue.push(...ready);
|
|
425
504
|
if (!this.isProcessing) {
|
|
426
|
-
this.scheduleDataQueueFlush();
|
|
505
|
+
this.scheduleDataQueueFlush(queueWasEmpty && ready.length === 1 && allowImmediate);
|
|
427
506
|
}
|
|
428
507
|
}
|
|
429
508
|
applyCoreAppearance(appearance) {
|
|
@@ -481,7 +560,8 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
481
560
|
onData: data => this.handleUserInput(data),
|
|
482
561
|
onResize: size => void this.handleResize(size),
|
|
483
562
|
onStateChange: this.handleStateChange,
|
|
484
|
-
onError: this.handleError
|
|
563
|
+
onError: this.handleError,
|
|
564
|
+
onRender: durationMs => this.options.onRender?.(durationMs),
|
|
485
565
|
}, this.logger ?? noopLogger);
|
|
486
566
|
this.terminalCore = terminalCore;
|
|
487
567
|
await terminalCore.initialize({ priority: 'interactive', signal: abortController.signal });
|
|
@@ -495,7 +575,7 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
495
575
|
terminalCore.startHistoryReplay(30000);
|
|
496
576
|
}
|
|
497
577
|
const sessionId = this.options.sessionId;
|
|
498
|
-
if (sessionId) {
|
|
578
|
+
if (sessionId && !isAtomicTransport(this.options.transport)) {
|
|
499
579
|
const dimensions = terminalCore.getDimensions();
|
|
500
580
|
await this.options.transport.resize(sessionId, dimensions.cols, dimensions.rows);
|
|
501
581
|
}
|
|
@@ -533,9 +613,20 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
533
613
|
this.setConnectionState(ConnectionState.CONNECTING);
|
|
534
614
|
this.setConnectionError(null);
|
|
535
615
|
this.setLoading('attaching', 'Attaching to session...');
|
|
616
|
+
const connectGeneration = ++this.connectGeneration;
|
|
536
617
|
try {
|
|
537
618
|
const dims = this.terminalCore?.getDimensions() ?? this.dimensions;
|
|
538
|
-
|
|
619
|
+
if (isAtomicTransport(this.options.transport)) {
|
|
620
|
+
const attached = await this.options.transport.attachWithHistoryBoundary(sessionId, dims.cols, dims.rows);
|
|
621
|
+
if (connectGeneration !== this.connectGeneration || this.disposed)
|
|
622
|
+
return;
|
|
623
|
+
await this.recoverAtomicHistory(sessionId, attached);
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
await this.options.transport.attach(sessionId, dims.cols, dims.rows);
|
|
627
|
+
}
|
|
628
|
+
if (connectGeneration !== this.connectGeneration || this.disposed)
|
|
629
|
+
return;
|
|
539
630
|
this.setConnectionState(ConnectionState.CONNECTED);
|
|
540
631
|
this.retryCount = 0;
|
|
541
632
|
this.emit();
|
|
@@ -547,6 +638,8 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
547
638
|
}
|
|
548
639
|
}
|
|
549
640
|
catch (error) {
|
|
641
|
+
if (connectGeneration !== this.connectGeneration || this.disposed)
|
|
642
|
+
return;
|
|
550
643
|
const terminalError = createTerminalError('transport', error);
|
|
551
644
|
this.setConnectionState(ConnectionState.FAILED);
|
|
552
645
|
this.setConnectionError(terminalError);
|
|
@@ -554,6 +647,85 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
554
647
|
this.scheduleConnectionRetry();
|
|
555
648
|
}
|
|
556
649
|
}
|
|
650
|
+
async recoverAtomicHistory(sessionId, attachment) {
|
|
651
|
+
const boundary = attachment.historyBoundarySequence;
|
|
652
|
+
const historyGeneration = attachment.historyGeneration;
|
|
653
|
+
const historyStartSequence = attachment.historyStartSequence;
|
|
654
|
+
if (!Number.isSafeInteger(boundary) || boundary < 0) {
|
|
655
|
+
throw new Error('terminal live history boundary is invalid');
|
|
656
|
+
}
|
|
657
|
+
if (!Number.isSafeInteger(historyGeneration) || historyGeneration < 1) {
|
|
658
|
+
throw new Error('terminal live history generation is invalid');
|
|
659
|
+
}
|
|
660
|
+
if (!Number.isSafeInteger(historyStartSequence)
|
|
661
|
+
|| historyStartSequence < 1
|
|
662
|
+
|| historyStartSequence > boundary + 1) {
|
|
663
|
+
throw new Error('terminal live history start sequence is invalid');
|
|
664
|
+
}
|
|
665
|
+
if (!isAtomicTransport(this.options.transport)) {
|
|
666
|
+
throw new Error('terminal atomic history page transport is required');
|
|
667
|
+
}
|
|
668
|
+
this.lastAppliedSequence = Math.max(this.lastAppliedSequence, historyStartSequence - 1);
|
|
669
|
+
this.applyPendingGeometryEvents();
|
|
670
|
+
let queuedHistoryOutput = false;
|
|
671
|
+
let startSequence = Math.max(this.lastAppliedSequence + 1, historyStartSequence);
|
|
672
|
+
while (startSequence <= boundary) {
|
|
673
|
+
const page = await this.options.transport.historyPage(sessionId, startSequence, boundary, historyGeneration);
|
|
674
|
+
if (page.historyGeneration !== historyGeneration || page.historyReset) {
|
|
675
|
+
throw new Error('terminal history generation changed during atomic replay');
|
|
676
|
+
}
|
|
677
|
+
if (page.snapshotEndSequence !== boundary) {
|
|
678
|
+
throw new Error('terminal history snapshot boundary does not match live attachment');
|
|
679
|
+
}
|
|
680
|
+
if (page.historyTruncated) {
|
|
681
|
+
throw new Error('terminal history was truncated before the acknowledged live boundary');
|
|
682
|
+
}
|
|
683
|
+
if (!Number.isSafeInteger(page.coveredThroughSequence)
|
|
684
|
+
|| page.coveredThroughSequence < startSequence - 1
|
|
685
|
+
|| page.coveredThroughSequence > boundary) {
|
|
686
|
+
throw new Error('terminal history page coverage is invalid');
|
|
687
|
+
}
|
|
688
|
+
let expectedSequence = startSequence;
|
|
689
|
+
for (const chunk of page.chunks) {
|
|
690
|
+
if (!Number.isSafeInteger(chunk.sequence) || chunk.sequence !== expectedSequence) {
|
|
691
|
+
throw new Error(`missing terminal output sequence ${expectedSequence} before replay boundary ${boundary}`);
|
|
692
|
+
}
|
|
693
|
+
if (chunk.sequence > page.coveredThroughSequence) {
|
|
694
|
+
throw new Error('terminal history chunk exceeded its page coverage');
|
|
695
|
+
}
|
|
696
|
+
this.addChunkToQueue(chunk);
|
|
697
|
+
queuedHistoryOutput = true;
|
|
698
|
+
expectedSequence += 1;
|
|
699
|
+
}
|
|
700
|
+
const explicitlyCleared = page.chunks.length === 0 && page.totalBytes === 0;
|
|
701
|
+
if (page.coveredThroughSequence >= expectedSequence && !explicitlyCleared) {
|
|
702
|
+
throw new Error(`missing terminal output sequence ${expectedSequence} before replay boundary ${boundary}`);
|
|
703
|
+
}
|
|
704
|
+
if (!page.hasMore) {
|
|
705
|
+
if (page.coveredThroughSequence !== boundary) {
|
|
706
|
+
throw new Error('terminal history did not cover the acknowledged live boundary');
|
|
707
|
+
}
|
|
708
|
+
startSequence = boundary + 1;
|
|
709
|
+
break;
|
|
710
|
+
}
|
|
711
|
+
if (!Number.isSafeInteger(page.nextStartSequence)
|
|
712
|
+
|| page.nextStartSequence !== page.coveredThroughSequence + 1) {
|
|
713
|
+
throw new Error('terminal history page cursor is invalid');
|
|
714
|
+
}
|
|
715
|
+
startSequence = page.nextStartSequence;
|
|
716
|
+
}
|
|
717
|
+
const ready = this.sequenceBuffer.coverThrough(boundary);
|
|
718
|
+
if (ready.length > 0) {
|
|
719
|
+
this.dataQueue.push(...ready);
|
|
720
|
+
this.scheduleDataQueueFlush();
|
|
721
|
+
}
|
|
722
|
+
if (!queuedHistoryOutput) {
|
|
723
|
+
this.lastAppliedSequence = Math.max(this.lastAppliedSequence, boundary);
|
|
724
|
+
this.applyPendingGeometryEvents();
|
|
725
|
+
}
|
|
726
|
+
this.replayCompleteReceived = true;
|
|
727
|
+
this.finishReplayIfIdle();
|
|
728
|
+
}
|
|
557
729
|
scheduleConnectionRetry() {
|
|
558
730
|
if (this.connectionState !== ConnectionState.FAILED || this.disposed) {
|
|
559
731
|
return;
|
|
@@ -594,41 +766,93 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
594
766
|
this.setLoading('processing_history', 'Restoring terminal...');
|
|
595
767
|
const lastSeq = this.terminalCore ? this.lastAppliedSequence : 0;
|
|
596
768
|
const unsubscribe = this.options.eventSource.onTerminalData(sessionId, (payload) => {
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
769
|
+
try {
|
|
770
|
+
if (payload.type === 'error') {
|
|
771
|
+
throw new Error(payload.error || 'Terminal stream failed');
|
|
772
|
+
}
|
|
773
|
+
if (payload.type === 'replay-complete') {
|
|
774
|
+
const boundary = payload.sequence ?? this.lastAppliedSequence;
|
|
775
|
+
this.sequenceBuffer.assertCoveredThrough(boundary);
|
|
776
|
+
this.replayCompleteReceived = true;
|
|
777
|
+
const ready = this.sequenceBuffer.flushPending();
|
|
778
|
+
if (ready.length > 0) {
|
|
779
|
+
this.dataQueue.push(...ready);
|
|
780
|
+
this.scheduleDataQueueFlush();
|
|
781
|
+
}
|
|
782
|
+
this.finishReplayIfIdle();
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
const chunk = {
|
|
786
|
+
data: payload.data,
|
|
787
|
+
sequence: payload.sequence ?? 0,
|
|
788
|
+
timestampMs: payload.timestampMs ?? Date.now()
|
|
789
|
+
};
|
|
790
|
+
this.addChunkToQueue(chunk, payload.liveBatchSize === 1);
|
|
791
|
+
}
|
|
792
|
+
catch (value) {
|
|
793
|
+
const error = value instanceof Error ? value : new Error(String(value));
|
|
794
|
+
const terminalError = createTerminalError('connection', error);
|
|
600
795
|
this.setConnectionState(ConnectionState.FAILED);
|
|
601
796
|
this.setConnectionError(terminalError);
|
|
602
797
|
this.setLoading('ready', '');
|
|
603
|
-
this.updateState({ error
|
|
604
|
-
this.options.onError?.(
|
|
798
|
+
this.updateState({ error, state: TerminalState.ERROR });
|
|
799
|
+
this.options.onError?.(error);
|
|
800
|
+
this.scheduleConnectionRetry();
|
|
801
|
+
}
|
|
802
|
+
}, { lastSeq });
|
|
803
|
+
this.terminalDataUnsubscribe = unsubscribe;
|
|
804
|
+
}
|
|
805
|
+
subscribeToTerminalGeometry() {
|
|
806
|
+
this.terminalGeometryUnsubscribe?.();
|
|
807
|
+
this.terminalGeometryUnsubscribe = null;
|
|
808
|
+
if (!this.options.config?.responsive?.reportHostDimensionsWithFixedGrid) {
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
const sessionId = this.options.sessionId;
|
|
812
|
+
const subscribe = this.options.eventSource.onTerminalGeometry;
|
|
813
|
+
if (!sessionId || !subscribe) {
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
this.terminalGeometryUnsubscribe = subscribe(sessionId, (event) => {
|
|
817
|
+
if (!Number.isSafeInteger(event.generation) || event.generation <= 0 ||
|
|
818
|
+
!Number.isSafeInteger(event.outputSequenceBoundary) || event.outputSequenceBoundary < 0 ||
|
|
819
|
+
!Number.isSafeInteger(event.cols) || event.cols <= 0 ||
|
|
820
|
+
!Number.isSafeInteger(event.rows) || event.rows <= 0) {
|
|
821
|
+
this.handleError(new Error('terminal live geometry is invalid'));
|
|
605
822
|
return;
|
|
606
823
|
}
|
|
607
|
-
if (
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
&& this.dataQueue.length === 0
|
|
617
|
-
&& !this.isProcessing) {
|
|
618
|
-
this.lastAppliedSequence = payload.sequence;
|
|
619
|
-
this.sequenceBuffer.reset(payload.sequence + 1);
|
|
824
|
+
if (event.generation <= this.lastGeometryGeneration) {
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
const duplicate = this.pendingGeometryEvents.find(pending => pending.generation === event.generation);
|
|
828
|
+
if (duplicate) {
|
|
829
|
+
if (duplicate.outputSequenceBoundary !== event.outputSequenceBoundary
|
|
830
|
+
|| duplicate.cols !== event.cols
|
|
831
|
+
|| duplicate.rows !== event.rows) {
|
|
832
|
+
this.handleError(new Error('terminal live geometry generation is inconsistent'));
|
|
620
833
|
}
|
|
621
|
-
this.finishReplayIfIdle();
|
|
622
834
|
return;
|
|
623
835
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
836
|
+
this.pendingGeometryEvents.push(event);
|
|
837
|
+
this.pendingGeometryEvents.sort((left, right) => left.generation - right.generation);
|
|
838
|
+
this.applyPendingGeometryEvents();
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
applyPendingGeometryEvents() {
|
|
842
|
+
if (!this.terminalCore)
|
|
843
|
+
return;
|
|
844
|
+
while (this.pendingGeometryEvents.length > 0) {
|
|
845
|
+
const event = this.pendingGeometryEvents[0];
|
|
846
|
+
if (event.generation <= this.lastGeometryGeneration) {
|
|
847
|
+
this.pendingGeometryEvents.shift();
|
|
848
|
+
continue;
|
|
849
|
+
}
|
|
850
|
+
if (event.outputSequenceBoundary > this.lastAppliedSequence)
|
|
851
|
+
return;
|
|
852
|
+
this.pendingGeometryEvents.shift();
|
|
853
|
+
this.lastGeometryGeneration = event.generation;
|
|
854
|
+
this.terminalCore.setFixedDimensions({ cols: event.cols, rows: event.rows });
|
|
855
|
+
}
|
|
632
856
|
}
|
|
633
857
|
async reinitialize() {
|
|
634
858
|
this.terminalDataUnsubscribe?.();
|
|
@@ -638,6 +862,8 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
638
862
|
this.replayCompleteReceived = false;
|
|
639
863
|
this.isReplayActive = true;
|
|
640
864
|
this.lastAppliedSequence = 0;
|
|
865
|
+
this.lastGeometryGeneration = 0;
|
|
866
|
+
this.pendingGeometryEvents = [];
|
|
641
867
|
this.dataQueue = [];
|
|
642
868
|
this.isProcessing = false;
|
|
643
869
|
this.cancelDataQueueFlush();
|
|
@@ -645,6 +871,7 @@ export class FrameworkNeutralTerminalInstanceController {
|
|
|
645
871
|
this.setLoading('processing_history', 'Restoring terminal...');
|
|
646
872
|
this.cleanupTerminal();
|
|
647
873
|
this.subscribeToTerminalData();
|
|
874
|
+
this.subscribeToTerminalGeometry();
|
|
648
875
|
await this.initializeTerminal();
|
|
649
876
|
}
|
|
650
877
|
}
|