muuuuse 2.2.0 → 2.2.1

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/package.json +1 -1
  2. package/src/runtime.js +54 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muuuuse",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "🔌Muuuuse arms two regular terminals and relays assistant output between them.",
5
5
  "type": "commonjs",
6
6
  "bin": {
package/src/runtime.js CHANGED
@@ -35,7 +35,8 @@ const {
35
35
  writeJson,
36
36
  } = require("./util");
37
37
 
38
- const TYPE_DELAY_MS = 70;
38
+ const TYPE_CHUNK_DELAY_MS = 18;
39
+ const TYPE_CHUNK_SIZE = 24;
39
40
  const MIRROR_SUPPRESSION_WINDOW_MS = 30 * 1000;
40
41
  const PENDING_RELAY_CONTEXT_TTL_MS = 2 * 60 * 1000;
41
42
  const EMITTED_ANSWER_TTL_MS = 5 * 60 * 1000;
@@ -435,24 +436,57 @@ function readSeatChallenge(paths, sessionName) {
435
436
  };
436
437
  }
437
438
 
438
- async function sendTextAndEnter(child, text, shouldAbort = () => false) {
439
- const payload = String(text || "")
439
+ function normalizeRelayPayloadForTyping(text) {
440
+ return String(text || "")
440
441
  .replace(/\r/g, "")
441
442
  .replace(/\s*\n+\s*/g, " ")
442
443
  .replace(/[ \t]{2,}/g, " ")
443
444
  .trim();
445
+ }
446
+
447
+ function chunkRelayPayloadForTyping(text, chunkSize = TYPE_CHUNK_SIZE) {
448
+ const normalized = String(text || "");
449
+ if (!normalized) {
450
+ return [];
451
+ }
452
+
453
+ const size = Number.isInteger(chunkSize) && chunkSize > 0 ? chunkSize : TYPE_CHUNK_SIZE;
454
+ const chunks = [];
455
+ for (let index = 0; index < normalized.length; index += size) {
456
+ chunks.push(normalized.slice(index, index + size));
457
+ }
458
+ return chunks;
459
+ }
460
+
461
+ function stripPassiveTerminalInput(input) {
462
+ return String(input || "")
463
+ .replace(/\u001b\][\s\S]*?(?:\u0007|\u001b\\)/g, "")
464
+ .replace(/\u001b\[(?:I|O)/g, "")
465
+ .replace(/\u001b\[\d+;\d+R/g, "")
466
+ .replace(/\u001b\[\?[0-9;]*c/g, "")
467
+ .replace(/\u0000/g, "");
468
+ }
469
+
470
+ function isMeaningfulTerminalInput(input) {
471
+ return stripPassiveTerminalInput(input).length > 0;
472
+ }
473
+
474
+ async function sendTextAndEnter(child, text, shouldAbort = () => false) {
475
+ const payload = normalizeRelayPayloadForTyping(text);
444
476
 
445
477
  if (payload.length > 0) {
446
- if (shouldAbort() || !child) {
447
- return false;
448
- }
478
+ for (const chunk of chunkRelayPayloadForTyping(payload)) {
479
+ if (shouldAbort() || !child) {
480
+ return false;
481
+ }
449
482
 
450
- try {
451
- child.write(payload);
452
- } catch {
453
- return false;
483
+ try {
484
+ child.write(chunk);
485
+ } catch {
486
+ return false;
487
+ }
488
+ await sleep(TYPE_CHUNK_DELAY_MS);
454
489
  }
455
- await sleep(TYPE_DELAY_MS);
456
490
  }
457
491
 
458
492
  if (shouldAbort() || !child) {
@@ -772,12 +806,15 @@ class ArmedSeat {
772
806
 
773
807
  installStdinProxy() {
774
808
  const handleData = (chunk) => {
775
- this.lastUserInputAtMs = Date.now();
776
- this.pendingInboundContext = null;
809
+ const chunkText = chunk.toString("utf8");
810
+ if (isMeaningfulTerminalInput(chunkText)) {
811
+ this.lastUserInputAtMs = Date.now();
812
+ this.pendingInboundContext = null;
813
+ }
777
814
  if (!this.child) {
778
815
  return;
779
816
  }
780
- this.child.write(chunk.toString("utf8"));
817
+ this.child.write(chunkText);
781
818
  };
782
819
 
783
820
  const handleEnd = () => {
@@ -1475,7 +1512,10 @@ function stopAllSessions() {
1475
1512
  module.exports = {
1476
1513
  ArmedSeat,
1477
1514
  buildChildEnv,
1515
+ chunkRelayPayloadForTyping,
1478
1516
  getStatusReport,
1517
+ isMeaningfulTerminalInput,
1518
+ normalizeRelayPayloadForTyping,
1479
1519
  resolveSessionName,
1480
1520
  stopAllSessions,
1481
1521
  };