agent-embassy 3.0.0 → 4.0.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.
Files changed (115) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/CONTRIBUTING.md +92 -200
  3. package/README.md +159 -138
  4. package/SECURITY.md +191 -335
  5. package/dist/src/gateway/broker-check.d.ts +26 -0
  6. package/dist/src/gateway/broker-check.js +89 -0
  7. package/dist/src/gateway/broker-check.js.map +1 -0
  8. package/dist/src/gateway/broker-control.d.ts +72 -0
  9. package/dist/src/gateway/broker-control.js +164 -0
  10. package/dist/src/gateway/broker-control.js.map +1 -0
  11. package/dist/src/gateway/broker.d.ts +117 -0
  12. package/dist/src/gateway/broker.js +186 -0
  13. package/dist/src/gateway/broker.js.map +1 -0
  14. package/dist/src/gateway/claude-peer.d.ts +1 -124
  15. package/dist/src/gateway/claude-peer.js +62 -1053
  16. package/dist/src/gateway/claude-peer.js.map +1 -1
  17. package/dist/src/gateway/codex-stateless-transport.d.ts +0 -12
  18. package/dist/src/gateway/codex-stateless-transport.js +8 -142
  19. package/dist/src/gateway/codex-stateless-transport.js.map +1 -1
  20. package/dist/src/gateway/config.d.ts +2 -6
  21. package/dist/src/gateway/config.js +17 -27
  22. package/dist/src/gateway/config.js.map +1 -1
  23. package/dist/src/gateway/coordinator.d.ts +57 -0
  24. package/dist/src/gateway/coordinator.js +217 -0
  25. package/dist/src/gateway/coordinator.js.map +1 -0
  26. package/dist/src/gateway/core-cli.d.ts +15 -0
  27. package/dist/src/gateway/core-cli.js +282 -0
  28. package/dist/src/gateway/core-cli.js.map +1 -0
  29. package/dist/src/gateway/core-service-command.d.ts +16 -0
  30. package/dist/src/gateway/core-service-command.js +71 -0
  31. package/dist/src/gateway/core-service-command.js.map +1 -0
  32. package/dist/src/gateway/endpoint-directory.d.ts +33 -0
  33. package/dist/src/gateway/endpoint-directory.js +223 -0
  34. package/dist/src/gateway/endpoint-directory.js.map +1 -0
  35. package/dist/src/gateway/federation.d.ts +89 -0
  36. package/dist/src/gateway/federation.js +632 -0
  37. package/dist/src/gateway/federation.js.map +1 -0
  38. package/dist/src/gateway/ledger-codec.d.ts +3 -0
  39. package/dist/src/gateway/ledger-codec.js +159 -0
  40. package/dist/src/gateway/ledger-codec.js.map +1 -0
  41. package/dist/src/gateway/ledger.d.ts +138 -0
  42. package/dist/src/gateway/ledger.js +319 -0
  43. package/dist/src/gateway/ledger.js.map +1 -0
  44. package/dist/src/gateway/local-control.d.ts +23 -0
  45. package/dist/src/gateway/local-control.js +489 -0
  46. package/dist/src/gateway/local-control.js.map +1 -0
  47. package/dist/src/gateway/native-destinations.d.ts +34 -0
  48. package/dist/src/gateway/native-destinations.js +272 -0
  49. package/dist/src/gateway/native-destinations.js.map +1 -0
  50. package/dist/src/gateway/owned-state.d.ts +57 -0
  51. package/dist/src/gateway/owned-state.js +398 -0
  52. package/dist/src/gateway/owned-state.js.map +1 -0
  53. package/dist/src/gateway/provenance-envelope.d.ts +3 -3
  54. package/dist/src/gateway/provenance-envelope.js +3 -23
  55. package/dist/src/gateway/provenance-envelope.js.map +1 -1
  56. package/dist/src/gateway/runtime.d.ts +41 -0
  57. package/dist/src/gateway/runtime.js +175 -0
  58. package/dist/src/gateway/runtime.js.map +1 -0
  59. package/docs/CONFIGURATION.md +178 -266
  60. package/docs/DELIVERY.md +133 -82
  61. package/docs/GATEWAY-ARCHITECTURE.md +276 -943
  62. package/package.json +5 -5
  63. package/skills/embassy-peer/SKILL.md +38 -194
  64. package/skills/embassy-peer/agents/openai.yaml +2 -2
  65. package/dist/src/gateway/claude-helper-client.d.ts +0 -2
  66. package/dist/src/gateway/claude-helper-client.js +0 -2
  67. package/dist/src/gateway/claude-helper-client.js.map +0 -1
  68. package/dist/src/gateway/claude-helper-protocol.d.ts +0 -117
  69. package/dist/src/gateway/claude-helper-protocol.js +0 -122
  70. package/dist/src/gateway/claude-helper-protocol.js.map +0 -1
  71. package/dist/src/gateway/claude-helper-supervisor.d.ts +0 -87
  72. package/dist/src/gateway/claude-helper-supervisor.js +0 -347
  73. package/dist/src/gateway/claude-helper-supervisor.js.map +0 -1
  74. package/dist/src/gateway/claude-helper.d.ts +0 -1
  75. package/dist/src/gateway/claude-helper.js +0 -252
  76. package/dist/src/gateway/claude-helper.js.map +0 -1
  77. package/dist/src/gateway/cli.d.ts +0 -57
  78. package/dist/src/gateway/cli.js +0 -1503
  79. package/dist/src/gateway/cli.js.map +0 -1
  80. package/dist/src/gateway/codex-socket-holder.d.ts +0 -26
  81. package/dist/src/gateway/codex-socket-holder.js +0 -76
  82. package/dist/src/gateway/codex-socket-holder.js.map +0 -1
  83. package/dist/src/gateway/control.d.ts +0 -261
  84. package/dist/src/gateway/control.js +0 -903
  85. package/dist/src/gateway/control.js.map +0 -1
  86. package/dist/src/gateway/peer-client.d.ts +0 -58
  87. package/dist/src/gateway/peer-client.js +0 -217
  88. package/dist/src/gateway/peer-client.js.map +0 -1
  89. package/dist/src/gateway/peer-mailbox.d.ts +0 -78
  90. package/dist/src/gateway/peer-mailbox.js +0 -168
  91. package/dist/src/gateway/peer-mailbox.js.map +0 -1
  92. package/dist/src/gateway/peer-protocol.d.ts +0 -105
  93. package/dist/src/gateway/peer-protocol.js +0 -70
  94. package/dist/src/gateway/peer-protocol.js.map +0 -1
  95. package/dist/src/gateway/peer-stdio.d.ts +0 -23
  96. package/dist/src/gateway/peer-stdio.js +0 -100
  97. package/dist/src/gateway/peer-stdio.js.map +0 -1
  98. package/dist/src/gateway/providers.d.ts +0 -163
  99. package/dist/src/gateway/providers.js +0 -972
  100. package/dist/src/gateway/providers.js.map +0 -1
  101. package/dist/src/gateway/server.d.ts +0 -47
  102. package/dist/src/gateway/server.js +0 -219
  103. package/dist/src/gateway/server.js.map +0 -1
  104. package/dist/src/gateway/service.d.ts +0 -373
  105. package/dist/src/gateway/service.js +0 -2274
  106. package/dist/src/gateway/service.js.map +0 -1
  107. package/dist/src/gateway/status-view.d.ts +0 -167
  108. package/dist/src/gateway/status-view.js +0 -488
  109. package/dist/src/gateway/status-view.js.map +0 -1
  110. package/dist/src/gateway/store.d.ts +0 -185
  111. package/dist/src/gateway/store.js +0 -2359
  112. package/dist/src/gateway/store.js.map +0 -1
  113. package/dist/src/gateway/types.d.ts +0 -528
  114. package/dist/src/gateway/types.js +0 -341
  115. package/dist/src/gateway/types.js.map +0 -1
