relay-claude-channel 0.3.16 → 0.3.17
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/contracts/relay-v1.lock.json +2 -2
- package/package.json +2 -2
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/contracts/relay-v1.lock.json +2 -2
- package/plugin/runtime/server.mjs +79 -12
- package/runtime/server.mjs +79 -12
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "relay",
|
|
4
4
|
"displayName": "Relay Messenger",
|
|
5
5
|
"description": "Relay Messenger channel for Claude Code with durable acknowledged delivery, explicit Read receipts, and retry-safe replies.",
|
|
6
|
-
"version": "0.3.
|
|
6
|
+
"version": "0.3.17",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Relay Messenger",
|
|
9
9
|
"url": "https://relayapp.im"
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
},
|
|
8
8
|
"relaySdk": {
|
|
9
9
|
"package": "@relaymessenger/sdk",
|
|
10
|
-
"version": "0.5.
|
|
11
|
-
"integrity": "sha512-
|
|
10
|
+
"version": "0.5.5",
|
|
11
|
+
"integrity": "sha512-LnCzswBvfcruckCJ1z8Hr1agjM0EXmPsZ6olD+9g+I6WVwoY4TNCeXMdDeJvqAdEYo1AXp4vaoi9tO2EH+DSIg==",
|
|
12
12
|
"workspaceOpenapiSha256": "79bd85b0150ef45ea4bbe5f498507dd86d784e7fbf6c3b299a5a81db091aacdd"
|
|
13
13
|
},
|
|
14
14
|
"claudeCode": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "relay-claude-channel",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.17",
|
|
4
4
|
"description": "Relay Messenger channel for Claude Code over Relay v1 WebSocket delivery.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
43
|
-
"@relaymessenger/sdk": "0.5.
|
|
43
|
+
"@relaymessenger/sdk": "0.5.5"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "26.6.2",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "relay",
|
|
4
4
|
"displayName": "Relay Messenger",
|
|
5
5
|
"description": "Relay Messenger channel for Claude Code with durable acknowledged delivery, explicit Read receipts, and retry-safe replies.",
|
|
6
|
-
"version": "0.3.
|
|
6
|
+
"version": "0.3.17",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Relay Messenger",
|
|
9
9
|
"url": "https://relayapp.im"
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
},
|
|
8
8
|
"relaySdk": {
|
|
9
9
|
"package": "@relaymessenger/sdk",
|
|
10
|
-
"version": "0.5.
|
|
11
|
-
"integrity": "sha512-
|
|
10
|
+
"version": "0.5.5",
|
|
11
|
+
"integrity": "sha512-LnCzswBvfcruckCJ1z8Hr1agjM0EXmPsZ6olD+9g+I6WVwoY4TNCeXMdDeJvqAdEYo1AXp4vaoi9tO2EH+DSIg==",
|
|
12
12
|
"workspaceOpenapiSha256": "79bd85b0150ef45ea4bbe5f498507dd86d784e7fbf6c3b299a5a81db091aacdd"
|
|
13
13
|
},
|
|
14
14
|
"claudeCode": {
|
|
@@ -21084,6 +21084,8 @@ var WebSocketStoppedError = class extends Error {
|
|
|
21084
21084
|
this.closeCode = closeCode;
|
|
21085
21085
|
}
|
|
21086
21086
|
};
|
|
21087
|
+
var UnknownStatusWebSocketError = class extends Error {
|
|
21088
|
+
};
|
|
21087
21089
|
var DurableApplicationError = class extends Error {
|
|
21088
21090
|
sequence;
|
|
21089
21091
|
closeCode = CLIENT_CLOSE_DURABLE_ACCEPTANCE;
|
|
@@ -21094,14 +21096,25 @@ var DurableApplicationError = class extends Error {
|
|
|
21094
21096
|
};
|
|
21095
21097
|
var RetryableWebSocketError = class extends Error {
|
|
21096
21098
|
closeCode;
|
|
21097
|
-
|
|
21099
|
+
retryAfterMs;
|
|
21100
|
+
constructor(message, closeCode = CLIENT_CLOSE_RECONNECT, retryAfterMs) {
|
|
21098
21101
|
super(message);
|
|
21099
21102
|
this.closeCode = closeCode;
|
|
21103
|
+
this.retryAfterMs = retryAfterMs;
|
|
21100
21104
|
}
|
|
21101
21105
|
};
|
|
21102
|
-
var
|
|
21106
|
+
var AGENT_TOKEN_REFUSED_CODE = 2004;
|
|
21107
|
+
var agentTokenRefused = (detail, options2 = {}) => new RelayAPIError(`Relay refused this Agent Token (${detail}): it is invalid or was revoked, so Relay will not reconnect with it. Create a new Agent Token in Relay Console, or run npx relaymessenger connect , then start again.`, {
|
|
21108
|
+
status: 401,
|
|
21109
|
+
code: options2.code ?? AGENT_TOKEN_REFUSED_CODE,
|
|
21110
|
+
...options2.traceId === void 0 ? {} : { traceId: options2.traceId },
|
|
21111
|
+
...options2.body === void 0 ? {} : { body: options2.body }
|
|
21112
|
+
});
|
|
21113
|
+
var upgradeResponseBody = (status, statusMessage, textBody, retryAfterHeader) => {
|
|
21103
21114
|
let body = textBody;
|
|
21104
21115
|
let message;
|
|
21116
|
+
let code;
|
|
21117
|
+
let retryAfter = Number(retryAfterHeader ?? NaN);
|
|
21105
21118
|
let traceId;
|
|
21106
21119
|
try {
|
|
21107
21120
|
const parsed = textBody ? JSON.parse(textBody) : void 0;
|
|
@@ -21112,9 +21125,22 @@ var upgradeResponseBody = (status, statusMessage, textBody) => {
|
|
|
21112
21125
|
if (isRecord2(parsed.error) && typeof parsed.error.message === "string") {
|
|
21113
21126
|
message = parsed.error.message;
|
|
21114
21127
|
}
|
|
21128
|
+
if (isRecord2(parsed.error) && typeof parsed.error.code === "number") {
|
|
21129
|
+
code = parsed.error.code;
|
|
21130
|
+
}
|
|
21131
|
+
if (isRecord2(parsed.error) && typeof parsed.error.retry_after === "number") {
|
|
21132
|
+
retryAfter = parsed.error.retry_after;
|
|
21133
|
+
}
|
|
21115
21134
|
}
|
|
21116
21135
|
} catch {
|
|
21117
21136
|
}
|
|
21137
|
+
if (status === 401) {
|
|
21138
|
+
return agentTokenRefused(`HTTP 401${message ? `: ${message}` : ""}`, {
|
|
21139
|
+
...code === void 0 ? {} : { code },
|
|
21140
|
+
...traceId === void 0 ? {} : { traceId },
|
|
21141
|
+
body
|
|
21142
|
+
});
|
|
21143
|
+
}
|
|
21118
21144
|
if (status === 409) {
|
|
21119
21145
|
return new RelayWebhookConfiguredError(message ?? "This Agent delivers by webhook; delete its webhook subscription to use the WebSocket.", {
|
|
21120
21146
|
...traceId === void 0 ? {} : { traceId },
|
|
@@ -21123,7 +21149,10 @@ var upgradeResponseBody = (status, statusMessage, textBody) => {
|
|
|
21123
21149
|
}
|
|
21124
21150
|
const fallback = status > 0 ? `Relay WebSocket upgrade failed with HTTP ${status}${statusMessage ? ` ${statusMessage}` : ""}.` : "Relay WebSocket upgrade failed before receiving an HTTP status.";
|
|
21125
21151
|
const errorMessage = message ?? fallback;
|
|
21126
|
-
|
|
21152
|
+
if (status === 429) {
|
|
21153
|
+
return new RetryableWebSocketError(errorMessage, CLIENT_CLOSE_RECONNECT, Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter * 1e3 : void 0);
|
|
21154
|
+
}
|
|
21155
|
+
return status >= 500 || status === 0 ? new RetryableWebSocketError(errorMessage) : new WebSocketStoppedError(errorMessage);
|
|
21127
21156
|
};
|
|
21128
21157
|
var deriveWebSocketURL = (baseURL, observe = false) => {
|
|
21129
21158
|
let url;
|
|
@@ -21166,6 +21195,7 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21166
21195
|
Authorization: `Bearer ${agentToken}`
|
|
21167
21196
|
}
|
|
21168
21197
|
});
|
|
21198
|
+
const statusUnknown = typeof socket.on !== "function";
|
|
21169
21199
|
let chain = Promise.resolve();
|
|
21170
21200
|
let settled = false;
|
|
21171
21201
|
let ready = false;
|
|
@@ -21241,6 +21271,8 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21241
21271
|
};
|
|
21242
21272
|
const onUnexpectedResponse = (_request, response) => {
|
|
21243
21273
|
const chunks = [];
|
|
21274
|
+
const header = response.headers?.["retry-after"];
|
|
21275
|
+
const retryAfterHeader = Array.isArray(header) ? header[0] : header;
|
|
21244
21276
|
let bytes = 0;
|
|
21245
21277
|
response.setEncoding?.("utf8");
|
|
21246
21278
|
response.on("data", (chunk) => {
|
|
@@ -21251,10 +21283,10 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21251
21283
|
chunks.push(value.slice(0, Math.max(0, 65536 - (bytes - value.length))));
|
|
21252
21284
|
});
|
|
21253
21285
|
response.on("end", () => {
|
|
21254
|
-
finish(upgradeResponseBody(response.statusCode ?? 0, response.statusMessage, chunks.join("")));
|
|
21286
|
+
finish(upgradeResponseBody(response.statusCode ?? 0, response.statusMessage, chunks.join(""), retryAfterHeader));
|
|
21255
21287
|
});
|
|
21256
21288
|
response.on("error", () => {
|
|
21257
|
-
finish(upgradeResponseBody(response.statusCode ?? 0, response.statusMessage, chunks.join("")));
|
|
21289
|
+
finish(upgradeResponseBody(response.statusCode ?? 0, response.statusMessage, chunks.join(""), retryAfterHeader));
|
|
21258
21290
|
});
|
|
21259
21291
|
};
|
|
21260
21292
|
const onMessage = (message) => {
|
|
@@ -21297,6 +21329,9 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21297
21329
|
if (parsed.reason === "heartbeat_timeout" || parsed.reason === "restart") {
|
|
21298
21330
|
throw new RetryableWebSocketError(parsed.reason === "restart" ? "Relay WebSocket is restarting." : "Relay WebSocket heartbeat timed out.");
|
|
21299
21331
|
}
|
|
21332
|
+
if (parsed.reason === "revoked") {
|
|
21333
|
+
throw agentTokenRefused("disconnect: revoked");
|
|
21334
|
+
}
|
|
21300
21335
|
if (parsed.reason === "webhook_configured") {
|
|
21301
21336
|
throw new RelayWebhookConfiguredError("Webhook delivery is now configured for this Agent.", { code: 4410 });
|
|
21302
21337
|
}
|
|
@@ -21397,7 +21432,8 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21397
21432
|
if (settled)
|
|
21398
21433
|
return;
|
|
21399
21434
|
stopReceiving();
|
|
21400
|
-
|
|
21435
|
+
const refused = error2 instanceof RelayAPIError && error2.status === 401;
|
|
21436
|
+
socket.close(refused ? 4401 : error2 instanceof WebSocketStoppedError ? error2.closeCode : error2 instanceof WebSocketProtocolError ? error2.closeCode : error2 instanceof RetryableWebSocketError ? error2.closeCode : CLIENT_CLOSE_DURABLE_ACCEPTANCE, refused || error2 instanceof WebSocketStoppedError ? "Relay stopped this consumer" : error2 instanceof WebSocketProtocolError ? "protocol error" : error2 instanceof RetryableWebSocketError ? "Relay requested reconnect" : error2 instanceof DurableApplicationError && error2.sequence !== void 0 ? `durable application failed at sequence ${error2.sequence}` : "durable application failed");
|
|
21401
21437
|
finish(error2);
|
|
21402
21438
|
});
|
|
21403
21439
|
};
|
|
@@ -21418,12 +21454,16 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21418
21454
|
}));
|
|
21419
21455
|
return;
|
|
21420
21456
|
}
|
|
21457
|
+
if (event.code === 4401) {
|
|
21458
|
+
finish(agentTokenRefused(`close 4401${event.reason ? `: ${event.reason}` : ""}`));
|
|
21459
|
+
return;
|
|
21460
|
+
}
|
|
21421
21461
|
if (event.code !== void 0 && event.code >= 4400 && event.code <= 4499 && event.code !== 4408) {
|
|
21422
21462
|
finish(new WebSocketStoppedError(`Relay WebSocket closed permanently (${event.code}): ${event.reason ?? "server policy changed"}.`, event.code));
|
|
21423
21463
|
return;
|
|
21424
21464
|
}
|
|
21425
21465
|
if (!ready) {
|
|
21426
|
-
finish(new Error(`Relay WebSocket closed before ready (${event.code ?? 1006}): ${event.reason ?? "connection ended"}.`));
|
|
21466
|
+
finish(new (statusUnknown ? UnknownStatusWebSocketError : Error)(`Relay WebSocket closed before ready (${event.code ?? 1006}): ${event.reason ?? "connection ended"}.`));
|
|
21427
21467
|
return;
|
|
21428
21468
|
}
|
|
21429
21469
|
finish();
|
|
@@ -21435,7 +21475,7 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21435
21475
|
void drained().then(() => finish());
|
|
21436
21476
|
return;
|
|
21437
21477
|
}
|
|
21438
|
-
const error2 = new Error("Relay WebSocket connection failed.");
|
|
21478
|
+
const error2 = new (statusUnknown && !ready ? UnknownStatusWebSocketError : Error)("Relay WebSocket connection failed.");
|
|
21439
21479
|
void drained().then(() => finish(error2));
|
|
21440
21480
|
};
|
|
21441
21481
|
const onAbort = () => {
|
|
@@ -21455,6 +21495,26 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21455
21495
|
else
|
|
21456
21496
|
options2.signal?.addEventListener("abort", onAbort, { once: true });
|
|
21457
21497
|
});
|
|
21498
|
+
var refusedToken = async (baseURL, agentToken, signal) => {
|
|
21499
|
+
try {
|
|
21500
|
+
const url = new URL(baseURL);
|
|
21501
|
+
url.pathname = "/v1/me";
|
|
21502
|
+
url.search = "";
|
|
21503
|
+
url.hash = "";
|
|
21504
|
+
const response = await fetch(url, {
|
|
21505
|
+
headers: { Authorization: `Bearer ${agentToken}` },
|
|
21506
|
+
...signal ? { signal } : {}
|
|
21507
|
+
});
|
|
21508
|
+
if (response.status !== 401) {
|
|
21509
|
+
await response.body?.cancel();
|
|
21510
|
+
return void 0;
|
|
21511
|
+
}
|
|
21512
|
+
const answer = upgradeResponseBody(401, void 0, await response.text());
|
|
21513
|
+
return answer instanceof RelayAPIError ? answer : void 0;
|
|
21514
|
+
} catch {
|
|
21515
|
+
return void 0;
|
|
21516
|
+
}
|
|
21517
|
+
};
|
|
21458
21518
|
var runWebSocket = async (baseURL, agentToken, options2) => {
|
|
21459
21519
|
if (options2.observe !== void 0 && typeof options2.observe !== "boolean") {
|
|
21460
21520
|
throw new TypeError("WebSocket observe must be a boolean when provided.");
|
|
@@ -21483,6 +21543,7 @@ var runWebSocket = async (baseURL, agentToken, options2) => {
|
|
|
21483
21543
|
report(new RelayUnknownEventTypeError(eventType, sequence));
|
|
21484
21544
|
};
|
|
21485
21545
|
while (!options2.signal?.aborted) {
|
|
21546
|
+
let retryAfterMs = 0;
|
|
21486
21547
|
options2.onConnectionState?.("connecting");
|
|
21487
21548
|
try {
|
|
21488
21549
|
await runConnection(url, agentToken, options2, Constructor, (frame) => {
|
|
@@ -21494,13 +21555,19 @@ var runWebSocket = async (baseURL, agentToken, options2) => {
|
|
|
21494
21555
|
failing = false;
|
|
21495
21556
|
attempt = 0;
|
|
21496
21557
|
});
|
|
21497
|
-
} catch (
|
|
21558
|
+
} catch (caught) {
|
|
21559
|
+
if (options2.signal?.aborted)
|
|
21560
|
+
return;
|
|
21561
|
+
const error2 = caught instanceof UnknownStatusWebSocketError ? await refusedToken(baseURL, agentToken, options2.signal) ?? caught : caught;
|
|
21498
21562
|
if (options2.signal?.aborted)
|
|
21499
21563
|
return;
|
|
21500
21564
|
report(error2);
|
|
21501
21565
|
if (error2 instanceof DurableApplicationError)
|
|
21502
21566
|
failing = true;
|
|
21503
|
-
if (error2 instanceof
|
|
21567
|
+
if (error2 instanceof RetryableWebSocketError && error2.retryAfterMs !== void 0) {
|
|
21568
|
+
retryAfterMs = error2.retryAfterMs;
|
|
21569
|
+
}
|
|
21570
|
+
if (error2 instanceof WebSocketStoppedError || error2 instanceof WebSocketProtocolError || error2 instanceof RelayAPIError && !error2.retryable)
|
|
21504
21571
|
throw error2;
|
|
21505
21572
|
attempt += 1;
|
|
21506
21573
|
} finally {
|
|
@@ -21509,7 +21576,7 @@ var runWebSocket = async (baseURL, agentToken, options2) => {
|
|
|
21509
21576
|
if (options2.signal?.aborted)
|
|
21510
21577
|
return;
|
|
21511
21578
|
const ceiling = Math.min(maximum, minimum * 2 ** Math.max(0, attempt - 1));
|
|
21512
|
-
await wait(Math.floor(random() * ceiling), options2.signal);
|
|
21579
|
+
await wait(Math.max(retryAfterMs, Math.floor(random() * ceiling)), options2.signal);
|
|
21513
21580
|
}
|
|
21514
21581
|
};
|
|
21515
21582
|
|
|
@@ -24844,7 +24911,7 @@ var RelayStateStore = class {
|
|
|
24844
24911
|
};
|
|
24845
24912
|
|
|
24846
24913
|
// server.ts
|
|
24847
|
-
var VERSION = true ? "0.3.
|
|
24914
|
+
var VERSION = true ? "0.3.17" : createRequire(import.meta.url)("./package.json").version;
|
|
24848
24915
|
if (process.argv.includes("--version")) {
|
|
24849
24916
|
process.stdout.write(`${VERSION}
|
|
24850
24917
|
`);
|
package/runtime/server.mjs
CHANGED
|
@@ -21084,6 +21084,8 @@ var WebSocketStoppedError = class extends Error {
|
|
|
21084
21084
|
this.closeCode = closeCode;
|
|
21085
21085
|
}
|
|
21086
21086
|
};
|
|
21087
|
+
var UnknownStatusWebSocketError = class extends Error {
|
|
21088
|
+
};
|
|
21087
21089
|
var DurableApplicationError = class extends Error {
|
|
21088
21090
|
sequence;
|
|
21089
21091
|
closeCode = CLIENT_CLOSE_DURABLE_ACCEPTANCE;
|
|
@@ -21094,14 +21096,25 @@ var DurableApplicationError = class extends Error {
|
|
|
21094
21096
|
};
|
|
21095
21097
|
var RetryableWebSocketError = class extends Error {
|
|
21096
21098
|
closeCode;
|
|
21097
|
-
|
|
21099
|
+
retryAfterMs;
|
|
21100
|
+
constructor(message, closeCode = CLIENT_CLOSE_RECONNECT, retryAfterMs) {
|
|
21098
21101
|
super(message);
|
|
21099
21102
|
this.closeCode = closeCode;
|
|
21103
|
+
this.retryAfterMs = retryAfterMs;
|
|
21100
21104
|
}
|
|
21101
21105
|
};
|
|
21102
|
-
var
|
|
21106
|
+
var AGENT_TOKEN_REFUSED_CODE = 2004;
|
|
21107
|
+
var agentTokenRefused = (detail, options2 = {}) => new RelayAPIError(`Relay refused this Agent Token (${detail}): it is invalid or was revoked, so Relay will not reconnect with it. Create a new Agent Token in Relay Console, or run npx relaymessenger connect , then start again.`, {
|
|
21108
|
+
status: 401,
|
|
21109
|
+
code: options2.code ?? AGENT_TOKEN_REFUSED_CODE,
|
|
21110
|
+
...options2.traceId === void 0 ? {} : { traceId: options2.traceId },
|
|
21111
|
+
...options2.body === void 0 ? {} : { body: options2.body }
|
|
21112
|
+
});
|
|
21113
|
+
var upgradeResponseBody = (status, statusMessage, textBody, retryAfterHeader) => {
|
|
21103
21114
|
let body = textBody;
|
|
21104
21115
|
let message;
|
|
21116
|
+
let code;
|
|
21117
|
+
let retryAfter = Number(retryAfterHeader ?? NaN);
|
|
21105
21118
|
let traceId;
|
|
21106
21119
|
try {
|
|
21107
21120
|
const parsed = textBody ? JSON.parse(textBody) : void 0;
|
|
@@ -21112,9 +21125,22 @@ var upgradeResponseBody = (status, statusMessage, textBody) => {
|
|
|
21112
21125
|
if (isRecord2(parsed.error) && typeof parsed.error.message === "string") {
|
|
21113
21126
|
message = parsed.error.message;
|
|
21114
21127
|
}
|
|
21128
|
+
if (isRecord2(parsed.error) && typeof parsed.error.code === "number") {
|
|
21129
|
+
code = parsed.error.code;
|
|
21130
|
+
}
|
|
21131
|
+
if (isRecord2(parsed.error) && typeof parsed.error.retry_after === "number") {
|
|
21132
|
+
retryAfter = parsed.error.retry_after;
|
|
21133
|
+
}
|
|
21115
21134
|
}
|
|
21116
21135
|
} catch {
|
|
21117
21136
|
}
|
|
21137
|
+
if (status === 401) {
|
|
21138
|
+
return agentTokenRefused(`HTTP 401${message ? `: ${message}` : ""}`, {
|
|
21139
|
+
...code === void 0 ? {} : { code },
|
|
21140
|
+
...traceId === void 0 ? {} : { traceId },
|
|
21141
|
+
body
|
|
21142
|
+
});
|
|
21143
|
+
}
|
|
21118
21144
|
if (status === 409) {
|
|
21119
21145
|
return new RelayWebhookConfiguredError(message ?? "This Agent delivers by webhook; delete its webhook subscription to use the WebSocket.", {
|
|
21120
21146
|
...traceId === void 0 ? {} : { traceId },
|
|
@@ -21123,7 +21149,10 @@ var upgradeResponseBody = (status, statusMessage, textBody) => {
|
|
|
21123
21149
|
}
|
|
21124
21150
|
const fallback = status > 0 ? `Relay WebSocket upgrade failed with HTTP ${status}${statusMessage ? ` ${statusMessage}` : ""}.` : "Relay WebSocket upgrade failed before receiving an HTTP status.";
|
|
21125
21151
|
const errorMessage = message ?? fallback;
|
|
21126
|
-
|
|
21152
|
+
if (status === 429) {
|
|
21153
|
+
return new RetryableWebSocketError(errorMessage, CLIENT_CLOSE_RECONNECT, Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter * 1e3 : void 0);
|
|
21154
|
+
}
|
|
21155
|
+
return status >= 500 || status === 0 ? new RetryableWebSocketError(errorMessage) : new WebSocketStoppedError(errorMessage);
|
|
21127
21156
|
};
|
|
21128
21157
|
var deriveWebSocketURL = (baseURL, observe = false) => {
|
|
21129
21158
|
let url;
|
|
@@ -21166,6 +21195,7 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21166
21195
|
Authorization: `Bearer ${agentToken}`
|
|
21167
21196
|
}
|
|
21168
21197
|
});
|
|
21198
|
+
const statusUnknown = typeof socket.on !== "function";
|
|
21169
21199
|
let chain = Promise.resolve();
|
|
21170
21200
|
let settled = false;
|
|
21171
21201
|
let ready = false;
|
|
@@ -21241,6 +21271,8 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21241
21271
|
};
|
|
21242
21272
|
const onUnexpectedResponse = (_request, response) => {
|
|
21243
21273
|
const chunks = [];
|
|
21274
|
+
const header = response.headers?.["retry-after"];
|
|
21275
|
+
const retryAfterHeader = Array.isArray(header) ? header[0] : header;
|
|
21244
21276
|
let bytes = 0;
|
|
21245
21277
|
response.setEncoding?.("utf8");
|
|
21246
21278
|
response.on("data", (chunk) => {
|
|
@@ -21251,10 +21283,10 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21251
21283
|
chunks.push(value.slice(0, Math.max(0, 65536 - (bytes - value.length))));
|
|
21252
21284
|
});
|
|
21253
21285
|
response.on("end", () => {
|
|
21254
|
-
finish(upgradeResponseBody(response.statusCode ?? 0, response.statusMessage, chunks.join("")));
|
|
21286
|
+
finish(upgradeResponseBody(response.statusCode ?? 0, response.statusMessage, chunks.join(""), retryAfterHeader));
|
|
21255
21287
|
});
|
|
21256
21288
|
response.on("error", () => {
|
|
21257
|
-
finish(upgradeResponseBody(response.statusCode ?? 0, response.statusMessage, chunks.join("")));
|
|
21289
|
+
finish(upgradeResponseBody(response.statusCode ?? 0, response.statusMessage, chunks.join(""), retryAfterHeader));
|
|
21258
21290
|
});
|
|
21259
21291
|
};
|
|
21260
21292
|
const onMessage = (message) => {
|
|
@@ -21297,6 +21329,9 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21297
21329
|
if (parsed.reason === "heartbeat_timeout" || parsed.reason === "restart") {
|
|
21298
21330
|
throw new RetryableWebSocketError(parsed.reason === "restart" ? "Relay WebSocket is restarting." : "Relay WebSocket heartbeat timed out.");
|
|
21299
21331
|
}
|
|
21332
|
+
if (parsed.reason === "revoked") {
|
|
21333
|
+
throw agentTokenRefused("disconnect: revoked");
|
|
21334
|
+
}
|
|
21300
21335
|
if (parsed.reason === "webhook_configured") {
|
|
21301
21336
|
throw new RelayWebhookConfiguredError("Webhook delivery is now configured for this Agent.", { code: 4410 });
|
|
21302
21337
|
}
|
|
@@ -21397,7 +21432,8 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21397
21432
|
if (settled)
|
|
21398
21433
|
return;
|
|
21399
21434
|
stopReceiving();
|
|
21400
|
-
|
|
21435
|
+
const refused = error2 instanceof RelayAPIError && error2.status === 401;
|
|
21436
|
+
socket.close(refused ? 4401 : error2 instanceof WebSocketStoppedError ? error2.closeCode : error2 instanceof WebSocketProtocolError ? error2.closeCode : error2 instanceof RetryableWebSocketError ? error2.closeCode : CLIENT_CLOSE_DURABLE_ACCEPTANCE, refused || error2 instanceof WebSocketStoppedError ? "Relay stopped this consumer" : error2 instanceof WebSocketProtocolError ? "protocol error" : error2 instanceof RetryableWebSocketError ? "Relay requested reconnect" : error2 instanceof DurableApplicationError && error2.sequence !== void 0 ? `durable application failed at sequence ${error2.sequence}` : "durable application failed");
|
|
21401
21437
|
finish(error2);
|
|
21402
21438
|
});
|
|
21403
21439
|
};
|
|
@@ -21418,12 +21454,16 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21418
21454
|
}));
|
|
21419
21455
|
return;
|
|
21420
21456
|
}
|
|
21457
|
+
if (event.code === 4401) {
|
|
21458
|
+
finish(agentTokenRefused(`close 4401${event.reason ? `: ${event.reason}` : ""}`));
|
|
21459
|
+
return;
|
|
21460
|
+
}
|
|
21421
21461
|
if (event.code !== void 0 && event.code >= 4400 && event.code <= 4499 && event.code !== 4408) {
|
|
21422
21462
|
finish(new WebSocketStoppedError(`Relay WebSocket closed permanently (${event.code}): ${event.reason ?? "server policy changed"}.`, event.code));
|
|
21423
21463
|
return;
|
|
21424
21464
|
}
|
|
21425
21465
|
if (!ready) {
|
|
21426
|
-
finish(new Error(`Relay WebSocket closed before ready (${event.code ?? 1006}): ${event.reason ?? "connection ended"}.`));
|
|
21466
|
+
finish(new (statusUnknown ? UnknownStatusWebSocketError : Error)(`Relay WebSocket closed before ready (${event.code ?? 1006}): ${event.reason ?? "connection ended"}.`));
|
|
21427
21467
|
return;
|
|
21428
21468
|
}
|
|
21429
21469
|
finish();
|
|
@@ -21435,7 +21475,7 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21435
21475
|
void drained().then(() => finish());
|
|
21436
21476
|
return;
|
|
21437
21477
|
}
|
|
21438
|
-
const error2 = new Error("Relay WebSocket connection failed.");
|
|
21478
|
+
const error2 = new (statusUnknown && !ready ? UnknownStatusWebSocketError : Error)("Relay WebSocket connection failed.");
|
|
21439
21479
|
void drained().then(() => finish(error2));
|
|
21440
21480
|
};
|
|
21441
21481
|
const onAbort = () => {
|
|
@@ -21455,6 +21495,26 @@ var runConnection = (url, agentToken, options2, Constructor, onReady, onUnknownE
|
|
|
21455
21495
|
else
|
|
21456
21496
|
options2.signal?.addEventListener("abort", onAbort, { once: true });
|
|
21457
21497
|
});
|
|
21498
|
+
var refusedToken = async (baseURL, agentToken, signal) => {
|
|
21499
|
+
try {
|
|
21500
|
+
const url = new URL(baseURL);
|
|
21501
|
+
url.pathname = "/v1/me";
|
|
21502
|
+
url.search = "";
|
|
21503
|
+
url.hash = "";
|
|
21504
|
+
const response = await fetch(url, {
|
|
21505
|
+
headers: { Authorization: `Bearer ${agentToken}` },
|
|
21506
|
+
...signal ? { signal } : {}
|
|
21507
|
+
});
|
|
21508
|
+
if (response.status !== 401) {
|
|
21509
|
+
await response.body?.cancel();
|
|
21510
|
+
return void 0;
|
|
21511
|
+
}
|
|
21512
|
+
const answer = upgradeResponseBody(401, void 0, await response.text());
|
|
21513
|
+
return answer instanceof RelayAPIError ? answer : void 0;
|
|
21514
|
+
} catch {
|
|
21515
|
+
return void 0;
|
|
21516
|
+
}
|
|
21517
|
+
};
|
|
21458
21518
|
var runWebSocket = async (baseURL, agentToken, options2) => {
|
|
21459
21519
|
if (options2.observe !== void 0 && typeof options2.observe !== "boolean") {
|
|
21460
21520
|
throw new TypeError("WebSocket observe must be a boolean when provided.");
|
|
@@ -21483,6 +21543,7 @@ var runWebSocket = async (baseURL, agentToken, options2) => {
|
|
|
21483
21543
|
report(new RelayUnknownEventTypeError(eventType, sequence));
|
|
21484
21544
|
};
|
|
21485
21545
|
while (!options2.signal?.aborted) {
|
|
21546
|
+
let retryAfterMs = 0;
|
|
21486
21547
|
options2.onConnectionState?.("connecting");
|
|
21487
21548
|
try {
|
|
21488
21549
|
await runConnection(url, agentToken, options2, Constructor, (frame) => {
|
|
@@ -21494,13 +21555,19 @@ var runWebSocket = async (baseURL, agentToken, options2) => {
|
|
|
21494
21555
|
failing = false;
|
|
21495
21556
|
attempt = 0;
|
|
21496
21557
|
});
|
|
21497
|
-
} catch (
|
|
21558
|
+
} catch (caught) {
|
|
21559
|
+
if (options2.signal?.aborted)
|
|
21560
|
+
return;
|
|
21561
|
+
const error2 = caught instanceof UnknownStatusWebSocketError ? await refusedToken(baseURL, agentToken, options2.signal) ?? caught : caught;
|
|
21498
21562
|
if (options2.signal?.aborted)
|
|
21499
21563
|
return;
|
|
21500
21564
|
report(error2);
|
|
21501
21565
|
if (error2 instanceof DurableApplicationError)
|
|
21502
21566
|
failing = true;
|
|
21503
|
-
if (error2 instanceof
|
|
21567
|
+
if (error2 instanceof RetryableWebSocketError && error2.retryAfterMs !== void 0) {
|
|
21568
|
+
retryAfterMs = error2.retryAfterMs;
|
|
21569
|
+
}
|
|
21570
|
+
if (error2 instanceof WebSocketStoppedError || error2 instanceof WebSocketProtocolError || error2 instanceof RelayAPIError && !error2.retryable)
|
|
21504
21571
|
throw error2;
|
|
21505
21572
|
attempt += 1;
|
|
21506
21573
|
} finally {
|
|
@@ -21509,7 +21576,7 @@ var runWebSocket = async (baseURL, agentToken, options2) => {
|
|
|
21509
21576
|
if (options2.signal?.aborted)
|
|
21510
21577
|
return;
|
|
21511
21578
|
const ceiling = Math.min(maximum, minimum * 2 ** Math.max(0, attempt - 1));
|
|
21512
|
-
await wait(Math.floor(random() * ceiling), options2.signal);
|
|
21579
|
+
await wait(Math.max(retryAfterMs, Math.floor(random() * ceiling)), options2.signal);
|
|
21513
21580
|
}
|
|
21514
21581
|
};
|
|
21515
21582
|
|
|
@@ -24844,7 +24911,7 @@ var RelayStateStore = class {
|
|
|
24844
24911
|
};
|
|
24845
24912
|
|
|
24846
24913
|
// server.ts
|
|
24847
|
-
var VERSION = true ? "0.3.
|
|
24914
|
+
var VERSION = true ? "0.3.17" : createRequire(import.meta.url)("./package.json").version;
|
|
24848
24915
|
if (process.argv.includes("--version")) {
|
|
24849
24916
|
process.stdout.write(`${VERSION}
|
|
24850
24917
|
`);
|