agent-embassy 2.0.1 → 3.1.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/CHANGELOG.md +77 -0
- package/CONTRIBUTING.md +23 -36
- package/README.md +123 -222
- package/SECURITY.md +72 -93
- package/dist/src/errors.d.ts +10 -1
- package/dist/src/errors.js +3 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/gateway/claude-helper-protocol.d.ts +8 -11
- package/dist/src/gateway/claude-helper-protocol.js +12 -11
- package/dist/src/gateway/claude-helper-protocol.js.map +1 -1
- package/dist/src/gateway/claude-helper-supervisor.d.ts +1 -5
- package/dist/src/gateway/claude-helper-supervisor.js +45 -17
- package/dist/src/gateway/claude-helper-supervisor.js.map +1 -1
- package/dist/src/gateway/claude-helper.js +6 -6
- package/dist/src/gateway/claude-helper.js.map +1 -1
- package/dist/src/gateway/claude-peer.d.ts +0 -3
- package/dist/src/gateway/claude-peer.js +7 -19
- package/dist/src/gateway/claude-peer.js.map +1 -1
- package/dist/src/gateway/cli.d.ts +17 -7
- package/dist/src/gateway/cli.js +945 -265
- package/dist/src/gateway/cli.js.map +1 -1
- package/dist/src/gateway/codex-socket-holder.d.ts +26 -0
- package/dist/src/gateway/codex-socket-holder.js +76 -0
- package/dist/src/gateway/codex-socket-holder.js.map +1 -0
- package/dist/src/gateway/codex-stateless-transport.js +1 -1
- package/dist/src/gateway/codex-stateless-transport.js.map +1 -1
- package/dist/src/gateway/config.d.ts +1 -10
- package/dist/src/gateway/config.js +4 -10
- package/dist/src/gateway/config.js.map +1 -1
- package/dist/src/gateway/control.d.ts +66 -80
- package/dist/src/gateway/control.js +92 -147
- package/dist/src/gateway/control.js.map +1 -1
- package/dist/src/gateway/federation-nodes.d.ts +29 -2
- package/dist/src/gateway/federation-nodes.js +177 -7
- package/dist/src/gateway/federation-nodes.js.map +1 -1
- package/dist/src/gateway/peer-client.d.ts +4 -3
- package/dist/src/gateway/peer-client.js +22 -13
- package/dist/src/gateway/peer-client.js.map +1 -1
- package/dist/src/gateway/peer-protocol.d.ts +13 -11
- package/dist/src/gateway/peer-protocol.js +14 -12
- package/dist/src/gateway/peer-protocol.js.map +1 -1
- package/dist/src/gateway/provenance-envelope.d.ts +0 -1
- package/dist/src/gateway/provenance-envelope.js +4 -19
- package/dist/src/gateway/provenance-envelope.js.map +1 -1
- package/dist/src/gateway/providers.d.ts +11 -7
- package/dist/src/gateway/providers.js +49 -50
- package/dist/src/gateway/providers.js.map +1 -1
- package/dist/src/gateway/server.d.ts +4 -14
- package/dist/src/gateway/server.js +32 -54
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service-agent.d.ts +187 -0
- package/dist/src/gateway/service-agent.js +758 -0
- package/dist/src/gateway/service-agent.js.map +1 -0
- package/dist/src/gateway/service.d.ts +119 -38
- package/dist/src/gateway/service.js +754 -798
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/status-view.d.ts +119 -0
- package/dist/src/gateway/status-view.js +484 -0
- package/dist/src/gateway/status-view.js.map +1 -0
- package/dist/src/gateway/store.d.ts +106 -21
- package/dist/src/gateway/store.js +463 -537
- package/dist/src/gateway/store.js.map +1 -1
- package/dist/src/gateway/types.d.ts +64 -102
- package/dist/src/gateway/types.js +40 -86
- package/dist/src/gateway/types.js.map +1 -1
- package/docs/CONFIGURATION.md +174 -45
- package/docs/DELIVERY.md +11 -11
- package/docs/GATEWAY-ARCHITECTURE.md +292 -384
- package/package.json +4 -12
- package/skills/embassy-peer/SKILL.md +69 -92
- package/skills/embassy-peer/agents/openai.yaml +1 -1
- package/README.zh-CN.md +0 -275
- package/assets/live-dashboard/app.css +0 -1619
- package/assets/vendor/react/LICENSE +0 -21
- package/assets/vendor/react/react-dom.production.min.js +0 -267
- package/assets/vendor/react/react.production.min.js +0 -31
- package/dist/src/gateway/acp-client.d.ts +0 -110
- package/dist/src/gateway/acp-client.js +0 -407
- package/dist/src/gateway/acp-client.js.map +0 -1
- package/dist/src/gateway/acp-provider.d.ts +0 -66
- package/dist/src/gateway/acp-provider.js +0 -275
- package/dist/src/gateway/acp-provider.js.map +0 -1
- package/dist/src/gateway/claude-helper-client.d.ts +0 -2
- package/dist/src/gateway/claude-helper-client.js +0 -2
- package/dist/src/gateway/claude-helper-client.js.map +0 -1
- package/dist/src/gateway/cli-copy.d.ts +0 -8
- package/dist/src/gateway/cli-copy.en.d.ts +0 -22
- package/dist/src/gateway/cli-copy.en.js +0 -62
- package/dist/src/gateway/cli-copy.en.js.map +0 -1
- package/dist/src/gateway/cli-copy.js +0 -27
- package/dist/src/gateway/cli-copy.js.map +0 -1
- package/dist/src/gateway/cli-copy.zh-CN.d.ts +0 -22
- package/dist/src/gateway/cli-copy.zh-CN.js +0 -62
- package/dist/src/gateway/cli-copy.zh-CN.js.map +0 -1
- package/dist/src/gateway/codex-doctor.d.ts +0 -36
- package/dist/src/gateway/codex-doctor.js +0 -127
- package/dist/src/gateway/codex-doctor.js.map +0 -1
- package/dist/src/gateway/dashboard-copy.d.ts +0 -7
- package/dist/src/gateway/dashboard-copy.en.d.ts +0 -504
- package/dist/src/gateway/dashboard-copy.en.js +0 -505
- package/dist/src/gateway/dashboard-copy.en.js.map +0 -1
- package/dist/src/gateway/dashboard-copy.js +0 -514
- package/dist/src/gateway/dashboard-copy.js.map +0 -1
- package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +0 -504
- package/dist/src/gateway/dashboard-copy.zh-CN.js +0 -505
- package/dist/src/gateway/dashboard-copy.zh-CN.js.map +0 -1
- package/dist/src/gateway/dashboard-model.d.ts +0 -343
- package/dist/src/gateway/dashboard-model.js +0 -1061
- package/dist/src/gateway/dashboard-model.js.map +0 -1
- package/dist/src/gateway/dashboard.d.ts +0 -20
- package/dist/src/gateway/dashboard.js +0 -874
- package/dist/src/gateway/dashboard.js.map +0 -1
- package/dist/src/gateway/deepseek-detect.d.ts +0 -14
- package/dist/src/gateway/deepseek-detect.js +0 -41
- package/dist/src/gateway/deepseek-detect.js.map +0 -1
- package/dist/src/gateway/live-dashboard-app/app.js +0 -2385
- package/dist/src/gateway/live-dashboard-assets.d.ts +0 -10
- package/dist/src/gateway/live-dashboard-assets.js +0 -74
- package/dist/src/gateway/live-dashboard-assets.js.map +0 -1
- package/dist/src/gateway/live-dashboard-command.d.ts +0 -60
- package/dist/src/gateway/live-dashboard-command.js +0 -334
- package/dist/src/gateway/live-dashboard-command.js.map +0 -1
- package/dist/src/gateway/live-dashboard-http.d.ts +0 -39
- package/dist/src/gateway/live-dashboard-http.js +0 -383
- package/dist/src/gateway/live-dashboard-http.js.map +0 -1
- package/dist/src/gateway/live-dashboard-protocol.d.ts +0 -34
- package/dist/src/gateway/live-dashboard-protocol.js +0 -114
- package/dist/src/gateway/live-dashboard-protocol.js.map +0 -1
- package/dist/src/gateway/live-dashboard-server.d.ts +0 -33
- package/dist/src/gateway/live-dashboard-server.js +0 -144
- package/dist/src/gateway/live-dashboard-server.js.map +0 -1
- package/dist/src/gateway/live-dashboard-stream.d.ts +0 -46
- package/dist/src/gateway/live-dashboard-stream.js +0 -234
- package/dist/src/gateway/live-dashboard-stream.js.map +0 -1
- package/dist/src/gateway/live-dashboard.d.ts +0 -28
- package/dist/src/gateway/live-dashboard.js +0 -154
- package/dist/src/gateway/live-dashboard.js.map +0 -1
- package/dist/src/gateway/locale.d.ts +0 -4
- package/dist/src/gateway/locale.js +0 -10
- package/dist/src/gateway/locale.js.map +0 -1
- package/dist/src/gateway/progress-watch-machine.d.ts +0 -45
- package/dist/src/gateway/progress-watch-machine.js +0 -70
- package/dist/src/gateway/progress-watch-machine.js.map +0 -1
- package/docs/CONFIGURATION.zh-CN.md +0 -97
- package/docs/DASHBOARD.md +0 -98
- package/docs/DASHBOARD.zh-CN.md +0 -49
- package/docs/DELIVERY.zh-CN.md +0 -55
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
export declare const gatewayProviders: readonly ["claude", "codex", "
|
|
1
|
+
export declare const gatewayProviders: readonly ["claude", "codex", "peer"];
|
|
2
2
|
export type GatewayProvider = (typeof gatewayProviders)[number];
|
|
3
3
|
export declare const gatewayRegistrationIngressPrefixes: Readonly<{
|
|
4
4
|
claude: undefined;
|
|
5
5
|
codex: string;
|
|
6
|
-
deepseek: string;
|
|
7
|
-
grok: string;
|
|
8
6
|
peer: string;
|
|
9
7
|
}>;
|
|
10
|
-
export declare const gatewayInboundModes: readonly ["paired", "open"];
|
|
11
|
-
export type GatewayInboundMode = (typeof gatewayInboundModes)[number];
|
|
12
8
|
export declare const connectorHealthStates: readonly ["offline", "connecting", "healthy", "degraded"];
|
|
13
9
|
export type ConnectorHealth = (typeof connectorHealthStates)[number];
|
|
14
10
|
export declare const routeStates: readonly ["stale", "idle", "busy", "awaiting_approval", "offline", "disabled"];
|
|
@@ -22,7 +18,6 @@ export type ParsedMessageDirection = Readonly<{
|
|
|
22
18
|
}>;
|
|
23
19
|
export declare const isGatewayProvider: (value: unknown) => value is GatewayProvider;
|
|
24
20
|
export declare function directionId(sourceProvider: GatewayProvider, targetProvider: GatewayProvider): MessageDirection;
|
|
25
|
-
export declare const messageDirections: readonly MessageDirection[];
|
|
26
21
|
export declare function parseDirection(value: unknown): ParsedMessageDirection | undefined;
|
|
27
22
|
export declare const isMessageDirection: (value: unknown) => value is MessageDirection;
|
|
28
23
|
export declare const deliveryStates: readonly ["queued", "duplicate", "dispatching", "transport_written", "held", "delivered", "unconfirmed", "failed", "ambiguous", "expired", "cancelled", "abandoned", "rejected"];
|
|
@@ -36,9 +31,6 @@ export declare const gatewayPublicSnapshotLimits: Readonly<{
|
|
|
36
31
|
readonly registryRejectionCodes: 32;
|
|
37
32
|
readonly availablePeers: 256;
|
|
38
33
|
readonly routes: 256;
|
|
39
|
-
readonly consentEdges: 256;
|
|
40
|
-
readonly progressWatches: 64;
|
|
41
|
-
readonly progressWatchEvents: 256;
|
|
42
34
|
readonly activityEvents: 256;
|
|
43
35
|
readonly messages: 1024;
|
|
44
36
|
readonly alerts: 256;
|
|
@@ -76,22 +68,6 @@ export type GatewayRouteRecord = {
|
|
|
76
68
|
updatedAt: string;
|
|
77
69
|
counters: RouteCounters;
|
|
78
70
|
};
|
|
79
|
-
/**
|
|
80
|
-
* Durable bidirectional consent between two exact route owners. Aliases are
|
|
81
|
-
* display coordinates; the private registration identities prevent an alias from silently
|
|
82
|
-
* retargeting an existing permission edge.
|
|
83
|
-
*/
|
|
84
|
-
export type GatewayConsentEndpoint = Readonly<{
|
|
85
|
-
alias: string;
|
|
86
|
-
provider: GatewayProvider;
|
|
87
|
-
registrationId: string;
|
|
88
|
-
}>;
|
|
89
|
-
export type GatewayConsentEdgeRecord = {
|
|
90
|
-
endpoints: readonly [GatewayConsentEndpoint, GatewayConsentEndpoint];
|
|
91
|
-
createdAt: string;
|
|
92
|
-
updatedAt: string;
|
|
93
|
-
counters: RouteCounters;
|
|
94
|
-
};
|
|
95
71
|
/**
|
|
96
72
|
* Controller-internal route view used to prove ownership across a restart.
|
|
97
73
|
* This type must never cross the control protocol or enter a public snapshot.
|
|
@@ -113,8 +89,6 @@ export type QueuedMessageMetadata = {
|
|
|
113
89
|
deadlineAt: string;
|
|
114
90
|
bytes: number;
|
|
115
91
|
body?: string;
|
|
116
|
-
pair?: true;
|
|
117
|
-
transientTarget?: true;
|
|
118
92
|
steer?: true;
|
|
119
93
|
};
|
|
120
94
|
export type DedupeRecord = {
|
|
@@ -124,7 +98,6 @@ export type DedupeRecord = {
|
|
|
124
98
|
sourceAlias: string;
|
|
125
99
|
targetAlias: string;
|
|
126
100
|
direction: MessageDirection;
|
|
127
|
-
pair?: true;
|
|
128
101
|
firstSeenAt: string;
|
|
129
102
|
expiresAt: string;
|
|
130
103
|
};
|
|
@@ -163,7 +136,7 @@ export type GatewayAccounting = {
|
|
|
163
136
|
queuedBytes: number;
|
|
164
137
|
};
|
|
165
138
|
export type GatewayPreparedWriteEvidence = {
|
|
166
|
-
kind: "claude_mailbox" | "codex_turn_start" | "codex_turn_steer" | "
|
|
139
|
+
kind: "claude_mailbox" | "codex_turn_start" | "codex_turn_steer" | "peer_mailbox" | "peer_handoff";
|
|
167
140
|
bodyBytes: number;
|
|
168
141
|
bodySha256: string;
|
|
169
142
|
frameBytes: number;
|
|
@@ -173,8 +146,7 @@ export type GatewayMessageAttemptAuthority = {
|
|
|
173
146
|
attemptId: string;
|
|
174
147
|
attemptCount: number;
|
|
175
148
|
targetRegistrationId: string;
|
|
176
|
-
sourceRegistrationId: string
|
|
177
|
-
consentEdge: readonly [GatewayConsentEndpoint, GatewayConsentEndpoint] | null;
|
|
149
|
+
sourceRegistrationId: string;
|
|
178
150
|
};
|
|
179
151
|
export type GatewayMessageState = {
|
|
180
152
|
phase: "queued";
|
|
@@ -201,9 +173,8 @@ export type GatewayMessageState = {
|
|
|
201
173
|
export type GatewayMessageRecord = QueuedMessageMetadata & {
|
|
202
174
|
sequence: number;
|
|
203
175
|
deliveryToken?: string;
|
|
204
|
-
sourceRegistrationId: string
|
|
176
|
+
sourceRegistrationId: string;
|
|
205
177
|
targetRegistrationId: string | null;
|
|
206
|
-
consentEdge: readonly [GatewayConsentEndpoint, GatewayConsentEndpoint] | null;
|
|
207
178
|
state: GatewayMessageState;
|
|
208
179
|
};
|
|
209
180
|
export type GatewayMessageActivity = {
|
|
@@ -216,7 +187,7 @@ export type GatewayRuntimeActivity = {
|
|
|
216
187
|
};
|
|
217
188
|
export type GatewayStateActivity = GatewayMessageActivity | GatewayRuntimeActivity;
|
|
218
189
|
export type GatewayPersistedState = {
|
|
219
|
-
schemaVersion:
|
|
190
|
+
schemaVersion: 5;
|
|
220
191
|
commit: {
|
|
221
192
|
sequence: number;
|
|
222
193
|
id: string;
|
|
@@ -225,7 +196,6 @@ export type GatewayPersistedState = {
|
|
|
225
196
|
updatedAt: string;
|
|
226
197
|
eventSequence: number;
|
|
227
198
|
routes: GatewayRouteRecord[];
|
|
228
|
-
consentEdges: GatewayConsentEdgeRecord[];
|
|
229
199
|
messages: GatewayMessageRecord[];
|
|
230
200
|
dedupe: DedupeRecord[];
|
|
231
201
|
rateBuckets: RateBucket[];
|
|
@@ -246,16 +216,6 @@ export type PublicRouteSnapshot = {
|
|
|
246
216
|
safeErrorCode?: string;
|
|
247
217
|
mutable?: boolean;
|
|
248
218
|
};
|
|
249
|
-
export type PublicConsentEndpointSnapshot = Readonly<{
|
|
250
|
-
alias: string;
|
|
251
|
-
provider: GatewayProvider;
|
|
252
|
-
}>;
|
|
253
|
-
export type PublicConsentEdgeSnapshot = {
|
|
254
|
-
endpoints: readonly [PublicConsentEndpointSnapshot, PublicConsentEndpointSnapshot];
|
|
255
|
-
host: string;
|
|
256
|
-
counters: RouteCounters;
|
|
257
|
-
mutable?: boolean;
|
|
258
|
-
};
|
|
259
219
|
export type PublicConnectorSnapshot = {
|
|
260
220
|
provider: GatewayProvider;
|
|
261
221
|
host: string;
|
|
@@ -264,15 +224,26 @@ export type PublicConnectorSnapshot = {
|
|
|
264
224
|
protocolVersion: string;
|
|
265
225
|
lastSeenAt?: string;
|
|
266
226
|
observationAgeMs?: number;
|
|
267
|
-
codexDoctor?: PublicCodexDoctorSnapshot;
|
|
268
227
|
safeErrorCode?: string;
|
|
269
228
|
registry?: PublicRegistryObservationSnapshot;
|
|
270
229
|
};
|
|
271
|
-
export type PublicCodexDoctorCondition = "split_brain" | "orphaned" | "attached" | "observation_stale" | "managed_layout_missing" | "unknown";
|
|
272
|
-
export type PublicCodexDoctorSnapshot = Readonly<{
|
|
273
|
-
conditions: readonly PublicCodexDoctorCondition[];
|
|
274
|
-
}>;
|
|
275
230
|
export declare const CONNECTOR_OBSERVATION_STALE_AFTER_MS = 35000;
|
|
231
|
+
/** The words a connector is allowed to say. Never a sentence, never a number. */
|
|
232
|
+
export type StatusWord = "ok" | "stale" | "degraded" | "offline";
|
|
233
|
+
/**
|
|
234
|
+
* Connector words. A connector reporting `CONNECTOR_OBSERVATION_STALE` has
|
|
235
|
+
* nothing wrong with it: no route of that provider was observed inside the
|
|
236
|
+
* broker's window. That is `stale`, not `degraded`, and the difference is the
|
|
237
|
+
* point — an idle Mac with no registered Codex task must not read as broken.
|
|
238
|
+
*/
|
|
239
|
+
export declare function connectorWord(connector: PublicConnectorSnapshot): StatusWord;
|
|
240
|
+
/**
|
|
241
|
+
* The overall word is informational and derived from the two connectors a
|
|
242
|
+
* message actually travels through. A shell peer never contributes: its
|
|
243
|
+
* mailbox is pull-only, so "nobody is awaiting it" is a fact about the
|
|
244
|
+
* operator's other terminal, not about the broker.
|
|
245
|
+
*/
|
|
246
|
+
export declare function gatewayHealthWord(connectors: readonly PublicConnectorSnapshot[]): StatusWord;
|
|
276
247
|
/**
|
|
277
248
|
* Bounded, native-ID-free evidence attached to one Claude connector. Counts
|
|
278
249
|
* describe only the latest pass; the monotonic flag distinguishes an ordinary
|
|
@@ -295,7 +266,10 @@ export type PublicAvailablePeerState = (typeof publicAvailablePeerStates)[number
|
|
|
295
266
|
* A transient, metadata-only discovery row. Native provider IDs, process
|
|
296
267
|
* identifiers, registry/socket paths, and generations are deliberately absent.
|
|
297
268
|
* Version 1 uses this for genuine Claude peers; Codex inventory remains the
|
|
298
|
-
* explicit PublicRouteSnapshot list.
|
|
269
|
+
* explicit PublicRouteSnapshot list. `routed` means the session currently has
|
|
270
|
+
* an installed logical route — it is a fact about the route table, never a
|
|
271
|
+
* permission: any discovered session is addressable, and its route installs on
|
|
272
|
+
* first use.
|
|
299
273
|
*/
|
|
300
274
|
export type PublicAvailablePeerSnapshot = {
|
|
301
275
|
alias: string;
|
|
@@ -303,13 +277,18 @@ export type PublicAvailablePeerSnapshot = {
|
|
|
303
277
|
host: string;
|
|
304
278
|
state: PublicAvailablePeerState;
|
|
305
279
|
validated: boolean;
|
|
306
|
-
|
|
280
|
+
routed: boolean;
|
|
307
281
|
lastSeenAt?: string;
|
|
308
282
|
safeErrorCode?: string;
|
|
309
283
|
};
|
|
310
|
-
export declare const gatewayActivityKinds: readonly ["discovery", "
|
|
284
|
+
export declare const gatewayActivityKinds: readonly ["discovery", "registration"];
|
|
311
285
|
export type GatewayActivityKind = (typeof gatewayActivityKinds)[number];
|
|
312
|
-
|
|
286
|
+
/**
|
|
287
|
+
* `claude_route_installed` and `claude_route_retired` are journaled by the
|
|
288
|
+
* store when a send installs, renames, or displaces a discovered Claude
|
|
289
|
+
* session's route; there is no explicit Claude registration command.
|
|
290
|
+
*/
|
|
291
|
+
export declare const gatewayActivityActions: readonly ["discovery_refreshed", "codex_registered", "codex_succeeded", "codex_unregistered", "claude_route_installed", "claude_route_retired", "route_retired"];
|
|
313
292
|
export type GatewayActivityAction = (typeof gatewayActivityActions)[number];
|
|
314
293
|
export type PublicGatewayActivityEvent = {
|
|
315
294
|
sequence: number;
|
|
@@ -335,8 +314,6 @@ export type DeadlinePressureSnapshot = {
|
|
|
335
314
|
expiredEvents: number;
|
|
336
315
|
buckets: DeadlinePressureBucket[];
|
|
337
316
|
};
|
|
338
|
-
export declare function isPublicAvailablePeerSnapshot(value: unknown): value is PublicAvailablePeerSnapshot;
|
|
339
|
-
export declare function arePublicAvailablePeerSnapshots(value: unknown, maximumRows?: number): value is PublicAvailablePeerSnapshot[];
|
|
340
317
|
export declare function isPublicRegistryObservationSnapshot(value: unknown): value is PublicRegistryObservationSnapshot;
|
|
341
318
|
export type SafeGatewayAlert = {
|
|
342
319
|
code: string;
|
|
@@ -346,35 +323,13 @@ export type SafeGatewayAlert = {
|
|
|
346
323
|
host?: string;
|
|
347
324
|
alias?: string;
|
|
348
325
|
};
|
|
349
|
-
export type PublicProgressWatchSnapshot = {
|
|
350
|
-
conversationIdSuffix: string;
|
|
351
|
-
ownerAlias: string;
|
|
352
|
-
workerAlias: string;
|
|
353
|
-
lastActivityAt: string;
|
|
354
|
-
nextActionAt: string;
|
|
355
|
-
nudgeCount: 0 | 1 | 2;
|
|
356
|
-
};
|
|
357
|
-
export type PublicProgressWatchEventSnapshot = {
|
|
358
|
-
sequence: number;
|
|
359
|
-
timestamp: string;
|
|
360
|
-
conversationIdSuffix: string;
|
|
361
|
-
ownerAlias: string;
|
|
362
|
-
workerAlias: string;
|
|
363
|
-
kind: "opened" | "replaced" | "settled";
|
|
364
|
-
actor: "owner" | "worker" | "operator" | "gateway" | "unknown";
|
|
365
|
-
reason?: "done" | "untracked" | "idle_timeout" | "pair_removed" | "endpoint_retired" | "tracking_disabled";
|
|
366
|
-
};
|
|
367
326
|
export type GatewayPublicSnapshot = {
|
|
368
327
|
schemaVersion: 2;
|
|
369
328
|
generatedAt: string;
|
|
370
|
-
inboundMode: GatewayInboundMode;
|
|
371
329
|
health: ConnectorHealth;
|
|
372
330
|
connectors: PublicConnectorSnapshot[];
|
|
373
331
|
availablePeers: PublicAvailablePeerSnapshot[];
|
|
374
332
|
routes: PublicRouteSnapshot[];
|
|
375
|
-
consentEdges: PublicConsentEdgeSnapshot[];
|
|
376
|
-
progressWatches?: PublicProgressWatchSnapshot[];
|
|
377
|
-
progressWatchEvents?: PublicProgressWatchEventSnapshot[];
|
|
378
333
|
activityEvents?: PublicGatewayActivityEvent[];
|
|
379
334
|
deadlinePressure?: DeadlinePressureSnapshot;
|
|
380
335
|
messages: NormalizedMessageEvent[];
|
|
@@ -386,9 +341,6 @@ export type GatewaySnapshotTruncation = {
|
|
|
386
341
|
connectors: number;
|
|
387
342
|
availablePeers: number;
|
|
388
343
|
routes: number;
|
|
389
|
-
consentEdges: number;
|
|
390
|
-
progressWatches?: number;
|
|
391
|
-
progressWatchEvents?: number;
|
|
392
344
|
activityEvents?: number;
|
|
393
345
|
messages: number;
|
|
394
346
|
alerts: number;
|
|
@@ -397,13 +349,23 @@ export type GatewaySnapshotTruncation = {
|
|
|
397
349
|
* Deterministically projects a canonical snapshot under the local control
|
|
398
350
|
* byte budget. Content is never shortened: complete metadata rows are either
|
|
399
351
|
* retained or counted as omitted. Registry rejection-code detail is shed
|
|
400
|
-
* before
|
|
352
|
+
* before routes; connector inventory remains last.
|
|
401
353
|
*/
|
|
402
354
|
export declare function projectGatewayPublicSnapshot(snapshot: GatewayPublicSnapshot, maximumBytes?: number): GatewayPublicSnapshot;
|
|
403
355
|
export type RegisterRouteInput = {
|
|
404
356
|
alias: string;
|
|
405
357
|
binding: LogicalRouteBinding;
|
|
406
358
|
registrationMode: RouteRegistrationMode;
|
|
359
|
+
/**
|
|
360
|
+
* An ephemeral registration is real in memory — it routes, queues, and
|
|
361
|
+
* settles exactly like any other — but it is projected out of the durable
|
|
362
|
+
* state document along with every row that names it, so it cannot survive
|
|
363
|
+
* a restart and cannot be published to a federation peer; and when it is
|
|
364
|
+
* removed, by `unregister-peer` or by its own expiry, those rows leave the
|
|
365
|
+
* live state with it, so nothing of it is written afterwards either.
|
|
366
|
+
* `embassy check` uses one so a self-test leaves nothing behind.
|
|
367
|
+
*/
|
|
368
|
+
ephemeral?: true;
|
|
407
369
|
};
|
|
408
370
|
export type GatewayReservedAttempt = Readonly<{
|
|
409
371
|
messageId: string;
|
|
@@ -415,9 +377,8 @@ export type GatewayReservedAttempt = Readonly<{
|
|
|
415
377
|
sourceAlias: string;
|
|
416
378
|
targetAlias: string;
|
|
417
379
|
conversationIdSuffix?: string;
|
|
418
|
-
sourceRegistrationId: string
|
|
380
|
+
sourceRegistrationId: string;
|
|
419
381
|
targetRegistrationId: string;
|
|
420
|
-
consentEdge: readonly [GatewayConsentEndpoint, GatewayConsentEndpoint] | null;
|
|
421
382
|
bytes: number;
|
|
422
383
|
steer?: true;
|
|
423
384
|
}>;
|
|
@@ -442,7 +403,7 @@ type SettledAttemptResult = Readonly<{
|
|
|
442
403
|
settlement: TerminalMessageSettlement;
|
|
443
404
|
}>;
|
|
444
405
|
export type AuthorizeMessageInput = AttemptInput & Readonly<{
|
|
445
|
-
sourceRegistrationId: string
|
|
406
|
+
sourceRegistrationId: string;
|
|
446
407
|
targetRegistrationId: string;
|
|
447
408
|
prepared: GatewayPreparedWriteEvidence;
|
|
448
409
|
}>;
|
|
@@ -450,7 +411,7 @@ export type AuthorizeMessageResult = Readonly<{
|
|
|
450
411
|
status: "authorized";
|
|
451
412
|
}> | Readonly<{
|
|
452
413
|
status: "stale";
|
|
453
|
-
reason: "not_reserved" | "attempt_mismatch" | "registration_changed"
|
|
414
|
+
reason: "not_reserved" | "attempt_mismatch" | "registration_changed";
|
|
454
415
|
}> | Readonly<{
|
|
455
416
|
status: "terminal";
|
|
456
417
|
reason: "expired" | "fenced";
|
|
@@ -500,6 +461,14 @@ export type ReplaceCodexRegistrationAtomicResult = Readonly<{
|
|
|
500
461
|
idempotent: boolean;
|
|
501
462
|
settlements: readonly TerminalMessageSettlement[];
|
|
502
463
|
}>;
|
|
464
|
+
/**
|
|
465
|
+
* Result of installing a discovered Claude session's route on first send.
|
|
466
|
+
* `settlements` carries the work of any route the install displaced.
|
|
467
|
+
*/
|
|
468
|
+
export type InstallClaudeRouteResult = Readonly<{
|
|
469
|
+
installed: boolean;
|
|
470
|
+
settlements: readonly TerminalMessageSettlement[];
|
|
471
|
+
}>;
|
|
503
472
|
export type EnqueueMessageInput = {
|
|
504
473
|
sourceAlias: string;
|
|
505
474
|
targetAlias: string;
|
|
@@ -512,26 +481,18 @@ export type EnqueueMessageInput = {
|
|
|
512
481
|
steer?: true;
|
|
513
482
|
};
|
|
514
483
|
/**
|
|
515
|
-
*
|
|
516
|
-
* The binding
|
|
517
|
-
* in-memory call argument.
|
|
484
|
+
* The native Claude sender of one inbound message: its installed route's
|
|
485
|
+
* alias and exact binding. The binding carries a native session identifier
|
|
486
|
+
* and must remain an in-memory call argument.
|
|
518
487
|
*/
|
|
519
|
-
export type
|
|
488
|
+
export type NativeClaudeSender = {
|
|
520
489
|
alias: string;
|
|
521
490
|
binding: LogicalRouteBinding;
|
|
522
491
|
};
|
|
523
492
|
export type EnqueueNativeIngressInput = Omit<EnqueueMessageInput, "sourceAlias" | "targetAlias" | "expectedSourceRegistrationId" | "expectedTargetRegistrationId"> & {
|
|
524
|
-
source:
|
|
493
|
+
source: NativeClaudeSender;
|
|
525
494
|
targetAlias: string;
|
|
526
495
|
expectedTargetRegistrationId: string;
|
|
527
|
-
authorizedPairTeardownReply?: true;
|
|
528
|
-
};
|
|
529
|
-
export type EnqueueNativeReplyInput = Omit<EnqueueMessageInput, "sourceAlias" | "targetAlias" | "expectedSourceRegistrationId" | "expectedTargetRegistrationId"> & {
|
|
530
|
-
sourceAlias: string;
|
|
531
|
-
expectedSourceRegistrationId: string;
|
|
532
|
-
target: TransientNativeClaudePeer;
|
|
533
|
-
pair?: true;
|
|
534
|
-
exposeDeliveryToken?: true;
|
|
535
496
|
};
|
|
536
497
|
export type EnqueueMessageResult = {
|
|
537
498
|
accepted: boolean;
|
|
@@ -539,7 +500,6 @@ export type EnqueueMessageResult = {
|
|
|
539
500
|
messageId?: string;
|
|
540
501
|
messageIdSuffix: string;
|
|
541
502
|
deliveryToken?: string;
|
|
542
|
-
pair?: true;
|
|
543
503
|
supersededSettlement?: TerminalMessageSettlement;
|
|
544
504
|
};
|
|
545
505
|
/**
|
|
@@ -554,8 +514,6 @@ export type TerminalMessageSettlement = {
|
|
|
554
514
|
};
|
|
555
515
|
export type GatewayStoreLimits = {
|
|
556
516
|
maxRoutes: number;
|
|
557
|
-
maxConsentEdges: number;
|
|
558
|
-
maxWatches?: number;
|
|
559
517
|
eventCapacity: number;
|
|
560
518
|
eventTtlMs: number;
|
|
561
519
|
dedupeCapacity: number;
|
|
@@ -575,5 +533,9 @@ export type GatewayStoreDependencies = {
|
|
|
575
533
|
randomId?: () => string;
|
|
576
534
|
renameStateFile?: (source: string, target: string) => Promise<void>;
|
|
577
535
|
afterStateFileRename?: () => void | Promise<void>;
|
|
536
|
+
/** Controller-lock liveness probe; the default is `process.kill(pid, 0)`. */
|
|
537
|
+
isProcessAlive?: (pid: number) => boolean;
|
|
538
|
+
/** This machine's name as the controller lock records it; the default is `os.hostname()`. */
|
|
539
|
+
hostname?: () => string;
|
|
578
540
|
};
|
|
579
541
|
export {};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export const gatewayProviders = ["claude", "codex", "
|
|
2
|
-
export const gatewayRegistrationIngressPrefixes = Object.freeze({ claude: undefined, codex: "codex-",
|
|
3
|
-
export const gatewayInboundModes = ["paired", "open"];
|
|
1
|
+
export const gatewayProviders = ["claude", "codex", "peer"];
|
|
2
|
+
export const gatewayRegistrationIngressPrefixes = Object.freeze({ claude: undefined, codex: "codex-", peer: "peer-" });
|
|
4
3
|
export const connectorHealthStates = ["offline", "connecting", "healthy", "degraded"];
|
|
5
4
|
export const routeStates = ["stale", "idle", "busy", "awaiting_approval", "offline", "disabled"];
|
|
6
5
|
export const routeRegistrationModes = ["explicit_opt_in", "selected_live_peer", "federated_peer"];
|
|
@@ -8,7 +7,6 @@ export const isGatewayProvider = (value) => typeof value === "string" && gateway
|
|
|
8
7
|
export function directionId(sourceProvider, targetProvider) {
|
|
9
8
|
return `${sourceProvider}_to_${targetProvider}`;
|
|
10
9
|
}
|
|
11
|
-
export const messageDirections = Object.freeze(gatewayProviders.flatMap((sourceProvider) => gatewayProviders.map((targetProvider) => directionId(sourceProvider, targetProvider))));
|
|
12
10
|
export function parseDirection(value) {
|
|
13
11
|
if (typeof value !== "string")
|
|
14
12
|
return undefined;
|
|
@@ -31,12 +29,37 @@ export const alertSeverities = ["info", "warning", "error"];
|
|
|
31
29
|
export const gatewayPublicSnapshotLimits = Object.freeze({
|
|
32
30
|
connectors: 64, registryRejectionCodes: 32,
|
|
33
31
|
availablePeers: 256, routes: 256,
|
|
34
|
-
|
|
35
|
-
progressWatchEvents: 256, activityEvents: 256,
|
|
32
|
+
activityEvents: 256,
|
|
36
33
|
messages: 1_024, alerts: 256,
|
|
37
34
|
});
|
|
38
35
|
export const GATEWAY_PUBLIC_SNAPSHOT_BYTE_BUDGET = 240 * 1024;
|
|
39
36
|
export const CONNECTOR_OBSERVATION_STALE_AFTER_MS = 35_000;
|
|
37
|
+
/**
|
|
38
|
+
* Connector words. A connector reporting `CONNECTOR_OBSERVATION_STALE` has
|
|
39
|
+
* nothing wrong with it: no route of that provider was observed inside the
|
|
40
|
+
* broker's window. That is `stale`, not `degraded`, and the difference is the
|
|
41
|
+
* point — an idle Mac with no registered Codex task must not read as broken.
|
|
42
|
+
*/
|
|
43
|
+
export function connectorWord(connector) {
|
|
44
|
+
if (connector.health === "healthy" || connector.health === "connecting")
|
|
45
|
+
return "ok";
|
|
46
|
+
if (connector.health === "offline")
|
|
47
|
+
return "offline";
|
|
48
|
+
return connector.safeErrorCode === "CONNECTOR_OBSERVATION_STALE" ? "stale" : "degraded";
|
|
49
|
+
}
|
|
50
|
+
const severityRank = (word) => word === "degraded" || word === "offline" ? 0 : word === "stale" ? 1 : 2;
|
|
51
|
+
/**
|
|
52
|
+
* The overall word is informational and derived from the two connectors a
|
|
53
|
+
* message actually travels through. A shell peer never contributes: its
|
|
54
|
+
* mailbox is pull-only, so "nobody is awaiting it" is a fact about the
|
|
55
|
+
* operator's other terminal, not about the broker.
|
|
56
|
+
*/
|
|
57
|
+
export function gatewayHealthWord(connectors) {
|
|
58
|
+
const routed = connectors.filter((connector) => connector.provider === "claude" || connector.provider === "codex");
|
|
59
|
+
if (routed.length === 0)
|
|
60
|
+
return "offline";
|
|
61
|
+
return routed.map(connectorWord).reduce((worst, word) => severityRank(word) < severityRank(worst) ? word : worst, "ok");
|
|
62
|
+
}
|
|
40
63
|
export const publicAvailablePeerStates = [
|
|
41
64
|
"idle",
|
|
42
65
|
"busy",
|
|
@@ -45,21 +68,21 @@ export const publicAvailablePeerStates = [
|
|
|
45
68
|
];
|
|
46
69
|
export const gatewayActivityKinds = [
|
|
47
70
|
"discovery",
|
|
48
|
-
"selection",
|
|
49
71
|
"registration",
|
|
50
|
-
"pairing",
|
|
51
|
-
"watch",
|
|
52
72
|
];
|
|
73
|
+
/**
|
|
74
|
+
* `claude_route_installed` and `claude_route_retired` are journaled by the
|
|
75
|
+
* store when a send installs, renames, or displaces a discovered Claude
|
|
76
|
+
* session's route; there is no explicit Claude registration command.
|
|
77
|
+
*/
|
|
53
78
|
export const gatewayActivityActions = [
|
|
54
79
|
"discovery_refreshed",
|
|
55
|
-
"claude_selected",
|
|
56
|
-
"claude_unselected",
|
|
57
80
|
"codex_registered",
|
|
58
81
|
"codex_succeeded",
|
|
59
82
|
"codex_unregistered",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
83
|
+
"claude_route_installed",
|
|
84
|
+
"claude_route_retired",
|
|
85
|
+
"route_retired",
|
|
63
86
|
];
|
|
64
87
|
export const deadlinePressureBucketNames = [
|
|
65
88
|
"under_1m",
|
|
@@ -68,8 +91,6 @@ export const deadlinePressureBucketNames = [
|
|
|
68
91
|
"15m_to_60m",
|
|
69
92
|
"over_60m",
|
|
70
93
|
];
|
|
71
|
-
const PUBLIC_ALIAS_PATTERN = /^[a-z][a-z0-9_-]{0,31}@[a-z0-9](?:[a-z0-9.-]{0,61}[a-z0-9])?$/;
|
|
72
|
-
const PUBLIC_HOST_PATTERN = /^[a-z0-9](?:[a-z0-9.-]{0,61}[a-z0-9])?$/;
|
|
73
94
|
const PUBLIC_SAFE_CODE_PATTERN = /^[A-Z][A-Z0-9_]{0,63}$/;
|
|
74
95
|
function publicRecord(value) {
|
|
75
96
|
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
@@ -80,42 +101,9 @@ function exactPublicKeys(value, required, optional = []) {
|
|
|
80
101
|
return required.every((key) => Object.hasOwn(value, key)) &&
|
|
81
102
|
keys.every((key) => required.includes(key) || optional.includes(key));
|
|
82
103
|
}
|
|
83
|
-
function publicTimestamp(value) {
|
|
84
|
-
return typeof value === "string" && value.length >= 20 && value.length <= 35 && Number.isFinite(Date.parse(value));
|
|
85
|
-
}
|
|
86
104
|
function nonNegative(value) {
|
|
87
105
|
return Number.isSafeInteger(value) && Number(value) >= 0;
|
|
88
106
|
}
|
|
89
|
-
export function isPublicAvailablePeerSnapshot(value) {
|
|
90
|
-
const candidate = publicRecord(value);
|
|
91
|
-
if (candidate === undefined ||
|
|
92
|
-
!exactPublicKeys(candidate, ["alias", "provider", "host", "state", "validated", "selected"], ["lastSeenAt", "safeErrorCode"]) ||
|
|
93
|
-
typeof candidate.alias !== "string" ||
|
|
94
|
-
!PUBLIC_ALIAS_PATTERN.test(candidate.alias) ||
|
|
95
|
-
typeof candidate.host !== "string" ||
|
|
96
|
-
!PUBLIC_HOST_PATTERN.test(candidate.host) ||
|
|
97
|
-
!candidate.alias.endsWith(`@${candidate.host}`) ||
|
|
98
|
-
candidate.provider !== "claude" ||
|
|
99
|
-
typeof candidate.state !== "string" ||
|
|
100
|
-
!publicAvailablePeerStates.includes(candidate.state) ||
|
|
101
|
-
typeof candidate.validated !== "boolean" ||
|
|
102
|
-
typeof candidate.selected !== "boolean")
|
|
103
|
-
return false;
|
|
104
|
-
return (candidate.lastSeenAt === undefined || publicTimestamp(candidate.lastSeenAt)) &&
|
|
105
|
-
(candidate.safeErrorCode === undefined ||
|
|
106
|
-
(typeof candidate.safeErrorCode === "string" && PUBLIC_SAFE_CODE_PATTERN.test(candidate.safeErrorCode)));
|
|
107
|
-
}
|
|
108
|
-
export function arePublicAvailablePeerSnapshots(value, maximumRows = gatewayPublicSnapshotLimits.availablePeers) {
|
|
109
|
-
if (!Array.isArray(value) ||
|
|
110
|
-
!Number.isSafeInteger(maximumRows) ||
|
|
111
|
-
maximumRows < 0 ||
|
|
112
|
-
value.length > maximumRows ||
|
|
113
|
-
!value.every(isPublicAvailablePeerSnapshot)) {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
const aliases = value.map((peer) => `${peer.provider}\0${peer.alias}`);
|
|
117
|
-
return new Set(aliases).size === aliases.length;
|
|
118
|
-
}
|
|
119
107
|
export function isPublicRegistryObservationSnapshot(value) {
|
|
120
108
|
const candidate = publicRecord(value);
|
|
121
109
|
if (candidate === undefined ||
|
|
@@ -180,7 +168,7 @@ function snapshotBytes(snapshot) {
|
|
|
180
168
|
* Deterministically projects a canonical snapshot under the local control
|
|
181
169
|
* byte budget. Content is never shortened: complete metadata rows are either
|
|
182
170
|
* retained or counted as omitted. Registry rejection-code detail is shed
|
|
183
|
-
* before
|
|
171
|
+
* before routes; connector inventory remains last.
|
|
184
172
|
*/
|
|
185
173
|
export function projectGatewayPublicSnapshot(snapshot, maximumBytes = GATEWAY_PUBLIC_SNAPSHOT_BYTE_BUDGET) {
|
|
186
174
|
if (!Number.isSafeInteger(maximumBytes) ||
|
|
@@ -193,18 +181,9 @@ export function projectGatewayPublicSnapshot(snapshot, maximumBytes = GATEWAY_PU
|
|
|
193
181
|
connectors: snapshot.truncation.connectors + omitted(snapshot.connectors.length, gatewayPublicSnapshotLimits.connectors),
|
|
194
182
|
availablePeers: snapshot.truncation.availablePeers + omitted(snapshot.availablePeers.length, gatewayPublicSnapshotLimits.availablePeers),
|
|
195
183
|
routes: snapshot.truncation.routes + omitted(snapshot.routes.length, gatewayPublicSnapshotLimits.routes),
|
|
196
|
-
consentEdges: snapshot.truncation.consentEdges + omitted(snapshot.consentEdges.length, gatewayPublicSnapshotLimits.consentEdges),
|
|
197
184
|
messages: snapshot.truncation.messages + omitted(snapshot.messages.length, gatewayPublicSnapshotLimits.messages),
|
|
198
185
|
alerts: snapshot.truncation.alerts + omitted(snapshot.alerts.length, gatewayPublicSnapshotLimits.alerts),
|
|
199
186
|
};
|
|
200
|
-
if (snapshot.progressWatches !== undefined) {
|
|
201
|
-
truncation.progressWatches = (snapshot.truncation.progressWatches ?? 0) +
|
|
202
|
-
omitted(snapshot.progressWatches.length, gatewayPublicSnapshotLimits.progressWatches);
|
|
203
|
-
}
|
|
204
|
-
if (snapshot.progressWatchEvents !== undefined) {
|
|
205
|
-
truncation.progressWatchEvents = (snapshot.truncation.progressWatchEvents ?? 0) +
|
|
206
|
-
omitted(snapshot.progressWatchEvents.length, gatewayPublicSnapshotLimits.progressWatchEvents);
|
|
207
|
-
}
|
|
208
187
|
if (snapshot.activityEvents !== undefined) {
|
|
209
188
|
truncation.activityEvents = (snapshot.truncation.activityEvents ?? 0) +
|
|
210
189
|
omitted(snapshot.activityEvents.length, gatewayPublicSnapshotLimits.activityEvents);
|
|
@@ -214,13 +193,6 @@ export function projectGatewayPublicSnapshot(snapshot, maximumBytes = GATEWAY_PU
|
|
|
214
193
|
connectors: structuredClone(snapshot.connectors.slice(0, gatewayPublicSnapshotLimits.connectors)),
|
|
215
194
|
availablePeers: snapshot.availablePeers.slice(0, gatewayPublicSnapshotLimits.availablePeers),
|
|
216
195
|
routes: snapshot.routes.slice(0, gatewayPublicSnapshotLimits.routes),
|
|
217
|
-
consentEdges: snapshot.consentEdges.slice(0, gatewayPublicSnapshotLimits.consentEdges),
|
|
218
|
-
...(snapshot.progressWatches === undefined ? {} : {
|
|
219
|
-
progressWatches: snapshot.progressWatches.slice(0, gatewayPublicSnapshotLimits.progressWatches),
|
|
220
|
-
}),
|
|
221
|
-
...(snapshot.progressWatchEvents === undefined ? {} : {
|
|
222
|
-
progressWatchEvents: snapshot.progressWatchEvents.slice(-gatewayPublicSnapshotLimits.progressWatchEvents),
|
|
223
|
-
}),
|
|
224
196
|
...(snapshot.activityEvents === undefined ? {} : {
|
|
225
197
|
activityEvents: snapshot.activityEvents.slice(-gatewayPublicSnapshotLimits.activityEvents),
|
|
226
198
|
}),
|
|
@@ -256,13 +228,6 @@ export function projectGatewayPublicSnapshot(snapshot, maximumBytes = GATEWAY_PU
|
|
|
256
228
|
const retained = count === 0 ? [] : newest ? rows.slice(-count) : rows.slice(0, count);
|
|
257
229
|
apply(retained, priorOmissions + rows.length - count);
|
|
258
230
|
});
|
|
259
|
-
const watchEvents = projected.progressWatchEvents ?? [];
|
|
260
|
-
if (watchEvents.length > 0 &&
|
|
261
|
-
retainRows(watchEvents, projected.truncation.progressWatchEvents ?? 0, true, (rows, omissions) => {
|
|
262
|
-
projected.progressWatchEvents = rows;
|
|
263
|
-
projected.truncation.progressWatchEvents = omissions;
|
|
264
|
-
}))
|
|
265
|
-
return projected;
|
|
266
231
|
const activityEvents = projected.activityEvents ?? [];
|
|
267
232
|
if (activityEvents.length > 0 &&
|
|
268
233
|
retainRows(activityEvents, projected.truncation.activityEvents ?? 0, true, (rows, omissions) => {
|
|
@@ -277,8 +242,8 @@ export function projectGatewayPublicSnapshot(snapshot, maximumBytes = GATEWAY_PU
|
|
|
277
242
|
}))
|
|
278
243
|
return projected;
|
|
279
244
|
const peers = [...projected.availablePeers].sort((left, right) => {
|
|
280
|
-
if (left.
|
|
281
|
-
return left.
|
|
245
|
+
if (left.routed !== right.routed)
|
|
246
|
+
return left.routed ? -1 : 1;
|
|
282
247
|
const byState = peerPriority(left.state) - peerPriority(right.state);
|
|
283
248
|
if (byState !== 0)
|
|
284
249
|
return byState;
|
|
@@ -335,17 +300,6 @@ export function projectGatewayPublicSnapshot(snapshot, maximumBytes = GATEWAY_PU
|
|
|
335
300
|
return byState;
|
|
336
301
|
return left.alias.localeCompare(right.alias);
|
|
337
302
|
});
|
|
338
|
-
const consentEdges = [...projected.consentEdges].sort((left, right) => left.endpoints
|
|
339
|
-
.map((endpoint) => `${endpoint.provider}\0${endpoint.alias}`)
|
|
340
|
-
.join("\0")
|
|
341
|
-
.localeCompare(right.endpoints
|
|
342
|
-
.map((endpoint) => `${endpoint.provider}\0${endpoint.alias}`)
|
|
343
|
-
.join("\0")));
|
|
344
|
-
if (retainRows(consentEdges, projected.truncation.consentEdges, false, (rows, omissions) => {
|
|
345
|
-
projected.consentEdges = rows;
|
|
346
|
-
projected.truncation.consentEdges = omissions;
|
|
347
|
-
}))
|
|
348
|
-
return projected;
|
|
349
303
|
if (retainRows(routes, projected.truncation.routes, false, (rows, omissions) => {
|
|
350
304
|
projected.routes = rows;
|
|
351
305
|
projected.truncation.routes = omissions;
|