airloom 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1111,21 +1111,57 @@ function getTerminalLaunchDisplay(explicitCommand) {
1111
1111
  const command = getDefaultTerminalCommand(explicitCommand);
1112
1112
  return [command.file, ...command.args].join(" ");
1113
1113
  }
1114
+ var MAX_BUFFER_BYTES = 512 * 1024;
1114
1115
  var TerminalSession = class {
1115
1116
  constructor(channel, getLaunchCommand, broadcastFn) {
1116
1117
  this.channel = channel;
1117
1118
  this.getLaunchCommand = getLaunchCommand;
1118
1119
  this.broadcastFn = broadcastFn;
1120
+ this.start();
1119
1121
  }
1120
1122
  pty = null;
1121
1123
  stream = null;
1122
1124
  batcher = null;
1123
1125
  cols = 120;
1124
1126
  rows = 36;
1127
+ outputBuffer = "";
1128
+ start() {
1129
+ const command = getDefaultTerminalCommand(this.getLaunchCommand?.());
1130
+ const file = resolveExecutable2(command.file) ?? command.file;
1131
+ console.log(`[host] PTY spawn: ${file} ${command.args.join(" ")} (${this.cols}x${this.rows})`);
1132
+ const env = { ...process.env, TERM: "xterm-256color" };
1133
+ try {
1134
+ this.pty = spawn2(file, command.args, {
1135
+ name: "xterm-256color",
1136
+ cols: this.cols,
1137
+ rows: this.rows,
1138
+ cwd: process.cwd(),
1139
+ env
1140
+ });
1141
+ } catch (err) {
1142
+ console.error("[host] PTY spawn failed:", err.message);
1143
+ return;
1144
+ }
1145
+ this.pty.onData((data) => {
1146
+ process.stdout.write(data);
1147
+ this.outputBuffer += data;
1148
+ if (this.outputBuffer.length > MAX_BUFFER_BYTES) {
1149
+ this.outputBuffer = this.outputBuffer.slice(this.outputBuffer.length - MAX_BUFFER_BYTES);
1150
+ }
1151
+ this.batcher?.write(data);
1152
+ this.broadcastFn?.({ type: "terminal_output", data });
1153
+ });
1154
+ this.pty.onExit(({ exitCode, signal }) => {
1155
+ this.batcher?.flush();
1156
+ this.detachStream();
1157
+ this.channel.send({ type: "terminal_exit", exitCode, signal });
1158
+ this.pty = null;
1159
+ });
1160
+ }
1125
1161
  handleMessage(message) {
1126
1162
  switch (message.type) {
1127
1163
  case "terminal_open":
1128
- this.open(message);
1164
+ this.attach(message);
1129
1165
  break;
1130
1166
  case "terminal_input":
1131
1167
  this.writeInput(message);
@@ -1134,66 +1170,45 @@ var TerminalSession = class {
1134
1170
  this.resize(message);
1135
1171
  break;
1136
1172
  case "terminal_close":
1137
- this.close();
1173
+ this.detachStream();
1138
1174
  break;
1139
1175
  case "terminal_exit":
1140
1176
  break;
1141
1177
  }
1142
1178
  }
1143
- close() {
1179
+ attach(message) {
1180
+ this.cols = Math.max(20, Math.floor(message.cols || this.cols));
1181
+ this.rows = Math.max(5, Math.floor(message.rows || this.rows));
1182
+ this.pty?.resize(this.cols, this.rows);
1183
+ this.detachStream();
1184
+ const meta = { kind: "terminal", cols: this.cols, rows: this.rows };
1185
+ this.stream = this.channel.createStream(meta);
1186
+ this.batcher = new AdaptiveOutputBatcher((data) => {
1187
+ this.stream?.write(data);
1188
+ });
1189
+ if (this.outputBuffer) {
1190
+ this.stream.write(this.outputBuffer);
1191
+ }
1192
+ if (!this.pty) {
1193
+ this.start();
1194
+ }
1195
+ }
1196
+ /** End the current stream without killing the PTY (called on peer disconnect). */
1197
+ detachStream() {
1144
1198
  this.batcher?.destroy();
1145
1199
  this.batcher = null;
1146
1200
  if (this.stream && !this.stream.ended) this.stream.end();
1147
1201
  this.stream = null;
1202
+ }
1203
+ /** Kill the PTY — called only on host shutdown. */
1204
+ destroy() {
1205
+ this.detachStream();
1148
1206
  try {
1149
1207
  this.pty?.kill();
1150
1208
  } catch {
1151
1209
  }
1152
1210
  this.pty = null;
1153
- }
1154
- open(message) {
1155
- this.cols = Math.max(20, Math.floor(message.cols || this.cols));
1156
- this.rows = Math.max(5, Math.floor(message.rows || this.rows));
1157
- if (this.pty) {
1158
- this.pty.resize(this.cols, this.rows);
1159
- if (!this.stream || this.stream.ended) {
1160
- const meta2 = { kind: "terminal", cols: this.cols, rows: this.rows };
1161
- this.stream = this.channel.createStream(meta2);
1162
- this.batcher = new AdaptiveOutputBatcher((data) => {
1163
- this.stream?.write(data);
1164
- });
1165
- this.pty.write("\f");
1166
- }
1167
- return;
1168
- }
1169
- const command = getDefaultTerminalCommand(this.getLaunchCommand?.());
1170
- const file = resolveExecutable2(command.file) ?? command.file;
1171
- const meta = { kind: "terminal", cols: this.cols, rows: this.rows };
1172
- this.stream = this.channel.createStream(meta);
1173
- this.batcher = new AdaptiveOutputBatcher((data) => {
1174
- this.stream?.write(data);
1175
- });
1176
- const env = { ...process.env, TERM: "xterm-256color" };
1177
- this.pty = spawn2(file, command.args, {
1178
- name: "xterm-256color",
1179
- cols: this.cols,
1180
- rows: this.rows,
1181
- cwd: process.cwd(),
1182
- env
1183
- });
1184
- this.pty.onData((data) => {
1185
- process.stdout.write(data);
1186
- this.batcher?.write(data);
1187
- this.broadcastFn?.({ type: "terminal_output", data });
1188
- });
1189
- this.pty.onExit(({ exitCode, signal }) => {
1190
- this.batcher?.flush();
1191
- this.stream?.end();
1192
- this.channel.send({ type: "terminal_exit", exitCode, signal });
1193
- this.stream = null;
1194
- this.batcher = null;
1195
- this.pty = null;
1196
- });
1211
+ this.outputBuffer = "";
1197
1212
  }
1198
1213
  writeInput(message) {
1199
1214
  if (!this.pty) return;
@@ -1977,11 +1992,12 @@ async function main() {
1977
1992
  channel.on("peer_left", () => {
1978
1993
  console.log("[host] Phone disconnected.");
1979
1994
  state.connected = false;
1980
- terminal.close();
1995
+ terminal.detachStream();
1981
1996
  broadcast({ type: "peer_disconnected" });
1982
1997
  });
1983
1998
  channel.on("message", (data) => {
1984
1999
  if (isTerminalMessage(data)) {
2000
+ console.log("[host] Terminal message from phone:", data.type);
1985
2001
  terminal.handleMessage(data);
1986
2002
  return;
1987
2003
  }
@@ -2003,7 +2019,7 @@ async function main() {
2003
2019
  if (shuttingDown) return;
2004
2020
  shuttingDown = true;
2005
2021
  console.log("\n[host] Shutting down...");
2006
- terminal.close();
2022
+ terminal.destroy();
2007
2023
  state.adapter?.destroy?.();
2008
2024
  try {
2009
2025
  channel.close();
@@ -1 +1 @@
1
- import{g as c}from"./index-BkOD4g6Y.js";function f(t,i){for(var o=0;o<i.length;o++){const e=i[o];if(typeof e!="string"&&!Array.isArray(e)){for(const r in e)if(r!=="default"&&!(r in t)){const s=Object.getOwnPropertyDescriptor(e,r);s&&Object.defineProperty(t,r,s.get?s:{enumerable:!0,get:()=>e[r]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}var n,a;function b(){return a||(a=1,n=function(){throw new Error("ws does not work in the browser. Browser clients must use the native WebSocket object")}),n}var u=b();const w=c(u),p=f({__proto__:null,default:w},[u]);export{p as b};
1
+ import{g as c}from"./index-CoclVuPf.js";function f(t,i){for(var o=0;o<i.length;o++){const e=i[o];if(typeof e!="string"&&!Array.isArray(e)){for(const r in e)if(r!=="default"&&!(r in t)){const s=Object.getOwnPropertyDescriptor(e,r);s&&Object.defineProperty(t,r,s.get?s:{enumerable:!0,get:()=>e[r]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}var n,a;function b(){return a||(a=1,n=function(){throw new Error("ws does not work in the browser. Browser clients must use the native WebSocket object")}),n}var u=b();const w=c(u),p=f({__proto__:null,default:w},[u]);export{p as b};