agent-comms 1.13.0 → 1.15.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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/dist/bridges/claude-code/channel.d.ts.map +1 -1
- package/dist/bridges/claude-code/channel.js +6 -1
- package/dist/bridges/claude-code/channel.js.map +1 -1
- package/dist/bridges/codex/tool.d.ts.map +1 -1
- package/dist/bridges/codex/tool.js +6 -1
- package/dist/bridges/codex/tool.js.map +1 -1
- package/dist/bridges/mcp/index.d.ts.map +1 -1
- package/dist/bridges/mcp/index.js +6 -1
- package/dist/bridges/mcp/index.js.map +1 -1
- package/dist/bridges/opencode/plugin.d.ts.map +1 -1
- package/dist/bridges/opencode/plugin.js +5 -0
- package/dist/bridges/opencode/plugin.js.map +1 -1
- package/dist/bridges/pi/index.d.ts +5 -2
- package/dist/bridges/pi/index.d.ts.map +1 -1
- package/dist/bridges/pi/index.js +125 -20
- package/dist/bridges/pi/index.js.map +1 -1
- package/dist/bridges/user/controller.d.ts +10 -1
- package/dist/bridges/user/controller.d.ts.map +1 -1
- package/dist/bridges/user/controller.js +37 -1
- package/dist/bridges/user/controller.js.map +1 -1
- package/dist/bridges/user/tui.js +4 -0
- package/dist/bridges/user/tui.js.map +1 -1
- package/dist/bridges/user/web/build.d.ts +4 -4
- package/dist/bridges/user/web/build.js +53 -34
- package/dist/bridges/user/web/build.js.map +1 -1
- package/dist/bridges/user/web/frontend/components/App.d.ts +28 -0
- package/dist/bridges/user/web/frontend/components/App.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/components/App.js +7 -0
- package/dist/bridges/user/web/frontend/components/App.js.map +1 -0
- package/dist/bridges/user/web/frontend/components/ChatArea.d.ts +14 -0
- package/dist/bridges/user/web/frontend/components/ChatArea.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/components/ChatArea.js +38 -0
- package/dist/bridges/user/web/frontend/components/ChatArea.js.map +1 -0
- package/dist/bridges/user/web/frontend/components/CreateRoomForm.d.ts +11 -0
- package/dist/bridges/user/web/frontend/components/CreateRoomForm.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/components/CreateRoomForm.js +33 -0
- package/dist/bridges/user/web/frontend/components/CreateRoomForm.js.map +1 -0
- package/dist/bridges/user/web/frontend/components/JoinForm.d.ts +11 -0
- package/dist/bridges/user/web/frontend/components/JoinForm.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/components/JoinForm.js +28 -0
- package/dist/bridges/user/web/frontend/components/JoinForm.js.map +1 -0
- package/dist/bridges/user/web/frontend/components/Message.d.ts +8 -0
- package/dist/bridges/user/web/frontend/components/Message.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/components/Message.js +15 -0
- package/dist/bridges/user/web/frontend/components/Message.js.map +1 -0
- package/dist/bridges/user/web/frontend/components/MessageList.d.ts +8 -0
- package/dist/bridges/user/web/frontend/components/MessageList.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/components/MessageList.js +16 -0
- package/dist/bridges/user/web/frontend/components/MessageList.js.map +1 -0
- package/dist/bridges/user/web/frontend/components/ProjectTree.d.ts +17 -0
- package/dist/bridges/user/web/frontend/components/ProjectTree.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/components/ProjectTree.js +62 -0
- package/dist/bridges/user/web/frontend/components/ProjectTree.js.map +1 -0
- package/dist/bridges/user/web/frontend/components/RelayPanel.d.ts +15 -0
- package/dist/bridges/user/web/frontend/components/RelayPanel.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/components/RelayPanel.js +46 -0
- package/dist/bridges/user/web/frontend/components/RelayPanel.js.map +1 -0
- package/dist/bridges/user/web/frontend/components/Sidebar.d.ts +21 -0
- package/dist/bridges/user/web/frontend/components/Sidebar.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/components/Sidebar.js +37 -0
- package/dist/bridges/user/web/frontend/components/Sidebar.js.map +1 -0
- package/dist/bridges/user/web/frontend/dom.d.ts +12 -22
- package/dist/bridges/user/web/frontend/dom.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/dom.js +24 -49
- package/dist/bridges/user/web/frontend/dom.js.map +1 -1
- package/dist/bridges/user/web/frontend/input.d.ts +15 -0
- package/dist/bridges/user/web/frontend/input.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/input.js +39 -1
- package/dist/bridges/user/web/frontend/input.js.map +1 -1
- package/dist/bridges/user/web/frontend/main.d.ts +3 -3
- package/dist/bridges/user/web/frontend/main.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/main.js +135 -52
- package/dist/bridges/user/web/frontend/main.js.map +1 -1
- package/dist/bridges/user/web/frontend/mesh-client.d.ts +43 -0
- package/dist/bridges/user/web/frontend/mesh-client.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/mesh-client.js +132 -0
- package/dist/bridges/user/web/frontend/mesh-client.js.map +1 -0
- package/dist/bridges/user/web/frontend/mesh-worker.d.ts +14 -0
- package/dist/bridges/user/web/frontend/mesh-worker.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/mesh-worker.js +274 -0
- package/dist/bridges/user/web/frontend/mesh-worker.js.map +1 -0
- package/dist/bridges/user/web/frontend/messages.d.ts +17 -0
- package/dist/bridges/user/web/frontend/messages.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/messages.js +82 -0
- package/dist/bridges/user/web/frontend/messages.js.map +1 -0
- package/dist/bridges/user/web/frontend/project-tree.d.ts +9 -0
- package/dist/bridges/user/web/frontend/project-tree.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/project-tree.js +173 -0
- package/dist/bridges/user/web/frontend/project-tree.js.map +1 -0
- package/dist/bridges/user/web/frontend/relay-client.d.ts +40 -0
- package/dist/bridges/user/web/frontend/relay-client.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/relay-client.js +97 -0
- package/dist/bridges/user/web/frontend/relay-client.js.map +1 -0
- package/dist/bridges/user/web/frontend/relay-worker.d.ts +15 -0
- package/dist/bridges/user/web/frontend/relay-worker.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/relay-worker.js +366 -0
- package/dist/bridges/user/web/frontend/relay-worker.js.map +1 -0
- package/dist/bridges/user/web/frontend/state.d.ts +8 -1
- package/dist/bridges/user/web/frontend/state.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/state.js +17 -1
- package/dist/bridges/user/web/frontend/state.js.map +1 -1
- package/dist/bridges/user/web/frontend/sw.d.ts +16 -0
- package/dist/bridges/user/web/frontend/sw.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/sw.js +145 -0
- package/dist/bridges/user/web/frontend/sw.js.map +1 -0
- package/dist/bridges/user/web/frontend/types.d.ts +52 -0
- package/dist/bridges/user/web/frontend/types.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/url-sync.d.ts +48 -0
- package/dist/bridges/user/web/frontend/url-sync.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/url-sync.js +74 -0
- package/dist/bridges/user/web/frontend/url-sync.js.map +1 -0
- package/dist/bridges/user/web/server.d.ts +10 -3
- package/dist/bridges/user/web/server.d.ts.map +1 -1
- package/dist/bridges/user/web/server.js +280 -15
- package/dist/bridges/user/web/server.js.map +1 -1
- package/dist/bridges/user/web/test/web-server.integration.test.d.ts +7 -0
- package/dist/bridges/user/web/test/web-server.integration.test.d.ts.map +1 -0
- package/dist/bridges/user/web/test/web-server.integration.test.js +187 -0
- package/dist/bridges/user/web/test/web-server.integration.test.js.map +1 -0
- package/dist/core/bridge.d.ts +43 -0
- package/dist/core/bridge.d.ts.map +1 -1
- package/dist/core/bridge.js +197 -0
- package/dist/core/bridge.js.map +1 -1
- package/dist/core/comms-store.d.ts +22 -1
- package/dist/core/comms-store.d.ts.map +1 -1
- package/dist/core/discovery-mdns.d.ts +33 -0
- package/dist/core/discovery-mdns.d.ts.map +1 -0
- package/dist/core/discovery-mdns.js +182 -0
- package/dist/core/discovery-mdns.js.map +1 -0
- package/dist/core/discovery-tailscale.d.ts +40 -0
- package/dist/core/discovery-tailscale.d.ts.map +1 -0
- package/dist/core/discovery-tailscale.js +158 -0
- package/dist/core/discovery-tailscale.js.map +1 -0
- package/dist/core/discovery.d.ts +82 -0
- package/dist/core/discovery.d.ts.map +1 -0
- package/dist/core/discovery.js +194 -0
- package/dist/core/discovery.js.map +1 -0
- package/dist/core/federation.d.ts +100 -0
- package/dist/core/federation.d.ts.map +1 -0
- package/dist/core/federation.js +411 -0
- package/dist/core/federation.js.map +1 -0
- package/dist/core/identity.d.ts +31 -0
- package/dist/core/identity.d.ts.map +1 -0
- package/dist/core/identity.js +251 -0
- package/dist/core/identity.js.map +1 -0
- package/dist/core/index.d.ts +12 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +7 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/mesh-store.d.ts +75 -26
- package/dist/core/mesh-store.d.ts.map +1 -1
- package/dist/core/mesh-store.js +570 -355
- package/dist/core/mesh-store.js.map +1 -1
- package/dist/core/push-manager.d.ts +41 -0
- package/dist/core/push-manager.d.ts.map +1 -0
- package/dist/core/push-manager.js +60 -0
- package/dist/core/push-manager.js.map +1 -0
- package/dist/core/store.d.ts +21 -1
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +44 -0
- package/dist/core/store.js.map +1 -1
- package/dist/core/tcp-transport.d.ts +77 -0
- package/dist/core/tcp-transport.d.ts.map +1 -0
- package/dist/core/tcp-transport.js +596 -0
- package/dist/core/tcp-transport.js.map +1 -0
- package/dist/core/test/bridge.unit.test.d.ts +5 -0
- package/dist/core/test/bridge.unit.test.d.ts.map +1 -0
- package/dist/core/test/bridge.unit.test.js +120 -0
- package/dist/core/test/bridge.unit.test.js.map +1 -0
- package/dist/core/test/identity.unit.test.d.ts +5 -0
- package/dist/core/test/identity.unit.test.d.ts.map +1 -0
- package/dist/core/test/identity.unit.test.js +70 -0
- package/dist/core/test/identity.unit.test.js.map +1 -0
- package/dist/core/tls-transport.d.ts +69 -0
- package/dist/core/tls-transport.d.ts.map +1 -0
- package/dist/core/tls-transport.js +602 -0
- package/dist/core/tls-transport.js.map +1 -0
- package/dist/core/tool.d.ts +23 -2
- package/dist/core/tool.d.ts.map +1 -1
- package/dist/core/tool.js +269 -1
- package/dist/core/tool.js.map +1 -1
- package/dist/core/transport.d.ts +166 -0
- package/dist/core/transport.d.ts.map +1 -0
- package/dist/core/transport.js +20 -0
- package/dist/core/transport.js.map +1 -0
- package/dist/core/types.d.ts +146 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +77 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/vapid.d.ts +22 -0
- package/dist/core/vapid.d.ts.map +1 -0
- package/dist/core/vapid.js +50 -0
- package/dist/core/vapid.js.map +1 -0
- package/dist/core/web-push.d.ts +37 -0
- package/dist/core/web-push.d.ts.map +1 -0
- package/dist/core/web-push.js +198 -0
- package/dist/core/web-push.js.map +1 -0
- package/dist/core/wire-protocol.d.ts +131 -0
- package/dist/core/wire-protocol.d.ts.map +1 -0
- package/dist/core/wire-protocol.js +54 -0
- package/dist/core/wire-protocol.js.map +1 -0
- package/dist/core/ws-transport.d.ts +71 -0
- package/dist/core/ws-transport.d.ts.map +1 -0
- package/dist/core/ws-transport.js +560 -0
- package/dist/core/ws-transport.js.map +1 -0
- package/dist/test/approval.integration.test.d.ts +9 -0
- package/dist/test/approval.integration.test.d.ts.map +1 -0
- package/dist/test/approval.integration.test.js +361 -0
- package/dist/test/approval.integration.test.js.map +1 -0
- package/dist/test/delivery-receipt.helper.d.ts +16 -0
- package/dist/test/delivery-receipt.helper.d.ts.map +1 -0
- package/dist/test/delivery-receipt.helper.js +409 -0
- package/dist/test/delivery-receipt.helper.js.map +1 -0
- package/dist/test/delivery-receipt.runner.d.ts +13 -0
- package/dist/test/delivery-receipt.runner.d.ts.map +1 -0
- package/dist/test/delivery-receipt.runner.js +51 -0
- package/dist/test/delivery-receipt.runner.js.map +1 -0
- package/dist/test/federation.integration.test.d.ts +15 -0
- package/dist/test/federation.integration.test.d.ts.map +1 -0
- package/dist/test/federation.integration.test.js +218 -0
- package/dist/test/federation.integration.test.js.map +1 -0
- package/dist/test/listener-policy.integration.test.d.ts +9 -0
- package/dist/test/listener-policy.integration.test.d.ts.map +1 -0
- package/dist/test/listener-policy.integration.test.js +239 -0
- package/dist/test/listener-policy.integration.test.js.map +1 -0
- package/dist/test/tls-transport.integration.test.d.ts +8 -0
- package/dist/test/tls-transport.integration.test.d.ts.map +1 -0
- package/dist/test/tls-transport.integration.test.js +158 -0
- package/dist/test/tls-transport.integration.test.js.map +1 -0
- package/dist/test/visibility.integration.test.d.ts +12 -0
- package/dist/test/visibility.integration.test.d.ts.map +1 -0
- package/dist/test/visibility.integration.test.js +181 -0
- package/dist/test/visibility.integration.test.js.map +1 -0
- package/package.json +7 -3
- package/dist/bridges/user/web/frontend/render.d.ts +0 -30
- package/dist/bridges/user/web/frontend/render.d.ts.map +0 -1
- package/dist/bridges/user/web/frontend/render.js +0 -129
- package/dist/bridges/user/web/frontend/render.js.map +0 -1
- package/dist/bridges/user/web/frontend/test/dom.unit.test.d.ts +0 -5
- package/dist/bridges/user/web/frontend/test/dom.unit.test.d.ts.map +0 -1
- package/dist/bridges/user/web/frontend/test/dom.unit.test.js +0 -149
- package/dist/bridges/user/web/frontend/test/dom.unit.test.js.map +0 -1
- package/dist/bridges/user/web/frontend/test/input.unit.test.d.ts +0 -5
- package/dist/bridges/user/web/frontend/test/input.unit.test.d.ts.map +0 -1
- package/dist/bridges/user/web/frontend/test/input.unit.test.js +0 -131
- package/dist/bridges/user/web/frontend/test/input.unit.test.js.map +0 -1
- package/dist/bridges/user/web/frontend/test/render.unit.test.d.ts +0 -5
- package/dist/bridges/user/web/frontend/test/render.unit.test.d.ts.map +0 -1
- package/dist/bridges/user/web/frontend/test/render.unit.test.js +0 -436
- package/dist/bridges/user/web/frontend/test/render.unit.test.js.map +0 -1
- package/dist/bridges/user/web/frontend/test/state.unit.test.d.ts +0 -5
- package/dist/bridges/user/web/frontend/test/state.unit.test.d.ts.map +0 -1
- package/dist/bridges/user/web/frontend/test/state.unit.test.js +0 -119
- package/dist/bridges/user/web/frontend/test/state.unit.test.js.map +0 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web Push encryption and VAPID JWT signing (RFC 8291 + RFC 8292).
|
|
3
|
+
*
|
|
4
|
+
* Implements the Web Push protocol using only Node.js built-in `crypto`
|
|
5
|
+
* and `https` — no external dependencies.
|
|
6
|
+
*
|
|
7
|
+
* Encryption flow (RFC 8291):
|
|
8
|
+
* 1. Derive a shared ECDH secret from the subscription's p256dh key
|
|
9
|
+
* 2. HKDF-derive the encryption key and nonce from the shared secret + auth
|
|
10
|
+
* 3. Encrypt the payload with AES-128-GCM
|
|
11
|
+
* 4. Prepend the sender's public key (65 bytes) to the ciphertext
|
|
12
|
+
*
|
|
13
|
+
* VAPID signing (RFC 8292):
|
|
14
|
+
* 1. Build a JWT with { sub, exp, aud } claims
|
|
15
|
+
* 2. Sign with ES256 (ECDSA + P-256 + SHA-256)
|
|
16
|
+
* 3. Append the public key and token to the Crypto-Key header
|
|
17
|
+
*/
|
|
18
|
+
import * as crypto from "node:crypto";
|
|
19
|
+
import * as https from "node:https";
|
|
20
|
+
import * as http from "node:http";
|
|
21
|
+
import { URL } from "node:url";
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Constants
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
const CONTENT_ENCODING = "aes128gcm";
|
|
26
|
+
const KEY_LENGTH = 16;
|
|
27
|
+
const NONCE_LENGTH = 12;
|
|
28
|
+
const SALT_LENGTH = 16;
|
|
29
|
+
const MAX_PAYLOAD_SIZE = 4078;
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Public API
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
/**
|
|
34
|
+
* Send a Web Push notification.
|
|
35
|
+
*
|
|
36
|
+
* Encrypts the payload per RFC 8291, signs with VAPID per RFC 8292,
|
|
37
|
+
* and POSTs to the push service endpoint.
|
|
38
|
+
*/
|
|
39
|
+
export async function sendWebPush(subscription, payload, vapidKeys, subject) {
|
|
40
|
+
const plaintext = JSON.stringify(payload);
|
|
41
|
+
const plaintextBuf = Buffer.from(plaintext, "utf-8");
|
|
42
|
+
if (plaintextBuf.length > MAX_PAYLOAD_SIZE) {
|
|
43
|
+
throw new Error(`Payload too large: ${String(plaintextBuf.length)} bytes (max ${String(MAX_PAYLOAD_SIZE)})`);
|
|
44
|
+
}
|
|
45
|
+
const encrypted = encrypt(plaintextBuf, subscription.keys);
|
|
46
|
+
const headers = buildHeaders(encrypted, subscription.endpoint, vapidKeys, subject);
|
|
47
|
+
await post(subscription.endpoint, headers, encrypted);
|
|
48
|
+
}
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Encryption (RFC 8291)
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
function encrypt(plaintext, keys) {
|
|
53
|
+
// Decode the subscription's p256dh and auth keys
|
|
54
|
+
const recipientPubKey = base64urlDecode(keys.p256dh);
|
|
55
|
+
const authKey = base64urlDecode(keys.auth);
|
|
56
|
+
// Generate an ephemeral ECDH key pair for this message
|
|
57
|
+
const ecdh = crypto.generateKeyPairSync("ec", { namedCurve: "P-256" });
|
|
58
|
+
const senderPrivateKey = crypto.createPrivateKey({
|
|
59
|
+
key: ecdh.privateKey.export({ type: "pkcs8", format: "der" }),
|
|
60
|
+
format: "der",
|
|
61
|
+
type: "pkcs8",
|
|
62
|
+
});
|
|
63
|
+
const senderPublicDer = ecdh.publicKey.export({
|
|
64
|
+
type: "spki",
|
|
65
|
+
format: "der",
|
|
66
|
+
});
|
|
67
|
+
const senderPublicKey = senderPublicDer.subarray(senderPublicDer.length - 65);
|
|
68
|
+
// Derive the shared secret via ECDH
|
|
69
|
+
const sharedSecret = crypto.diffieHellman({
|
|
70
|
+
privateKey: senderPrivateKey,
|
|
71
|
+
publicKey: crypto.createPublicKey({
|
|
72
|
+
key: concat(Buffer.from("3059301306072a8648ce3d020106082a8648ce3d030107034200", "hex"), recipientPubKey),
|
|
73
|
+
format: "der",
|
|
74
|
+
type: "spki",
|
|
75
|
+
}),
|
|
76
|
+
});
|
|
77
|
+
// Derive the pseudo-random key (PRK) using HKDF with auth
|
|
78
|
+
const prk = hkdfExtract(authKey, sharedSecret);
|
|
79
|
+
// Derive the encryption key and nonce
|
|
80
|
+
const keyInfo = concat(Buffer.from("Content-Encoding: aes128gcm\0", "utf-8"), senderPublicKey);
|
|
81
|
+
const nonceInfo = Buffer.from("Content-Encoding: nonce\0", "utf-8");
|
|
82
|
+
const encryptionKey = hkdfExpand(prk, keyInfo, KEY_LENGTH);
|
|
83
|
+
const nonce = hkdfExpand(prk, nonceInfo, NONCE_LENGTH);
|
|
84
|
+
// Generate a random salt
|
|
85
|
+
const salt = crypto.randomBytes(SALT_LENGTH);
|
|
86
|
+
// Pad the plaintext: plaintext + 2-byte padding delimiter (0x02 0x00 for no padding)
|
|
87
|
+
// RFC 8291 §4: record is plaintext || 0x02 || padding zeros
|
|
88
|
+
const padded = concat(plaintext, Buffer.from([0x02]));
|
|
89
|
+
// Encrypt with AES-128-GCM
|
|
90
|
+
const cipher = crypto.createCipheriv("aes-128-gcm", encryptionKey, nonce);
|
|
91
|
+
const ciphertext = cipher.update(padded);
|
|
92
|
+
const authTag = cipher.getAuthTag();
|
|
93
|
+
// RFC 8291 §4: salt (16) || rs (4, big-endian, 4096) || sender pubkey (65) || ciphertext || tag
|
|
94
|
+
const rs = Buffer.alloc(4);
|
|
95
|
+
rs.writeUInt32BE(4096);
|
|
96
|
+
return concat(salt, rs, senderPublicKey, ciphertext, authTag);
|
|
97
|
+
}
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// HKDF helpers
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
function hkdfExtract(salt, ikm) {
|
|
102
|
+
const hmac = crypto.createHmac("sha256", salt);
|
|
103
|
+
hmac.update(ikm);
|
|
104
|
+
return hmac.digest();
|
|
105
|
+
}
|
|
106
|
+
function hkdfExpand(prk, info, length) {
|
|
107
|
+
const hmac = crypto.createHmac("sha256", prk);
|
|
108
|
+
hmac.update(concat(info, Buffer.from([0x01])));
|
|
109
|
+
const t = hmac.digest();
|
|
110
|
+
return t.subarray(0, length);
|
|
111
|
+
}
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
// VAPID JWT signing (RFC 8292)
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
function buildVapidJwt(audience, vapidKeys, subject) {
|
|
116
|
+
const header = base64url(Buffer.from('{"alg":"ES256","typ":"JWT"}', "utf-8"));
|
|
117
|
+
const exp = Math.floor(Date.now() / 1000) + 12 * 60 * 60; // 12 hours
|
|
118
|
+
const claims = JSON.stringify({ aud: audience, exp, sub: subject });
|
|
119
|
+
const payload = base64url(Buffer.from(claims, "utf-8"));
|
|
120
|
+
const signInput = `${header}.${payload}`;
|
|
121
|
+
// Reconstruct the private key from the raw 32-byte scalar
|
|
122
|
+
// P-256 PKCS8 DER wrapper: 39 bytes header + 32 bytes scalar (with 0x00 prefix)
|
|
123
|
+
const privScalar = base64urlDecode(vapidKeys.privateKey);
|
|
124
|
+
// Build the EC private key in SEC1 DER format
|
|
125
|
+
const sec1Der = concat(Buffer.from("30770201010420", "hex"), privScalar, Buffer.from("a00a06082a8648ce3d030107a14403420004", "hex"), base64urlDecode(vapidKeys.publicKey));
|
|
126
|
+
const privateKey = crypto.createPrivateKey({
|
|
127
|
+
key: sec1Der,
|
|
128
|
+
format: "der",
|
|
129
|
+
type: "sec1",
|
|
130
|
+
});
|
|
131
|
+
const signature = crypto.sign("sha256", Buffer.from(signInput), privateKey);
|
|
132
|
+
// ECDSA signature is a DER-encoded SEQUENCE of two INTEGERs.
|
|
133
|
+
// Web Push requires base64url encoding of the raw DER.
|
|
134
|
+
const sigB64 = base64url(signature);
|
|
135
|
+
return `${signInput}.${sigB64}`;
|
|
136
|
+
}
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
// HTTP headers
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
function buildHeaders(encrypted, endpoint, vapidKeys, subject) {
|
|
141
|
+
const audience = new URL(endpoint).origin;
|
|
142
|
+
const jwt = buildVapidJwt(audience, vapidKeys, subject);
|
|
143
|
+
return {
|
|
144
|
+
"Content-Type": "application/octet-stream",
|
|
145
|
+
"Content-Encoding": CONTENT_ENCODING,
|
|
146
|
+
"Content-Length": String(encrypted.length),
|
|
147
|
+
Authorization: `vapid t=${jwt}, k=${vapidKeys.publicKey}`,
|
|
148
|
+
TTL: "86400",
|
|
149
|
+
Urgency: "high",
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
// HTTP POST
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
function post(endpoint, headers, body) {
|
|
156
|
+
return new Promise((resolve, reject) => {
|
|
157
|
+
const url = new URL(endpoint);
|
|
158
|
+
const isHttps = url.protocol === "https:";
|
|
159
|
+
const mod = isHttps ? https : http;
|
|
160
|
+
const req = mod.request({
|
|
161
|
+
hostname: url.hostname,
|
|
162
|
+
port: url.port || (isHttps ? 443 : 80),
|
|
163
|
+
path: url.pathname + url.search,
|
|
164
|
+
method: "POST",
|
|
165
|
+
headers,
|
|
166
|
+
}, (res) => {
|
|
167
|
+
// Drain the response body
|
|
168
|
+
const chunks = [];
|
|
169
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
170
|
+
res.on("end", () => {
|
|
171
|
+
if (res.statusCode !== undefined &&
|
|
172
|
+
(res.statusCode < 200 || res.statusCode > 299)) {
|
|
173
|
+
const body = Buffer.concat(chunks).toString("utf-8");
|
|
174
|
+
reject(new Error(`Push service returned ${String(res.statusCode)}: ${body}`));
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
resolve();
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
req.on("error", reject);
|
|
182
|
+
req.write(body);
|
|
183
|
+
req.end();
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
// Utilities
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
189
|
+
function base64urlDecode(input) {
|
|
190
|
+
return Buffer.from(input, "base64url");
|
|
191
|
+
}
|
|
192
|
+
function base64url(input) {
|
|
193
|
+
return input.toString("base64url");
|
|
194
|
+
}
|
|
195
|
+
function concat(...buffers) {
|
|
196
|
+
return Buffer.concat(buffers);
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=web-push.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-push.js","sourceRoot":"","sources":["../../src/core/web-push.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire protocol — framing, encoding, and message types for the TCP mesh.
|
|
3
|
+
*
|
|
4
|
+
* Transport-agnostic: carries the protocol contract between peers without
|
|
5
|
+
* depending on net.Socket or any specific transport implementation.
|
|
6
|
+
* TcpTransport, TlsTransport, and WebSocketTransport all use these types.
|
|
7
|
+
*/
|
|
8
|
+
import type { AgentIdentity, DeliveryEvent, DmMessage, Room, RoomMessage } from "./types.js";
|
|
9
|
+
export interface PeerInfo {
|
|
10
|
+
id: string;
|
|
11
|
+
port: number;
|
|
12
|
+
startedAt: string;
|
|
13
|
+
}
|
|
14
|
+
export interface SerialisedState {
|
|
15
|
+
agents: Record<string, AgentIdentity>;
|
|
16
|
+
rooms: Record<string, Room>;
|
|
17
|
+
messages: Record<string, RoomMessage[]>;
|
|
18
|
+
dms: Record<string, DmMessage[]>;
|
|
19
|
+
}
|
|
20
|
+
export type MeshStatePatch = {
|
|
21
|
+
type: "agent_upsert";
|
|
22
|
+
agent: AgentIdentity;
|
|
23
|
+
} | {
|
|
24
|
+
type: "agent_offline";
|
|
25
|
+
agentId: string;
|
|
26
|
+
} | {
|
|
27
|
+
type: "room_upsert";
|
|
28
|
+
room: Room;
|
|
29
|
+
} | {
|
|
30
|
+
type: "room_delete";
|
|
31
|
+
roomId: string;
|
|
32
|
+
} | {
|
|
33
|
+
type: "message_add";
|
|
34
|
+
roomId: string;
|
|
35
|
+
message: RoomMessage;
|
|
36
|
+
} | {
|
|
37
|
+
type: "dm_add";
|
|
38
|
+
key: string;
|
|
39
|
+
message: DmMessage;
|
|
40
|
+
} | {
|
|
41
|
+
type: "delivery";
|
|
42
|
+
agentId: string;
|
|
43
|
+
event: DeliveryEvent;
|
|
44
|
+
} | {
|
|
45
|
+
type: "message_read";
|
|
46
|
+
messageId: string;
|
|
47
|
+
readBy: string;
|
|
48
|
+
room?: string;
|
|
49
|
+
};
|
|
50
|
+
export type MeshMessage = {
|
|
51
|
+
method: "state_sync";
|
|
52
|
+
state: SerialisedState;
|
|
53
|
+
} | {
|
|
54
|
+
method: "state_update";
|
|
55
|
+
patch: MeshStatePatch;
|
|
56
|
+
} | {
|
|
57
|
+
method: "introduce";
|
|
58
|
+
peerId: string;
|
|
59
|
+
dataPort: number;
|
|
60
|
+
} | {
|
|
61
|
+
method: "connect_request";
|
|
62
|
+
peerId: string;
|
|
63
|
+
dataPort: number;
|
|
64
|
+
name: string;
|
|
65
|
+
fingerprint: string;
|
|
66
|
+
} | {
|
|
67
|
+
method: "connect_accepted";
|
|
68
|
+
peerId: string;
|
|
69
|
+
dataPort: number;
|
|
70
|
+
} | {
|
|
71
|
+
method: "connect_rejected";
|
|
72
|
+
peerId: string;
|
|
73
|
+
reason: string;
|
|
74
|
+
} | {
|
|
75
|
+
method: "peer_list";
|
|
76
|
+
peers: PeerInfo[];
|
|
77
|
+
} | {
|
|
78
|
+
method: "peer_joined";
|
|
79
|
+
peer: PeerInfo;
|
|
80
|
+
} | {
|
|
81
|
+
method: "peer_left";
|
|
82
|
+
peerId: string;
|
|
83
|
+
} | {
|
|
84
|
+
method: "become_coordinator";
|
|
85
|
+
peerList: PeerInfo[];
|
|
86
|
+
} | {
|
|
87
|
+
method: "pong";
|
|
88
|
+
peerId: string;
|
|
89
|
+
} | {
|
|
90
|
+
method: "fed_handshake";
|
|
91
|
+
meshId: string;
|
|
92
|
+
name: string;
|
|
93
|
+
version: string;
|
|
94
|
+
} | {
|
|
95
|
+
method: "fed_ack";
|
|
96
|
+
meshId: string;
|
|
97
|
+
name: string;
|
|
98
|
+
version: string;
|
|
99
|
+
} | {
|
|
100
|
+
method: "fed_agent_visible";
|
|
101
|
+
agent: AgentIdentity;
|
|
102
|
+
} | {
|
|
103
|
+
method: "fed_agent_gone";
|
|
104
|
+
agentId: string;
|
|
105
|
+
} | {
|
|
106
|
+
method: "fed_room_message";
|
|
107
|
+
roomId: string;
|
|
108
|
+
message: RoomMessage;
|
|
109
|
+
} | {
|
|
110
|
+
method: "fed_room_join";
|
|
111
|
+
roomId: string;
|
|
112
|
+
agentId: string;
|
|
113
|
+
agentName: string;
|
|
114
|
+
} | {
|
|
115
|
+
method: "fed_room_leave";
|
|
116
|
+
roomId: string;
|
|
117
|
+
agentId: string;
|
|
118
|
+
} | {
|
|
119
|
+
method: "fed_ping";
|
|
120
|
+
} | {
|
|
121
|
+
method: "fed_pong";
|
|
122
|
+
};
|
|
123
|
+
export declare function encode(msg: MeshMessage): string;
|
|
124
|
+
export declare class MessageBuffer {
|
|
125
|
+
private buffer;
|
|
126
|
+
append(data: string): unknown[];
|
|
127
|
+
}
|
|
128
|
+
export declare function isMeshMessage(value: unknown): value is MeshMessage;
|
|
129
|
+
/** Deterministic key for a DM conversation between two agents. */
|
|
130
|
+
export declare function dmKey(a: string, b: string): string;
|
|
131
|
+
//# sourceMappingURL=wire-protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire-protocol.d.ts","sourceRoot":"","sources":["../../src/core/wire-protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire protocol — framing, encoding, and message types for the TCP mesh.
|
|
3
|
+
*
|
|
4
|
+
* Transport-agnostic: carries the protocol contract between peers without
|
|
5
|
+
* depending on net.Socket or any specific transport implementation.
|
|
6
|
+
* TcpTransport, TlsTransport, and WebSocketTransport all use these types.
|
|
7
|
+
*/
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Framing — newline-delimited JSON
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
export function encode(msg) {
|
|
12
|
+
return JSON.stringify(msg) + "\n";
|
|
13
|
+
}
|
|
14
|
+
export class MessageBuffer {
|
|
15
|
+
buffer = "";
|
|
16
|
+
append(data) {
|
|
17
|
+
this.buffer += data;
|
|
18
|
+
const results = [];
|
|
19
|
+
let idx = this.buffer.indexOf("\n");
|
|
20
|
+
while (idx !== -1) {
|
|
21
|
+
const line = this.buffer.slice(0, idx);
|
|
22
|
+
this.buffer = this.buffer.slice(idx + 1);
|
|
23
|
+
if (line.length > 0) {
|
|
24
|
+
try {
|
|
25
|
+
results.push(JSON.parse(line));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
/* skip malformed lines */
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
idx = this.buffer.indexOf("\n");
|
|
32
|
+
}
|
|
33
|
+
return results;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Type guard
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
export function isMeshMessage(value) {
|
|
40
|
+
if (typeof value !== "object" || value === null)
|
|
41
|
+
return false;
|
|
42
|
+
if (!("method" in value))
|
|
43
|
+
return false;
|
|
44
|
+
return typeof value.method === "string";
|
|
45
|
+
}
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Helpers
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
/** Deterministic key for a DM conversation between two agents. */
|
|
50
|
+
export function dmKey(a, b) {
|
|
51
|
+
const sorted = [a, b].sort();
|
|
52
|
+
return `${sorted[0] ?? a}--${sorted[1] ?? b}`;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=wire-protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire-protocol.js","sourceRoot":"","sources":["../../src/core/wire-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmFH,8EAA8E;AAC9E,mCAAmC;AACnC,8EAA8E;AAE9E,MAAM,UAAU,MAAM,CAAC,GAAgB;IACrC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;AACpC,CAAC;AAED,MAAM,OAAO,aAAa;IAChB,MAAM,GAAG,EAAE,CAAC;IAEpB,MAAM,CAAC,IAAY;QACjB,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;QACpB,MAAM,OAAO,GAAc,EAAE,CAAC;QAC9B,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YACvC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YACzC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,IAAI,CAAC;oBACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBACjC,CAAC;gBAAC,MAAM,CAAC;oBACP,0BAA0B;gBAC5B,CAAC;YACH,CAAC;YACD,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,IAAI,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,OAAO,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC;AAC1C,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,kEAAkE;AAClE,MAAM,UAAU,KAAK,CAAC,CAAS,EAAE,CAAS;IACxC,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7B,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocketTransport — WebSocket transport for the peer mesh.
|
|
3
|
+
*
|
|
4
|
+
* Carries the same wire protocol as TcpTransport but over WebSocket frames.
|
|
5
|
+
* Each WS frame is a complete JSON message — no newline delimiter or
|
|
6
|
+
* MessageBuffer needed. This enables browser-based peers (PWAs) to
|
|
7
|
+
* participate in the mesh.
|
|
8
|
+
*
|
|
9
|
+
* The transport is a drop-in replacement for TcpTransport. Same interface,
|
|
10
|
+
* same wire protocol, same event callbacks. MeshStore cannot tell the
|
|
11
|
+
* difference.
|
|
12
|
+
*/
|
|
13
|
+
import type { MeshMessage, PeerInfo } from "./wire-protocol.js";
|
|
14
|
+
import type { ConnectionHandle, ListenerInfo, MeshTransport, TransportEvents } from "./transport.js";
|
|
15
|
+
export declare class WebSocketTransport implements MeshTransport {
|
|
16
|
+
private dataServer;
|
|
17
|
+
private _dataPort;
|
|
18
|
+
private coordinatorServer;
|
|
19
|
+
private _isCoordinator;
|
|
20
|
+
private coordinatorWs;
|
|
21
|
+
private peerConnections;
|
|
22
|
+
private dataServerSockets;
|
|
23
|
+
private coordinatorServerSockets;
|
|
24
|
+
private introConnections;
|
|
25
|
+
private pendingConnections;
|
|
26
|
+
private shutDown;
|
|
27
|
+
private _peerId;
|
|
28
|
+
private readonly events;
|
|
29
|
+
constructor(events: TransportEvents);
|
|
30
|
+
get dataPort(): number;
|
|
31
|
+
get isCoordinator(): boolean;
|
|
32
|
+
startDataServer(): Promise<void>;
|
|
33
|
+
connectToCoordinator(host: string, port: number, peerId: string, localDataPort: number): Promise<void>;
|
|
34
|
+
connectToRemote(host: string, port: number, peerId: string, _localDataPort: number, name: string, fingerprint: string): Promise<void>;
|
|
35
|
+
becomeCoordinator(host: string, port: number): Promise<void>;
|
|
36
|
+
connectToPeer(peer: PeerInfo, ownPeerId: string): Promise<void>;
|
|
37
|
+
send(handle: ConnectionHandle, message: MeshMessage): Promise<void>;
|
|
38
|
+
acceptConnection(handle: ConnectionHandle): Promise<void>;
|
|
39
|
+
rejectConnection(handle: ConnectionHandle, reason: string): Promise<void>;
|
|
40
|
+
broadcast(message: MeshMessage): Promise<void>;
|
|
41
|
+
addListener(): Promise<string>;
|
|
42
|
+
removeListener(): Promise<void>;
|
|
43
|
+
listListeners(): ListenerInfo[];
|
|
44
|
+
shutdown(): Promise<void>;
|
|
45
|
+
unref(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Handles messages received on the coordinator client socket (the
|
|
48
|
+
* connection from this peer TO the coordinator). Fires the appropriate
|
|
49
|
+
* TransportEvents for peer_list, peer_joined, and become_coordinator.
|
|
50
|
+
*/
|
|
51
|
+
private dispatchCoordinatorClientMessage;
|
|
52
|
+
/**
|
|
53
|
+
* Routes a message received on a peer data connection to the
|
|
54
|
+
* appropriate event. become_coordinator has its own event; all
|
|
55
|
+
* other messages fire onMessage for MeshStore to handle.
|
|
56
|
+
*/
|
|
57
|
+
private dispatchDataMessage;
|
|
58
|
+
/**
|
|
59
|
+
* Accepts a new connection on the coordinator server. Reads
|
|
60
|
+
* introduce messages and fires onIntroduction so MeshStore can
|
|
61
|
+
* respond with the peer list and broadcast the arrival.
|
|
62
|
+
*/
|
|
63
|
+
private handleCoordinatorServerConnection;
|
|
64
|
+
/**
|
|
65
|
+
* Accepts a new connection on the data server. Reads the initial
|
|
66
|
+
* pong to identify the peer, then fires onMessage for subsequent
|
|
67
|
+
* messages. Tracks the connection for cleanup on close/error.
|
|
68
|
+
*/
|
|
69
|
+
private handleIncomingDataConnection;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=ws-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-transport.d.ts","sourceRoot":"","sources":["../../src/core/ws-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,eAAe,EAChB,MAAM,gBAAgB,CAAC;AA8BxB,qBAAa,kBAAmB,YAAW,aAAa;IAEtD,OAAO,CAAC,UAAU,CAA8B;IAChD,OAAO,CAAC,SAAS,CAAK;IAGtB,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,cAAc,CAAS;IAG/B,OAAO,CAAC,aAAa,CAAwB;IAG7C,OAAO,CAAC,eAAe,CAAgC;IAGvD,OAAO,CAAC,iBAAiB,CAAwB;IAGjD,OAAO,CAAC,wBAAwB,CAAwB;IAKxD,OAAO,CAAC,gBAAgB,CAAgC;IAGxD,OAAO,CAAC,kBAAkB,CAStB;IAGJ,OAAO,CAAC,QAAQ,CAAS;IAGzB,OAAO,CAAC,OAAO,CAAM;IAErB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAE7B,MAAM,EAAE,eAAe;IAMnC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,aAAa,IAAI,OAAO,CAE3B;IAMK,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BhC,oBAAoB,CACxB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;IAuDV,eAAe,CACnB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAoEV,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB5D,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoD/D,IAAI,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBnE,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BzD,gBAAgB,CACpB,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAkBV,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB9C,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAI9B,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrC,aAAa,IAAI,YAAY,EAAE;IAQzB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA2C/B,KAAK,IAAI,IAAI;IAUb;;;;OAIG;IACH,OAAO,CAAC,gCAAgC;IAgBxC;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;;;OAIG;IACH,OAAO,CAAC,iCAAiC;IA4CzC;;;;OAIG;IACH,OAAO,CAAC,4BAA4B;CAiDrC"}
|