@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.
Files changed (62) hide show
  1. package/README.md +21 -1
  2. package/dist/core/PagedTerminalOutputCoordinator.js +3 -4
  3. package/dist/core/PagedTerminalOutputCoordinator.js.map +1 -1
  4. package/dist/core/TerminalCore.d.ts +3 -0
  5. package/dist/core/TerminalCore.d.ts.map +1 -1
  6. package/dist/core/TerminalCore.js +121 -35
  7. package/dist/core/TerminalCore.js.map +1 -1
  8. package/dist/core/TerminalInputBridge.d.ts +17 -7
  9. package/dist/core/TerminalInputBridge.d.ts.map +1 -1
  10. package/dist/core/TerminalInputBridge.js +78 -73
  11. package/dist/core/TerminalInputBridge.js.map +1 -1
  12. package/dist/core/TerminalOutputPipeline.js +2 -2
  13. package/dist/core/TerminalOutputPipeline.js.map +1 -1
  14. package/dist/entries/live.d.ts +7 -0
  15. package/dist/entries/live.d.ts.map +1 -0
  16. package/dist/entries/live.js +4 -0
  17. package/dist/entries/live.js.map +1 -0
  18. package/dist/fabric/BeamtermFabricRenderer.d.ts +11 -4
  19. package/dist/fabric/BeamtermFabricRenderer.d.ts.map +1 -1
  20. package/dist/fabric/BeamtermFabricRenderer.js +259 -47
  21. package/dist/fabric/BeamtermFabricRenderer.js.map +1 -1
  22. package/dist/fabric/TerminalFabricCoordinator.d.ts +1 -1
  23. package/dist/fabric/TerminalFabricCoordinator.d.ts.map +1 -1
  24. package/dist/fabric/TerminalFabricCoordinator.js +4 -7
  25. package/dist/fabric/TerminalFabricCoordinator.js.map +1 -1
  26. package/dist/fabric/TerminalLiveFabric.d.ts +3 -43
  27. package/dist/fabric/TerminalLiveFabric.d.ts.map +1 -1
  28. package/dist/fabric/TerminalLiveFabric.js +3 -97
  29. package/dist/fabric/TerminalLiveFabric.js.map +1 -1
  30. package/dist/fabric/types.d.ts +41 -3
  31. package/dist/fabric/types.d.ts.map +1 -1
  32. package/dist/index.d.ts +1 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/internal/BeamtermResourceLoader.d.ts +1 -1
  36. package/dist/internal/BeamtermResourceLoader.d.ts.map +1 -1
  37. package/dist/internal/BeamtermResourceLoader.js +1 -1
  38. package/dist/internal/BeamtermResourceLoader.js.map +1 -1
  39. package/dist/internal/SequenceBuffer.d.ts +7 -11
  40. package/dist/internal/SequenceBuffer.d.ts.map +1 -1
  41. package/dist/internal/SequenceBuffer.js +52 -103
  42. package/dist/internal/SequenceBuffer.js.map +1 -1
  43. package/dist/live/client.d.ts +62 -0
  44. package/dist/live/client.d.ts.map +1 -0
  45. package/dist/live/client.js +326 -0
  46. package/dist/live/client.js.map +1 -0
  47. package/dist/live/codec.d.ts +97 -0
  48. package/dist/live/codec.d.ts.map +1 -0
  49. package/dist/live/codec.js +386 -0
  50. package/dist/live/codec.js.map +1 -0
  51. package/dist/live/transport.d.ts +37 -0
  52. package/dist/live/transport.d.ts.map +1 -0
  53. package/dist/live/transport.js +194 -0
  54. package/dist/live/transport.js.map +1 -0
  55. package/dist/manager/TerminalInstanceController.d.ts +11 -0
  56. package/dist/manager/TerminalInstanceController.d.ts.map +1 -1
  57. package/dist/manager/TerminalInstanceController.js +265 -38
  58. package/dist/manager/TerminalInstanceController.js.map +1 -1
  59. package/dist/types.d.ts +41 -2
  60. package/dist/types.d.ts.map +1 -1
  61. package/dist/types.js.map +1 -1
  62. 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,EAIrB,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,EACnC,KAAK,uBAAuB,EAE5B,KAAK,wBAAwB,EAE7B,KAAK,sBAAsB,EAG5B,MAAM,aAAa,CAAC;AAiCrB,qBAAa,0CAA2C,YAAW,0BAA0B;IAC3F,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4B;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IAEjE,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,uBAAuB,CAA6B;IAC5D,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,mBAAmB,CAAK;IAEhC,OAAO,CAAC,YAAY,CAAgC;IACpD,OAAO,CAAC,cAAc,CAAM;IAC5B,OAAO,CAAC,eAAe,CAAyC;IAChE,OAAO,CAAC,eAAe,CAA8B;IACrD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,6BAA6B,CAAgC;IACrE,OAAO,CAAC,iBAAiB,CAA8C;IAEvE,OAAO,CAAC,KAAK,CAIX;IACF,OAAO,CAAC,UAAU,CAA0B;IAE5C,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,QAAQ,CAAS;IAEzB,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CA6CtC;gBAEU,OAAO,EAAE,uBAAuB;IAO5C,IAAI,UAAU,IAAI,4BAA4B,CAE7C;IAEK,KAAK,CAAC,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlD,OAAO,IAAI,IAAI;IAOf,OAAO,IAAI,IAAI;IAiBf,aAAa,CAAC,OAAO,EAAE,8BAA8B,GAAG,IAAI;IAsD5D,WAAW,IAAI,wBAAwB;IASvC,SAAS,CAAC,QAAQ,EAAE,wBAAwB,GAAG,MAAM,IAAI;IAQzD,OAAO,IAAI,gBAAgB,GAAG,IAAI;IAIlC,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,kBAAkB;IAK1B,OAAO,CAAC,qBAAqB;IAqB7B,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,iBAAiB,CAEvB;IAEF,OAAO,CAAC,YAAY,CAelB;IAEF,OAAO,CAAC,WAAW,CAGjB;IAEF,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,sBAAsB;IAe9B,OAAO,CAAC,oBAAoB;YAQd,gBAAgB;IA2D9B,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,mBAAmB;IA+B3B,OAAO,CAAC,kBAAkB;YAOZ,kBAAkB;YA6ElB,gBAAgB;IA+B9B,OAAO,CAAC,uBAAuB;IAe/B,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,uBAAuB;YAyDjB,YAAY;CAiB3B;AAED,eAAO,MAAM,sBAAsB,GAAI,SAAS,uBAAuB,KAAG,0BAEzE,CAAC"}
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 = 64;
19
- const MAX_WRITE_BATCH_BYTES = 256 * 1024;
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 || this.dataQueue.length === 0) {
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
- const batch = this.dataQueue.splice(0, Math.max(1, batchLength));
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.write(payload);
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
- await this.options.transport.attach(sessionId, dims.cols, dims.rows);
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
- if (payload.type === 'error') {
598
- const message = payload.error || 'Terminal stream failed';
599
- const terminalError = createTerminalError('connection', new Error(message));
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: new Error(message), state: TerminalState.ERROR });
604
- this.options.onError?.(new Error(message));
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 (payload.type === 'replay-complete') {
608
- this.replayCompleteReceived = true;
609
- const ready = this.sequenceBuffer.flushPending();
610
- if (ready.length > 0) {
611
- this.dataQueue.push(...ready);
612
- this.scheduleDataQueueFlush();
613
- }
614
- else if (typeof payload.sequence === 'number'
615
- && payload.sequence > this.lastAppliedSequence
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
- const chunk = {
625
- data: payload.data,
626
- sequence: payload.sequence ?? 0,
627
- timestampMs: payload.timestampMs ?? Date.now()
628
- };
629
- this.addChunkToQueue(chunk);
630
- }, { lastSeq });
631
- this.terminalDataUnsubscribe = unsubscribe;
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
  }