@lvce-editor/pty-host 8.10.0 → 8.11.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 (2) hide show
  1. package/dist/ptyHostMain.js +284 -45
  2. package/package.json +4 -2
@@ -1,5 +1,6 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import { fileURLToPath } from 'node:url';
3
+ import { Terminal } from '@xterm/headless';
3
4
  import { Console } from 'node:console';
4
5
  import { createWriteStream, readFileSync } from 'node:fs';
5
6
  import { tmpdir } from 'node:os';
@@ -1078,7 +1079,7 @@ const getErrorResponse = (id, error, preparePrettyError, logError) => {
1078
1079
  const errorProperty = getErrorProperty(error, prettyError);
1079
1080
  return create$1$1(id, errorProperty);
1080
1081
  };
1081
- const create$9 = (message, result) => {
1082
+ const create$a = (message, result) => {
1082
1083
  return {
1083
1084
  id: message.id,
1084
1085
  jsonrpc: Two$1,
@@ -1087,7 +1088,7 @@ const create$9 = (message, result) => {
1087
1088
  };
1088
1089
  const getSuccessResponse = (message, result) => {
1089
1090
  const resultProperty = result ?? null;
1090
- return create$9(message, resultProperty);
1091
+ return create$a(message, resultProperty);
1091
1092
  };
1092
1093
  const getErrorResponseSimple = (id, error) => {
1093
1094
  return {
@@ -1181,7 +1182,7 @@ const handleJsonRpcMessage = async (...args) => {
1181
1182
 
1182
1183
  const Two = '2.0';
1183
1184
 
1184
- const create$8 = (method, params) => {
1185
+ const create$9 = (method, params) => {
1185
1186
  return {
1186
1187
  jsonrpc: Two,
1187
1188
  method,
@@ -1189,7 +1190,7 @@ const create$8 = (method, params) => {
1189
1190
  };
1190
1191
  };
1191
1192
 
1192
- const create$7 = (id, method, params) => {
1193
+ const create$8 = (id, method, params) => {
1193
1194
  const message = {
1194
1195
  id,
1195
1196
  jsonrpc: Two,
@@ -1200,12 +1201,12 @@ const create$7 = (id, method, params) => {
1200
1201
  };
1201
1202
 
1202
1203
  let id = 0;
1203
- const create$6 = () => {
1204
+ const create$7 = () => {
1204
1205
  return ++id;
1205
1206
  };
1206
1207
 
1207
1208
  const registerPromise = map => {
1208
- const id = create$6();
1209
+ const id = create$7();
1209
1210
  const {
1210
1211
  promise,
1211
1212
  resolve
@@ -1222,7 +1223,7 @@ const invokeHelper = async (callbacks, ipc, method, params, useSendAndTransfer)
1222
1223
  id,
1223
1224
  promise
1224
1225
  } = registerPromise(callbacks);
1225
- const message = create$7(id, method, params);
1226
+ const message = create$8(id, method, params);
1226
1227
  if (useSendAndTransfer && ipc.sendAndTransfer) {
1227
1228
  ipc.sendAndTransfer(message);
1228
1229
  } else {
@@ -1258,7 +1259,7 @@ const createRpc = ipc => {
1258
1259
  * @deprecated
1259
1260
  */
1260
1261
  send(method, ...params) {
1261
- const message = create$8(method, params);
1262
+ const message = create$9(method, params);
1262
1263
  ipc.send(message);
1263
1264
  }
1264
1265
  };
@@ -1298,7 +1299,7 @@ const listen$2 = async (module, options) => {
1298
1299
  return ipc;
1299
1300
  };
1300
1301
 
1301
- const create$5 = async ({
1302
+ const create$6 = async ({
1302
1303
  commandMap,
1303
1304
  messagePort,
1304
1305
  requiresSocket
@@ -1318,10 +1319,10 @@ const create$5 = async ({
1318
1319
 
1319
1320
  const ElectronMessagePortRpcClient = {
1320
1321
  __proto__: null,
1321
- create: create$5
1322
+ create: create$6
1322
1323
  };
1323
1324
 
1324
- const create$4 = async ({
1325
+ const create$5 = async ({
1325
1326
  commandMap
1326
1327
  }) => {
1327
1328
  // TODO create a commandMap per rpc instance
@@ -1334,10 +1335,10 @@ const create$4 = async ({
1334
1335
 
1335
1336
  const ElectronUtilityProcessRpcClient = {
1336
1337
  __proto__: null,
1337
- create: create$4
1338
+ create: create$5
1338
1339
  };
1339
1340
 
1340
- const create$3 = async ({
1341
+ const create$4 = async ({
1341
1342
  commandMap
1342
1343
  }) => {
1343
1344
  // TODO create a commandMap per rpc instance
@@ -1350,10 +1351,10 @@ const create$3 = async ({
1350
1351
 
1351
1352
  const NodeForkedProcessRpcClient = {
1352
1353
  __proto__: null,
1353
- create: create$3
1354
+ create: create$4
1354
1355
  };
1355
1356
 
1356
- const create$2 = async ({
1357
+ const create$3 = async ({
1357
1358
  commandMap,
1358
1359
  handle,
1359
1360
  request,
@@ -1375,7 +1376,236 @@ const create$2 = async ({
1375
1376
 
1376
1377
  const NodeWebSocketRpcClient = {
1377
1378
  __proto__: null,
1378
- create: create$2
1379
+ create: create$3
1380
+ };
1381
+
1382
+ /**
1383
+ * Copyright (c) 2014-2024 The xterm.js authors. All rights reserved.
1384
+ * @license MIT
1385
+ *
1386
+ * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
1387
+ * @license MIT
1388
+ *
1389
+ * Originally forked from (with the author's permission):
1390
+ * Fabrice Bellard's javascript vt100 for jslinux:
1391
+ * http://bellard.org/jslinux/
1392
+ * Copyright (c) 2011 Fabrice Bellard
1393
+ */
1394
+ /*---------------------------------------------------------------------------------------------
1395
+ * Copyright (c) Microsoft Corporation. All rights reserved.
1396
+ * Licensed under the MIT License. See License.txt in the project root for license information.
1397
+ *--------------------------------------------------------------------------------------------*/
1398
+ var m=0,p=0,g=0,b=0;var I;(r=>{function u(t,a,s,i){return i!==void 0?`#${B(t)}${B(a)}${B(s)}${B(i)}`:`#${B(t)}${B(a)}${B(s)}`}r.toCss=u;function o(t,a,s,i=255){return (t<<24|a<<16|s<<8|i)>>>0}r.toRgba=o;function e(t,a,s,i){return {css:r.toCss(t,a,s,i),rgba:r.toRgba(t,a,s,i)}}r.toColor=e;})(I||={});var $;(i=>{function u(n,l){if(b=(l.rgba&255)/255,b===1)return {css:l.css,rgba:l.rgba};let f=l.rgba>>24&255,d=l.rgba>>16&255,c=l.rgba>>8&255,C=n.rgba>>24&255,h=n.rgba>>16&255,x=n.rgba>>8&255;m=C+Math.round((f-C)*b),p=h+Math.round((d-h)*b),g=x+Math.round((c-x)*b);let R=I.toCss(m,p,g),L=I.toRgba(m,p,g);return {css:R,rgba:L}}i.blend=u;function o(n){return (n.rgba&255)===255}i.isOpaque=o;function e(n,l,f){let d=y.ensureContrastRatio(n.rgba,l.rgba,f);if(d)return I.toColor(d>>24&255,d>>16&255,d>>8&255)}i.ensureContrastRatio=e;function r(n){let l=(n.rgba|255)>>>0;return [m,p,g]=y.toChannels(l),{css:I.toCss(m,p,g),rgba:l}}i.opaque=r;function t(n,l){return b=Math.round(l*255),[m,p,g]=y.toChannels(n.rgba),{css:I.toCss(m,p,g,b),rgba:I.toRgba(m,p,g,b)}}i.opacity=t;function a(n,l){return b=n.rgba&255,t(n,b*l/255)}i.multiplyOpacity=a;function s(n){return [n.rgba>>24&255,n.rgba>>16&255,n.rgba>>8&255]}i.toColorRGB=s;})($||={});var _;(r=>{let u,o;try{let t=document.createElement("canvas");t.width=1,t.height=1;let a=t.getContext("2d",{willReadFrequently:!0});a&&(u=a,u.globalCompositeOperation="copy",o=u.createLinearGradient(0,0,1,1));}catch{}function e(t){if(t.match(/#[\da-f]{3,8}/i))switch(t.length){case 4:return m=parseInt(t.slice(1,2).repeat(2),16),p=parseInt(t.slice(2,3).repeat(2),16),g=parseInt(t.slice(3,4).repeat(2),16),I.toColor(m,p,g);case 5:return m=parseInt(t.slice(1,2).repeat(2),16),p=parseInt(t.slice(2,3).repeat(2),16),g=parseInt(t.slice(3,4).repeat(2),16),b=parseInt(t.slice(4,5).repeat(2),16),I.toColor(m,p,g,b);case 7:return {css:t,rgba:(parseInt(t.slice(1),16)<<8|255)>>>0};case 9:return {css:t,rgba:parseInt(t.slice(1),16)>>>0}}let a=t.match(/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(,\s*(0|1|\d?\.(\d+))\s*)?\)/);if(a)return m=parseInt(a[1]),p=parseInt(a[2]),g=parseInt(a[3]),b=Math.round((a[5]===void 0?1:parseFloat(a[5]))*255),I.toColor(m,p,g,b);if(!u||!o)throw new Error("css.toColor: Unsupported css format");if(u.fillStyle=o,u.fillStyle=t,typeof u.fillStyle!="string")throw new Error("css.toColor: Unsupported css format");if(u.fillRect(0,0,1,1),[m,p,g,b]=u.getImageData(0,0,1,1).data,b!==255)throw new Error("css.toColor: Unsupported css format");return {rgba:I.toRgba(m,p,g,b),css:t}}r.toColor=e;})(_||={});var v;(e=>{function u(r){return o(r>>16&255,r>>8&255,r&255)}e.relativeLuminance=u;function o(r,t,a){let s=r/255,i=t/255,n=a/255,l=s<=.03928?s/12.92:Math.pow((s+.055)/1.055,2.4),f=i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4),d=n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4);return l*.2126+f*.7152+d*.0722}e.relativeLuminance2=o;})(v||={});var y;(a=>{function u(s,i){if(b=(i&255)/255,b===1)return i;let n=i>>24&255,l=i>>16&255,f=i>>8&255,d=s>>24&255,c=s>>16&255,C=s>>8&255;return m=d+Math.round((n-d)*b),p=c+Math.round((l-c)*b),g=C+Math.round((f-C)*b),I.toRgba(m,p,g)}a.blend=u;function o(s,i,n){let l=v.relativeLuminance(s>>8),f=v.relativeLuminance(i>>8);if(F(l,f)<n){if(f<l){let h=e(s,i,n),x=F(l,v.relativeLuminance(h>>8));if(x<n){let R=r(s,i,n),L=F(l,v.relativeLuminance(R>>8));return x>L?h:R}return h}let c=r(s,i,n),C=F(l,v.relativeLuminance(c>>8));if(C<n){let h=e(s,i,n),x=F(l,v.relativeLuminance(h>>8));return C>x?c:h}return c}}a.ensureContrastRatio=o;function e(s,i,n){let l=s>>24&255,f=s>>16&255,d=s>>8&255,c=i>>24&255,C=i>>16&255,h=i>>8&255,x=F(v.relativeLuminance2(c,C,h),v.relativeLuminance2(l,f,d));for(;x<n&&(c>0||C>0||h>0);)c-=Math.max(0,Math.ceil(c*.1)),C-=Math.max(0,Math.ceil(C*.1)),h-=Math.max(0,Math.ceil(h*.1)),x=F(v.relativeLuminance2(c,C,h),v.relativeLuminance2(l,f,d));return (c<<24|C<<16|h<<8|255)>>>0}a.reduceLuminance=e;function r(s,i,n){let l=s>>24&255,f=s>>16&255,d=s>>8&255,c=i>>24&255,C=i>>16&255,h=i>>8&255,x=F(v.relativeLuminance2(c,C,h),v.relativeLuminance2(l,f,d));for(;x<n&&(c<255||C<255||h<255);)c=Math.min(255,c+Math.ceil((255-c)*.1)),C=Math.min(255,C+Math.ceil((255-C)*.1)),h=Math.min(255,h+Math.ceil((255-h)*.1)),x=F(v.relativeLuminance2(c,C,h),v.relativeLuminance2(l,f,d));return (c<<24|C<<16|h<<8|255)>>>0}a.increaseLuminance=r;function t(s){return [s>>24&255,s>>16&255,s>>8&255,s&255]}a.toChannels=t;})(y||={});function B(u){let o=u.toString(16);return o.length<2?"0"+o:o}function F(u,o){return u<o?(o+.05)/(u+.05):(u+.05)/(o+.05)}var E=Object.freeze((()=>{let u=[_.toColor("#2e3436"),_.toColor("#cc0000"),_.toColor("#4e9a06"),_.toColor("#c4a000"),_.toColor("#3465a4"),_.toColor("#75507b"),_.toColor("#06989a"),_.toColor("#d3d7cf"),_.toColor("#555753"),_.toColor("#ef2929"),_.toColor("#8ae234"),_.toColor("#fce94f"),_.toColor("#729fcf"),_.toColor("#ad7fa8"),_.toColor("#34e2e2"),_.toColor("#eeeeec")],o=[0,95,135,175,215,255];for(let e=0;e<216;e++){let r=o[e/36%6|0],t=o[e/6%6|0],a=o[e%6];u.push({css:I.toCss(r,t,a),rgba:I.toRgba(r,t,a)});}for(let e=0;e<24;e++){let r=8+e*10;u.push({css:I.toCss(r,r,r),rgba:I.toRgba(r,r,r)});}return u})());function A(u,o,e){return Math.max(o,Math.min(u,e))}function O(u){switch(u){case "&":return "&amp;";case "<":return "&lt;"}return u}var S=class{constructor(o){this._buffer=o;}serialize(o,e){let r=this._buffer.getNullCell(),t=this._buffer.getNullCell(),a=r,s=o.start.y,i=o.end.y,n=o.start.x,l=o.end.x;this._beforeSerialize(i-s,s,i);for(let f=s;f<=i;f++){let d=this._buffer.getLine(f);if(d){let c=f===o.start.y?n:0,C=f===o.end.y?l:d.length;for(let h=c;h<C;h++){let x=d.getCell(h,a===r?t:r);if(!x){console.warn(`Can't get cell at row=${f}, col=${h}`);continue}this._nextCell(x,a,f,h),a=x;}}this._rowEnd(f,f===i);}return this._afterSerialize(),this._serializeString(e)}_nextCell(o,e,r,t){}_rowEnd(o,e){}_beforeSerialize(o,e,r){}_afterSerialize(){}_serializeString(o){return ""}};function T(u,o){return u.getFgColorMode()===o.getFgColorMode()&&u.getFgColor()===o.getFgColor()}function w(u,o){return u.getBgColorMode()===o.getBgColorMode()&&u.getBgColor()===o.getBgColor()}function z(u,o){return u.isInverse()===o.isInverse()&&u.isBold()===o.isBold()&&u.isUnderline()===o.isUnderline()&&u.isOverline()===o.isOverline()&&u.isBlink()===o.isBlink()&&u.isInvisible()===o.isInvisible()&&u.isItalic()===o.isItalic()&&u.isDim()===o.isDim()&&u.isStrikethrough()===o.isStrikethrough()}var k=class extends S{constructor(e,r){super(e);this._terminal=r;this._rowIndex=0;this._allRows=new Array;this._allRowSeparators=new Array;this._currentRow="";this._nullCellCount=0;this._cursorStyle=this._buffer.getNullCell();this._cursorStyleRow=0;this._cursorStyleCol=0;this._backgroundCell=this._buffer.getNullCell();this._firstRow=0;this._lastCursorRow=0;this._lastCursorCol=0;this._lastContentCursorRow=0;this._lastContentCursorCol=0;this._thisRowLastChar=this._buffer.getNullCell();this._thisRowLastSecondChar=this._buffer.getNullCell();this._nextRowFirstChar=this._buffer.getNullCell();}_beforeSerialize(e,r,t){this._allRows=new Array(e),this._lastContentCursorRow=r,this._lastCursorRow=r,this._firstRow=r;}_rowEnd(e,r){this._nullCellCount>0&&!w(this._cursorStyle,this._backgroundCell)&&(this._currentRow+=`\x1B[${this._nullCellCount}X`);let t="";if(!r){e-this._firstRow>=this._terminal.rows&&this._buffer.getLine(this._cursorStyleRow)?.getCell(this._cursorStyleCol,this._backgroundCell);let a=this._buffer.getLine(e),s=this._buffer.getLine(e+1);if(!s.isWrapped)t=`\r
1399
+ `,this._lastCursorRow=e+1,this._lastCursorCol=0;else {t="";let i=a.getCell(a.length-1,this._thisRowLastChar),n=a.getCell(a.length-2,this._thisRowLastSecondChar),l=s.getCell(0,this._nextRowFirstChar),f=l.getWidth()>1,d=false;(l.getChars()&&f?this._nullCellCount<=1:this._nullCellCount<=0)&&((i.getChars()||i.getWidth()===0)&&w(i,l)&&(d=true),f&&(n.getChars()||n.getWidth()===0)&&w(i,l)&&w(n,l)&&(d=true)),d||(t="-".repeat(this._nullCellCount+1),t+="\x1B[1D\x1B[1X",this._nullCellCount>0&&(t+="\x1B[A",t+=`\x1B[${a.length-this._nullCellCount}C`,t+=`\x1B[${this._nullCellCount}X`,t+=`\x1B[${a.length-this._nullCellCount}D`,t+="\x1B[B"),this._lastContentCursorRow=e+1,this._lastContentCursorCol=0,this._lastCursorRow=e+1,this._lastCursorCol=0);}}this._allRows[this._rowIndex]=this._currentRow,this._allRowSeparators[this._rowIndex++]=t,this._currentRow="",this._nullCellCount=0;}_diffStyle(e,r){let t=[],a=!T(e,r),s=!w(e,r),i=!z(e,r);if(a||s||i)if(e.isAttributeDefault())r.isAttributeDefault()||t.push(0);else {if(a){let n=e.getFgColor();e.isFgRGB()?t.push(38,2,n>>>16&255,n>>>8&255,n&255):e.isFgPalette()?n>=16?t.push(38,5,n):t.push(n&8?90+(n&7):30+(n&7)):t.push(39);}if(s){let n=e.getBgColor();e.isBgRGB()?t.push(48,2,n>>>16&255,n>>>8&255,n&255):e.isBgPalette()?n>=16?t.push(48,5,n):t.push(n&8?100+(n&7):40+(n&7)):t.push(49);}i&&(e.isInverse()!==r.isInverse()&&t.push(e.isInverse()?7:27),e.isBold()!==r.isBold()&&t.push(e.isBold()?1:22),e.isUnderline()!==r.isUnderline()&&t.push(e.isUnderline()?4:24),e.isOverline()!==r.isOverline()&&t.push(e.isOverline()?53:55),e.isBlink()!==r.isBlink()&&t.push(e.isBlink()?5:25),e.isInvisible()!==r.isInvisible()&&t.push(e.isInvisible()?8:28),e.isItalic()!==r.isItalic()&&t.push(e.isItalic()?3:23),e.isDim()!==r.isDim()&&t.push(e.isDim()?2:22),e.isStrikethrough()!==r.isStrikethrough()&&t.push(e.isStrikethrough()?9:29));}return t}_nextCell(e,r,t,a){if(e.getWidth()===0)return;let i=e.getChars()==="",n=this._diffStyle(e,this._cursorStyle);if(i?!w(this._cursorStyle,e):n.length>0){this._nullCellCount>0&&(w(this._cursorStyle,this._backgroundCell)||(this._currentRow+=`\x1B[${this._nullCellCount}X`),this._currentRow+=`\x1B[${this._nullCellCount}C`,this._nullCellCount=0),this._lastContentCursorRow=this._lastCursorRow=t,this._lastContentCursorCol=this._lastCursorCol=a,this._currentRow+=`\x1B[${n.join(";")}m`;let f=this._buffer.getLine(t);f!==void 0&&(f.getCell(a,this._cursorStyle),this._cursorStyleRow=t,this._cursorStyleCol=a);}i?this._nullCellCount+=e.getWidth():(this._nullCellCount>0&&(w(this._cursorStyle,this._backgroundCell)?this._currentRow+=`\x1B[${this._nullCellCount}C`:(this._currentRow+=`\x1B[${this._nullCellCount}X`,this._currentRow+=`\x1B[${this._nullCellCount}C`),this._nullCellCount=0),this._currentRow+=e.getChars(),this._lastContentCursorRow=this._lastCursorRow=t,this._lastContentCursorCol=this._lastCursorCol=a+e.getWidth());}_serializeString(e){let r=this._allRows.length;this._buffer.length-this._firstRow<=this._terminal.rows&&(r=this._lastContentCursorRow+1-this._firstRow,this._lastCursorCol=this._lastContentCursorCol,this._lastCursorRow=this._lastContentCursorRow);let t="";for(let i=0;i<r;i++)t+=this._allRows[i],i+1<r&&(t+=this._allRowSeparators[i]);if(!e){let i=this._buffer.baseY+this._buffer.cursorY,n=this._buffer.cursorX,l=i!==this._lastCursorRow||n!==this._lastCursorCol,f=c=>{c>0?t+=`\x1B[${c}C`:c<0&&(t+=`\x1B[${-c}D`);};l&&((c=>{c>0?t+=`\x1B[${c}B`:c<0&&(t+=`\x1B[${-c}A`);})(i-this._lastCursorRow),f(n-this._lastCursorCol));}let a=this._terminal._core._inputHandler._curAttrData,s=this._diffStyle(a,this._cursorStyle);return s.length>0&&(t+=`\x1B[${s.join(";")}m`),t}},D=class{activate(o){this._terminal=o;}_serializeBufferByScrollback(o,e,r){let t=e.length,a=r===void 0?t:A(r+o.rows,0,t);return this._serializeBufferByRange(o,e,{start:t-a,end:t-1},false)}_serializeBufferByRange(o,e,r,t){return new k(e,o).serialize({start:{x:0,y:typeof r.start=="number"?r.start:r.start.line},end:{x:o.cols,y:typeof r.end=="number"?r.end:r.end.line}},t)}_serializeBufferAsHTML(o,e){let r=o.buffer.active,t=new M(r,o,e),a=e.onlySelection??false,s=e.range;if(s)return t.serialize({start:{x:s.startCol,y:(s.startLine)},end:{x:o.cols,y:(s.endLine)}});if(!a){let n=r.length,l=e.scrollback,f=l===void 0?n:A(l+o.rows,0,n);return t.serialize({start:{x:0,y:n-f},end:{x:o.cols,y:n-1}})}let i=this._terminal?.getSelectionPosition();return i!==void 0?t.serialize({start:{x:i.start.x,y:i.start.y},end:{x:i.end.x,y:i.end.y}}):""}_serializeModes(o){let e="",r=o.modes;if(r.applicationCursorKeysMode&&(e+="\x1B[?1h"),r.applicationKeypadMode&&(e+="\x1B[?66h"),r.bracketedPasteMode&&(e+="\x1B[?2004h"),r.insertMode&&(e+="\x1B[4h"),r.originMode&&(e+="\x1B[?6h"),r.reverseWraparoundMode&&(e+="\x1B[?45h"),r.sendFocusMode&&(e+="\x1B[?1004h"),r.wraparoundMode===false&&(e+="\x1B[?7l"),r.mouseTrackingMode!=="none")switch(r.mouseTrackingMode){case "x10":e+="\x1B[?9h";break;case "vt200":e+="\x1B[?1000h";break;case "drag":e+="\x1B[?1002h";break;case "any":e+="\x1B[?1003h";break}return e}serialize(o){if(!this._terminal)throw new Error("Cannot use addon until it has been loaded");let e=o?.range?this._serializeBufferByRange(this._terminal,this._terminal.buffer.normal,o.range,true):this._serializeBufferByScrollback(this._terminal,this._terminal.buffer.normal,o?.scrollback);if(!o?.excludeAltBuffer&&this._terminal.buffer.active.type==="alternate"){let r=this._serializeBufferByScrollback(this._terminal,this._terminal.buffer.alternate,void 0);e+=`\x1B[?1049h\x1B[H${r}`;}return o?.excludeModes||(e+=this._serializeModes(this._terminal)),e}serializeAsHTML(o){if(!this._terminal)throw new Error("Cannot use addon until it has been loaded");return this._serializeBufferAsHTML(this._terminal,o||{})}dispose(){}},M=class extends S{constructor(e,r,t){super(e);this._terminal=r;this._options=t;this._currentRow="";this._htmlContent="";r._core._themeService?this._ansiColors=r._core._themeService.colors.ansi:this._ansiColors=E;}_padStart(e,r,t){return r=r>>0,t=t??" ",e.length>r?e:(r-=e.length,r>t.length&&(t+=t.repeat(r/t.length)),t.slice(0,r)+e)}_beforeSerialize(e,r,t){this._htmlContent+="<html><body><!--StartFragment--><pre>";let a="#000000",s="#ffffff";(this._options.includeGlobalBackground??false)&&(a=this._terminal.options.theme?.foreground??"#ffffff",s=this._terminal.options.theme?.background??"#000000");let i=[];i.push("color: "+a+";"),i.push("background-color: "+s+";"),i.push("font-family: "+this._terminal.options.fontFamily+";"),i.push("font-size: "+this._terminal.options.fontSize+"px;"),this._htmlContent+="<div style='"+i.join(" ")+"'>";}_afterSerialize(){this._htmlContent+="</div>",this._htmlContent+="</pre><!--EndFragment--></body></html>";}_rowEnd(e,r){this._htmlContent+="<div><span>"+this._currentRow+"</span></div>",this._currentRow="";}_getHexColor(e,r){let t=r?e.getFgColor():e.getBgColor();if(r?e.isFgRGB():e.isBgRGB())return "#"+[t>>16&255,t>>8&255,t&255].map(s=>this._padStart(s.toString(16),2,"0")).join("");if(r?e.isFgPalette():e.isBgPalette())return this._ansiColors[t].css}_diffStyle(e,r){let t=[],a=!T(e,r),s=!w(e,r),i=!z(e,r);if(a||s||i){let n=this._getHexColor(e,true);n&&t.push("color: "+n+";");let l=this._getHexColor(e,false);return l&&t.push("background-color: "+l+";"),e.isInverse()&&t.push("color: #000000; background-color: #BFBFBF;"),e.isBold()&&t.push("font-weight: bold;"),e.isUnderline()&&e.isOverline()?t.push("text-decoration: overline underline;"):e.isUnderline()?t.push("text-decoration: underline;"):e.isOverline()&&t.push("text-decoration: overline;"),e.isBlink()&&t.push("text-decoration: blink;"),e.isInvisible()&&t.push("visibility: hidden;"),e.isItalic()&&t.push("font-style: italic;"),e.isDim()&&t.push("opacity: 0.5;"),e.isStrikethrough()&&t.push("text-decoration: line-through;"),t}}_nextCell(e,r,t,a){if(e.getWidth()===0)return;let i=e.getChars()==="",n=this._diffStyle(e,r);n&&(this._currentRow+=n.length===0?"</span><span>":"</span><span style='"+n.join(" ")+"'>"),i?this._currentRow+=" ":this._currentRow+=O(e.getChars());}_serializeString(){return this._htmlContent}};
1400
+
1401
+ const connections$1 = new WeakMap();
1402
+ const set = (ipc, id, pty) => {
1403
+ let terminals = connections$1.get(ipc);
1404
+ if (!terminals) {
1405
+ terminals = new Map();
1406
+ connections$1.set(ipc, terminals);
1407
+ }
1408
+ terminals.set(id, pty);
1409
+ };
1410
+ const get = (ipc, id) => connections$1.get(ipc)?.get(id);
1411
+ const remove = (ipc, id) => {
1412
+ connections$1.get(ipc)?.delete(id);
1413
+ };
1414
+
1415
+ // Capability tokens are accepted only over a server-authenticated SSH transport.
1416
+ const authorized = new WeakSet();
1417
+ const bindings = new WeakMap();
1418
+ const sessions = new Map();
1419
+ const reconnectTimeout = 120_000;
1420
+ const maxSessions = 128;
1421
+ const authorize = ipc => {
1422
+ authorized.add(ipc);
1423
+ };
1424
+ const send = (binding, method, data) => {
1425
+ binding.ipc.send({
1426
+ jsonrpc: '2.0',
1427
+ method: 'Viewlet.send',
1428
+ params: [binding.id, method, data]
1429
+ });
1430
+ };
1431
+ const unbind = session => {
1432
+ const {
1433
+ binding
1434
+ } = session;
1435
+ if (!binding) return;
1436
+ binding.cancel?.();
1437
+ bindings.get(binding.ipc)?.delete(binding);
1438
+ if (get(binding.ipc, binding.id) === binding.terminal) remove(binding.ipc, binding.id);
1439
+ session.binding = undefined;
1440
+ };
1441
+ const cancelExpiry = session => {
1442
+ clearTimeout(session.timer);
1443
+ session.timer = undefined;
1444
+ session.released?.();
1445
+ session.released = undefined;
1446
+ };
1447
+ const destroy = (session, kill) => {
1448
+ if (session.destroyed) return;
1449
+ session.destroyed = true;
1450
+ sessions.delete(session.token);
1451
+ unbind(session);
1452
+ cancelExpiry(session);
1453
+ session.pty?.removeEventListener('data', session.onData);
1454
+ session.pty?.removeEventListener('exit', session.onExit);
1455
+ session.screen.dispose();
1456
+ if (kill) session.pty?.dispose();
1457
+ };
1458
+ const detach = session => {
1459
+ unbind(session);
1460
+ return new Promise(resolve => {
1461
+ session.released = resolve;
1462
+ session.timer = setTimeout(destroy, reconnectTimeout, session, true);
1463
+ session.timer.unref?.();
1464
+ });
1465
+ };
1466
+ const detachConnection = ipc => {
1467
+ const owned = bindings.get(ipc);
1468
+ bindings.delete(ipc);
1469
+ authorized.delete(ipc);
1470
+ if (!owned?.size) return undefined;
1471
+ return (async () => {
1472
+ await Promise.all(Array.from(owned, ({
1473
+ session
1474
+ }) => detach(session)));
1475
+ })();
1476
+ };
1477
+ const newSession = (token, createPty) => {
1478
+ const screen = new Terminal({
1479
+ allowProposedApi: true,
1480
+ cols: 80,
1481
+ rows: 24,
1482
+ scrollback: 1000
1483
+ });
1484
+ const serializer = new D();
1485
+ screen.loadAddon(serializer);
1486
+ const session = {
1487
+ destroyed: false,
1488
+ onData(event) {
1489
+ if (session.destroyed) return;
1490
+ const {
1491
+ data
1492
+ } = event;
1493
+ session.queuedBytes += data.length;
1494
+ // Stop reading from the PTY until xterm has consumed queued output.
1495
+ if (session.queuedBytes >= 65_536) session.pty.pause();
1496
+ screen.write(data, () => {
1497
+ if (session.destroyed) return;
1498
+ session.queuedBytes -= data.length;
1499
+ if (session.queuedBytes < 65_536) session.pty.resume();
1500
+ if (session.binding?.ready) send(session.binding, 'handleData', data);
1501
+ });
1502
+ },
1503
+ onExit(event) {
1504
+ // Flush output before reporting exit; detached exits are reclaimed immediately.
1505
+ screen.write('', () => {
1506
+ if (session.destroyed) return;
1507
+ if (session.binding) send(session.binding, 'handleExit', event.data);
1508
+ destroy(session, false);
1509
+ });
1510
+ },
1511
+ opening: Promise.resolve(),
1512
+ queuedBytes: 0,
1513
+ screen,
1514
+ serializer,
1515
+ token
1516
+ };
1517
+ sessions.set(token, session);
1518
+ session.opening = (async () => {
1519
+ try {
1520
+ const pty = await createPty();
1521
+ if (session.destroyed) {
1522
+ pty.dispose();
1523
+ return;
1524
+ }
1525
+ session.pty = pty;
1526
+ pty.addEventListener('data', session.onData);
1527
+ pty.addEventListener('exit', session.onExit);
1528
+ } catch (error) {
1529
+ destroy(session, false);
1530
+ throw error;
1531
+ }
1532
+ })();
1533
+ return session;
1534
+ };
1535
+ const create$2 = async (ipc, id, token, restoreOnly, createPty) => {
1536
+ if (!authorized.has(ipc)) throw new Error('Persistent terminals require an authenticated SSH connection');
1537
+ if (typeof token !== 'string' || !/^[a-f0-9]{64}$/.test(token)) throw new Error('Invalid terminal session capability');
1538
+ if (get(ipc, id)) throw new Error('Terminal id already exists');
1539
+ let session = sessions.get(token);
1540
+ if (!session) {
1541
+ if (restoreOnly) return {
1542
+ attached: false
1543
+ };
1544
+ if (sessions.size >= maxSessions) throw new Error('Too many persistent terminals');
1545
+ session = newSession(token, createPty);
1546
+ }
1547
+ const current = session;
1548
+ // Replace the old binding atomically. Old close/dispose messages no longer own it.
1549
+ unbind(current);
1550
+ cancelExpiry(current);
1551
+ const binding = {
1552
+ id,
1553
+ ipc,
1554
+ ready: false,
1555
+ session: current,
1556
+ terminal: undefined
1557
+ };
1558
+ binding.terminal = {
1559
+ dispose() {
1560
+ if (current.binding === binding) destroy(current, true);
1561
+ },
1562
+ resize(columns, rows) {
1563
+ if (!Number.isSafeInteger(columns) || !Number.isSafeInteger(rows) || columns < 2 || rows < 1 || columns > 500 || rows > 200) {
1564
+ throw new Error('Invalid persistent terminal dimensions');
1565
+ }
1566
+ if (current.binding !== binding || !binding.ready) return;
1567
+ current.screen.resize(columns, rows);
1568
+ current.pty.resize(columns, rows);
1569
+ },
1570
+ write(data) {
1571
+ if (current.binding === binding && binding.ready) current.pty.write(data);
1572
+ }
1573
+ };
1574
+ current.binding = binding;
1575
+ let owned = bindings.get(ipc);
1576
+ if (!owned) {
1577
+ owned = new Set();
1578
+ bindings.set(ipc, owned);
1579
+ }
1580
+ owned.add(binding);
1581
+ set(ipc, id, binding.terminal);
1582
+ await current.opening;
1583
+ if (current.destroyed || current.binding !== binding) return {
1584
+ attached: false
1585
+ };
1586
+ return new Promise(resolve => {
1587
+ binding.cancel = () => resolve({
1588
+ attached: false
1589
+ });
1590
+ current.screen.write('', () => {
1591
+ if (current.destroyed || current.binding !== binding) {
1592
+ resolve({
1593
+ attached: false
1594
+ });
1595
+ return;
1596
+ }
1597
+ send(binding, 'handleRestore', {
1598
+ columns: current.screen.cols,
1599
+ data: current.serializer.serialize(),
1600
+ rows: current.screen.rows
1601
+ });
1602
+ binding.cancel = undefined;
1603
+ binding.ready = true;
1604
+ resolve({
1605
+ attached: true
1606
+ });
1607
+ });
1608
+ });
1379
1609
  };
1380
1610
 
1381
1611
  class DataEvent extends Event {
@@ -1409,6 +1639,12 @@ class Pty extends EventTarget {
1409
1639
  this.pty.onData(handleData);
1410
1640
  this.pty.onExit(handleExit);
1411
1641
  }
1642
+ pause() {
1643
+ this.pty.pause();
1644
+ }
1645
+ resume() {
1646
+ this.pty.resume();
1647
+ }
1412
1648
  resize(columns, rows) {
1413
1649
  this.pty.resize(columns, rows);
1414
1650
  }
@@ -1457,28 +1693,15 @@ const create$1 = async ({
1457
1693
  }
1458
1694
  };
1459
1695
 
1460
- const connections$1 = new WeakMap();
1461
- const set = (ipc, id, pty) => {
1462
- let terminals = connections$1.get(ipc);
1463
- if (!terminals) {
1464
- terminals = new Map();
1465
- connections$1.set(ipc, terminals);
1466
- }
1467
- terminals.set(id, pty);
1468
- };
1469
- const get = (ipc, id) => connections$1.get(ipc)?.get(id);
1470
- const remove = (ipc, id) => {
1471
- connections$1.get(ipc)?.delete(id);
1472
- };
1473
-
1474
1696
  const connections = new WeakMap();
1475
1697
  const cleanup = new WeakMap();
1476
1698
  const closedConnections = new WeakSet();
1477
1699
  const disposeConnection = ipc => {
1700
+ const detached = detachConnection(ipc);
1478
1701
  closedConnections.add(ipc);
1479
1702
  const entries = connections.get(ipc);
1480
1703
  connections.delete(ipc);
1481
- if (!entries) return;
1704
+ if (!entries) return detached;
1482
1705
  for (const entry of entries) {
1483
1706
  entry.closed = true;
1484
1707
  if (entry.pty) {
@@ -1486,6 +1709,7 @@ const disposeConnection = ipc => {
1486
1709
  entry.pty.dispose();
1487
1710
  }
1488
1711
  }
1712
+ return detached;
1489
1713
  };
1490
1714
 
1491
1715
  // TODO maybe merge pty and pty controller
@@ -1553,7 +1777,19 @@ const createWithDependencies = async (ipc, id, cwd, command, args, createPty) =>
1553
1777
  });
1554
1778
  set(ipc, id, pty);
1555
1779
  };
1556
- const create = (ipc, id, cwd, command, args) => {
1780
+ const create = (ipc, id, cwd, command, args, options) => {
1781
+ if (options?.sessionToken) {
1782
+ number(id);
1783
+ string(cwd);
1784
+ string(command);
1785
+ array(args);
1786
+ if (closedConnections.has(ipc)) throw new Error('Terminal connection closed');
1787
+ return create$2(ipc, id, options.sessionToken, options.restoreOnly === true, () => create$1({
1788
+ args,
1789
+ command,
1790
+ cwd
1791
+ }));
1792
+ }
1557
1793
  return createWithDependencies(ipc, id, cwd, command, args, create$1);
1558
1794
  };
1559
1795
  const write = (ipc, id, data) => {
@@ -1597,10 +1833,9 @@ const connect = async (handle, id, create) => {
1597
1833
  if (closed) return;
1598
1834
  closed = true;
1599
1835
  handle.off('close', onClose);
1600
- try {
1601
- if (rpc) disposeConnection(rpc.ipc);
1602
- } finally {
1603
- if (id !== undefined) void release(id);
1836
+ const detached = rpc ? disposeConnection(rpc.ipc) : undefined;
1837
+ if (id !== undefined) {
1838
+ if (detached) void detached.then(() => release(id));else void release(id);
1604
1839
  }
1605
1840
  };
1606
1841
  handle.on('close', onClose);
@@ -1608,7 +1843,7 @@ const connect = async (handle, id, create) => {
1608
1843
  if (handle.destroyed) throw new Error('Terminal connection closed');
1609
1844
  rpc = await create();
1610
1845
  if (closed) {
1611
- disposeConnection(rpc.ipc);
1846
+ void disposeConnection(rpc.ipc);
1612
1847
  await rpc.dispose();
1613
1848
  }
1614
1849
  } catch (error) {
@@ -1639,10 +1874,10 @@ const handleMessagePortWithDependencies = async (messagePort, sourceRpcId, conne
1639
1874
  await connect(messagePort, connectionId, create);
1640
1875
  };
1641
1876
  const handleTerminalMessagePort = (messagePort, connectionId) => {
1642
- return handleMessagePortWithDependencies(messagePort, undefined, connectionId, create$5);
1877
+ return handleMessagePortWithDependencies(messagePort, undefined, connectionId, create$6);
1643
1878
  };
1644
1879
  const handleElectronMessagePort = (messagePort, sourceRpcId) => {
1645
- return handleMessagePortWithDependencies(messagePort, sourceRpcId, undefined, create$5);
1880
+ return handleMessagePortWithDependencies(messagePort, sourceRpcId, undefined, create$6);
1646
1881
  };
1647
1882
 
1648
1883
  const NodeWorker = 1;
@@ -1708,12 +1943,16 @@ const handleNodeMessagePort = async messagePort => {
1708
1943
  const handleWebSocket = async (handle, request, connectionId) => {
1709
1944
  object(handle);
1710
1945
  object(request);
1711
- await connect(handle, connectionId, () => create$2({
1712
- commandMap: {},
1713
- handle,
1714
- request,
1715
- requiresSocket: requiresSocket
1716
- }));
1946
+ await connect(handle, connectionId, async () => {
1947
+ const rpc = await create$3({
1948
+ commandMap: {},
1949
+ handle,
1950
+ request,
1951
+ requiresSocket: requiresSocket
1952
+ });
1953
+ if (request.remoteAuthorityAuthenticated === true) authorize(rpc.ipc);
1954
+ return rpc;
1955
+ });
1717
1956
  };
1718
1957
 
1719
1958
  const dispose = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/pty-host",
3
- "version": "8.10.0",
3
+ "version": "8.11.0",
4
4
  "keywords": [
5
5
  "lvce-editor",
6
6
  "pty-host"
@@ -15,7 +15,9 @@
15
15
  "main": "dist/ptyHostMain.js",
16
16
  "bin": "bin/ptyHost.js",
17
17
  "dependencies": {
18
- "@lvce-editor/command": "^2.0.0"
18
+ "@lvce-editor/command": "^2.0.0",
19
+ "@xterm/addon-serialize": "^0.14.0",
20
+ "@xterm/headless": "^6.0.0"
19
21
  },
20
22
  "optionalDependencies": {
21
23
  "node-pty": "1.1.0-beta34"