@yefengr/remote-pi 0.7.4 → 0.7.6
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/README.md +81 -586
- package/dist/bin/supervisord.js +4 -5
- package/dist/bin/supervisord.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -2
- package/dist/daemon/cli-links.d.ts +30 -0
- package/dist/daemon/cli-links.js +134 -0
- package/dist/daemon/cli-links.js.map +1 -0
- package/dist/daemon/commands.d.ts +27 -0
- package/dist/daemon/commands.js +295 -0
- package/dist/daemon/commands.js.map +1 -0
- package/dist/daemon/control_protocol.d.ts +53 -31
- package/dist/daemon/control_protocol.js +8 -31
- package/dist/daemon/control_protocol.js.map +1 -1
- package/dist/daemon/cron_log.d.ts +2 -23
- package/dist/daemon/cron_log.js +10 -25
- package/dist/daemon/cron_log.js.map +1 -1
- package/dist/daemon/cron_registry.d.ts +3 -40
- package/dist/daemon/cron_registry.js +58 -103
- package/dist/daemon/cron_registry.js.map +1 -1
- package/dist/daemon/install-runtime.d.ts +10 -0
- package/dist/daemon/install-runtime.js +81 -0
- package/dist/daemon/install-runtime.js.map +1 -0
- package/dist/daemon/install.d.ts +3 -63
- package/dist/daemon/install.js +5 -289
- package/dist/daemon/install.js.map +1 -1
- package/dist/daemon/preflight.d.ts +51 -0
- package/dist/daemon/preflight.js +136 -0
- package/dist/daemon/preflight.js.map +1 -0
- package/dist/daemon/registry.d.ts +33 -45
- package/dist/daemon/registry.js +171 -117
- package/dist/daemon/registry.js.map +1 -1
- package/dist/daemon/rpc_child.d.ts +92 -146
- package/dist/daemon/rpc_child.js +336 -263
- package/dist/daemon/rpc_child.js.map +1 -1
- package/dist/daemon/status.d.ts +45 -0
- package/dist/daemon/status.js +87 -0
- package/dist/daemon/status.js.map +1 -0
- package/dist/daemon/supervisor-ipc.d.ts +2 -0
- package/dist/daemon/supervisor-ipc.js +20 -0
- package/dist/daemon/supervisor-ipc.js.map +1 -0
- package/dist/daemon/supervisor.d.ts +48 -71
- package/dist/daemon/supervisor.js +430 -420
- package/dist/daemon/supervisor.js.map +1 -1
- package/dist/extension_ui_bridge.d.ts +4 -3
- package/dist/extension_ui_bridge.js +10 -0
- package/dist/extension_ui_bridge.js.map +1 -1
- package/dist/index.d.ts +25 -230
- package/dist/index.js +515 -5553
- package/dist/index.js.map +1 -1
- package/dist/pairing/crypto.d.ts +8 -1
- package/dist/pairing/crypto.js +56 -6
- package/dist/pairing/crypto.js.map +1 -1
- package/dist/pairing/owner_storage.d.ts +42 -0
- package/dist/pairing/owner_storage.js +207 -0
- package/dist/pairing/owner_storage.js.map +1 -0
- package/dist/pairing/qr.d.ts +3 -42
- package/dist/pairing/qr.js +9 -59
- package/dist/pairing/qr.js.map +1 -1
- package/dist/pairing/storage.d.ts +3 -45
- package/dist/pairing/storage.js +10 -223
- package/dist/pairing/storage.js.map +1 -1
- package/dist/protocol/types.d.ts +1 -1
- package/dist/protocol/v2/schemas.d.ts +1 -1
- package/dist/protocol/v2/schemas.js +1 -1
- package/dist/protocol/v2/schemas.js.map +1 -1
- package/dist/runtime/owner_router.d.ts +16 -0
- package/dist/runtime/owner_router.js +37 -0
- package/dist/runtime/owner_router.js.map +1 -0
- package/dist/session/ipc.d.ts +1 -22
- package/dist/session/ipc.js +4 -11
- package/dist/session/ipc.js.map +1 -1
- package/dist/session/local_config.d.ts +4 -47
- package/dist/session/local_config.js +19 -101
- package/dist/session/local_config.js.map +1 -1
- package/dist/transport/peer_channel.d.ts +25 -39
- package/dist/transport/peer_channel.js +74 -131
- package/dist/transport/peer_channel.js.map +1 -1
- package/dist/transport/relay_client.d.ts +26 -70
- package/dist/transport/relay_client.js +37 -106
- package/dist/transport/relay_client.js.map +1 -1
- package/docs/daemon.md +91 -207
- package/package.json +21 -17
- package/dist/daemon/id.d.ts +0 -24
- package/dist/daemon/id.js +0 -36
- package/dist/daemon/id.js.map +0 -1
- package/dist/mcp/mesh_result.d.ts +0 -10
- package/dist/mcp/mesh_result.js +0 -42
- package/dist/mcp/mesh_result.js.map +0 -1
- package/dist/mcp/mesh_server.d.ts +0 -16
- package/dist/mcp/mesh_server.js +0 -327
- package/dist/mcp/mesh_server.js.map +0 -1
- package/dist/mesh/canonical.d.ts +0 -30
- package/dist/mesh/canonical.js +0 -61
- package/dist/mesh/canonical.js.map +0 -1
- package/dist/mesh/client.d.ts +0 -18
- package/dist/mesh/client.js +0 -125
- package/dist/mesh/client.js.map +0 -1
- package/dist/mesh/encoding.d.ts +0 -38
- package/dist/mesh/encoding.js +0 -216
- package/dist/mesh/encoding.js.map +0 -1
- package/dist/mesh/self_revoke.d.ts +0 -73
- package/dist/mesh/self_revoke.js +0 -401
- package/dist/mesh/self_revoke.js.map +0 -1
- package/dist/mesh/siblings.d.ts +0 -49
- package/dist/mesh/siblings.js +0 -159
- package/dist/mesh/siblings.js.map +0 -1
- package/dist/mesh/types.d.ts +0 -34
- package/dist/mesh/types.js +0 -11
- package/dist/mesh/types.js.map +0 -1
- package/dist/mesh/verify.d.ts +0 -17
- package/dist/mesh/verify.js +0 -86
- package/dist/mesh/verify.js.map +0 -1
- package/dist/rooms.d.ts +0 -29
- package/dist/rooms.js +0 -57
- package/dist/rooms.js.map +0 -1
- package/dist/session/bridge.d.ts +0 -37
- package/dist/session/bridge.js +0 -130
- package/dist/session/bridge.js.map +0 -1
- package/dist/session/broker.d.ts +0 -189
- package/dist/session/broker.js +0 -507
- package/dist/session/broker.js.map +0 -1
- package/dist/session/broker_remote.d.ts +0 -74
- package/dist/session/broker_remote.js +0 -583
- package/dist/session/broker_remote.js.map +0 -1
- package/dist/session/cwd_lock.d.ts +0 -33
- package/dist/session/cwd_lock.js +0 -126
- package/dist/session/cwd_lock.js.map +0 -1
- package/dist/session/envelope.d.ts +0 -33
- package/dist/session/envelope.js +0 -117
- package/dist/session/envelope.js.map +0 -1
- package/dist/session/global_config.d.ts +0 -33
- package/dist/session/global_config.js +0 -73
- package/dist/session/global_config.js.map +0 -1
- package/dist/session/leader_election.d.ts +0 -32
- package/dist/session/leader_election.js +0 -106
- package/dist/session/leader_election.js.map +0 -1
- package/dist/session/mesh_node.d.ts +0 -116
- package/dist/session/mesh_node.js +0 -573
- package/dist/session/mesh_node.js.map +0 -1
- package/dist/session/peer.d.ts +0 -139
- package/dist/session/peer.js +0 -451
- package/dist/session/peer.js.map +0 -1
- package/dist/session/peer_inventory.d.ts +0 -13
- package/dist/session/peer_inventory.js +0 -48
- package/dist/session/peer_inventory.js.map +0 -1
- package/dist/session/peer_limits.d.ts +0 -9
- package/dist/session/peer_limits.js +0 -21
- package/dist/session/peer_limits.js.map +0 -1
- package/dist/session/setup_wizard.d.ts +0 -39
- package/dist/session/setup_wizard.js +0 -63
- package/dist/session/setup_wizard.js.map +0 -1
- package/dist/session/tools.d.ts +0 -24
- package/dist/session/tools.js +0 -252
- package/dist/session/tools.js.map +0 -1
- package/dist/session/wizard.d.ts +0 -13
- package/dist/session/wizard.js +0 -20
- package/dist/session/wizard.js.map +0 -1
- package/dist/transport/pi_forward_client.d.ts +0 -29
- package/dist/transport/pi_forward_client.js +0 -62
- package/dist/transport/pi_forward_client.js.map +0 -1
- package/dist/ui/footer.d.ts +0 -32
- package/dist/ui/footer.js +0 -34
- package/dist/ui/footer.js.map +0 -1
- package/skills/agent-network/SKILL.md +0 -310
|
@@ -1,91 +1,47 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
2
|
import type { Ed25519Keypair } from "../pairing/crypto.js";
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
export type EndpointMetadata = {
|
|
4
|
+
kind: "daemon" | "interactive";
|
|
5
|
+
name?: string;
|
|
6
|
+
cwd?: string;
|
|
7
|
+
pid?: number;
|
|
8
|
+
started_at?: number;
|
|
8
9
|
model?: string;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export declare class RoomAlreadyOpenError extends Error {
|
|
24
|
-
readonly roomId: string | undefined;
|
|
25
|
-
constructor(roomId: string | undefined);
|
|
26
|
-
}
|
|
10
|
+
thinking?: string;
|
|
11
|
+
working?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export type HostConnectOptions = {
|
|
14
|
+
role: "host";
|
|
15
|
+
endpointId: string;
|
|
16
|
+
runtimeInstanceId: string;
|
|
17
|
+
metadata: EndpointMetadata;
|
|
18
|
+
authorizedOwnerIds: readonly string[];
|
|
19
|
+
};
|
|
20
|
+
export type OwnerConnectOptions = {
|
|
21
|
+
role: "owner";
|
|
22
|
+
};
|
|
23
|
+
export type ConnectOptions = HostConnectOptions | OwnerConnectOptions;
|
|
27
24
|
export interface RelayClientEvents {
|
|
28
|
-
/** A single JSONL line delivered by the relay (outer envelope). */
|
|
29
25
|
message: [line: string];
|
|
30
26
|
close: [];
|
|
31
27
|
error: [err: Error];
|
|
32
28
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Thin WebSocket client for the Remote Pi relay.
|
|
35
|
-
*
|
|
36
|
-
* Lifecycle:
|
|
37
|
-
* const relay = new RelayClient(url, ed25519Keypair)
|
|
38
|
-
* await relay.connect() // opens WS + runs Ed25519 challenge-response
|
|
39
|
-
* relay.on("message", line => …) // outer envelopes: { peer, ct }
|
|
40
|
-
* relay.send(jsonLine) // write to relay
|
|
41
|
-
* relay.close()
|
|
42
|
-
*
|
|
43
|
-
* Auth sequence (pairing.md §Challenge-response):
|
|
44
|
-
* → { type:"hello", pubkey: "<Ed25519 pubkey base64>" }
|
|
45
|
-
* ← { type:"challenge", nonce: "<32 bytes base64>" }
|
|
46
|
-
* → { type:"auth", sig: "<Ed25519 sig base64>" }
|
|
47
|
-
*/
|
|
29
|
+
/** Authenticated WebSocket client for the endpoint relay. */
|
|
48
30
|
export declare class RelayClient extends EventEmitter {
|
|
49
31
|
private readonly url;
|
|
50
32
|
private readonly keypair;
|
|
51
33
|
private ws;
|
|
52
|
-
/** Epoch ms of the last inbound frame (message / relay ping / pong). */
|
|
53
34
|
private lastActivityAt;
|
|
54
35
|
private livenessTimer;
|
|
55
36
|
constructor(url: string, keypair: Ed25519Keypair);
|
|
56
|
-
/**
|
|
57
|
-
* Connects and completes Ed25519 auth. Resolves when relay is ready.
|
|
58
|
-
*
|
|
59
|
-
* `options.roomId` (12-char id derived from cwd, see `src/rooms.ts`) is
|
|
60
|
-
* included in the hello so the relay can multiplex N concurrent peers
|
|
61
|
-
* with the same Ed25519 pubkey but different rooms (one pi-ext per cwd).
|
|
62
|
-
* Omitting `roomId` is backward-compat with old relays (treated as the
|
|
63
|
-
* default "main" room server-side).
|
|
64
|
-
*
|
|
65
|
-
* Throws `RoomAlreadyOpenError` if the relay rejects the hello because
|
|
66
|
-
* another peer already holds the (pubkey, room_id) tuple. Caller (e.g.
|
|
67
|
-
* `_cmdStart`) maps that to a clearer UI message.
|
|
68
|
-
*/
|
|
69
37
|
connect(options?: ConnectOptions): Promise<void>;
|
|
70
|
-
/** True only while the authenticated Relay WebSocket is currently open. */
|
|
71
38
|
isOpen(): boolean;
|
|
72
|
-
/** Sends a raw line to the relay (caller is responsible for framing). */
|
|
73
39
|
send(line: string): void;
|
|
74
|
-
/**
|
|
75
|
-
* Sends a control frame to the relay (not routed to app peer). Used for
|
|
76
|
-
* out-of-band metadata updates like `room_meta_update`. Silently no-ops if
|
|
77
|
-
* the WS isn't open (best-effort: control frames are observational; we
|
|
78
|
-
* don't want them throwing inside SDK event callbacks).
|
|
79
|
-
*/
|
|
80
40
|
sendControl(frame: object): void;
|
|
81
41
|
close(): void;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
private
|
|
86
|
-
private
|
|
87
|
-
private _authenticate;
|
|
88
|
-
/** Waits for the next single WS message with a timeout. */
|
|
89
|
-
private _nextMsg;
|
|
90
|
-
private _rawSend;
|
|
42
|
+
private startLiveness;
|
|
43
|
+
private stopLiveness;
|
|
44
|
+
private authenticate;
|
|
45
|
+
private nextMessage;
|
|
46
|
+
private rawSend;
|
|
91
47
|
}
|
|
@@ -2,48 +2,13 @@ import { EventEmitter } from "node:events";
|
|
|
2
2
|
import WebSocket from "ws";
|
|
3
3
|
import { ed25519Sign } from "../pairing/crypto.js";
|
|
4
4
|
const AUTH_TIMEOUT_MS = 5_000;
|
|
5
|
-
|
|
6
|
-
* Liveness watchdog. The relay sends a WS Ping every ~25s (relay `peer.rs`),
|
|
7
|
-
* so a healthy connection sees inbound frames at least that often. If NOTHING
|
|
8
|
-
* arrives for this long the socket is silently dead — NAT/router idle drop,
|
|
9
|
-
* laptop sleep, or the relay/Cloudflare reaping the connection WITHOUT a clean
|
|
10
|
-
* close frame. That half-open case never fires `close`, so reconnect never
|
|
11
|
-
* triggers and a background daemon sits "online" but dead after a few idle
|
|
12
|
-
* hours. We force-close on timeout so `close` drives the caller's reconnect.
|
|
13
|
-
*/
|
|
14
|
-
const LIVENESS_TIMEOUT_MS = 70_000; // ~2.8 missed relay pings → confidently dead
|
|
5
|
+
const LIVENESS_TIMEOUT_MS = 70_000;
|
|
15
6
|
const LIVENESS_CHECK_MS = 20_000;
|
|
16
|
-
/**
|
|
17
|
-
export class RoomAlreadyOpenError extends Error {
|
|
18
|
-
roomId;
|
|
19
|
-
constructor(roomId) {
|
|
20
|
-
super(roomId
|
|
21
|
-
? `relay rejected hello: room ${roomId} already open for this peer`
|
|
22
|
-
: "relay rejected hello: peer already connected");
|
|
23
|
-
this.roomId = roomId;
|
|
24
|
-
this.name = "RoomAlreadyOpenError";
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Thin WebSocket client for the Remote Pi relay.
|
|
29
|
-
*
|
|
30
|
-
* Lifecycle:
|
|
31
|
-
* const relay = new RelayClient(url, ed25519Keypair)
|
|
32
|
-
* await relay.connect() // opens WS + runs Ed25519 challenge-response
|
|
33
|
-
* relay.on("message", line => …) // outer envelopes: { peer, ct }
|
|
34
|
-
* relay.send(jsonLine) // write to relay
|
|
35
|
-
* relay.close()
|
|
36
|
-
*
|
|
37
|
-
* Auth sequence (pairing.md §Challenge-response):
|
|
38
|
-
* → { type:"hello", pubkey: "<Ed25519 pubkey base64>" }
|
|
39
|
-
* ← { type:"challenge", nonce: "<32 bytes base64>" }
|
|
40
|
-
* → { type:"auth", sig: "<Ed25519 sig base64>" }
|
|
41
|
-
*/
|
|
7
|
+
/** Authenticated WebSocket client for the endpoint relay. */
|
|
42
8
|
export class RelayClient extends EventEmitter {
|
|
43
9
|
url;
|
|
44
10
|
keypair;
|
|
45
11
|
ws = null;
|
|
46
|
-
/** Epoch ms of the last inbound frame (message / relay ping / pong). */
|
|
47
12
|
lastActivityAt = 0;
|
|
48
13
|
livenessTimer = null;
|
|
49
14
|
constructor(url, keypair) {
|
|
@@ -51,31 +16,14 @@ export class RelayClient extends EventEmitter {
|
|
|
51
16
|
this.url = url;
|
|
52
17
|
this.keypair = keypair;
|
|
53
18
|
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Connects and completes Ed25519 auth. Resolves when relay is ready.
|
|
57
|
-
*
|
|
58
|
-
* `options.roomId` (12-char id derived from cwd, see `src/rooms.ts`) is
|
|
59
|
-
* included in the hello so the relay can multiplex N concurrent peers
|
|
60
|
-
* with the same Ed25519 pubkey but different rooms (one pi-ext per cwd).
|
|
61
|
-
* Omitting `roomId` is backward-compat with old relays (treated as the
|
|
62
|
-
* default "main" room server-side).
|
|
63
|
-
*
|
|
64
|
-
* Throws `RoomAlreadyOpenError` if the relay rejects the hello because
|
|
65
|
-
* another peer already holds the (pubkey, room_id) tuple. Caller (e.g.
|
|
66
|
-
* `_cmdStart`) maps that to a clearer UI message.
|
|
67
|
-
*/
|
|
68
|
-
async connect(options = {}) {
|
|
19
|
+
async connect(options = { role: "owner" }) {
|
|
69
20
|
return new Promise((resolve, reject) => {
|
|
70
21
|
const ws = new WebSocket(this.url);
|
|
71
22
|
this.ws = ws;
|
|
72
23
|
ws.on("error", (err) => reject(err));
|
|
73
24
|
ws.on("open", async () => {
|
|
74
25
|
try {
|
|
75
|
-
await this.
|
|
76
|
-
// Auth done — wire persistent message handler. Every inbound frame
|
|
77
|
-
// (data, plus the relay's keepalive ping/pong below) refreshes the
|
|
78
|
-
// liveness clock.
|
|
26
|
+
await this.authenticate(ws, options);
|
|
79
27
|
this.lastActivityAt = Date.now();
|
|
80
28
|
ws.on("message", (raw) => {
|
|
81
29
|
this.lastActivityAt = Date.now();
|
|
@@ -86,17 +34,13 @@ export class RelayClient extends EventEmitter {
|
|
|
86
34
|
this.emit("message", trimmed);
|
|
87
35
|
}
|
|
88
36
|
});
|
|
89
|
-
// The relay pings every ~25s; `ws` auto-replies Pong (keeping the
|
|
90
|
-
// relay's view of us alive). The relay ignores client pings rather
|
|
91
|
-
// than ponging, so these inbound pings — not a ping/pong we initiate
|
|
92
|
-
// — are our liveness signal.
|
|
93
37
|
ws.on("ping", () => { this.lastActivityAt = Date.now(); });
|
|
94
38
|
ws.on("pong", () => { this.lastActivityAt = Date.now(); });
|
|
95
39
|
ws.on("close", () => {
|
|
96
|
-
this.
|
|
40
|
+
this.stopLiveness();
|
|
97
41
|
this.emit("close");
|
|
98
42
|
});
|
|
99
|
-
this.
|
|
43
|
+
this.startLiveness(ws);
|
|
100
44
|
resolve();
|
|
101
45
|
}
|
|
102
46
|
catch (err) {
|
|
@@ -106,62 +50,56 @@ export class RelayClient extends EventEmitter {
|
|
|
106
50
|
});
|
|
107
51
|
});
|
|
108
52
|
}
|
|
109
|
-
/** True only while the authenticated Relay WebSocket is currently open. */
|
|
110
53
|
isOpen() {
|
|
111
54
|
return this.ws?.readyState === WebSocket.OPEN;
|
|
112
55
|
}
|
|
113
|
-
/** Sends a raw line to the relay (caller is responsible for framing). */
|
|
114
56
|
send(line) {
|
|
115
57
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
116
58
|
throw new Error("relay: not connected");
|
|
117
59
|
}
|
|
118
60
|
this.ws.send(line);
|
|
119
61
|
}
|
|
120
|
-
/**
|
|
121
|
-
* Sends a control frame to the relay (not routed to app peer). Used for
|
|
122
|
-
* out-of-band metadata updates like `room_meta_update`. Silently no-ops if
|
|
123
|
-
* the WS isn't open (best-effort: control frames are observational; we
|
|
124
|
-
* don't want them throwing inside SDK event callbacks).
|
|
125
|
-
*/
|
|
126
62
|
sendControl(frame) {
|
|
127
63
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
|
|
128
64
|
return;
|
|
129
65
|
this.ws.send(JSON.stringify(frame));
|
|
130
66
|
}
|
|
131
67
|
close() {
|
|
132
|
-
this.
|
|
68
|
+
this.stopLiveness();
|
|
133
69
|
this.ws?.close();
|
|
134
70
|
this.ws = null;
|
|
135
71
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
* `LIVENESS_TIMEOUT_MS` — see the constant's doc for why. `terminate()`
|
|
139
|
-
* fires `close`, which the owner turns into a reconnect. */
|
|
140
|
-
_startLiveness(ws) {
|
|
141
|
-
this._stopLiveness();
|
|
72
|
+
startLiveness(ws) {
|
|
73
|
+
this.stopLiveness();
|
|
142
74
|
this.livenessTimer = setInterval(() => {
|
|
143
75
|
if (Date.now() - this.lastActivityAt > LIVENESS_TIMEOUT_MS) {
|
|
144
|
-
this.
|
|
76
|
+
this.stopLiveness();
|
|
145
77
|
ws.terminate();
|
|
146
78
|
}
|
|
147
79
|
}, LIVENESS_CHECK_MS);
|
|
148
80
|
}
|
|
149
|
-
|
|
150
|
-
if (this.livenessTimer)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
81
|
+
stopLiveness() {
|
|
82
|
+
if (!this.livenessTimer)
|
|
83
|
+
return;
|
|
84
|
+
clearInterval(this.livenessTimer);
|
|
85
|
+
this.livenessTimer = null;
|
|
154
86
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
87
|
+
async authenticate(ws, options) {
|
|
88
|
+
const pubkey = Buffer.from(this.keypair.publicKey).toString("base64");
|
|
89
|
+
const hello = options.role === "host"
|
|
90
|
+
? {
|
|
91
|
+
type: "hello",
|
|
92
|
+
protocol_version: 2,
|
|
93
|
+
role: "host",
|
|
94
|
+
pubkey,
|
|
95
|
+
endpoint_id: options.endpointId,
|
|
96
|
+
runtime_instance_id: options.runtimeInstanceId,
|
|
97
|
+
metadata: options.metadata,
|
|
98
|
+
authorized_owner_ids: options.authorizedOwnerIds,
|
|
99
|
+
}
|
|
100
|
+
: { type: "hello", protocol_version: 2, role: "owner", pubkey };
|
|
101
|
+
this.rawSend(ws, JSON.stringify(hello));
|
|
102
|
+
const challengeRaw = await this.nextMessage(ws);
|
|
165
103
|
let challenge;
|
|
166
104
|
try {
|
|
167
105
|
challenge = JSON.parse(challengeRaw);
|
|
@@ -170,27 +108,20 @@ export class RelayClient extends EventEmitter {
|
|
|
170
108
|
throw new Error(`relay auth_failed: not JSON: ${challengeRaw}`);
|
|
171
109
|
}
|
|
172
110
|
if (challenge.type === "error") {
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
throw new RoomAlreadyOpenError(opts.roomId);
|
|
176
|
-
}
|
|
177
|
-
throw new Error(`relay rejected hello: ${code || challenge.message || "unknown"}`);
|
|
111
|
+
const detail = challenge.code || challenge.message || "unknown";
|
|
112
|
+
throw new Error(`relay rejected hello: ${detail}`);
|
|
178
113
|
}
|
|
179
114
|
if (challenge.type !== "challenge" || !challenge.nonce) {
|
|
180
115
|
throw new Error(`relay auth_failed: expected challenge, got ${challengeRaw}`);
|
|
181
116
|
}
|
|
182
117
|
const nonce = Buffer.from(challenge.nonce, "base64");
|
|
183
|
-
const sig = ed25519Sign(this.keypair.secretKey, nonce);
|
|
184
118
|
const auth = {
|
|
185
119
|
type: "auth",
|
|
186
|
-
sig: Buffer.from(
|
|
120
|
+
sig: Buffer.from(ed25519Sign(this.keypair.secretKey, nonce)).toString("base64"),
|
|
187
121
|
};
|
|
188
|
-
this.
|
|
189
|
-
// Relay does not send an explicit "ok" — it simply starts routing.
|
|
190
|
-
// Proceed immediately after sending auth.
|
|
122
|
+
this.rawSend(ws, JSON.stringify(auth));
|
|
191
123
|
}
|
|
192
|
-
|
|
193
|
-
_nextMsg(ws) {
|
|
124
|
+
nextMessage(ws) {
|
|
194
125
|
return new Promise((resolve, reject) => {
|
|
195
126
|
const timer = setTimeout(() => reject(new Error("relay auth timeout")), AUTH_TIMEOUT_MS);
|
|
196
127
|
ws.once("message", (raw) => {
|
|
@@ -199,7 +130,7 @@ export class RelayClient extends EventEmitter {
|
|
|
199
130
|
});
|
|
200
131
|
});
|
|
201
132
|
}
|
|
202
|
-
|
|
133
|
+
rawSend(ws, data) {
|
|
203
134
|
ws.send(data);
|
|
204
135
|
}
|
|
205
136
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay_client.js","sourceRoot":"","sources":["../../src/transport/relay_client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,MAAM,eAAe,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"relay_client.js","sourceRoot":"","sources":["../../src/transport/relay_client.ts"],"names":[],"mappings":"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"}
|