echoclaw-relay-agent 0.4.0 → 0.4.2
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/main.js +122 -2
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2963,11 +2963,14 @@ var GatewayRpcProxy = class extends import_events2.EventEmitter {
|
|
|
2963
2963
|
}
|
|
2964
2964
|
handleEvent(frame, generation) {
|
|
2965
2965
|
const runId = frame.payload?.runId;
|
|
2966
|
+
const state = frame.payload?.state;
|
|
2966
2967
|
const streamId = frame.payload?.streamId || frame.payload?.id;
|
|
2968
|
+
console.log(`[rpc-proxy] Event received: event=${frame.event}, state=${state}, runId=${runId?.slice(0, 8) ?? "none"}, streams=${this.streams.size}, runIdMap=${this.runIdToRpc.size}`);
|
|
2967
2969
|
let rpcId = runId ? this.runIdToRpc.get(runId) : void 0;
|
|
2968
2970
|
if (!rpcId && streamId) rpcId = streamId;
|
|
2969
2971
|
const stream = rpcId ? this.streams.get(rpcId) : null;
|
|
2970
2972
|
if (!stream) {
|
|
2973
|
+
console.log(`[rpc-proxy] No matching stream for runId=${runId?.slice(0, 8) ?? "none"}, forwarding as unmatched event`);
|
|
2971
2974
|
this.emit("gateway_event", frame);
|
|
2972
2975
|
return;
|
|
2973
2976
|
}
|
|
@@ -2983,7 +2986,6 @@ var GatewayRpcProxy = class extends import_events2.EventEmitter {
|
|
|
2983
2986
|
this.cancelStream(stream.requestId);
|
|
2984
2987
|
return;
|
|
2985
2988
|
}
|
|
2986
|
-
const state = frame.payload?.state;
|
|
2987
2989
|
const isFinal = state === "final" || state === "aborted" || state === "error";
|
|
2988
2990
|
this.emitTunnelResponse(stream.requestId, frame, isFinal);
|
|
2989
2991
|
if (isFinal) {
|
|
@@ -3071,6 +3073,16 @@ function startGateway(gwConfig) {
|
|
|
3071
3073
|
rpcProxy.on("response", (response) => {
|
|
3072
3074
|
sendEncryptedPayload(response);
|
|
3073
3075
|
});
|
|
3076
|
+
rpcProxy.on("gateway_event", (frame) => {
|
|
3077
|
+
console.log(`[relay-agent] Forwarding unmatched gateway event: ${frame.event ?? frame.type}`);
|
|
3078
|
+
sendEncryptedPayload({
|
|
3079
|
+
request_id: `evt-${Date.now().toString(36)}`,
|
|
3080
|
+
direction: "response",
|
|
3081
|
+
type: "ws-rpc",
|
|
3082
|
+
frame,
|
|
3083
|
+
final: false
|
|
3084
|
+
});
|
|
3085
|
+
});
|
|
3074
3086
|
gatewayConn.on("state", (newState, oldState) => {
|
|
3075
3087
|
console.log(`[relay-agent] Gateway: ${oldState} \u2192 ${newState}`);
|
|
3076
3088
|
broadcastControlState();
|
|
@@ -3826,6 +3838,106 @@ function isServiceInstalled() {
|
|
|
3826
3838
|
}
|
|
3827
3839
|
}
|
|
3828
3840
|
|
|
3841
|
+
// src/service/updater.ts
|
|
3842
|
+
var import_child_process2 = require("child_process");
|
|
3843
|
+
var PACKAGE_NAME = "echoclaw-relay-agent";
|
|
3844
|
+
var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
3845
|
+
var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
|
|
3846
|
+
var updateTimer = null;
|
|
3847
|
+
function compareSemver(a, b) {
|
|
3848
|
+
const pa = a.replace(/^v/, "").split(".").map(Number);
|
|
3849
|
+
const pb = b.replace(/^v/, "").split(".").map(Number);
|
|
3850
|
+
for (let i = 0; i < 3; i++) {
|
|
3851
|
+
const na = pa[i] || 0;
|
|
3852
|
+
const nb = pb[i] || 0;
|
|
3853
|
+
if (na > nb) return 1;
|
|
3854
|
+
if (na < nb) return -1;
|
|
3855
|
+
}
|
|
3856
|
+
return 0;
|
|
3857
|
+
}
|
|
3858
|
+
async function fetchLatestVersion() {
|
|
3859
|
+
try {
|
|
3860
|
+
const res = await fetch(REGISTRY_URL, {
|
|
3861
|
+
signal: AbortSignal.timeout(1e4),
|
|
3862
|
+
headers: { "Accept": "application/json" }
|
|
3863
|
+
});
|
|
3864
|
+
if (!res.ok) return null;
|
|
3865
|
+
const data = await res.json();
|
|
3866
|
+
return data.version ?? null;
|
|
3867
|
+
} catch {
|
|
3868
|
+
return null;
|
|
3869
|
+
}
|
|
3870
|
+
}
|
|
3871
|
+
function performUpdate(targetVersion) {
|
|
3872
|
+
console.log(`[updater] Downloading ${PACKAGE_NAME}@${targetVersion}...`);
|
|
3873
|
+
try {
|
|
3874
|
+
const npmRoot = (0, import_child_process2.execSync)("npm root -g", { encoding: "utf-8" }).trim();
|
|
3875
|
+
(0, import_child_process2.execSync)(`npm install -g ${PACKAGE_NAME}@${targetVersion} --prefer-online`, {
|
|
3876
|
+
encoding: "utf-8",
|
|
3877
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
3878
|
+
timeout: 12e4
|
|
3879
|
+
});
|
|
3880
|
+
console.log(`[updater] \u2705 Downloaded ${PACKAGE_NAME}@${targetVersion}`);
|
|
3881
|
+
if (isServiceInstalled()) {
|
|
3882
|
+
console.log("[updater] Updating service...");
|
|
3883
|
+
installService();
|
|
3884
|
+
console.log("[updater] \u2705 Service updated and restarted");
|
|
3885
|
+
}
|
|
3886
|
+
return true;
|
|
3887
|
+
} catch (err2) {
|
|
3888
|
+
console.error(`[updater] Update failed: ${err2.message}`);
|
|
3889
|
+
return false;
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
async function checkForUpdate(currentVersion) {
|
|
3893
|
+
const latest = await fetchLatestVersion();
|
|
3894
|
+
if (!latest) return null;
|
|
3895
|
+
if (compareSemver(latest, currentVersion) > 0) {
|
|
3896
|
+
return latest;
|
|
3897
|
+
}
|
|
3898
|
+
return null;
|
|
3899
|
+
}
|
|
3900
|
+
async function startupUpdateCheck(currentVersion, autoUpdate) {
|
|
3901
|
+
const latest = await checkForUpdate(currentVersion);
|
|
3902
|
+
if (!latest) return;
|
|
3903
|
+
console.log("");
|
|
3904
|
+
console.log(` \u{1F4E6} Update available: v${currentVersion} \u2192 v${latest}`);
|
|
3905
|
+
if (autoUpdate && isServiceInstalled()) {
|
|
3906
|
+
console.log(" Auto-updating...");
|
|
3907
|
+
const ok = performUpdate(latest);
|
|
3908
|
+
if (ok) {
|
|
3909
|
+
console.log(" \u2705 Update complete \u2014 service will restart.");
|
|
3910
|
+
process.exit(0);
|
|
3911
|
+
} else {
|
|
3912
|
+
console.log(" \u26A0\uFE0F Auto-update failed \u2014 continuing with current version.");
|
|
3913
|
+
}
|
|
3914
|
+
} else {
|
|
3915
|
+
console.log(` Run: npm cache clean --force && npx ${PACKAGE_NAME}@${latest}`);
|
|
3916
|
+
console.log("");
|
|
3917
|
+
}
|
|
3918
|
+
}
|
|
3919
|
+
function startPeriodicUpdateCheck(currentVersion) {
|
|
3920
|
+
if (updateTimer) return;
|
|
3921
|
+
updateTimer = setInterval(async () => {
|
|
3922
|
+
const latest = await checkForUpdate(currentVersion);
|
|
3923
|
+
if (latest && isServiceInstalled()) {
|
|
3924
|
+
console.log(`[updater] New version available: v${latest} \u2014 auto-updating...`);
|
|
3925
|
+
const ok = performUpdate(latest);
|
|
3926
|
+
if (ok) {
|
|
3927
|
+
console.log("[updater] Update complete \u2014 restarting.");
|
|
3928
|
+
process.exit(0);
|
|
3929
|
+
}
|
|
3930
|
+
}
|
|
3931
|
+
}, CHECK_INTERVAL_MS);
|
|
3932
|
+
if (updateTimer.unref) updateTimer.unref();
|
|
3933
|
+
}
|
|
3934
|
+
function stopPeriodicUpdateCheck() {
|
|
3935
|
+
if (updateTimer) {
|
|
3936
|
+
clearInterval(updateTimer);
|
|
3937
|
+
updateTimer = null;
|
|
3938
|
+
}
|
|
3939
|
+
}
|
|
3940
|
+
|
|
3829
3941
|
// src/gateway/token-discovery.ts
|
|
3830
3942
|
var import_fs5 = __toESM(require("fs"));
|
|
3831
3943
|
var import_path5 = __toESM(require("path"));
|
|
@@ -3888,7 +4000,7 @@ async function discoverGatewayToken() {
|
|
|
3888
4000
|
}
|
|
3889
4001
|
|
|
3890
4002
|
// src/main.ts
|
|
3891
|
-
var VERSION = "0.4.
|
|
4003
|
+
var VERSION = "0.4.2";
|
|
3892
4004
|
function parseArgs() {
|
|
3893
4005
|
const args = process.argv.slice(2);
|
|
3894
4006
|
const opts = {
|
|
@@ -4111,6 +4223,9 @@ async function main() {
|
|
|
4111
4223
|
console.log(" \u2502 Open Source \xB7 Apache License 2.0 \u2502");
|
|
4112
4224
|
console.log(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
|
|
4113
4225
|
console.log("");
|
|
4226
|
+
const isService = isServiceInstalled();
|
|
4227
|
+
startupUpdateCheck(VERSION, isService).catch(() => {
|
|
4228
|
+
});
|
|
4114
4229
|
if (!opts.bridgeUrl) {
|
|
4115
4230
|
const discovered = await discoverBridge();
|
|
4116
4231
|
if (discovered) {
|
|
@@ -4190,14 +4305,19 @@ async function main() {
|
|
|
4190
4305
|
resumeSessionKey,
|
|
4191
4306
|
gatewayConfig
|
|
4192
4307
|
});
|
|
4308
|
+
if (isService) {
|
|
4309
|
+
startPeriodicUpdateCheck(VERSION);
|
|
4310
|
+
}
|
|
4193
4311
|
}
|
|
4194
4312
|
process.on("SIGINT", () => {
|
|
4195
4313
|
console.log("\n[relay-agent] Shutting down...");
|
|
4314
|
+
stopPeriodicUpdateCheck();
|
|
4196
4315
|
stopRelayClient();
|
|
4197
4316
|
process.exit(0);
|
|
4198
4317
|
});
|
|
4199
4318
|
process.on("SIGTERM", () => {
|
|
4200
4319
|
console.log("\n[relay-agent] Terminated");
|
|
4320
|
+
stopPeriodicUpdateCheck();
|
|
4201
4321
|
stopRelayClient();
|
|
4202
4322
|
process.exit(0);
|
|
4203
4323
|
});
|