@phenx-inc/ctlsurf 0.1.7 → 0.1.9
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/out/headless/index.mjs +41 -23
- package/out/headless/index.mjs.map +2 -2
- package/out/main/index.js +41 -23
- package/package.json +1 -1
- package/src/main/bridge.ts +45 -20
- package/src/main/orchestrator.ts +5 -5
package/out/headless/index.mjs
CHANGED
|
@@ -3647,8 +3647,8 @@ var ConversationBridge = class {
|
|
|
3647
3647
|
inputBuffer = "";
|
|
3648
3648
|
// Virtual terminal for processing escape sequences into rendered text
|
|
3649
3649
|
terminal;
|
|
3650
|
-
|
|
3651
|
-
|
|
3650
|
+
lastSnapshot = "";
|
|
3651
|
+
pendingWrites = 0;
|
|
3652
3652
|
constructor() {
|
|
3653
3653
|
this.terminal = new import_headless.Terminal({ cols: 120, rows: 50, scrollback: 1e4 });
|
|
3654
3654
|
}
|
|
@@ -3657,19 +3657,26 @@ var ConversationBridge = class {
|
|
|
3657
3657
|
}
|
|
3658
3658
|
startSession() {
|
|
3659
3659
|
this.terminal.reset();
|
|
3660
|
-
this.
|
|
3660
|
+
this.lastSnapshot = "";
|
|
3661
|
+
this.pendingWrites = 0;
|
|
3661
3662
|
this.inputBuffer = "";
|
|
3662
3663
|
this.sessionActive = true;
|
|
3663
3664
|
console.log("[bridge] Session started");
|
|
3664
3665
|
}
|
|
3665
3666
|
/**
|
|
3666
3667
|
* Feed terminal output data into the bridge.
|
|
3667
|
-
*
|
|
3668
|
-
*
|
|
3668
|
+
* xterm.write() is async — we track pending writes and only flush
|
|
3669
|
+
* when all writes have been processed into the buffer.
|
|
3669
3670
|
*/
|
|
3670
3671
|
feedOutput(data) {
|
|
3671
3672
|
if (!this.sessionActive) return;
|
|
3672
|
-
this.
|
|
3673
|
+
this.pendingWrites++;
|
|
3674
|
+
this.terminal.write(data, () => {
|
|
3675
|
+
this.pendingWrites--;
|
|
3676
|
+
this.scheduleFlush();
|
|
3677
|
+
});
|
|
3678
|
+
}
|
|
3679
|
+
scheduleFlush() {
|
|
3673
3680
|
if (this.flushTimer) {
|
|
3674
3681
|
clearTimeout(this.flushTimer);
|
|
3675
3682
|
}
|
|
@@ -3686,29 +3693,36 @@ var ConversationBridge = class {
|
|
|
3686
3693
|
this.inputBuffer = "";
|
|
3687
3694
|
}
|
|
3688
3695
|
}
|
|
3689
|
-
/**
|
|
3690
|
-
* Resize the virtual terminal to match the actual PTY dimensions.
|
|
3691
|
-
*/
|
|
3692
3696
|
resize(cols, rows) {
|
|
3693
3697
|
this.terminal.resize(cols, rows);
|
|
3694
3698
|
}
|
|
3695
3699
|
/**
|
|
3696
3700
|
* Read new content from the terminal buffer since the last flush.
|
|
3701
|
+
* Only flushes when all pending writes have completed.
|
|
3697
3702
|
*/
|
|
3698
3703
|
flush() {
|
|
3704
|
+
if (this.pendingWrites > 0) {
|
|
3705
|
+
this.scheduleFlush();
|
|
3706
|
+
return;
|
|
3707
|
+
}
|
|
3699
3708
|
const buf = this.terminal.buffer.active;
|
|
3700
|
-
const totalLines = buf.baseY +
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
for (let i = this.lastSnapshotLines; i < totalLines; i++) {
|
|
3709
|
+
const totalLines = buf.baseY + this.terminal.rows;
|
|
3710
|
+
const allLines = [];
|
|
3711
|
+
for (let i = 0; i < totalLines; i++) {
|
|
3704
3712
|
const line = buf.getLine(i);
|
|
3705
3713
|
if (line) {
|
|
3706
|
-
|
|
3714
|
+
allLines.push(line.translateToString(true));
|
|
3707
3715
|
}
|
|
3708
3716
|
}
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3717
|
+
const currentSnapshot = allLines.join("\n");
|
|
3718
|
+
let newContent;
|
|
3719
|
+
if (currentSnapshot.startsWith(this.lastSnapshot)) {
|
|
3720
|
+
newContent = currentSnapshot.slice(this.lastSnapshot.length);
|
|
3721
|
+
} else {
|
|
3722
|
+
newContent = currentSnapshot;
|
|
3723
|
+
}
|
|
3724
|
+
this.lastSnapshot = currentSnapshot;
|
|
3725
|
+
const cleaned = newContent.replace(/\n{3,}/g, "\n\n").trim();
|
|
3712
3726
|
if (cleaned.length === 0) return;
|
|
3713
3727
|
this.sendEntry("terminal_output", cleaned);
|
|
3714
3728
|
}
|
|
@@ -3720,8 +3734,12 @@ var ConversationBridge = class {
|
|
|
3720
3734
|
content
|
|
3721
3735
|
});
|
|
3722
3736
|
}
|
|
3723
|
-
endSession() {
|
|
3737
|
+
async endSession() {
|
|
3724
3738
|
if (!this.sessionActive) return;
|
|
3739
|
+
if (this.pendingWrites > 0) {
|
|
3740
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3741
|
+
}
|
|
3742
|
+
this.pendingWrites = 0;
|
|
3725
3743
|
this.flush();
|
|
3726
3744
|
if (this.flushTimer) {
|
|
3727
3745
|
clearTimeout(this.flushTimer);
|
|
@@ -4223,7 +4241,7 @@ var Orchestrator = class {
|
|
|
4223
4241
|
// ─── PTY & Agent ────────────────────────────────
|
|
4224
4242
|
async spawnAgent(agent, cwd) {
|
|
4225
4243
|
if (this.ptyManager) {
|
|
4226
|
-
this.bridge.endSession();
|
|
4244
|
+
await this.bridge.endSession();
|
|
4227
4245
|
this.ptyManager.kill();
|
|
4228
4246
|
}
|
|
4229
4247
|
this.currentAgent = agent;
|
|
@@ -4239,9 +4257,9 @@ var Orchestrator = class {
|
|
|
4239
4257
|
this.streamTerminalData(data);
|
|
4240
4258
|
});
|
|
4241
4259
|
const thisPtyManager = this.ptyManager;
|
|
4242
|
-
this.ptyManager.onExit((exitCode) => {
|
|
4260
|
+
this.ptyManager.onExit(async (exitCode) => {
|
|
4243
4261
|
this.events.onPtyExit(exitCode);
|
|
4244
|
-
this.bridge.endSession();
|
|
4262
|
+
await this.bridge.endSession();
|
|
4245
4263
|
if (thisPtyManager === this.ptyManager && this.currentAgent && isCodingAgent(this.currentAgent)) {
|
|
4246
4264
|
this.workerWs.disconnect();
|
|
4247
4265
|
}
|
|
@@ -4264,7 +4282,7 @@ var Orchestrator = class {
|
|
|
4264
4282
|
this.workerWs.sendTerminalResize(cols, rows);
|
|
4265
4283
|
}
|
|
4266
4284
|
async killAgent() {
|
|
4267
|
-
this.bridge.endSession();
|
|
4285
|
+
await this.bridge.endSession();
|
|
4268
4286
|
this.ptyManager?.kill();
|
|
4269
4287
|
this.ptyManager = null;
|
|
4270
4288
|
if (this.currentAgent && isCodingAgent(this.currentAgent)) {
|
|
@@ -4313,7 +4331,7 @@ var Orchestrator = class {
|
|
|
4313
4331
|
}
|
|
4314
4332
|
// ─── Shutdown ───────────────────────────────────
|
|
4315
4333
|
async shutdown() {
|
|
4316
|
-
this.bridge.endSession();
|
|
4334
|
+
await this.bridge.endSession();
|
|
4317
4335
|
this.ptyManager?.kill();
|
|
4318
4336
|
this.ptyManager = null;
|
|
4319
4337
|
this.workerWs.disconnect();
|