echoclaw-relay-agent 0.3.2 → 0.4.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/main.js +32 -9
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -2734,7 +2734,8 @@ var GatewayConnection = class extends import_events.EventEmitter {
2734
2734
  const message = error?.message || "unknown error";
2735
2735
  console.error(`[gateway] \u274C Connect failed: ${code} \u2014 ${message}`);
2736
2736
  this.authFailures++;
2737
- if (this.cachedDeviceToken && (code === "INVALID_TOKEN" || code === "auth_failed")) {
2737
+ const tokenRetryErrors = ["INVALID_TOKEN", "auth_failed", "DEVICE_AUTH_SIGNATURE_INVALID", "DEVICE_AUTH_FAILED"];
2738
+ if (this.cachedDeviceToken && tokenRetryErrors.includes(code)) {
2738
2739
  console.log("[gateway] deviceToken rejected \u2014 clearing cache, will retry with gateway token");
2739
2740
  this.cachedDeviceToken = null;
2740
2741
  this.clearSession();
@@ -2836,10 +2837,13 @@ var GatewayConnection = class extends import_events.EventEmitter {
2836
2837
  var import_events2 = require("events");
2837
2838
  var MAX_FRAMES_PER_STREAM = 256;
2838
2839
  var MAX_BYTES_PER_STREAM = 1 * 1024 * 1024;
2840
+ var STREAMING_METHODS = /* @__PURE__ */ new Set(["chat.send"]);
2839
2841
  var GatewayRpcProxy = class extends import_events2.EventEmitter {
2840
2842
  gateway;
2841
2843
  streams = /* @__PURE__ */ new Map();
2842
2844
  // rpcId → stream
2845
+ runIdToRpc = /* @__PURE__ */ new Map();
2846
+ // runId → rpcId (for event routing)
2843
2847
  requestToRpc = /* @__PURE__ */ new Map();
2844
2848
  // requestId → rpcId
2845
2849
  constructor(gateway) {
@@ -2869,13 +2873,15 @@ var GatewayRpcProxy = class extends import_events2.EventEmitter {
2869
2873
  return false;
2870
2874
  }
2871
2875
  if (frame.type === "req") {
2876
+ const isStreaming = STREAMING_METHODS.has(frame.method ?? "");
2872
2877
  const stream = {
2873
2878
  requestId: payload.request_id,
2874
2879
  rpcId: frame.id,
2875
2880
  generation: this.gateway.currentGeneration,
2876
2881
  frameCount: 0,
2877
2882
  byteCount: 0,
2878
- createdAt: Date.now()
2883
+ createdAt: Date.now(),
2884
+ streaming: isStreaming
2879
2885
  };
2880
2886
  this.streams.set(frame.id, stream);
2881
2887
  this.requestToRpc.set(payload.request_id, frame.id);
@@ -2923,6 +2929,7 @@ var GatewayRpcProxy = class extends import_events2.EventEmitter {
2923
2929
  }, true);
2924
2930
  }
2925
2931
  this.streams.clear();
2932
+ this.runIdToRpc.clear();
2926
2933
  this.requestToRpc.clear();
2927
2934
  }
2928
2935
  // ── Internal: Gateway frame handling ───────────────────────
@@ -2941,25 +2948,38 @@ var GatewayRpcProxy = class extends import_events2.EventEmitter {
2941
2948
  this.removeStream(frame.id, "stale");
2942
2949
  return;
2943
2950
  }
2944
- this.emitTunnelResponse(stream.requestId, frame, true);
2945
- this.removeStream(frame.id, "complete");
2951
+ if (stream.streaming && frame.ok) {
2952
+ const runId = frame.payload?.runId;
2953
+ if (runId) {
2954
+ stream.runId = runId;
2955
+ this.runIdToRpc.set(runId, frame.id);
2956
+ console.log(`[rpc-proxy] Streaming ACK for ${frame.id} \u2192 runId=${runId}, keeping stream open`);
2957
+ }
2958
+ this.emitTunnelResponse(stream.requestId, frame, false);
2959
+ } else {
2960
+ this.emitTunnelResponse(stream.requestId, frame, true);
2961
+ this.removeStream(frame.id, "complete");
2962
+ }
2946
2963
  }
2947
2964
  handleEvent(frame, generation) {
2965
+ const runId = frame.payload?.runId;
2948
2966
  const streamId = frame.payload?.streamId || frame.payload?.id;
2949
- const stream = streamId ? this.streams.get(streamId) : null;
2967
+ let rpcId = runId ? this.runIdToRpc.get(runId) : void 0;
2968
+ if (!rpcId && streamId) rpcId = streamId;
2969
+ const stream = rpcId ? this.streams.get(rpcId) : null;
2950
2970
  if (!stream) {
2951
2971
  this.emit("gateway_event", frame);
2952
2972
  return;
2953
2973
  }
2954
2974
  if (stream.generation !== generation) {
2955
- console.warn(`[rpc-proxy] Dropping stale event for ${streamId}`);
2975
+ console.warn(`[rpc-proxy] Dropping stale event for ${rpcId}`);
2956
2976
  return;
2957
2977
  }
2958
2978
  const frameSize = JSON.stringify(frame).length;
2959
2979
  stream.frameCount++;
2960
2980
  stream.byteCount += frameSize;
2961
2981
  if (stream.frameCount > MAX_FRAMES_PER_STREAM || stream.byteCount > MAX_BYTES_PER_STREAM) {
2962
- console.warn(`[rpc-proxy] Stream ${streamId} exceeded limits (frames=${stream.frameCount}, bytes=${stream.byteCount})`);
2982
+ console.warn(`[rpc-proxy] Stream ${rpcId} exceeded limits (frames=${stream.frameCount}, bytes=${stream.byteCount})`);
2963
2983
  this.cancelStream(stream.requestId);
2964
2984
  return;
2965
2985
  }
@@ -2967,7 +2987,7 @@ var GatewayRpcProxy = class extends import_events2.EventEmitter {
2967
2987
  const isFinal = state === "final" || state === "aborted" || state === "error";
2968
2988
  this.emitTunnelResponse(stream.requestId, frame, isFinal);
2969
2989
  if (isFinal) {
2970
- this.removeStream(streamId, state);
2990
+ this.removeStream(rpcId, state);
2971
2991
  }
2972
2992
  }
2973
2993
  // ── Internal: emit tunnel response ─────────────────────────
@@ -2987,6 +3007,9 @@ var GatewayRpcProxy = class extends import_events2.EventEmitter {
2987
3007
  if (!stream) return;
2988
3008
  this.streams.delete(rpcId);
2989
3009
  this.requestToRpc.delete(stream.requestId);
3010
+ if (stream.runId) {
3011
+ this.runIdToRpc.delete(stream.runId);
3012
+ }
2990
3013
  }
2991
3014
  };
2992
3015
 
@@ -3865,7 +3888,7 @@ async function discoverGatewayToken() {
3865
3888
  }
3866
3889
 
3867
3890
  // src/main.ts
3868
- var VERSION = "0.3.0";
3891
+ var VERSION = "0.4.0";
3869
3892
  function parseArgs() {
3870
3893
  const args = process.argv.slice(2);
3871
3894
  const opts = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "echoclaw-relay-agent",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "EchoClaw Relay Agent — connects OpenClaw bridge to the EchoClaw Relay Server with E2E encryption",
5
5
  "main": "./dist/main.js",
6
6
  "bin": {