deckide 3.5.34 → 3.5.35

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.
@@ -243,6 +243,11 @@ export class AgentBrowserService {
243
243
  cdpSocket = null;
244
244
  cdpConnecting = null;
245
245
  screencastStarted = false;
246
+ // Raw JPEG bytes of the most recent screencast frame, kept so reconnecting or
247
+ // late-joining clients can be shown the current page immediately. Frames are
248
+ // pushed to clients as binary WebSocket messages (no base64) to cut ~33% size
249
+ // and avoid per-frame string allocation.
250
+ lastFrameBuffer = null;
246
251
  clients = new Set();
247
252
  viewport = { ...DEFAULT_VIEWPORT };
248
253
  pageUrl = null;
@@ -304,6 +309,7 @@ export class AgentBrowserService {
304
309
  this.pageUrl = null;
305
310
  this.pageTitle = null;
306
311
  this.screencastStarted = false;
312
+ this.lastFrameBuffer = null;
307
313
  if (proc && proc.exitCode == null && proc.signalCode == null) {
308
314
  await new Promise((resolve) => {
309
315
  const killTimer = setTimeout(() => {
@@ -438,6 +444,13 @@ export class AgentBrowserService {
438
444
  await this.start();
439
445
  await this.ensureCdp();
440
446
  await this.sendStatus(socket);
447
+ // Replay the most recent frame so a reconnecting or late-joining client
448
+ // sees the current page immediately. Screencast only emits frames on
449
+ // change, so without this a client attaching to a static page would stay
450
+ // blank until the page next repaints.
451
+ if (this.lastFrameBuffer) {
452
+ this.sendBinaryRaw(socket, this.lastFrameBuffer);
453
+ }
441
454
  if (this.clients.size > 0) {
442
455
  await this.startScreencast();
443
456
  }
@@ -660,11 +673,9 @@ export class AgentBrowserService {
660
673
  void this.cdp?.send('Page.screencastFrameAck', { sessionId }).catch(() => undefined);
661
674
  }
662
675
  if (data) {
663
- this.broadcast({
664
- type: 'frame',
665
- data,
666
- metadata: params.metadata ?? null,
667
- });
676
+ const buffer = Buffer.from(data, 'base64');
677
+ this.lastFrameBuffer = buffer;
678
+ this.broadcastBinary(buffer);
668
679
  }
669
680
  return;
670
681
  }
@@ -719,6 +730,37 @@ export class AgentBrowserService {
719
730
  send(socket, payload) {
720
731
  this.sendRaw(socket, JSON.stringify(payload));
721
732
  }
733
+ broadcastBinary(buffer) {
734
+ for (const socket of this.clients) {
735
+ this.sendBinaryRaw(socket, buffer);
736
+ }
737
+ }
738
+ sendBinaryRaw(socket, buffer) {
739
+ if (!isOpen(socket)) {
740
+ return;
741
+ }
742
+ // Drop the slow client rather than letting frames pile up in memory.
743
+ if (socket.bufferedAmount > MAX_CLIENT_BUFFERED_AMOUNT) {
744
+ try {
745
+ socket.close(1009, 'Browser stream overflow');
746
+ }
747
+ catch {
748
+ // ignore
749
+ }
750
+ return;
751
+ }
752
+ try {
753
+ socket.send(buffer, { binary: true });
754
+ }
755
+ catch {
756
+ try {
757
+ socket.close(1011, 'Browser stream send failed');
758
+ }
759
+ catch {
760
+ // ignore
761
+ }
762
+ }
763
+ }
722
764
  sendRaw(socket, payload) {
723
765
  if (!isOpen(socket)) {
724
766
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deckide",
3
- "version": "3.5.34",
3
+ "version": "3.5.35",
4
4
  "description": "Deck IDE - Browser-based IDE with terminal, file explorer, and git integration",
5
5
  "type": "module",
6
6
  "bin": {