@viraatdas/rudder 3.1.7 → 3.1.8

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/cloud.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { createHash, randomUUID } from "node:crypto";
3
+ import { EchoPredictor } from "./predict.js";
3
4
  import fsp from "node:fs/promises";
4
5
  import os from "node:os";
5
6
  import path from "node:path";
@@ -2828,12 +2829,19 @@ async function runAttach(target, options) {
2828
2829
  let result = "failed";
2829
2830
  const splashAllowed = isInteractive && !options.json && !options.quietBanner;
2830
2831
  const splash = splashAllowed ? new AttachSplash(stdout, target.label) : null;
2832
+ // Predictive local echo (src/predict.ts): typed characters appear at the
2833
+ // caret at once and the cloud's frame confirms them. RUDDER_PREDICT=0
2834
+ // turns it off; it only engages once the round trip is worth hiding.
2835
+ const predictor = isInteractive && process.env.RUDDER_PREDICT !== "0"
2836
+ ? new EchoPredictor(stdout.columns ?? 120, stdout.rows ?? 32, (text) => stdout.write(text))
2837
+ : null;
2831
2838
  const sendResize = () => {
2832
2839
  if (socket.readyState !== WebSocket.OPEN) {
2833
2840
  return;
2834
2841
  }
2835
2842
  const cols = stdout.columns ?? 120;
2836
2843
  const rows = stdout.rows ?? 32;
2844
+ predictor?.resize(cols, rows);
2837
2845
  socket.send(JSON.stringify({ type: "resize", cols, rows }));
2838
2846
  };
2839
2847
  let lastCtrlC = 0;
@@ -2911,6 +2919,7 @@ async function runAttach(target, options) {
2911
2919
  lastCtrlC = now;
2912
2920
  }
2913
2921
  socket.send(buffer, { binary: true });
2922
+ predictor?.onInput(buffer);
2914
2923
  };
2915
2924
  const onResize = () => {
2916
2925
  if (hasControl) {
@@ -2925,7 +2934,14 @@ async function runAttach(target, options) {
2925
2934
  // as a dropped connection, which attachWithReconnect reopens.
2926
2935
  let lastHeard = Date.now();
2927
2936
  let lastTick = Date.now();
2928
- socket.on("pong", () => { lastHeard = Date.now(); });
2937
+ let pingSentAt = 0;
2938
+ socket.on("pong", () => {
2939
+ lastHeard = Date.now();
2940
+ if (pingSentAt) {
2941
+ predictor?.noteRtt(Date.now() - pingSentAt);
2942
+ pingSentAt = 0;
2943
+ }
2944
+ });
2929
2945
  socket.on("message", () => { lastHeard = Date.now(); });
2930
2946
  const liveness = setInterval(() => {
2931
2947
  const now = Date.now();
@@ -2940,6 +2956,7 @@ async function runAttach(target, options) {
2940
2956
  }
2941
2957
  try {
2942
2958
  socket.ping();
2959
+ pingSentAt = Date.now();
2943
2960
  }
2944
2961
  catch {
2945
2962
  socket.terminate();
@@ -2952,6 +2969,7 @@ async function runAttach(target, options) {
2952
2969
  }
2953
2970
  cleaned = true;
2954
2971
  clearInterval(liveness);
2972
+ predictor?.dispose();
2955
2973
  stdin.off("data", onStdin);
2956
2974
  stdout.off("resize", onResize);
2957
2975
  process.off("SIGINT", onSigint);
@@ -3105,6 +3123,20 @@ async function runAttach(target, options) {
3105
3123
  };
3106
3124
  socket.on("open", () => {
3107
3125
  opened = true;
3126
+ // Measure the round trip at once: predictive echo waits on it.
3127
+ try {
3128
+ socket.ping();
3129
+ pingSentAt = Date.now();
3130
+ }
3131
+ catch {
3132
+ // the liveness timer retries
3133
+ }
3134
+ if (probeMode) {
3135
+ // An idle dashboard sends nothing; a resize makes it repaint, which is
3136
+ // the first frame the probe waits for.
3137
+ socket.send(JSON.stringify({ type: "resize", cols: 119, rows: 32 }));
3138
+ setTimeout(() => socket.send(JSON.stringify({ type: "resize", cols: 120, rows: 32 })), 200);
3139
+ }
3108
3140
  // Disable Nagle on the underlying TCP socket so single keystrokes don't
3109
3141
  // sit in the send buffer waiting for piggyback ACKs (~40ms savings per
3110
3142
  // keypress on the WAN).
@@ -3211,6 +3243,7 @@ async function runAttach(target, options) {
3211
3243
  setTimeout(sendResize, 150);
3212
3244
  }
3213
3245
  stdout.write(data);
3246
+ predictor?.onServerData(data);
3214
3247
  return;
3215
3248
  }
3216
3249
  const text = Buffer.isBuffer(data)
@@ -3673,6 +3706,9 @@ const LAPTOP_CONFIG_FILES = [
3673
3706
  "~/.codex/config.toml",
3674
3707
  "~/.codex/AGENTS.md",
3675
3708
  "~/.codex/hooks.json",
3709
+ // Service logins agents use from scripts (Kalshi signs requests with this key).
3710
+ "~/.kalshi/config.json",
3711
+ "~/.kalshi/private_key.pem",
3676
3712
  ];
3677
3713
  async function laptopConfigFiles() {
3678
3714
  const names = [...LAPTOP_CONFIG_FILES, "~/.aws/config", "~/.aws/credentials"];