agent-embassy 1.8.2 → 1.9.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/CHANGELOG.md +18 -0
- package/README.md +23 -3
- package/README.zh-CN.md +23 -3
- package/SECURITY.md +30 -6
- package/dist/src/gateway/cli-copy.en.d.ts +1 -1
- package/dist/src/gateway/cli-copy.en.js +8 -0
- package/dist/src/gateway/cli-copy.en.js.map +1 -1
- package/dist/src/gateway/cli-copy.zh-CN.d.ts +1 -1
- package/dist/src/gateway/cli-copy.zh-CN.js +8 -0
- package/dist/src/gateway/cli-copy.zh-CN.js.map +1 -1
- package/dist/src/gateway/cli.d.ts +8 -3
- package/dist/src/gateway/cli.js +191 -19
- package/dist/src/gateway/cli.js.map +1 -1
- package/dist/src/gateway/config.d.ts +2 -0
- package/dist/src/gateway/config.js +1 -1
- package/dist/src/gateway/config.js.map +1 -1
- package/dist/src/gateway/control.d.ts +79 -25
- package/dist/src/gateway/control.js +98 -18
- package/dist/src/gateway/control.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.d.ts +1 -1
- package/dist/src/gateway/dashboard-copy.en.d.ts +2 -0
- package/dist/src/gateway/dashboard-copy.en.js +2 -0
- package/dist/src/gateway/dashboard-copy.en.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.js +2 -0
- package/dist/src/gateway/dashboard-copy.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +2 -0
- package/dist/src/gateway/dashboard-copy.zh-CN.js +2 -0
- package/dist/src/gateway/dashboard-copy.zh-CN.js.map +1 -1
- package/dist/src/gateway/dashboard-model.d.ts +3 -0
- package/dist/src/gateway/dashboard-model.js +3 -0
- package/dist/src/gateway/dashboard-model.js.map +1 -1
- package/dist/src/gateway/federation-nodes.d.ts +18 -0
- package/dist/src/gateway/federation-nodes.js +142 -0
- package/dist/src/gateway/federation-nodes.js.map +1 -0
- package/dist/src/gateway/live-dashboard-app/app.js +5 -4
- package/dist/src/gateway/peer-client.d.ts +57 -0
- package/dist/src/gateway/peer-client.js +208 -0
- package/dist/src/gateway/peer-client.js.map +1 -0
- package/dist/src/gateway/peer-mailbox.d.ts +78 -0
- package/dist/src/gateway/peer-mailbox.js +168 -0
- package/dist/src/gateway/peer-mailbox.js.map +1 -0
- package/dist/src/gateway/peer-protocol.d.ts +107 -0
- package/dist/src/gateway/peer-protocol.js +72 -0
- package/dist/src/gateway/peer-protocol.js.map +1 -0
- package/dist/src/gateway/peer-stdio.d.ts +23 -0
- package/dist/src/gateway/peer-stdio.js +100 -0
- package/dist/src/gateway/peer-stdio.js.map +1 -0
- package/dist/src/gateway/provenance-envelope.js +6 -1
- package/dist/src/gateway/provenance-envelope.js.map +1 -1
- package/dist/src/gateway/providers.d.ts +5 -2
- package/dist/src/gateway/providers.js +10 -7
- package/dist/src/gateway/providers.js.map +1 -1
- package/dist/src/gateway/server.d.ts +4 -1
- package/dist/src/gateway/server.js +21 -8
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service.d.ts +19 -0
- package/dist/src/gateway/service.js +437 -37
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/state-v2-to-v3.js +1 -0
- package/dist/src/gateway/state-v2-to-v3.js.map +1 -1
- package/dist/src/gateway/store.d.ts +9 -1
- package/dist/src/gateway/store.js +183 -43
- package/dist/src/gateway/store.js.map +1 -1
- package/dist/src/gateway/types.d.ts +7 -6
- package/dist/src/gateway/types.js +5 -10
- package/dist/src/gateway/types.js.map +1 -1
- package/docs/CONFIGURATION.md +23 -8
- package/docs/CONFIGURATION.zh-CN.md +12 -4
- package/docs/DASHBOARD.md +2 -2
- package/docs/DASHBOARD.zh-CN.md +2 -2
- package/docs/DELIVERY.md +3 -1
- package/docs/DELIVERY.zh-CN.md +3 -1
- package/docs/GATEWAY-ARCHITECTURE.md +6 -4
- package/package.json +1 -1
- package/skills/embassy-peer/SKILL.md +32 -4
- package/skills/embassy-peer/agents/openai.yaml +2 -2
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { spawn as nodeSpawn } from "node:child_process";
|
|
2
|
+
import { Buffer } from "node:buffer";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { decodePeerParams, decodePeerResult, encodePeerFrame, peerEdgeRef, PEER_MAX_CATALOG_BYTES, PEER_MAX_REQUEST_BYTES, PEER_METHOD_NOT_FOUND, PEER_REQUEST_TIMEOUT_MS } from "./peer-protocol.js";
|
|
5
|
+
export class PeerRequestError extends Error {
|
|
6
|
+
detail;
|
|
7
|
+
constructor(detail) {
|
|
8
|
+
super(detail.message);
|
|
9
|
+
this.detail = detail;
|
|
10
|
+
this.name = "PeerRequestError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class PeerConnectionLostError extends Error {
|
|
14
|
+
failureClass;
|
|
15
|
+
constructor(message = "Peer connection lost", failureClass = "transport") {
|
|
16
|
+
super(message);
|
|
17
|
+
this.failureClass = failureClass;
|
|
18
|
+
this.name = "PeerConnectionLostError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class PeerClient {
|
|
22
|
+
child;
|
|
23
|
+
localHost;
|
|
24
|
+
timers;
|
|
25
|
+
pending = new Map();
|
|
26
|
+
nextId = 1;
|
|
27
|
+
buffer = Buffer.alloc(0);
|
|
28
|
+
writes = Promise.resolve();
|
|
29
|
+
closed = false;
|
|
30
|
+
remoteHost = "";
|
|
31
|
+
constructor(child, localHost, timers) {
|
|
32
|
+
this.child = child;
|
|
33
|
+
this.localHost = localHost;
|
|
34
|
+
this.timers = timers;
|
|
35
|
+
child.stderr.resume();
|
|
36
|
+
child.stdout.on("data", (chunk) => this.read(chunk));
|
|
37
|
+
child.once("error", () => this.fail(new PeerConnectionLostError()));
|
|
38
|
+
child.once("exit", () => this.fail(new PeerConnectionLostError()));
|
|
39
|
+
}
|
|
40
|
+
static async spawn(options) {
|
|
41
|
+
decodePeerParams("initialize", { protocolVersion: 1, host: options.node });
|
|
42
|
+
decodePeerParams("initialize", { protocolVersion: 1, host: options.localHost });
|
|
43
|
+
let child;
|
|
44
|
+
try {
|
|
45
|
+
child = (options.spawn ?? nodeSpawn)("/usr/bin/ssh", ["-T", "-x", "-o", "BatchMode=yes", "-o", "ClearAllForwardings=yes", "-o", "ForwardAgent=no", "-o", "PermitLocalCommand=no", "-o", "SendEnv=-*", "-o", "Tunnel=no", options.node, "embassy", "peer-stdio"], { env: peerEnvironment(process.env), shell: false, stdio: ["pipe", "pipe", "pipe"] });
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
throw new PeerConnectionLostError("Peer process could not be spawned", "spawn");
|
|
49
|
+
}
|
|
50
|
+
const client = new PeerClient(child, options.localHost, options.timers ?? { setTimeout, clearTimeout });
|
|
51
|
+
try {
|
|
52
|
+
const result = await client.request("initialize", { protocolVersion: 1, host: options.localHost });
|
|
53
|
+
if (result.host !== options.node)
|
|
54
|
+
throw new Error(`Peer host mismatch: expected ${options.node}, received ${result.host}`);
|
|
55
|
+
client.remoteHost = result.host;
|
|
56
|
+
return client;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
client.close();
|
|
60
|
+
throw new PeerConnectionLostError(error instanceof Error ? error.message : "Peer initialization failed", "initialize");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
get connectionInfo() { return { host: this.remoteHost, protocolVersion: 1 }; }
|
|
64
|
+
async catalog() {
|
|
65
|
+
const result = await this.request("catalog/get", {});
|
|
66
|
+
const routeIds = result.routes.flatMap((row) => [row.alias, row.ref]), connectorIds = result.connectors.map((row) => row.provider);
|
|
67
|
+
const invalid = (result.complete && result.truncated) || new Set(routeIds).size !== routeIds.length || new Set(connectorIds).size !== connectorIds.length ||
|
|
68
|
+
[...result.routes, ...result.connectors].some((row) => row.host !== this.remoteHost) || result.consentEdges.some((edge) => {
|
|
69
|
+
const hosts = edge.endpoints.map((endpoint) => endpoint.host).sort();
|
|
70
|
+
return hosts[0] !== [this.localHost, this.remoteHost].sort()[0] || hosts[1] !== [this.localHost, this.remoteHost].sort()[1] ||
|
|
71
|
+
edge.ownerHost !== hosts[0] || edge.ownerHost !== this.remoteHost || edge.ref !== peerEdgeRef(edge.endpoints);
|
|
72
|
+
}) || new Set(result.consentEdges.map((edge) => edge.ref)).size !== result.consentEdges.length ||
|
|
73
|
+
result.alerts.some((alert) => (alert.host !== undefined && alert.host !== this.remoteHost) ||
|
|
74
|
+
(alert.alias !== undefined && !alert.alias.endsWith(`@${this.remoteHost}`))) || result.consentEdges.some((edge) => edge.endpoints
|
|
75
|
+
.filter((endpoint) => endpoint.host === this.remoteHost).some((endpoint) => !result.routes.some((route) => route.alias === endpoint.alias && route.provider === endpoint.provider && route.ref === endpoint.routeRef)));
|
|
76
|
+
if (invalid) {
|
|
77
|
+
const error = new Error("Peer catalog is not a local, canonical projection");
|
|
78
|
+
this.fail(error);
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
prepareHandoff(params) {
|
|
84
|
+
decodePeerParams("handoff", params);
|
|
85
|
+
if (this.closed)
|
|
86
|
+
throw new PeerConnectionLostError();
|
|
87
|
+
if (params.source.host !== this.localHost || params.target.host !== this.remoteHost)
|
|
88
|
+
throw new Error("Peer handoff must be direct");
|
|
89
|
+
const id = this.nextId++, frame = encodePeerFrame({ jsonrpc: "2.0", id, method: "handoff", params }, PEER_MAX_REQUEST_BYTES);
|
|
90
|
+
let state = "prepared";
|
|
91
|
+
const used = () => { throw new Error("Peer handoff was already consumed"); };
|
|
92
|
+
return { bodyBytes: Buffer.byteLength(params.body), bodySha256: createHash("sha256").update(params.body).digest("hex"), frameBytes: Buffer.byteLength(frame), sha256: createHash("sha256").update(frame).digest("hex"),
|
|
93
|
+
cancel: () => { if (state !== "prepared")
|
|
94
|
+
used(); state = "cancelled"; }, perform: () => {
|
|
95
|
+
if (state !== "prepared")
|
|
96
|
+
return Promise.reject(used());
|
|
97
|
+
state = "performed";
|
|
98
|
+
return this.requestFrame("handoff", id, frame);
|
|
99
|
+
} };
|
|
100
|
+
}
|
|
101
|
+
close() { this.fail(new PeerConnectionLostError()); }
|
|
102
|
+
request(method, params) {
|
|
103
|
+
const id = this.nextId++;
|
|
104
|
+
return this.requestFrame(method, id, encodePeerFrame({ jsonrpc: "2.0", id, method, params }, PEER_MAX_REQUEST_BYTES));
|
|
105
|
+
}
|
|
106
|
+
requestFrame(method, id, frame) {
|
|
107
|
+
if (this.closed)
|
|
108
|
+
return Promise.reject(new PeerConnectionLostError());
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
const timer = this.timers.setTimeout(() => {
|
|
111
|
+
this.timers.clearTimeout(timer);
|
|
112
|
+
this.pending.delete(id);
|
|
113
|
+
const error = new PeerConnectionLostError("Peer request timed out");
|
|
114
|
+
this.fail(error);
|
|
115
|
+
reject(error);
|
|
116
|
+
}, PEER_REQUEST_TIMEOUT_MS);
|
|
117
|
+
timer.unref();
|
|
118
|
+
this.pending.set(id, { method, timer, resolve, reject });
|
|
119
|
+
void this.write(frame).catch((error) => { const pending = this.pending.get(id); if (pending)
|
|
120
|
+
this.timers.clearTimeout(pending.timer); this.pending.delete(id); this.fail(error); reject(error); });
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
write(frame) {
|
|
124
|
+
const operation = this.writes.then(() => new Promise((resolve, reject) => {
|
|
125
|
+
if (this.closed)
|
|
126
|
+
return reject(new PeerConnectionLostError());
|
|
127
|
+
this.child.stdin.write(frame, (error) => error ? reject(new PeerConnectionLostError()) : resolve());
|
|
128
|
+
}));
|
|
129
|
+
this.writes = operation.catch(() => undefined);
|
|
130
|
+
return operation;
|
|
131
|
+
}
|
|
132
|
+
read(chunk) {
|
|
133
|
+
if (this.closed)
|
|
134
|
+
return;
|
|
135
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
136
|
+
for (;;) {
|
|
137
|
+
const newline = this.buffer.indexOf(0x0a);
|
|
138
|
+
if (newline < 0) {
|
|
139
|
+
if (this.buffer.length > PEER_MAX_CATALOG_BYTES)
|
|
140
|
+
this.fail(new Error("Peer response exceeds 256 KiB"));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const line = this.buffer.subarray(0, newline);
|
|
144
|
+
this.buffer = this.buffer.subarray(newline + 1);
|
|
145
|
+
if (line.length > PEER_MAX_CATALOG_BYTES)
|
|
146
|
+
return this.fail(new Error("Peer response exceeds 256 KiB"));
|
|
147
|
+
let message;
|
|
148
|
+
try {
|
|
149
|
+
message = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(line));
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return this.fail(new Error("Peer returned malformed JSON"));
|
|
153
|
+
}
|
|
154
|
+
if (!object(message) || message.jsonrpc !== "2.0")
|
|
155
|
+
return this.fail(new Error("Peer returned an invalid JSON-RPC frame"));
|
|
156
|
+
if (typeof message.method === "string") {
|
|
157
|
+
if (!request(message))
|
|
158
|
+
return this.fail(new Error("Peer returned an invalid request"));
|
|
159
|
+
void this.write(encodePeerFrame({ jsonrpc: "2.0", id: message.id, error: { code: PEER_METHOD_NOT_FOUND, message: "Method not found" } }, PEER_MAX_REQUEST_BYTES)).catch((error) => this.fail(error));
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (!response(message))
|
|
163
|
+
return this.fail(new Error("Peer returned an invalid JSON-RPC response"));
|
|
164
|
+
const pending = this.pending.get(message.id);
|
|
165
|
+
if (!pending)
|
|
166
|
+
return this.fail(new Error("Peer returned an uncorrelated response"));
|
|
167
|
+
this.pending.delete(message.id);
|
|
168
|
+
this.timers.clearTimeout(pending.timer);
|
|
169
|
+
if (Object.hasOwn(message, "error")) {
|
|
170
|
+
const detail = error(message.error);
|
|
171
|
+
if (detail === undefined) {
|
|
172
|
+
const fault = new Error("Peer returned an invalid error response");
|
|
173
|
+
pending.reject(fault);
|
|
174
|
+
this.fail(fault);
|
|
175
|
+
}
|
|
176
|
+
else
|
|
177
|
+
pending.reject(new PeerRequestError(detail));
|
|
178
|
+
}
|
|
179
|
+
else
|
|
180
|
+
try {
|
|
181
|
+
pending.resolve(decodePeerResult(pending.method, message.result));
|
|
182
|
+
}
|
|
183
|
+
catch (fault) {
|
|
184
|
+
const error = fault instanceof Error ? fault : new Error("Invalid peer result");
|
|
185
|
+
pending.reject(error);
|
|
186
|
+
this.fail(error);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
fail(error) { if (this.closed)
|
|
191
|
+
return; this.closed = true; for (const pending of this.pending.values()) {
|
|
192
|
+
this.timers.clearTimeout(pending.timer);
|
|
193
|
+
pending.reject(error);
|
|
194
|
+
} this.pending.clear(); this.child.kill(); }
|
|
195
|
+
}
|
|
196
|
+
const peerEnvironment = (env) => Object.fromEntries(["HOME", "USER", "LOGNAME", "SSH_AUTH_SOCK"].flatMap((key) => env[key] === undefined ? [] : [[key, env[key]]]));
|
|
197
|
+
const object = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
198
|
+
const id = (value) => typeof value === "string" || typeof value === "number";
|
|
199
|
+
const request = (value) => Object.keys(value).length === 4 && id(value.id) && typeof value.method === "string" && Object.hasOwn(value, "params");
|
|
200
|
+
const response = (value) => Object.keys(value).length === 3 && id(value.id) && (Object.hasOwn(value, "result") !== Object.hasOwn(value, "error"));
|
|
201
|
+
function error(value) {
|
|
202
|
+
if (!object(value) || typeof value.code !== "number" || typeof value.message !== "string" ||
|
|
203
|
+
Object.keys(value).some((key) => key !== "code" && key !== "message" && key !== "data"))
|
|
204
|
+
return undefined;
|
|
205
|
+
return { code: value.code, message: value.message, ...(Object.hasOwn(value, "data") ? { data: value.data } : {}) };
|
|
206
|
+
}
|
|
207
|
+
export const spawnPeerClient = (options) => PeerClient.spawn(options);
|
|
208
|
+
//# sourceMappingURL=peer-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-client.js","sourceRoot":"","sources":["../../../src/gateway/peer-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { GatewayAdapterDispatchInput, GatewayProviderAdapter } from "./service.js";
|
|
2
|
+
export type PeerMailboxAwaitInput = Readonly<{
|
|
3
|
+
alias: string;
|
|
4
|
+
routeHandle: string;
|
|
5
|
+
registrationId: string;
|
|
6
|
+
timeoutMs?: number;
|
|
7
|
+
}>;
|
|
8
|
+
export type PeerMailboxAwaitResult = Readonly<{
|
|
9
|
+
state: "timeout";
|
|
10
|
+
}> | Readonly<{
|
|
11
|
+
state: "message";
|
|
12
|
+
frame: string;
|
|
13
|
+
receipt: string;
|
|
14
|
+
}>;
|
|
15
|
+
export type PeerMailboxReceiptInput = Readonly<{
|
|
16
|
+
alias: string;
|
|
17
|
+
routeHandle: string;
|
|
18
|
+
registrationId: string;
|
|
19
|
+
receipt: string;
|
|
20
|
+
}>;
|
|
21
|
+
export type PeerMailboxReceiptResult = "acknowledged" | "duplicate" | "rejected";
|
|
22
|
+
export type LocalPeerMailboxProviderOptions = Readonly<{
|
|
23
|
+
hostId: string;
|
|
24
|
+
awaitTimeoutMs?: number;
|
|
25
|
+
receiptTimeoutMs?: number;
|
|
26
|
+
createReceipt?: () => string;
|
|
27
|
+
now?: () => number;
|
|
28
|
+
}>;
|
|
29
|
+
type Binding = Readonly<{
|
|
30
|
+
alias: string;
|
|
31
|
+
routeHandle: string;
|
|
32
|
+
registrationId: string;
|
|
33
|
+
}>;
|
|
34
|
+
export declare function isPeerMailboxAwaitResult(value: unknown): value is PeerMailboxAwaitResult;
|
|
35
|
+
export declare class LocalPeerMailboxProvider implements GatewayProviderAdapter {
|
|
36
|
+
private readonly options;
|
|
37
|
+
readonly identity: Readonly<{
|
|
38
|
+
provider: "peer";
|
|
39
|
+
hostId: string;
|
|
40
|
+
}>;
|
|
41
|
+
readonly protocol = "peer-mailbox";
|
|
42
|
+
readonly protocolVersion = "1";
|
|
43
|
+
private readonly routes;
|
|
44
|
+
private readonly waiters;
|
|
45
|
+
private readonly receipts;
|
|
46
|
+
private readonly tombstones;
|
|
47
|
+
private closed;
|
|
48
|
+
constructor(options: LocalPeerMailboxProviderOptions);
|
|
49
|
+
initialize(): Promise<{
|
|
50
|
+
health: "healthy";
|
|
51
|
+
}>;
|
|
52
|
+
observeLogicalRoute(input: Binding): void;
|
|
53
|
+
forgetLogicalRoute(registrationId: string): void;
|
|
54
|
+
awaitMessage(input: PeerMailboxAwaitInput): Promise<PeerMailboxAwaitResult>;
|
|
55
|
+
acknowledgeReceipt(input: PeerMailboxReceiptInput): PeerMailboxReceiptResult;
|
|
56
|
+
dispatch(input: GatewayAdapterDispatchInput): Promise<{
|
|
57
|
+
state: "failed";
|
|
58
|
+
safeErrorCode: string;
|
|
59
|
+
} | {
|
|
60
|
+
state: "deferred";
|
|
61
|
+
safeErrorCode: string;
|
|
62
|
+
} | {
|
|
63
|
+
state: "ambiguous";
|
|
64
|
+
safeErrorCode: string;
|
|
65
|
+
} | {
|
|
66
|
+
state: "delivered";
|
|
67
|
+
safeErrorCode?: never;
|
|
68
|
+
} | {
|
|
69
|
+
state: "unconfirmed";
|
|
70
|
+
safeErrorCode: string;
|
|
71
|
+
}>;
|
|
72
|
+
close(): Promise<void>;
|
|
73
|
+
private cancelRegistration;
|
|
74
|
+
private cancelReceipt;
|
|
75
|
+
private finishReceipt;
|
|
76
|
+
private newReceipt;
|
|
77
|
+
}
|
|
78
|
+
export {};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
3
|
+
import { BridgeError } from "../errors.js";
|
|
4
|
+
import { composeProvenanceEnvelope, PROVENANCE_ENVELOPE_MAX_BYTES } from "./provenance-envelope.js";
|
|
5
|
+
const TIMEOUT = Object.freeze({ state: "timeout" });
|
|
6
|
+
const MAX_WAITERS = 16;
|
|
7
|
+
const RECEIPT = /^prc_[A-Za-z0-9_-]{24}$/;
|
|
8
|
+
const ALIAS = /^[a-z][a-z0-9_-]{0,31}@[a-z0-9](?:[a-z0-9.-]{0,61}[a-z0-9])?$/;
|
|
9
|
+
const CONVERSATION = /^conv_[A-Za-z0-9_-]{16,64}$/;
|
|
10
|
+
export function isPeerMailboxAwaitResult(value) {
|
|
11
|
+
if (!record(value))
|
|
12
|
+
return false;
|
|
13
|
+
if (value.state === "timeout")
|
|
14
|
+
return Object.keys(value).length === 1;
|
|
15
|
+
if (value.state !== "message" || Object.keys(value).length !== 3 || typeof value.receipt !== "string" || !RECEIPT.test(value.receipt) || typeof value.frame !== "string")
|
|
16
|
+
return false;
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(value.frame);
|
|
19
|
+
if (!record(parsed) || Object.keys(parsed).length !== 3 || parsed.ok !== true || parsed.command !== "await" || !record(parsed.result) || Object.keys(parsed.result).length !== 5)
|
|
20
|
+
return false;
|
|
21
|
+
const result = parsed.result;
|
|
22
|
+
return typeof result.fromAlias === "string" && ALIAS.test(result.fromAlias) && typeof result.toAlias === "string" && result.toAlias.startsWith("peer-") && ALIAS.test(result.toAlias) &&
|
|
23
|
+
typeof result.conversationId === "string" && CONVERSATION.test(result.conversationId) && typeof result.text === "string" && Buffer.byteLength(result.text) <= PROVENANCE_ENVELOPE_MAX_BYTES &&
|
|
24
|
+
typeof result.expectsReply === "boolean" && Buffer.byteLength(value.frame) <= PROVENANCE_ENVELOPE_MAX_BYTES && value.frame === `${JSON.stringify(parsed)}\n`;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export class LocalPeerMailboxProvider {
|
|
31
|
+
options;
|
|
32
|
+
identity;
|
|
33
|
+
protocol = "peer-mailbox";
|
|
34
|
+
protocolVersion = "1";
|
|
35
|
+
routes = new Map();
|
|
36
|
+
waiters = new Map();
|
|
37
|
+
receipts = new Map();
|
|
38
|
+
tombstones = new Map();
|
|
39
|
+
closed = false;
|
|
40
|
+
constructor(options) {
|
|
41
|
+
this.options = options;
|
|
42
|
+
this.identity = Object.freeze({ provider: "peer", hostId: options.hostId });
|
|
43
|
+
}
|
|
44
|
+
async initialize() { return { health: "healthy" }; }
|
|
45
|
+
observeLogicalRoute(input) {
|
|
46
|
+
const current = this.routes.get(input.registrationId);
|
|
47
|
+
if (!this.closed && (!current || same(current, input)))
|
|
48
|
+
this.routes.set(input.registrationId, Object.freeze({ ...input }));
|
|
49
|
+
}
|
|
50
|
+
forgetLogicalRoute(registrationId) {
|
|
51
|
+
this.routes.delete(registrationId);
|
|
52
|
+
this.cancelRegistration(registrationId);
|
|
53
|
+
this.tombstones.delete(registrationId);
|
|
54
|
+
}
|
|
55
|
+
async awaitMessage(input) {
|
|
56
|
+
const route = this.routes.get(input.registrationId);
|
|
57
|
+
if (this.closed || !same(route, input))
|
|
58
|
+
throw new BridgeError("ROUTE_UNREGISTERED", "The peer mailbox binding is not current.");
|
|
59
|
+
if (this.waiters.has(input.registrationId))
|
|
60
|
+
throw new BridgeError("ROUTE_BUSY", "The peer registration already has a waiter.", true);
|
|
61
|
+
if (this.waiters.size >= MAX_WAITERS)
|
|
62
|
+
throw new BridgeError("ROUTE_CAPACITY_REACHED", "The peer waiter limit is full.", true);
|
|
63
|
+
return await new Promise((resolve) => {
|
|
64
|
+
const timer = setTimeout(() => { this.waiters.delete(input.registrationId); resolve(TIMEOUT); }, input.timeoutMs ?? this.options.awaitTimeoutMs ?? 30_000);
|
|
65
|
+
this.waiters.set(input.registrationId, { alias: input.alias, routeHandle: input.routeHandle, registrationId: input.registrationId, resolve, timer });
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
acknowledgeReceipt(input) {
|
|
69
|
+
const key = receiptKey(input);
|
|
70
|
+
const tombstone = this.tombstones.get(input.registrationId);
|
|
71
|
+
if (tombstone?.receipt === input.receipt && tombstone.key === key)
|
|
72
|
+
return "duplicate";
|
|
73
|
+
const pending = this.receipts.get(input.receipt);
|
|
74
|
+
if (!same(pending, input))
|
|
75
|
+
return "rejected";
|
|
76
|
+
if (pending.acked)
|
|
77
|
+
return "duplicate";
|
|
78
|
+
pending.acked = true;
|
|
79
|
+
if (pending.accepted)
|
|
80
|
+
this.finishReceipt(input.receipt, pending, key);
|
|
81
|
+
return "acknowledged";
|
|
82
|
+
}
|
|
83
|
+
async dispatch(input) {
|
|
84
|
+
const route = this.routes.get(input.binding.registrationId);
|
|
85
|
+
if (this.closed || input.binding.provider !== "peer" || input.binding.hostId !== this.identity.hostId || input.targetAlias !== route?.alias || input.binding.routeHandle !== route.routeHandle)
|
|
86
|
+
return { state: "failed", safeErrorCode: "ROUTE_UNREGISTERED" };
|
|
87
|
+
const waiter = this.waiters.get(route.registrationId);
|
|
88
|
+
if (waiter === undefined)
|
|
89
|
+
return { state: "deferred", safeErrorCode: "PEER_NOT_AWAITING" };
|
|
90
|
+
let text;
|
|
91
|
+
try {
|
|
92
|
+
text = composeProvenanceEnvelope({ sourceProvider: input.sourceProvider, recipientProvider: "peer", sourceAlias: input.sourceAlias, targetAlias: input.targetAlias, conversationId: input.conversationId, body: input.text });
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return { state: "failed", safeErrorCode: "PROVENANCE_ENVELOPE_INVALID" };
|
|
96
|
+
}
|
|
97
|
+
const result = { fromAlias: input.sourceAlias, toAlias: input.targetAlias, conversationId: input.conversationId, text, expectsReply: input.expectsReply };
|
|
98
|
+
const frame = `${JSON.stringify({ ok: true, command: "await", result })}\n`;
|
|
99
|
+
if (Buffer.byteLength(frame) > PROVENANCE_ENVELOPE_MAX_BYTES)
|
|
100
|
+
return { state: "failed", safeErrorCode: "PROVENANCE_ENVELOPE_INVALID" };
|
|
101
|
+
const receipt = this.newReceipt();
|
|
102
|
+
const evidence = { attemptId: input.attemptId, kind: "peer_mailbox", bodyBytes: Buffer.byteLength(input.text), bodySha256: hash(input.text), frameBytes: Buffer.byteLength(frame), sha256: hash(frame) };
|
|
103
|
+
let authorized;
|
|
104
|
+
try {
|
|
105
|
+
authorized = await input.authorizeWrite(evidence);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return { state: "ambiguous", safeErrorCode: "DISPATCH_OUTCOME_AMBIGUOUS" };
|
|
109
|
+
}
|
|
110
|
+
if (!authorized)
|
|
111
|
+
return { state: "failed", safeErrorCode: "WRITE_AUTHORIZATION_DENIED" };
|
|
112
|
+
if (this.closed || this.waiters.get(route.registrationId) !== waiter)
|
|
113
|
+
return { state: "ambiguous", safeErrorCode: "DISPATCH_OUTCOME_AMBIGUOUS" };
|
|
114
|
+
clearTimeout(waiter.timer);
|
|
115
|
+
this.waiters.delete(route.registrationId);
|
|
116
|
+
const acked = new Promise((resolve) => {
|
|
117
|
+
const waitMs = Math.max(0, Math.min(this.options.receiptTimeoutMs ?? 2_147_483_647, Date.parse(input.deadlineAt) - (this.options.now?.() ?? Date.now())));
|
|
118
|
+
const timer = setTimeout(() => { this.receipts.delete(receipt); resolve(false); }, waitMs);
|
|
119
|
+
this.receipts.set(receipt, { ...route, resolve, timer, acked: false, accepted: false });
|
|
120
|
+
});
|
|
121
|
+
waiter.resolve({ state: "message", frame, receipt });
|
|
122
|
+
try {
|
|
123
|
+
await input.onAccepted({ attemptId: input.attemptId });
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
this.cancelReceipt(receipt);
|
|
127
|
+
return { state: "ambiguous", safeErrorCode: "DISPATCH_OUTCOME_AMBIGUOUS" };
|
|
128
|
+
}
|
|
129
|
+
const pending = this.receipts.get(receipt);
|
|
130
|
+
if (pending) {
|
|
131
|
+
pending.accepted = true;
|
|
132
|
+
if (pending.acked)
|
|
133
|
+
this.finishReceipt(receipt, pending, receiptKey({ ...route, receipt }));
|
|
134
|
+
}
|
|
135
|
+
return await acked ? { state: "delivered" } : { state: "unconfirmed", safeErrorCode: "DELIVERY_UNCONFIRMED" };
|
|
136
|
+
}
|
|
137
|
+
async close() {
|
|
138
|
+
this.closed = true;
|
|
139
|
+
for (const id of [...this.routes.keys()])
|
|
140
|
+
this.cancelRegistration(id);
|
|
141
|
+
this.routes.clear();
|
|
142
|
+
this.tombstones.clear();
|
|
143
|
+
}
|
|
144
|
+
cancelRegistration(id) {
|
|
145
|
+
const waiter = this.waiters.get(id);
|
|
146
|
+
if (waiter) {
|
|
147
|
+
clearTimeout(waiter.timer);
|
|
148
|
+
this.waiters.delete(id);
|
|
149
|
+
waiter.resolve(TIMEOUT);
|
|
150
|
+
}
|
|
151
|
+
for (const [receipt, pending] of this.receipts)
|
|
152
|
+
if (pending.registrationId === id)
|
|
153
|
+
this.cancelReceipt(receipt);
|
|
154
|
+
}
|
|
155
|
+
cancelReceipt(receipt) { const pending = this.receipts.get(receipt); if (pending) {
|
|
156
|
+
clearTimeout(pending.timer);
|
|
157
|
+
this.receipts.delete(receipt);
|
|
158
|
+
pending.resolve(false);
|
|
159
|
+
} }
|
|
160
|
+
finishReceipt(receipt, pending, key) { clearTimeout(pending.timer); this.receipts.delete(receipt); this.tombstones.set(pending.registrationId, { receipt, key }); pending.resolve(true); }
|
|
161
|
+
newReceipt() { const value = this.options.createReceipt?.() ?? `prc_${randomBytes(18).toString("base64url")}`; if (!RECEIPT.test(value) || this.receipts.has(value) || [...this.tombstones.values()].some((item) => item.receipt === value))
|
|
162
|
+
throw new Error("invalid receipt"); return value; }
|
|
163
|
+
}
|
|
164
|
+
const hash = (value) => createHash("sha256").update(value).digest("hex");
|
|
165
|
+
const same = (left, right) => left?.alias === right.alias && left.routeHandle === right.routeHandle && left.registrationId === right.registrationId;
|
|
166
|
+
const receiptKey = (input) => `${input.registrationId}\0${input.routeHandle}\0${input.alias}\0${input.receipt}`;
|
|
167
|
+
const record = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
168
|
+
//# sourceMappingURL=peer-mailbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-mailbox.js","sourceRoot":"","sources":["../../../src/gateway/peer-mailbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { type ConnectorHealth, type GatewayProvider, type RouteState } from "./types.js";
|
|
2
|
+
export declare const PEER_PROTOCOL_VERSION = 1, PEER_MAX_REQUEST_BYTES: number, PEER_MAX_CATALOG_BYTES: number, PEER_MAX_BODY_BYTES: number, PEER_REQUEST_TIMEOUT_MS = 30000, PEER_METHOD_NOT_FOUND = -32601;
|
|
3
|
+
export declare const peerCapabilities: readonly ["catalog", "handoff"];
|
|
4
|
+
export type PeerRpcId = string | number;
|
|
5
|
+
export type PeerRpcError = Readonly<{
|
|
6
|
+
code: number;
|
|
7
|
+
message: string;
|
|
8
|
+
data?: unknown;
|
|
9
|
+
}>;
|
|
10
|
+
export type PeerMethod = "initialize" | "catalog/get" | "handoff";
|
|
11
|
+
export type PeerEndpoint = Readonly<{
|
|
12
|
+
alias: string;
|
|
13
|
+
provider: GatewayProvider;
|
|
14
|
+
host: string;
|
|
15
|
+
routeRef: string;
|
|
16
|
+
}>;
|
|
17
|
+
export type PeerInitializeParams = Readonly<{
|
|
18
|
+
protocolVersion: 1;
|
|
19
|
+
host: string;
|
|
20
|
+
}>;
|
|
21
|
+
export type PeerInitializeResult = Readonly<{
|
|
22
|
+
protocolVersion: 1;
|
|
23
|
+
host: string;
|
|
24
|
+
capabilities: typeof peerCapabilities;
|
|
25
|
+
limits: Readonly<{
|
|
26
|
+
requestBytes: number;
|
|
27
|
+
catalogBytes: number;
|
|
28
|
+
bodyBytes: number;
|
|
29
|
+
}>;
|
|
30
|
+
}>;
|
|
31
|
+
export type PeerHandoffParams = Readonly<{
|
|
32
|
+
originAttemptId: string;
|
|
33
|
+
originMessageId: string;
|
|
34
|
+
source: PeerEndpoint;
|
|
35
|
+
target: PeerEndpoint;
|
|
36
|
+
edgeRef: string;
|
|
37
|
+
edgeOwnerHost: string;
|
|
38
|
+
deadlineAt: string;
|
|
39
|
+
expectsReply: boolean;
|
|
40
|
+
body: string;
|
|
41
|
+
steer?: true;
|
|
42
|
+
conversationCorrelation?: string;
|
|
43
|
+
}>;
|
|
44
|
+
export type PeerHandoffResult = Readonly<{
|
|
45
|
+
accepted: true;
|
|
46
|
+
}>;
|
|
47
|
+
export type PeerCatalogResult = Readonly<{
|
|
48
|
+
revision: number;
|
|
49
|
+
complete: boolean;
|
|
50
|
+
truncated: boolean;
|
|
51
|
+
generatedAt: string;
|
|
52
|
+
health: ConnectorHealth;
|
|
53
|
+
connectors: readonly Readonly<{
|
|
54
|
+
provider: GatewayProvider;
|
|
55
|
+
host: string;
|
|
56
|
+
health: ConnectorHealth;
|
|
57
|
+
protocol: string;
|
|
58
|
+
protocolVersion: string;
|
|
59
|
+
lastSeenAt?: string;
|
|
60
|
+
observationAgeMs?: number;
|
|
61
|
+
safeErrorCode?: string;
|
|
62
|
+
}>[];
|
|
63
|
+
routes: readonly Readonly<{
|
|
64
|
+
ref: string;
|
|
65
|
+
alias: string;
|
|
66
|
+
provider: GatewayProvider;
|
|
67
|
+
host: string;
|
|
68
|
+
enabled: boolean;
|
|
69
|
+
state: RouteState;
|
|
70
|
+
queueDepth: number;
|
|
71
|
+
lastSeenAt?: string;
|
|
72
|
+
safeErrorCode?: string;
|
|
73
|
+
}>[];
|
|
74
|
+
consentEdges: readonly Readonly<{
|
|
75
|
+
ref: string;
|
|
76
|
+
ownerHost: string;
|
|
77
|
+
endpoints: readonly [PeerEndpoint, PeerEndpoint];
|
|
78
|
+
}>[];
|
|
79
|
+
alerts: readonly Readonly<{
|
|
80
|
+
code: string;
|
|
81
|
+
severity: "info" | "warning" | "error";
|
|
82
|
+
timestamp: string;
|
|
83
|
+
provider?: GatewayProvider;
|
|
84
|
+
host?: string;
|
|
85
|
+
alias?: string;
|
|
86
|
+
}>[];
|
|
87
|
+
}>;
|
|
88
|
+
export type PeerMethodParams = {
|
|
89
|
+
initialize: PeerInitializeParams;
|
|
90
|
+
"catalog/get": Readonly<Record<string, never>>;
|
|
91
|
+
handoff: PeerHandoffParams;
|
|
92
|
+
};
|
|
93
|
+
export type PeerMethodResult = {
|
|
94
|
+
initialize: PeerInitializeResult;
|
|
95
|
+
"catalog/get": PeerCatalogResult;
|
|
96
|
+
handoff: PeerHandoffResult;
|
|
97
|
+
};
|
|
98
|
+
export declare class PeerProtocolError extends Error {
|
|
99
|
+
readonly code: string;
|
|
100
|
+
constructor(code: string);
|
|
101
|
+
}
|
|
102
|
+
export declare const isPeerMethod: (value: unknown) => value is PeerMethod;
|
|
103
|
+
export declare function peerEdgeRef(endpoints: readonly [PeerEndpoint, PeerEndpoint]): string;
|
|
104
|
+
export declare function peerInitializeResult(localHost: string): PeerInitializeResult;
|
|
105
|
+
export declare function decodePeerParams<M extends PeerMethod>(method: M, value: unknown): PeerMethodParams[M];
|
|
106
|
+
export declare function decodePeerResult<M extends PeerMethod>(method: M, value: unknown): PeerMethodResult[M];
|
|
107
|
+
export declare function encodePeerFrame(value: unknown, maximum: number): string;
|