@@ -1,373 +0,0 @@
1
- import type { GatewayConfig } from "./config.js";
2
- import { type GatewayControlHandlers, type GatewaySnapshotObservation } from "./control.js";
3
- import { spawnPeerClient } from "./peer-client.js";
4
- import { GatewayStore } from "./store.js";
5
- import { type GatewayPreparedWriteEvidence, type GatewayProvider, type GatewayPublicSnapshot, type LogicalRouteBinding } from "./types.js";
6
- export type GatewayAdapterRouteState = "idle" | "busy" | "awaiting_approval";
7
- export type GatewayAdapterRouteObservationState = GatewayAdapterRouteState | "unobserved";
8
- export type GatewayAdapterDiscovery = Readonly<{
9
- alias: string;
10
- routeHandle: string;
11
- kind: "interactive" | "bg";
12
- state: GatewayAdapterRouteState;
13
- }>;
14
- export type GatewayAdapterRegistryObservation = Readonly<{
15
- entriesScanned: number;
16
- parseableRecords: number;
17
- rejected: readonly Readonly<{
18
- safeErrorCode: string;
19
- count: number;
20
- }>[];
21
- }>;
22
- export type GatewayAdapterDiscoverySnapshot = Readonly<{
23
- peers: readonly GatewayAdapterDiscovery[];
24
- complete: boolean;
25
- registry?: GatewayAdapterRegistryObservation;
26
- }>;
27
- export type GatewayAdapterRouteObservation = Readonly<{
28
- route: LogicalRouteBinding;
29
- state: GatewayAdapterRouteObservationState;
30
- observedAt: string;
31
- safeErrorCode?: string;
32
- }>;
33
- export type GatewayAdapterNativeEndpoint = Readonly<{
34
- provider: GatewayProvider;
35
- hostId: string;
36
- routeHandle: string;
37
- }>;
38
- export type GatewayAdapterCallbacks = Readonly<{
39
- onRouteState: (event: GatewayAdapterRouteObservation) => void;
40
- onClaudeReply: (event: Readonly<{
41
- endpoint: GatewayAdapterNativeEndpoint;
42
- text: string;
43
- }>) => void;
44
- onClaudeMessage?: (event: Readonly<{
45
- endpoint: GatewayAdapterNativeEndpoint;
46
- sourceAlias: string;
47
- targetAlias: string;
48
- text: string;
49
- receiptHandle?: string;
50
- }>) => void;
51
- onProtocolNotice?: (event: Readonly<{
52
- code: string;
53
- }>) => void;
54
- }>;
55
- export type GatewayAdapterStart = Readonly<{
56
- health: "healthy" | "degraded";
57
- safeErrorCode?: string;
58
- ownedRoute?: Readonly<{
59
- alias: string;
60
- routeHandle: string;
61
- state: GatewayAdapterRouteState;
62
- }>;
63
- }>;
64
- export type GatewayAdapterDispatchResult = Readonly<{
65
- state: "deferred";
66
- safeErrorCode?: string;
67
- }> | Readonly<{
68
- state: "delivered" | "unconfirmed" | "failed" | "ambiguous" | "expired" | "cancelled";
69
- safeErrorCode?: string;
70
- replyText?: string;
71
- }>;
72
- export type GatewayAdapterDispatchInput = Readonly<{
73
- attemptId: string;
74
- sourceAlias: string;
75
- sourceProvider: GatewayProvider;
76
- targetAlias: string;
77
- conversationId: string;
78
- binding: LogicalRouteBinding;
79
- authorization: "selected_route";
80
- messageId: string;
81
- text: string;
82
- expectsReply: boolean;
83
- deadlineAt: string;
84
- steer?: true;
85
- queuedAhead?: number;
86
- authorizeWrite: (evidence: GatewayPreparedWriteEvidence & Readonly<{
87
- attemptId: string;
88
- }>) => Promise<boolean>;
89
- onAccepted: (evidence: Readonly<{
90
- attemptId: string;
91
- }>) => Promise<void>;
92
- }>;
93
- export interface GatewayProviderAdapter {
94
- readonly identity: Readonly<{
95
- provider: GatewayProvider;
96
- hostId: string;
97
- }>;
98
- readonly protocol: string;
99
- readonly protocolVersion: string;
100
- latestRegistryObservation?(): GatewayAdapterRegistryObservation | undefined;
101
- initialize(callbacks: GatewayAdapterCallbacks): Promise<GatewayAdapterStart>;
102
- observeLogicalRoute?(input: Readonly<{
103
- alias: string;
104
- routeHandle: string;
105
- registrationId: string;
106
- }>): void;
107
- forgetLogicalRoute?(registrationId: string): void;
108
- discoverClaudePeers?(): Promise<GatewayAdapterDiscoverySnapshot>;
109
- selectRoute?(input: Readonly<{
110
- alias: string;
111
- routeHandle: string;
112
- }>): Promise<{
113
- routeHandle: string;
114
- state: GatewayAdapterRouteState;
115
- }>;
116
- assertWorkspaceDisjoint?(routeHandle: string, stateRoot: string): Promise<void>;
117
- resolveReplyAddress?(address: string): Promise<{
118
- routeHandle: string;
119
- }>;
120
- advertiseNativeSourcePeer?(input: Readonly<{
121
- alias: string;
122
- sourceProvider: GatewayProvider;
123
- cwd: string;
124
- }>): Promise<void>;
125
- unadvertiseNativeSourcePeer?(alias: string): Promise<void>;
126
- updateNativeSourcePeerStatus?(alias: string, status: "idle" | "busy" | "waiting"): Promise<void>;
127
- updateNativeInboundStatus?(receiptHandle: string, status: "held" | "delivered" | "denied" | "expired", diagnosticCode?: string): Promise<void>;
128
- notifyNativeInboundProgress?(receiptHandle: string, progress: Readonly<{
129
- kind: "stall";
130
- reason: "ROUTE_BUSY" | "ROUTE_UNAVAILABLE" | "AWAITING_EXTERNAL_APPROVAL";
131
- queuedForMs: number;
132
- }>): Promise<void>;
133
- releaseNativeInboundReceipt?(receiptHandle: string): Promise<boolean>;
134
- dispatch(input: GatewayAdapterDispatchInput): Promise<GatewayAdapterDispatchResult>;
135
- releaseRoute?(routeHandle: string): Promise<void>;
136
- close(): Promise<void>;
137
- }
138
- type GatewayServiceTimer = ReturnType<typeof setTimeout>;
139
- type GatewayServiceTimers = Readonly<{
140
- setTimeout: (callback: () => void, delayMs: number) => GatewayServiceTimer;
141
- clearTimeout: (timer: GatewayServiceTimer) => void;
142
- }>;
143
- export type GatewayServiceOptions = Readonly<{
144
- config: GatewayConfig;
145
- adapters?: readonly GatewayProviderAdapter[];
146
- store?: GatewayStore;
147
- now?: () => Date;
148
- nativePeerCwd?: string;
149
- timers?: GatewayServiceTimers;
150
- /** True when a process outside Embassy holds the managed Codex control socket while the managed layout is missing. */
151
- managedCodexSocketHeld?: () => Promise<boolean>;
152
- spawnPeer?: typeof spawnPeerClient;
153
- }>;
154
- export declare class GatewayService {
155
- readonly config: GatewayConfig;
156
- readonly store: GatewayStore;
157
- private readonly adapters;
158
- private readonly now;
159
- private readonly timers;
160
- private readonly nativePeerCwd;
161
- private readonly managedCodexSocketHeld;
162
- private readonly spawnPeer;
163
- private readonly peerClients;
164
- private readonly peerCatalogs;
165
- private readonly peerCleanupAliases;
166
- /** View-only freshness; never consulted by routing or write authorization. */
167
- private readonly peerRouteViews;
168
- private readonly connectors;
169
- private readonly routeObservations;
170
- private readonly candidates;
171
- private readonly collidingClaudeAliases;
172
- private readonly conversations;
173
- private readonly messageContexts;
174
- private readonly activeAttempts;
175
- private readonly reserveOperations;
176
- private readonly inboundOperations;
177
- private readonly peerRefreshOperations;
178
- private readonly pendingClaudeReplies;
179
- private readonly nativeReceipts;
180
- private readonly dispatchRunners;
181
- private readonly steerRunners;
182
- private readonly startingTargets;
183
- private readonly runtimeAlerts;
184
- /**
185
- * Ephemeral peer registrations and the wall-clock instant each one dies.
186
- * Nothing durable records them, so this map is the whole lifetime: it is
187
- * swept on the ordinary maintenance tick, and a restart simply never sees
188
- * the routes at all.
189
- */
190
- private readonly ephemeralPeerExpiries;
191
- /** Consecutive failed retirements per ephemeral alias; cleared on success or removal. */
192
- private readonly ephemeralExpiryFailures;
193
- private control;
194
- private wakeTimer;
195
- private nextDiscoveryAt;
196
- private nextManagedCodexCheckAt;
197
- private nextPeerRefreshAt;
198
- private managedCodexSocketHeldOutside;
199
- private revision;
200
- private snapshotRevision;
201
- private snapshotFingerprint;
202
- private running;
203
- private closing;
204
- private closeInFlight;
205
- constructor(options: GatewayServiceOptions);
206
- start(signal?: AbortSignal): Promise<void>;
207
- close(): Promise<void>;
208
- private closeOnce;
209
- handlers(): GatewayControlHandlers;
210
- private buildPeerCatalog;
211
- private receivePeerHandoff;
212
- snapshot(): Promise<GatewayPublicSnapshot>;
213
- observeSnapshot(): Promise<GatewaySnapshotObservation>;
214
- private health;
215
- private installOwnedRoute;
216
- private observeLoadedRoutes;
217
- private observeRoute;
218
- private forgetRoute;
219
- private adapterFor;
220
- private claudeAdapter;
221
- private advertise;
222
- private unadvertise;
223
- private reconcileAdvertisement;
224
- private reconcileUnadvertisement;
225
- private removeOwnedRoute;
226
- private recordActivity;
227
- private registerCodex;
228
- private registerPeer;
229
- private assertPeer;
230
- private unregisterPeer;
231
- /**
232
- * Retires every ephemeral peer registration whose lifetime has run out. It
233
- * is the same removal an explicit `unregister-peer` performs — queued work
234
- * is settled, not abandoned — minus the token check, because the authority
235
- * here is the clock the broker set itself.
236
- *
237
- * The clock is keyed by alias, and an alias can be re-registered durably
238
- * after its ephemeral holder left, so nothing is retired unless the route
239
- * behind the alias is still an ephemeral one. A retirement that throws
240
- * keeps its entry and is retried `EPHEMERAL_EXPIRY_RETRY_MS` later, with an
241
- * alert each time; after `EPHEMERAL_EXPIRY_MAX_ATTEMPTS` consecutive
242
- * failures the entry is dropped and the registration is left to the next
243
- * restart, which clears it by construction.
244
- */
245
- private expireEphemeralPeers;
246
- private awaitPeer;
247
- private peerReceipt;
248
- private unregisterCodex;
249
- /**
250
- * The name this session may take. A name belongs to one route at a time, so
251
- * when another Claude route already holds it and THAT route's session is
252
- * still live, this session takes a disambiguated name rather than displacing
253
- * a working session and cancelling its queued work. Twins that share a
254
- * display name therefore both keep routes and both stay reachable by UUID;
255
- * only a route whose session is actually gone is displaced.
256
- */
257
- private claimableAlias;
258
- /**
259
- * Installs (or brings up to date) the route of one discovered Claude
260
- * session. The adapter pins the session's route handle, the workspace
261
- * check keeps deliberately broad workspaces out, and the store reuses the
262
- * registration of a session already bound under the same (host, UUID) so a
263
- * re-anchored or renamed session keeps its identity and in-flight
264
- * conversations. Any Claude route the install displaced is forgotten and
265
- * released at the adapter; its work was settled `ENDPOINT_RETIRED` by the
266
- * store — and only a route whose own session is gone is ever displaced.
267
- */
268
- private installClaudeRoute;
269
- /**
270
- * Two first sends to the same never-installed session race: both read no
271
- * route and both mint a registration, and the loser's write is refused
272
- * because the identity is now bound. That is a race, not a conflict — the
273
- * session is exactly the one the loser resolved — so re-read once and adopt
274
- * the registration that won instead of failing an honest send.
275
- */
276
- private installWithConcurrentFirstSend;
277
- /**
278
- * Looks a Claude selector up without writing anything. Callers that may
279
- * still refuse — a `--from` alias that must match the sending session, a
280
- * native sender whose adapter-reported name must match discovery — resolve
281
- * here first, refuse on the read, and only then materialize.
282
- *
283
- * THE ALIAS-COLLISION FENCE lives here (emb-94, moved into the send path by
284
- * emb-104). Invariant: discovery is refreshed inside every send that
285
- * addresses a Claude session, never only on the timer; a NAME currently
286
- * shared by more than one live session is refused with a hard,
287
- * non-retryable `PEER_ALIAS_COLLISION` naming that alias, so the broker
288
- * never picks first and never installs a route under an ambiguous name;
289
- * collisions stay sticky while a scan is incomplete
290
- * (`collidingClaudeAliases` retention in refreshClaudeDiscovery); and
291
- * `availablePeers` keeps filtering colliders so `status` never lists an
292
- * unaddressable name.
293
- *
294
- * The fence is a fence on NAMES, not on sessions. A session UUID is
295
- * unambiguous by construction, so a UUID selector — an explicit
296
- * `send --to <uuid>`, an identity-pinned route addressed by its own handle,
297
- * or a sender resolved from its inherited socket — passes the fence even
298
- * while its display name collides. That is the emb-94 escape hatch: the
299
- * operator can always reach an ambiguously named session, and a collision on
300
- * a *sender's* name never silences that sender, whose identity was attested
301
- * rather than typed. In-flight conversations are likewise unaffected:
302
- * `reply` resolves by exact binding.
303
- */
304
- private lookUpClaudeRoute;
305
- /**
306
- * The name discovery currently shows for a looked-up session, which a caller
307
- * compares against the alias it claimed before anything is written.
308
- */
309
- private claimedAlias;
310
- /** Installs the looked-up session's route if it is not already current. */
311
- private materializeClaudeRoute;
312
- private resolveClaudeRoute;
313
- private assertThread;
314
- /**
315
- * Direction follows the inherited principal, not the route table: a Claude
316
- * session or its target may have no route yet, because routes install on
317
- * first send. A Codex task sends to Claude sessions and shell peers; a
318
- * Claude session sends to Codex tasks and shell peers (Claude-to-Claude is
319
- * native); a shell peer sends to either.
320
- */
321
- private send;
322
- private sendToClaude;
323
- private sendToCodex;
324
- /**
325
- * A send addressed by conversation token: the caller must own one end, the
326
- * other end is the binding the conversation recorded, and the caller's
327
- * principal is the same attested one every send carries.
328
- */
329
- private replyToConversation;
330
- private assertReplyCaller;
331
- private enqueueConversation;
332
- /**
333
- * A renamed Claude session is the same principal under a new display name,
334
- * so its open conversations follow it: the registration, not the alias, is
335
- * the identity, and a reply under the current name must still resolve.
336
- */
337
- private renameConversationCoordinates;
338
- private rememberConversation;
339
- private conversationIsActive;
340
- private deliveryStatus;
341
- private messageUpdatedAt;
342
- private kick;
343
- private kickExact;
344
- private kickSteer;
345
- private startRunner;
346
- private runTarget;
347
- private settleAttemptForShutdown;
348
- private resolvePrewrite;
349
- private applyDispatchResult;
350
- private callbacksFor;
351
- private onRouteState;
352
- private onClaudeMessage;
353
- private onClaudeReply;
354
- private enqueueCorrelatedReply;
355
- private installPendingClaudeReply;
356
- private pruneExpiredPendingClaudeReplies;
357
- private retirePendingClaudeReply;
358
- private activatePendingClaudeReply;
359
- private deliverPendingClaudeReply;
360
- private finishSettlements;
361
- private finishSettlement;
362
- private scheduleTargetRetry;
363
- private scheduleWake;
364
- private onWake;
365
- private refreshPeers;
366
- private refreshClaudeDiscovery;
367
- private refreshManagedCodexSocket;
368
- private assertWritable;
369
- private routeObservationStillCurrent;
370
- private alert;
371
- private recordPeerFailure;
372
- }
373
- export {};