@agent-vm/control-protocol-contracts 0.0.109

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Shravan Sunder
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,397 @@
1
+ import { z } from "zod/v4";
2
+
3
+ //#region src/index.d.ts
4
+ declare const CONTROL_PROTOCOL_VERSION = 1;
5
+ declare const CONTROL_SESSION_TIMING_MS: {
6
+ readonly activeUseHeartbeatCadence: 30000;
7
+ readonly activeUseStaleTtl: 120000;
8
+ readonly clockSkewTolerance: 30000;
9
+ readonly commandAckTimeout: 2000;
10
+ readonly connectTimeout: 3000;
11
+ readonly controlSessionDeathGrace: 600000;
12
+ readonly engineIoPingInterval: 10000;
13
+ readonly engineIoPingTimeout: 10000;
14
+ readonly resyncTimeout: 5000;
15
+ };
16
+ declare const CONTROL_QUEUE_LIMITS: {
17
+ readonly dedupeWindowMessages: 512;
18
+ readonly dedupeWindowTtlMs: 60000;
19
+ readonly maxHttpBufferBytes: 65536;
20
+ readonly queueByteCap: number;
21
+ readonly queueMessageCap: 256;
22
+ };
23
+ declare const ControlDomainSchema: z.ZodString;
24
+ declare const KnownControlDomainSchema: z.ZodEnum<{
25
+ gateway_control: "gateway_control";
26
+ worker_control: "worker_control";
27
+ }>;
28
+ declare const ControlMessageKindSchema: z.ZodEnum<{
29
+ command: "command";
30
+ command_result: "command_result";
31
+ event: "event";
32
+ snapshot: "snapshot";
33
+ heartbeat: "heartbeat";
34
+ observation: "observation";
35
+ }>;
36
+ declare const ControlDeliveryPolicySchema: z.ZodEnum<{
37
+ latest_wins: "latest_wins";
38
+ droppable: "droppable";
39
+ acked_idempotent: "acked_idempotent";
40
+ critical_idempotent: "critical_idempotent";
41
+ append_only_observation: "append_only_observation";
42
+ single_use_critical: "single_use_critical";
43
+ forbidden_bulk: "forbidden_bulk";
44
+ }>;
45
+ declare const ControlSessionCloseReasonSchema: z.ZodEnum<{
46
+ normal_shutdown: "normal_shutdown";
47
+ controller_restart: "controller_restart";
48
+ peer_restart: "peer_restart";
49
+ auth_failed: "auth_failed";
50
+ protocol_version_mismatch: "protocol_version_mismatch";
51
+ domain_mismatch: "domain_mismatch";
52
+ generation_mismatch: "generation_mismatch";
53
+ controller_epoch_mismatch: "controller_epoch_mismatch";
54
+ duplicate_session: "duplicate_session";
55
+ stale_session: "stale_session";
56
+ sequence_gap: "sequence_gap";
57
+ ack_timeout: "ack_timeout";
58
+ command_timeout: "command_timeout";
59
+ resync_timeout: "resync_timeout";
60
+ queue_overflow: "queue_overflow";
61
+ message_too_large: "message_too_large";
62
+ schema_validation_failed: "schema_validation_failed";
63
+ forbidden_bulk_message: "forbidden_bulk_message";
64
+ transport_error: "transport_error";
65
+ }>;
66
+ declare const ControlEnvelopeSchema: z.ZodObject<{
67
+ bootId: z.ZodString;
68
+ commandId: z.ZodOptional<z.ZodString>;
69
+ connectionId: z.ZodString;
70
+ controllerEpoch: z.ZodString;
71
+ createdAtMs: z.ZodNumber;
72
+ deliveryPolicy: z.ZodEnum<{
73
+ latest_wins: "latest_wins";
74
+ droppable: "droppable";
75
+ acked_idempotent: "acked_idempotent";
76
+ critical_idempotent: "critical_idempotent";
77
+ append_only_observation: "append_only_observation";
78
+ single_use_critical: "single_use_critical";
79
+ forbidden_bulk: "forbidden_bulk";
80
+ }>;
81
+ domain: z.ZodString;
82
+ expiresAtMs: z.ZodOptional<z.ZodNumber>;
83
+ idempotencyKey: z.ZodOptional<z.ZodString>;
84
+ kind: z.ZodEnum<{
85
+ command: "command";
86
+ command_result: "command_result";
87
+ event: "event";
88
+ snapshot: "snapshot";
89
+ heartbeat: "heartbeat";
90
+ observation: "observation";
91
+ }>;
92
+ messageId: z.ZodString;
93
+ operation: z.ZodOptional<z.ZodString>;
94
+ peerId: z.ZodString;
95
+ protocolVersion: z.ZodLiteral<1>;
96
+ sequence: z.ZodNumber;
97
+ sessionId: z.ZodString;
98
+ zoneId: z.ZodString;
99
+ }, z.core.$strict>;
100
+ declare const ControlSessionStateSchema: z.ZodEnum<{
101
+ generation_mismatch: "generation_mismatch";
102
+ unknown: "unknown";
103
+ connecting: "connecting";
104
+ ready: "ready";
105
+ reconnecting: "reconnecting";
106
+ stale: "stale";
107
+ rejected: "rejected";
108
+ failed: "failed";
109
+ closed: "closed";
110
+ }>;
111
+ declare const ControlRpcResultBaseSchema: z.ZodEnum<{
112
+ rejected: "rejected";
113
+ failed: "failed";
114
+ ok: "ok";
115
+ timeout: "timeout";
116
+ cancelled: "cancelled";
117
+ stale_generation: "stale_generation";
118
+ }>;
119
+ declare const ControlRpcErrorSchema: z.ZodObject<{
120
+ errorClass: z.ZodString;
121
+ retryable: z.ZodOptional<z.ZodBoolean>;
122
+ safeMessage: z.ZodOptional<z.ZodString>;
123
+ }, z.core.$strict>;
124
+ declare const ControlCorrelationSchema: z.ZodObject<{
125
+ causationId: z.ZodOptional<z.ZodString>;
126
+ correlationId: z.ZodOptional<z.ZodString>;
127
+ requestId: z.ZodOptional<z.ZodString>;
128
+ runId: z.ZodOptional<z.ZodString>;
129
+ sessionKeyDigest: z.ZodOptional<z.ZodString>;
130
+ toolCallId: z.ZodOptional<z.ZodString>;
131
+ traceId: z.ZodOptional<z.ZodString>;
132
+ }, z.core.$strict>;
133
+ declare const ControlHelloSchema: z.ZodObject<{
134
+ bootId: z.ZodString;
135
+ controllerEpoch: z.ZodOptional<z.ZodString>;
136
+ domain: z.ZodString;
137
+ lastSeenControllerSequence: z.ZodOptional<z.ZodNumber>;
138
+ lastSeenPeerSequence: z.ZodOptional<z.ZodNumber>;
139
+ peerId: z.ZodString;
140
+ previousSessionId: z.ZodOptional<z.ZodString>;
141
+ protocolVersion: z.ZodLiteral<1>;
142
+ }, z.core.$strict>;
143
+ declare const ControlHelloResponseSchema: z.ZodObject<{
144
+ connectionId: z.ZodString;
145
+ controllerEpoch: z.ZodString;
146
+ fences: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
147
+ outcome: z.ZodEnum<{
148
+ generation_mismatch: "generation_mismatch";
149
+ rejected: "rejected";
150
+ accepted: "accepted";
151
+ resync_required: "resync_required";
152
+ }>;
153
+ sessionId: z.ZodString;
154
+ }, z.core.$strict>;
155
+ declare const ControlCloseSchema: z.ZodObject<{
156
+ reason: z.ZodEnum<{
157
+ normal_shutdown: "normal_shutdown";
158
+ controller_restart: "controller_restart";
159
+ peer_restart: "peer_restart";
160
+ auth_failed: "auth_failed";
161
+ protocol_version_mismatch: "protocol_version_mismatch";
162
+ domain_mismatch: "domain_mismatch";
163
+ generation_mismatch: "generation_mismatch";
164
+ controller_epoch_mismatch: "controller_epoch_mismatch";
165
+ duplicate_session: "duplicate_session";
166
+ stale_session: "stale_session";
167
+ sequence_gap: "sequence_gap";
168
+ ack_timeout: "ack_timeout";
169
+ command_timeout: "command_timeout";
170
+ resync_timeout: "resync_timeout";
171
+ queue_overflow: "queue_overflow";
172
+ message_too_large: "message_too_large";
173
+ schema_validation_failed: "schema_validation_failed";
174
+ forbidden_bulk_message: "forbidden_bulk_message";
175
+ transport_error: "transport_error";
176
+ }>;
177
+ safeMessage: z.ZodOptional<z.ZodString>;
178
+ sessionId: z.ZodString;
179
+ }, z.core.$strict>;
180
+ declare const ControlMessageAcceptedReceiptSchema: z.ZodObject<{
181
+ received: z.ZodLiteral<true>;
182
+ }, z.core.$strict>;
183
+ declare const ControlMessageRejectedReceiptSchema: z.ZodObject<{
184
+ errorClass: z.ZodString;
185
+ received: z.ZodLiteral<false>;
186
+ safeMessage: z.ZodOptional<z.ZodString>;
187
+ }, z.core.$strict>;
188
+ declare const ControlMessageReceiptSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
189
+ received: z.ZodLiteral<true>;
190
+ }, z.core.$strict>, z.ZodObject<{
191
+ errorClass: z.ZodString;
192
+ received: z.ZodLiteral<false>;
193
+ safeMessage: z.ZodOptional<z.ZodString>;
194
+ }, z.core.$strict>], "received">;
195
+ declare const DomainCommandResultResponseLinkSchema: z.ZodObject<{
196
+ kind: z.ZodLiteral<"command_result">;
197
+ payload: z.ZodObject<{
198
+ responseToMessageId: z.ZodString;
199
+ }, z.core.$loose>;
200
+ }, z.core.$loose>;
201
+ declare const ControlHandshakeCredentialSchema: z.ZodObject<{
202
+ audience: z.ZodEnum<{
203
+ gateway_control: "gateway_control";
204
+ worker_control: "worker_control";
205
+ }>;
206
+ bootId: z.ZodString;
207
+ controllerEpoch: z.ZodString;
208
+ credentialId: z.ZodString;
209
+ expiresAtMs: z.ZodNumber;
210
+ generationId: z.ZodString;
211
+ issuedAtMs: z.ZodNumber;
212
+ nonce: z.ZodString;
213
+ peerId: z.ZodString;
214
+ protocolVersion: z.ZodLiteral<1>;
215
+ zoneId: z.ZodString;
216
+ }, z.core.$strict>;
217
+ declare const ControlHandshakeProofSchema: z.ZodObject<{
218
+ audience: z.ZodEnum<{
219
+ gateway_control: "gateway_control";
220
+ worker_control: "worker_control";
221
+ }>;
222
+ bootId: z.ZodString;
223
+ controllerEpoch: z.ZodString;
224
+ credentialId: z.ZodString;
225
+ expiresAtMs: z.ZodNumber;
226
+ generationId: z.ZodString;
227
+ issuedAtMs: z.ZodNumber;
228
+ nonce: z.ZodString;
229
+ peerId: z.ZodString;
230
+ protocolVersion: z.ZodLiteral<1>;
231
+ zoneId: z.ZodString;
232
+ signature: z.ZodString;
233
+ }, z.core.$strict>;
234
+ declare const ControlReadyRequestCredentialSchema: z.ZodObject<{
235
+ audience: z.ZodEnum<{
236
+ gateway_control: "gateway_control";
237
+ worker_control: "worker_control";
238
+ }>;
239
+ bootId: z.ZodString;
240
+ controllerEpoch: z.ZodString;
241
+ generationId: z.ZodString;
242
+ issuedAtMs: z.ZodNumber;
243
+ peerId: z.ZodString;
244
+ protocolVersion: z.ZodLiteral<1>;
245
+ requestId: z.ZodString;
246
+ zoneId: z.ZodString;
247
+ }, z.core.$strict>;
248
+ declare const ControlReadyRequestProofSchema: z.ZodObject<{
249
+ audience: z.ZodEnum<{
250
+ gateway_control: "gateway_control";
251
+ worker_control: "worker_control";
252
+ }>;
253
+ bootId: z.ZodString;
254
+ controllerEpoch: z.ZodString;
255
+ generationId: z.ZodString;
256
+ issuedAtMs: z.ZodNumber;
257
+ peerId: z.ZodString;
258
+ protocolVersion: z.ZodLiteral<1>;
259
+ requestId: z.ZodString;
260
+ zoneId: z.ZodString;
261
+ signature: z.ZodString;
262
+ }, z.core.$strict>;
263
+ declare const ControlHandshakeHeadersSchema: z.ZodObject<{
264
+ proof: z.ZodObject<{
265
+ audience: z.ZodEnum<{
266
+ gateway_control: "gateway_control";
267
+ worker_control: "worker_control";
268
+ }>;
269
+ bootId: z.ZodString;
270
+ controllerEpoch: z.ZodString;
271
+ credentialId: z.ZodString;
272
+ expiresAtMs: z.ZodNumber;
273
+ generationId: z.ZodString;
274
+ issuedAtMs: z.ZodNumber;
275
+ nonce: z.ZodString;
276
+ peerId: z.ZodString;
277
+ protocolVersion: z.ZodLiteral<1>;
278
+ zoneId: z.ZodString;
279
+ signature: z.ZodString;
280
+ }, z.core.$strict>;
281
+ }, z.core.$strict>;
282
+ declare const CONTROL_HANDSHAKE_PROTOCOL_HEADER_VALUE = "agent-vm.control.v1";
283
+ declare const CONTROL_HANDSHAKE_HEADER_NAMES: {
284
+ readonly bootId: "x-agent-vm-control-boot-id";
285
+ readonly controllerEpoch: "x-agent-vm-control-controller-epoch";
286
+ readonly credentialId: "x-agent-vm-control-credential-id";
287
+ readonly domain: "x-agent-vm-control-domain";
288
+ readonly expiresAtMs: "x-agent-vm-control-expires-at-ms";
289
+ readonly generationId: "x-agent-vm-control-generation-id";
290
+ readonly issuedAtMs: "x-agent-vm-control-issued-at-ms";
291
+ readonly nonce: "x-agent-vm-control-nonce";
292
+ readonly peerId: "x-agent-vm-control-peer-id";
293
+ readonly protocol: "x-agent-vm-control-protocol";
294
+ readonly signature: "x-agent-vm-control-signature";
295
+ readonly zoneId: "x-agent-vm-control-zone-id";
296
+ };
297
+ declare const CONTROL_READY_HEADER_NAMES: {
298
+ readonly bootId: "x-agent-vm-control-boot-id";
299
+ readonly controllerEpoch: "x-agent-vm-control-controller-epoch";
300
+ readonly domain: "x-agent-vm-control-domain";
301
+ readonly generationId: "x-agent-vm-control-generation-id";
302
+ readonly issuedAtMs: "x-agent-vm-control-issued-at-ms";
303
+ readonly peerId: "x-agent-vm-control-peer-id";
304
+ readonly protocol: "x-agent-vm-control-protocol";
305
+ readonly requestId: "x-agent-vm-control-ready-request-id";
306
+ readonly signature: "x-agent-vm-control-signature";
307
+ readonly zoneId: "x-agent-vm-control-zone-id";
308
+ };
309
+ declare const controlMessageKindDisposition: {
310
+ readonly command: "rpc_lifecycle";
311
+ readonly command_result: "rpc_lifecycle";
312
+ readonly event: "domain_event";
313
+ readonly heartbeat: "priority_liveness";
314
+ readonly observation: "append_only_observation";
315
+ readonly snapshot: "latest_wins_state";
316
+ };
317
+ type ControlDomain = z.infer<typeof ControlDomainSchema>;
318
+ type KnownControlDomain = z.infer<typeof KnownControlDomainSchema>;
319
+ type ControlMessageKind = z.infer<typeof ControlMessageKindSchema>;
320
+ type ControlDeliveryPolicy = z.infer<typeof ControlDeliveryPolicySchema>;
321
+ type ControlEnvelope = z.infer<typeof ControlEnvelopeSchema>;
322
+ type ControlHello = z.infer<typeof ControlHelloSchema>;
323
+ type ControlHelloResponse = z.infer<typeof ControlHelloResponseSchema>;
324
+ type ControlMessageReceipt = z.infer<typeof ControlMessageReceiptSchema>;
325
+ type ControlClose = z.infer<typeof ControlCloseSchema>;
326
+ type ControlSessionCloseReason = z.infer<typeof ControlSessionCloseReasonSchema>;
327
+ type ControlHandshakeCredential = z.infer<typeof ControlHandshakeCredentialSchema>;
328
+ type ControlHandshakeProof = z.infer<typeof ControlHandshakeProofSchema>;
329
+ type ControlReadyRequestCredential = z.infer<typeof ControlReadyRequestCredentialSchema>;
330
+ type ControlReadyRequestProof = z.infer<typeof ControlReadyRequestProofSchema>;
331
+ type ControlHelloAcknowledge = (response: ControlHelloResponse) => void;
332
+ type ControlMessageAcknowledge = (receipt: ControlMessageReceipt) => void;
333
+ type ControlCloseAcknowledge = (receipt: ControlMessageReceipt) => void;
334
+ interface ControlSessionControllerToPeerEvents<TDomainMessage> {
335
+ 'control:close': (payload: ControlClose, acknowledge: ControlCloseAcknowledge) => void;
336
+ 'control:hello': (payload: ControlHello, acknowledge: ControlHelloAcknowledge) => void;
337
+ 'control:message': (envelope: ControlEnvelope, payload: TDomainMessage, acknowledge: ControlMessageAcknowledge) => void;
338
+ }
339
+ interface ControlSessionPeerToControllerEvents<TDomainMessage> {
340
+ 'control:close': (payload: ControlClose, acknowledge: ControlCloseAcknowledge) => void;
341
+ 'control:message': (envelope: ControlEnvelope, payload: TDomainMessage, acknowledge: ControlMessageAcknowledge) => void;
342
+ }
343
+ interface DomainControlMessageIdentity {
344
+ readonly kind: ControlMessageKind;
345
+ readonly operation?: string;
346
+ }
347
+ interface DeliveryPolicyDerivationProps {
348
+ readonly envelope: ControlEnvelope;
349
+ readonly policyByOperation: Readonly<Record<string, ControlDeliveryPolicy>>;
350
+ readonly policyByKind?: Partial<Record<ControlMessageKind, ControlDeliveryPolicy>>;
351
+ }
352
+ declare function assertControlEnvelopeMatchesDomainMessage(envelope: ControlEnvelope, domainMessage: DomainControlMessageIdentity): void;
353
+ declare function buildControlMessageReceipt(): ControlMessageReceipt;
354
+ declare function buildControlMessageRejectionReceipt(props: {
355
+ readonly errorClass: string;
356
+ readonly safeMessage?: string;
357
+ }): ControlMessageReceipt;
358
+ declare function buildControlMessageExceptionRejectionReceipt(props: {
359
+ readonly error: unknown;
360
+ readonly processingErrorClass: string;
361
+ readonly safeMessage: string;
362
+ readonly schemaErrorClass?: string;
363
+ }): ControlMessageReceipt;
364
+ declare function assertControlMessageReceiptAccepted(receiptPayload: unknown): void;
365
+ declare function extractDomainCommandResultResponseToMessageId(payload: unknown): string | undefined;
366
+ declare function buildControlHandshakeSignaturePayload(proof: ControlHandshakeCredential): string;
367
+ declare function buildControlReadyRequestSignaturePayload(proof: ControlReadyRequestCredential): string;
368
+ declare function deriveControlDeliveryPolicy(props: DeliveryPolicyDerivationProps): ControlDeliveryPolicy;
369
+ declare function assertDerivedControlDeliveryPolicy(props: DeliveryPolicyDerivationProps): void;
370
+ declare function coalesceLatestWinsByKey<TMessage>(messages: readonly TMessage[], keyForMessage: (message: TMessage) => string): readonly TMessage[];
371
+ declare function shouldReplayControlEnvelope(envelope: ControlEnvelope): boolean;
372
+ interface ControlSequenceContinuityProps {
373
+ readonly envelope: ControlEnvelope;
374
+ readonly lastSeenSequence: number;
375
+ }
376
+ interface ControlEnvelopeSequencedMessage {
377
+ readonly envelope: Pick<ControlEnvelope, 'sequence'>;
378
+ }
379
+ declare function orderControlMessagesByEnvelopeSequence<TControlMessage extends ControlEnvelopeSequencedMessage>(messages: readonly TControlMessage[]): readonly TControlMessage[];
380
+ type ControlSequenceContinuityDecision = {
381
+ readonly action: 'accept';
382
+ readonly nextLastSeenSequence: number;
383
+ } | {
384
+ readonly action: 'drop';
385
+ readonly nextLastSeenSequence: number;
386
+ readonly safeMessage: string;
387
+ } | {
388
+ readonly action: 'stale';
389
+ readonly closeReason: Extract<ControlSessionCloseReason, 'sequence_gap'>;
390
+ readonly nextLastSeenSequence: number;
391
+ readonly safeMessage: string;
392
+ };
393
+ declare function evaluateControlSequenceContinuity(props: ControlSequenceContinuityProps): ControlSequenceContinuityDecision;
394
+ declare function buildControlProtocolJsonSchemas(): Readonly<Record<string, unknown>>;
395
+ //#endregion
396
+ export { CONTROL_HANDSHAKE_HEADER_NAMES, CONTROL_HANDSHAKE_PROTOCOL_HEADER_VALUE, CONTROL_PROTOCOL_VERSION, CONTROL_QUEUE_LIMITS, CONTROL_READY_HEADER_NAMES, CONTROL_SESSION_TIMING_MS, ControlClose, ControlCloseAcknowledge, ControlCloseSchema, ControlCorrelationSchema, ControlDeliveryPolicy, ControlDeliveryPolicySchema, ControlDomain, ControlDomainSchema, ControlEnvelope, ControlEnvelopeSchema, ControlEnvelopeSequencedMessage, ControlHandshakeCredential, ControlHandshakeCredentialSchema, ControlHandshakeHeadersSchema, ControlHandshakeProof, ControlHandshakeProofSchema, ControlHello, ControlHelloAcknowledge, ControlHelloResponse, ControlHelloResponseSchema, ControlHelloSchema, ControlMessageAcceptedReceiptSchema, ControlMessageAcknowledge, ControlMessageKind, ControlMessageKindSchema, ControlMessageReceipt, ControlMessageReceiptSchema, ControlMessageRejectedReceiptSchema, ControlReadyRequestCredential, ControlReadyRequestCredentialSchema, ControlReadyRequestProof, ControlReadyRequestProofSchema, ControlRpcErrorSchema, ControlRpcResultBaseSchema, ControlSequenceContinuityDecision, ControlSequenceContinuityProps, ControlSessionCloseReason, ControlSessionCloseReasonSchema, ControlSessionControllerToPeerEvents, ControlSessionPeerToControllerEvents, ControlSessionStateSchema, DeliveryPolicyDerivationProps, DomainCommandResultResponseLinkSchema, DomainControlMessageIdentity, KnownControlDomain, KnownControlDomainSchema, assertControlEnvelopeMatchesDomainMessage, assertControlMessageReceiptAccepted, assertDerivedControlDeliveryPolicy, buildControlHandshakeSignaturePayload, buildControlMessageExceptionRejectionReceipt, buildControlMessageReceipt, buildControlMessageRejectionReceipt, buildControlProtocolJsonSchemas, buildControlReadyRequestSignaturePayload, coalesceLatestWinsByKey, controlMessageKindDisposition, deriveControlDeliveryPolicy, evaluateControlSequenceContinuity, extractDomainCommandResultResponseToMessageId, orderControlMessagesByEnvelopeSequence, shouldReplayControlEnvelope };
397
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,337 @@
1
+ import { ZodError, z } from "zod/v4";
2
+ //#region src/index.ts
3
+ const CONTROL_PROTOCOL_VERSION = 1;
4
+ const CONTROL_SESSION_TIMING_MS = {
5
+ activeUseHeartbeatCadence: 3e4,
6
+ activeUseStaleTtl: 12e4,
7
+ clockSkewTolerance: 3e4,
8
+ commandAckTimeout: 2e3,
9
+ connectTimeout: 3e3,
10
+ controlSessionDeathGrace: 6e5,
11
+ engineIoPingInterval: 1e4,
12
+ engineIoPingTimeout: 1e4,
13
+ resyncTimeout: 5e3
14
+ };
15
+ const CONTROL_QUEUE_LIMITS = {
16
+ dedupeWindowMessages: 512,
17
+ dedupeWindowTtlMs: 6e4,
18
+ maxHttpBufferBytes: 65536,
19
+ queueByteCap: 4 * 1024 * 1024,
20
+ queueMessageCap: 256
21
+ };
22
+ const ControlDomainSchema = z.string().regex(/^[a-z][a-z0-9_]*$/u);
23
+ const KnownControlDomainSchema = z.enum(["gateway_control", "worker_control"]);
24
+ const ControlMessageKindSchema = z.enum([
25
+ "command",
26
+ "command_result",
27
+ "event",
28
+ "snapshot",
29
+ "heartbeat",
30
+ "observation"
31
+ ]);
32
+ const ControlDeliveryPolicySchema = z.enum([
33
+ "latest_wins",
34
+ "droppable",
35
+ "acked_idempotent",
36
+ "critical_idempotent",
37
+ "append_only_observation",
38
+ "single_use_critical",
39
+ "forbidden_bulk"
40
+ ]);
41
+ const ControlSessionCloseReasonSchema = z.enum([
42
+ "normal_shutdown",
43
+ "controller_restart",
44
+ "peer_restart",
45
+ "auth_failed",
46
+ "protocol_version_mismatch",
47
+ "domain_mismatch",
48
+ "generation_mismatch",
49
+ "controller_epoch_mismatch",
50
+ "duplicate_session",
51
+ "stale_session",
52
+ "sequence_gap",
53
+ "ack_timeout",
54
+ "command_timeout",
55
+ "resync_timeout",
56
+ "queue_overflow",
57
+ "message_too_large",
58
+ "schema_validation_failed",
59
+ "forbidden_bulk_message",
60
+ "transport_error"
61
+ ]);
62
+ const ControlEnvelopeSchema = z.object({
63
+ bootId: z.string().min(1),
64
+ commandId: z.string().uuid().optional(),
65
+ connectionId: z.string().uuid(),
66
+ controllerEpoch: z.string().min(1),
67
+ createdAtMs: z.number().int().positive(),
68
+ deliveryPolicy: ControlDeliveryPolicySchema,
69
+ domain: ControlDomainSchema,
70
+ expiresAtMs: z.number().int().positive().optional(),
71
+ idempotencyKey: z.string().min(1).optional(),
72
+ kind: ControlMessageKindSchema,
73
+ messageId: z.string().uuid(),
74
+ operation: z.string().min(1).optional(),
75
+ peerId: z.string().min(1),
76
+ protocolVersion: z.literal(1),
77
+ sequence: z.number().int().nonnegative(),
78
+ sessionId: z.string().uuid(),
79
+ zoneId: z.string().min(1)
80
+ }).strict();
81
+ const ControlSessionStateSchema = z.enum([
82
+ "unknown",
83
+ "connecting",
84
+ "ready",
85
+ "reconnecting",
86
+ "stale",
87
+ "rejected",
88
+ "generation_mismatch",
89
+ "failed",
90
+ "closed"
91
+ ]);
92
+ const ControlRpcResultBaseSchema = z.enum([
93
+ "ok",
94
+ "failed",
95
+ "timeout",
96
+ "rejected",
97
+ "cancelled",
98
+ "stale_generation"
99
+ ]);
100
+ const ControlRpcErrorSchema = z.object({
101
+ errorClass: z.string().min(1),
102
+ retryable: z.boolean().optional(),
103
+ safeMessage: z.string().min(1).optional()
104
+ }).strict();
105
+ const ControlCorrelationSchema = z.object({
106
+ causationId: z.string().uuid().optional(),
107
+ correlationId: z.string().min(1).optional(),
108
+ requestId: z.string().min(1).optional(),
109
+ runId: z.string().min(1).optional(),
110
+ sessionKeyDigest: z.string().min(32).optional(),
111
+ toolCallId: z.string().min(1).optional(),
112
+ traceId: z.string().regex(/^[0-9a-f]{32}$/u).optional()
113
+ }).strict();
114
+ const ControlHelloSchema = z.object({
115
+ bootId: z.string().min(1),
116
+ controllerEpoch: z.string().min(1).optional(),
117
+ domain: ControlDomainSchema,
118
+ lastSeenControllerSequence: z.number().int().nonnegative().optional(),
119
+ lastSeenPeerSequence: z.number().int().nonnegative().optional(),
120
+ peerId: z.string().min(1),
121
+ previousSessionId: z.string().uuid().optional(),
122
+ protocolVersion: z.literal(1)
123
+ }).strict();
124
+ const ControlHelloResponseSchema = z.object({
125
+ connectionId: z.string().uuid(),
126
+ controllerEpoch: z.string().min(1),
127
+ fences: z.record(z.string(), z.string()).optional(),
128
+ outcome: z.enum([
129
+ "accepted",
130
+ "rejected",
131
+ "resync_required",
132
+ "generation_mismatch"
133
+ ]),
134
+ sessionId: z.string().uuid()
135
+ }).strict();
136
+ const ControlCloseSchema = z.object({
137
+ reason: ControlSessionCloseReasonSchema,
138
+ safeMessage: z.string().min(1).optional(),
139
+ sessionId: z.string().uuid()
140
+ }).strict();
141
+ const ControlMessageAcceptedReceiptSchema = z.object({ received: z.literal(true) }).strict();
142
+ const ControlMessageRejectedReceiptSchema = z.object({
143
+ errorClass: z.string().min(1),
144
+ received: z.literal(false),
145
+ safeMessage: z.string().min(1).optional()
146
+ }).strict();
147
+ const ControlMessageReceiptSchema = z.discriminatedUnion("received", [ControlMessageAcceptedReceiptSchema, ControlMessageRejectedReceiptSchema]);
148
+ const DomainCommandResultResponseLinkSchema = z.object({
149
+ kind: z.literal("command_result"),
150
+ payload: z.object({ responseToMessageId: z.string().uuid() }).passthrough()
151
+ }).passthrough();
152
+ const ControlHandshakeCredentialSchema = z.object({
153
+ audience: KnownControlDomainSchema,
154
+ bootId: z.string().min(1),
155
+ controllerEpoch: z.string().min(1),
156
+ credentialId: z.string().min(1),
157
+ expiresAtMs: z.number().int().positive(),
158
+ generationId: z.string().min(1),
159
+ issuedAtMs: z.number().int().positive(),
160
+ nonce: z.string().min(16),
161
+ peerId: z.string().min(1),
162
+ protocolVersion: z.literal(1),
163
+ zoneId: z.string().min(1)
164
+ }).strict().refine((value) => value.expiresAtMs > value.issuedAtMs, {
165
+ message: "expiresAtMs must be greater than issuedAtMs",
166
+ path: ["expiresAtMs"]
167
+ });
168
+ const ControlHandshakeProofSchema = ControlHandshakeCredentialSchema.extend({ signature: z.string().min(1) }).strict();
169
+ const ControlReadyRequestCredentialSchema = z.object({
170
+ audience: KnownControlDomainSchema,
171
+ bootId: z.string().min(1),
172
+ controllerEpoch: z.string().min(1),
173
+ generationId: z.string().min(1),
174
+ issuedAtMs: z.number().int().positive(),
175
+ peerId: z.string().min(1),
176
+ protocolVersion: z.literal(1),
177
+ requestId: z.string().uuid(),
178
+ zoneId: z.string().min(1)
179
+ }).strict();
180
+ const ControlReadyRequestProofSchema = ControlReadyRequestCredentialSchema.extend({ signature: z.string().min(1) }).strict();
181
+ const ControlHandshakeHeadersSchema = z.object({ proof: ControlHandshakeProofSchema }).strict();
182
+ const CONTROL_HANDSHAKE_PROTOCOL_HEADER_VALUE = "agent-vm.control.v1";
183
+ const CONTROL_HANDSHAKE_HEADER_NAMES = {
184
+ bootId: "x-agent-vm-control-boot-id",
185
+ controllerEpoch: "x-agent-vm-control-controller-epoch",
186
+ credentialId: "x-agent-vm-control-credential-id",
187
+ domain: "x-agent-vm-control-domain",
188
+ expiresAtMs: "x-agent-vm-control-expires-at-ms",
189
+ generationId: "x-agent-vm-control-generation-id",
190
+ issuedAtMs: "x-agent-vm-control-issued-at-ms",
191
+ nonce: "x-agent-vm-control-nonce",
192
+ peerId: "x-agent-vm-control-peer-id",
193
+ protocol: "x-agent-vm-control-protocol",
194
+ signature: "x-agent-vm-control-signature",
195
+ zoneId: "x-agent-vm-control-zone-id"
196
+ };
197
+ const CONTROL_READY_HEADER_NAMES = {
198
+ bootId: CONTROL_HANDSHAKE_HEADER_NAMES.bootId,
199
+ controllerEpoch: CONTROL_HANDSHAKE_HEADER_NAMES.controllerEpoch,
200
+ domain: CONTROL_HANDSHAKE_HEADER_NAMES.domain,
201
+ generationId: CONTROL_HANDSHAKE_HEADER_NAMES.generationId,
202
+ issuedAtMs: CONTROL_HANDSHAKE_HEADER_NAMES.issuedAtMs,
203
+ peerId: CONTROL_HANDSHAKE_HEADER_NAMES.peerId,
204
+ protocol: CONTROL_HANDSHAKE_HEADER_NAMES.protocol,
205
+ requestId: "x-agent-vm-control-ready-request-id",
206
+ signature: CONTROL_HANDSHAKE_HEADER_NAMES.signature,
207
+ zoneId: CONTROL_HANDSHAKE_HEADER_NAMES.zoneId
208
+ };
209
+ const controlMessageKindDisposition = {
210
+ command: "rpc_lifecycle",
211
+ command_result: "rpc_lifecycle",
212
+ event: "domain_event",
213
+ heartbeat: "priority_liveness",
214
+ observation: "append_only_observation",
215
+ snapshot: "latest_wins_state"
216
+ };
217
+ function assertControlEnvelopeMatchesDomainMessage(envelope, domainMessage) {
218
+ if (envelope.kind !== domainMessage.kind) throw new Error(`control message kind mismatch: ${envelope.kind} !== ${domainMessage.kind}`);
219
+ if (envelope.operation !== domainMessage.operation) throw new Error(`control message operation mismatch: ${envelope.operation ?? "<none>"} !== ${domainMessage.operation ?? "<none>"}`);
220
+ }
221
+ function buildControlMessageReceipt() {
222
+ return ControlMessageReceiptSchema.parse({ received: true });
223
+ }
224
+ function buildControlMessageRejectionReceipt(props) {
225
+ return ControlMessageReceiptSchema.parse({
226
+ errorClass: props.errorClass,
227
+ received: false,
228
+ ...props.safeMessage === void 0 ? {} : { safeMessage: props.safeMessage }
229
+ });
230
+ }
231
+ function buildControlMessageExceptionRejectionReceipt(props) {
232
+ return buildControlMessageRejectionReceipt({
233
+ errorClass: props.error instanceof ZodError ? props.schemaErrorClass ?? "schema_validation_failed" : props.processingErrorClass,
234
+ safeMessage: props.safeMessage
235
+ });
236
+ }
237
+ function assertControlMessageReceiptAccepted(receiptPayload) {
238
+ const receipt = ControlMessageReceiptSchema.parse(receiptPayload);
239
+ if (!receipt.received) throw new Error(receipt.safeMessage ?? receipt.errorClass);
240
+ }
241
+ function extractDomainCommandResultResponseToMessageId(payload) {
242
+ const parsed = DomainCommandResultResponseLinkSchema.safeParse(payload);
243
+ return parsed.success ? parsed.data.payload.responseToMessageId : void 0;
244
+ }
245
+ function buildControlHandshakeSignaturePayload(proof) {
246
+ return JSON.stringify({
247
+ audience: proof.audience,
248
+ bootId: proof.bootId,
249
+ controllerEpoch: proof.controllerEpoch,
250
+ credentialId: proof.credentialId,
251
+ expiresAtMs: proof.expiresAtMs,
252
+ generationId: proof.generationId,
253
+ issuedAtMs: proof.issuedAtMs,
254
+ nonce: proof.nonce,
255
+ peerId: proof.peerId,
256
+ protocolVersion: proof.protocolVersion,
257
+ zoneId: proof.zoneId
258
+ });
259
+ }
260
+ function buildControlReadyRequestSignaturePayload(proof) {
261
+ return JSON.stringify({
262
+ audience: proof.audience,
263
+ bootId: proof.bootId,
264
+ controllerEpoch: proof.controllerEpoch,
265
+ generationId: proof.generationId,
266
+ issuedAtMs: proof.issuedAtMs,
267
+ peerId: proof.peerId,
268
+ protocolVersion: proof.protocolVersion,
269
+ requestId: proof.requestId,
270
+ zoneId: proof.zoneId
271
+ });
272
+ }
273
+ function deriveControlDeliveryPolicy(props) {
274
+ if (props.envelope.operation !== void 0) {
275
+ const operationPolicy = props.policyByOperation[props.envelope.operation];
276
+ if (operationPolicy !== void 0) return operationPolicy;
277
+ }
278
+ const kindPolicy = props.policyByKind?.[props.envelope.kind];
279
+ if (kindPolicy !== void 0) return kindPolicy;
280
+ throw new Error(`no derived delivery policy for ${props.envelope.kind}:${props.envelope.operation ?? "<none>"}`);
281
+ }
282
+ function assertDerivedControlDeliveryPolicy(props) {
283
+ const derivedPolicy = deriveControlDeliveryPolicy(props);
284
+ if (props.envelope.deliveryPolicy !== derivedPolicy) throw new Error(`control delivery policy mismatch: ${props.envelope.deliveryPolicy} !== ${derivedPolicy}`);
285
+ }
286
+ function coalesceLatestWinsByKey(messages, keyForMessage) {
287
+ const latestByKey = /* @__PURE__ */ new Map();
288
+ for (const message of messages) latestByKey.set(keyForMessage(message), message);
289
+ return [...latestByKey.values()];
290
+ }
291
+ function shouldReplayControlEnvelope(envelope) {
292
+ return envelope.deliveryPolicy !== "droppable" && envelope.deliveryPolicy !== "latest_wins" && envelope.deliveryPolicy !== "forbidden_bulk";
293
+ }
294
+ function orderControlMessagesByEnvelopeSequence(messages) {
295
+ return messages.toSorted((left, right) => left.envelope.sequence - right.envelope.sequence);
296
+ }
297
+ function controlSequenceDiagnosticSuffix(envelope) {
298
+ return ` kind=${envelope.kind} operation=${envelope.operation ?? "<none>"} delivery=${envelope.deliveryPolicy} sessionId=${envelope.sessionId}`;
299
+ }
300
+ function evaluateControlSequenceContinuity(props) {
301
+ if (props.envelope.sequence <= props.lastSeenSequence) return {
302
+ action: "drop",
303
+ nextLastSeenSequence: props.lastSeenSequence,
304
+ safeMessage: `control sequence did not advance: last=${String(props.lastSeenSequence)} received=${String(props.envelope.sequence)}${controlSequenceDiagnosticSuffix(props.envelope)}`
305
+ };
306
+ if (props.envelope.deliveryPolicy === "droppable" || props.envelope.deliveryPolicy === "latest_wins") return {
307
+ action: "accept",
308
+ nextLastSeenSequence: props.lastSeenSequence
309
+ };
310
+ const expectedSequence = props.lastSeenSequence + 1;
311
+ if (props.envelope.sequence === expectedSequence) return {
312
+ action: "accept",
313
+ nextLastSeenSequence: props.envelope.sequence
314
+ };
315
+ return {
316
+ action: "stale",
317
+ closeReason: "sequence_gap",
318
+ nextLastSeenSequence: props.lastSeenSequence,
319
+ safeMessage: `control sequence gap: expected=${String(expectedSequence)} received=${String(props.envelope.sequence)}${controlSequenceDiagnosticSuffix(props.envelope)}`
320
+ };
321
+ }
322
+ function buildControlProtocolJsonSchemas() {
323
+ return {
324
+ close: z.toJSONSchema(ControlCloseSchema, { io: "input" }),
325
+ envelope: z.toJSONSchema(ControlEnvelopeSchema, { io: "input" }),
326
+ handshakeCredential: z.toJSONSchema(ControlHandshakeCredentialSchema, { io: "input" }),
327
+ handshakeProof: z.toJSONSchema(ControlHandshakeProofSchema, { io: "input" }),
328
+ hello: z.toJSONSchema(ControlHelloSchema, { io: "input" }),
329
+ helloResponse: z.toJSONSchema(ControlHelloResponseSchema, { io: "input" }),
330
+ readyRequestCredential: z.toJSONSchema(ControlReadyRequestCredentialSchema, { io: "input" }),
331
+ readyRequestProof: z.toJSONSchema(ControlReadyRequestProofSchema, { io: "input" })
332
+ };
333
+ }
334
+ //#endregion
335
+ export { CONTROL_HANDSHAKE_HEADER_NAMES, CONTROL_HANDSHAKE_PROTOCOL_HEADER_VALUE, CONTROL_PROTOCOL_VERSION, CONTROL_QUEUE_LIMITS, CONTROL_READY_HEADER_NAMES, CONTROL_SESSION_TIMING_MS, ControlCloseSchema, ControlCorrelationSchema, ControlDeliveryPolicySchema, ControlDomainSchema, ControlEnvelopeSchema, ControlHandshakeCredentialSchema, ControlHandshakeHeadersSchema, ControlHandshakeProofSchema, ControlHelloResponseSchema, ControlHelloSchema, ControlMessageAcceptedReceiptSchema, ControlMessageKindSchema, ControlMessageReceiptSchema, ControlMessageRejectedReceiptSchema, ControlReadyRequestCredentialSchema, ControlReadyRequestProofSchema, ControlRpcErrorSchema, ControlRpcResultBaseSchema, ControlSessionCloseReasonSchema, ControlSessionStateSchema, DomainCommandResultResponseLinkSchema, KnownControlDomainSchema, assertControlEnvelopeMatchesDomainMessage, assertControlMessageReceiptAccepted, assertDerivedControlDeliveryPolicy, buildControlHandshakeSignaturePayload, buildControlMessageExceptionRejectionReceipt, buildControlMessageReceipt, buildControlMessageRejectionReceipt, buildControlProtocolJsonSchemas, buildControlReadyRequestSignaturePayload, coalesceLatestWinsByKey, controlMessageKindDisposition, deriveControlDeliveryPolicy, evaluateControlSequenceContinuity, extractDomainCommandResultResponseToMessageId, orderControlMessagesByEnvelopeSequence, shouldReplayControlEnvelope };
336
+
337
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { ZodError, z } from 'zod/v4';\n\nexport const CONTROL_PROTOCOL_VERSION = 1;\n\nexport const CONTROL_SESSION_TIMING_MS = {\n\tactiveUseHeartbeatCadence: 30_000,\n\tactiveUseStaleTtl: 120_000,\n\tclockSkewTolerance: 30_000,\n\tcommandAckTimeout: 2_000,\n\tconnectTimeout: 3_000,\n\tcontrolSessionDeathGrace: 600_000,\n\tengineIoPingInterval: 10_000,\n\tengineIoPingTimeout: 10_000,\n\tresyncTimeout: 5_000,\n} as const;\n\nexport const CONTROL_QUEUE_LIMITS = {\n\tdedupeWindowMessages: 512,\n\tdedupeWindowTtlMs: 60_000,\n\tmaxHttpBufferBytes: 65_536,\n\tqueueByteCap: 4 * 1024 * 1024,\n\tqueueMessageCap: 256,\n} as const;\n\nexport const ControlDomainSchema = z.string().regex(/^[a-z][a-z0-9_]*$/u);\n\nexport const KnownControlDomainSchema = z.enum(['gateway_control', 'worker_control']);\n\nexport const ControlMessageKindSchema = z.enum([\n\t'command',\n\t'command_result',\n\t'event',\n\t'snapshot',\n\t'heartbeat',\n\t'observation',\n]);\n\nexport const ControlDeliveryPolicySchema = z.enum([\n\t'latest_wins',\n\t'droppable',\n\t'acked_idempotent',\n\t'critical_idempotent',\n\t'append_only_observation',\n\t'single_use_critical',\n\t'forbidden_bulk',\n]);\n\nexport const ControlSessionCloseReasonSchema = z.enum([\n\t'normal_shutdown',\n\t'controller_restart',\n\t'peer_restart',\n\t'auth_failed',\n\t'protocol_version_mismatch',\n\t'domain_mismatch',\n\t'generation_mismatch',\n\t'controller_epoch_mismatch',\n\t'duplicate_session',\n\t'stale_session',\n\t'sequence_gap',\n\t'ack_timeout',\n\t'command_timeout',\n\t'resync_timeout',\n\t'queue_overflow',\n\t'message_too_large',\n\t'schema_validation_failed',\n\t'forbidden_bulk_message',\n\t'transport_error',\n]);\n\nexport const ControlEnvelopeSchema = z\n\t.object({\n\t\tbootId: z.string().min(1),\n\t\tcommandId: z.string().uuid().optional(),\n\t\tconnectionId: z.string().uuid(),\n\t\tcontrollerEpoch: z.string().min(1),\n\t\tcreatedAtMs: z.number().int().positive(),\n\t\tdeliveryPolicy: ControlDeliveryPolicySchema,\n\t\tdomain: ControlDomainSchema,\n\t\texpiresAtMs: z.number().int().positive().optional(),\n\t\tidempotencyKey: z.string().min(1).optional(),\n\t\tkind: ControlMessageKindSchema,\n\t\tmessageId: z.string().uuid(),\n\t\toperation: z.string().min(1).optional(),\n\t\tpeerId: z.string().min(1),\n\t\tprotocolVersion: z.literal(CONTROL_PROTOCOL_VERSION),\n\t\tsequence: z.number().int().nonnegative(),\n\t\tsessionId: z.string().uuid(),\n\t\tzoneId: z.string().min(1),\n\t})\n\t.strict();\n\nexport const ControlSessionStateSchema = z.enum([\n\t'unknown',\n\t'connecting',\n\t'ready',\n\t'reconnecting',\n\t'stale',\n\t'rejected',\n\t'generation_mismatch',\n\t'failed',\n\t'closed',\n]);\n\nexport const ControlRpcResultBaseSchema = z.enum([\n\t'ok',\n\t'failed',\n\t'timeout',\n\t'rejected',\n\t'cancelled',\n\t'stale_generation',\n]);\n\nexport const ControlRpcErrorSchema = z\n\t.object({\n\t\terrorClass: z.string().min(1),\n\t\tretryable: z.boolean().optional(),\n\t\tsafeMessage: z.string().min(1).optional(),\n\t})\n\t.strict();\n\nexport const ControlCorrelationSchema = z\n\t.object({\n\t\tcausationId: z.string().uuid().optional(),\n\t\tcorrelationId: z.string().min(1).optional(),\n\t\trequestId: z.string().min(1).optional(),\n\t\trunId: z.string().min(1).optional(),\n\t\tsessionKeyDigest: z.string().min(32).optional(),\n\t\ttoolCallId: z.string().min(1).optional(),\n\t\ttraceId: z\n\t\t\t.string()\n\t\t\t.regex(/^[0-9a-f]{32}$/u)\n\t\t\t.optional(),\n\t})\n\t.strict();\n\nexport const ControlHelloSchema = z\n\t.object({\n\t\tbootId: z.string().min(1),\n\t\tcontrollerEpoch: z.string().min(1).optional(),\n\t\tdomain: ControlDomainSchema,\n\t\tlastSeenControllerSequence: z.number().int().nonnegative().optional(),\n\t\tlastSeenPeerSequence: z.number().int().nonnegative().optional(),\n\t\tpeerId: z.string().min(1),\n\t\tpreviousSessionId: z.string().uuid().optional(),\n\t\tprotocolVersion: z.literal(CONTROL_PROTOCOL_VERSION),\n\t})\n\t.strict();\n\nexport const ControlHelloResponseSchema = z\n\t.object({\n\t\tconnectionId: z.string().uuid(),\n\t\tcontrollerEpoch: z.string().min(1),\n\t\tfences: z.record(z.string(), z.string()).optional(),\n\t\toutcome: z.enum(['accepted', 'rejected', 'resync_required', 'generation_mismatch']),\n\t\tsessionId: z.string().uuid(),\n\t})\n\t.strict();\n\nexport const ControlCloseSchema = z\n\t.object({\n\t\treason: ControlSessionCloseReasonSchema,\n\t\tsafeMessage: z.string().min(1).optional(),\n\t\tsessionId: z.string().uuid(),\n\t})\n\t.strict();\n\nexport const ControlMessageAcceptedReceiptSchema = z\n\t.object({\n\t\treceived: z.literal(true),\n\t})\n\t.strict();\n\nexport const ControlMessageRejectedReceiptSchema = z\n\t.object({\n\t\terrorClass: z.string().min(1),\n\t\treceived: z.literal(false),\n\t\tsafeMessage: z.string().min(1).optional(),\n\t})\n\t.strict();\n\nexport const ControlMessageReceiptSchema = z.discriminatedUnion('received', [\n\tControlMessageAcceptedReceiptSchema,\n\tControlMessageRejectedReceiptSchema,\n]);\n\nexport const DomainCommandResultResponseLinkSchema = z\n\t.object({\n\t\tkind: z.literal('command_result'),\n\t\tpayload: z\n\t\t\t.object({\n\t\t\t\tresponseToMessageId: z.string().uuid(),\n\t\t\t})\n\t\t\t.passthrough(),\n\t})\n\t.passthrough();\n\nexport const ControlHandshakeCredentialSchema = z\n\t.object({\n\t\taudience: KnownControlDomainSchema,\n\t\tbootId: z.string().min(1),\n\t\tcontrollerEpoch: z.string().min(1),\n\t\tcredentialId: z.string().min(1),\n\t\texpiresAtMs: z.number().int().positive(),\n\t\tgenerationId: z.string().min(1),\n\t\tissuedAtMs: z.number().int().positive(),\n\t\tnonce: z.string().min(16),\n\t\tpeerId: z.string().min(1),\n\t\tprotocolVersion: z.literal(CONTROL_PROTOCOL_VERSION),\n\t\tzoneId: z.string().min(1),\n\t})\n\t.strict()\n\t.refine((value) => value.expiresAtMs > value.issuedAtMs, {\n\t\tmessage: 'expiresAtMs must be greater than issuedAtMs',\n\t\tpath: ['expiresAtMs'],\n\t});\n\nexport const ControlHandshakeProofSchema = ControlHandshakeCredentialSchema.extend({\n\tsignature: z.string().min(1),\n}).strict();\n\nexport const ControlReadyRequestCredentialSchema = z\n\t.object({\n\t\taudience: KnownControlDomainSchema,\n\t\tbootId: z.string().min(1),\n\t\tcontrollerEpoch: z.string().min(1),\n\t\tgenerationId: z.string().min(1),\n\t\tissuedAtMs: z.number().int().positive(),\n\t\tpeerId: z.string().min(1),\n\t\tprotocolVersion: z.literal(CONTROL_PROTOCOL_VERSION),\n\t\trequestId: z.string().uuid(),\n\t\tzoneId: z.string().min(1),\n\t})\n\t.strict();\n\nexport const ControlReadyRequestProofSchema = ControlReadyRequestCredentialSchema.extend({\n\tsignature: z.string().min(1),\n}).strict();\n\nexport const ControlHandshakeHeadersSchema = z\n\t.object({\n\t\tproof: ControlHandshakeProofSchema,\n\t})\n\t.strict();\n\nexport const CONTROL_HANDSHAKE_PROTOCOL_HEADER_VALUE = 'agent-vm.control.v1';\n\nexport const CONTROL_HANDSHAKE_HEADER_NAMES = {\n\tbootId: 'x-agent-vm-control-boot-id',\n\tcontrollerEpoch: 'x-agent-vm-control-controller-epoch',\n\tcredentialId: 'x-agent-vm-control-credential-id',\n\tdomain: 'x-agent-vm-control-domain',\n\texpiresAtMs: 'x-agent-vm-control-expires-at-ms',\n\tgenerationId: 'x-agent-vm-control-generation-id',\n\tissuedAtMs: 'x-agent-vm-control-issued-at-ms',\n\tnonce: 'x-agent-vm-control-nonce',\n\tpeerId: 'x-agent-vm-control-peer-id',\n\tprotocol: 'x-agent-vm-control-protocol',\n\tsignature: 'x-agent-vm-control-signature',\n\tzoneId: 'x-agent-vm-control-zone-id',\n} as const;\n\nexport const CONTROL_READY_HEADER_NAMES = {\n\tbootId: CONTROL_HANDSHAKE_HEADER_NAMES.bootId,\n\tcontrollerEpoch: CONTROL_HANDSHAKE_HEADER_NAMES.controllerEpoch,\n\tdomain: CONTROL_HANDSHAKE_HEADER_NAMES.domain,\n\tgenerationId: CONTROL_HANDSHAKE_HEADER_NAMES.generationId,\n\tissuedAtMs: CONTROL_HANDSHAKE_HEADER_NAMES.issuedAtMs,\n\tpeerId: CONTROL_HANDSHAKE_HEADER_NAMES.peerId,\n\tprotocol: CONTROL_HANDSHAKE_HEADER_NAMES.protocol,\n\trequestId: 'x-agent-vm-control-ready-request-id',\n\tsignature: CONTROL_HANDSHAKE_HEADER_NAMES.signature,\n\tzoneId: CONTROL_HANDSHAKE_HEADER_NAMES.zoneId,\n} as const;\n\nexport const controlMessageKindDisposition = {\n\tcommand: 'rpc_lifecycle',\n\tcommand_result: 'rpc_lifecycle',\n\tevent: 'domain_event',\n\theartbeat: 'priority_liveness',\n\tobservation: 'append_only_observation',\n\tsnapshot: 'latest_wins_state',\n} as const satisfies Record<ControlMessageKind, string>;\n\nexport type ControlDomain = z.infer<typeof ControlDomainSchema>;\nexport type KnownControlDomain = z.infer<typeof KnownControlDomainSchema>;\nexport type ControlMessageKind = z.infer<typeof ControlMessageKindSchema>;\nexport type ControlDeliveryPolicy = z.infer<typeof ControlDeliveryPolicySchema>;\nexport type ControlEnvelope = z.infer<typeof ControlEnvelopeSchema>;\nexport type ControlHello = z.infer<typeof ControlHelloSchema>;\nexport type ControlHelloResponse = z.infer<typeof ControlHelloResponseSchema>;\nexport type ControlMessageReceipt = z.infer<typeof ControlMessageReceiptSchema>;\nexport type ControlClose = z.infer<typeof ControlCloseSchema>;\nexport type ControlSessionCloseReason = z.infer<typeof ControlSessionCloseReasonSchema>;\nexport type ControlHandshakeCredential = z.infer<typeof ControlHandshakeCredentialSchema>;\nexport type ControlHandshakeProof = z.infer<typeof ControlHandshakeProofSchema>;\nexport type ControlReadyRequestCredential = z.infer<typeof ControlReadyRequestCredentialSchema>;\nexport type ControlReadyRequestProof = z.infer<typeof ControlReadyRequestProofSchema>;\n\nexport type ControlHelloAcknowledge = (response: ControlHelloResponse) => void;\nexport type ControlMessageAcknowledge = (receipt: ControlMessageReceipt) => void;\nexport type ControlCloseAcknowledge = (receipt: ControlMessageReceipt) => void;\n\nexport interface ControlSessionControllerToPeerEvents<TDomainMessage> {\n\t'control:close': (payload: ControlClose, acknowledge: ControlCloseAcknowledge) => void;\n\t'control:hello': (payload: ControlHello, acknowledge: ControlHelloAcknowledge) => void;\n\t'control:message': (\n\t\tenvelope: ControlEnvelope,\n\t\tpayload: TDomainMessage,\n\t\tacknowledge: ControlMessageAcknowledge,\n\t) => void;\n}\n\nexport interface ControlSessionPeerToControllerEvents<TDomainMessage> {\n\t'control:close': (payload: ControlClose, acknowledge: ControlCloseAcknowledge) => void;\n\t'control:message': (\n\t\tenvelope: ControlEnvelope,\n\t\tpayload: TDomainMessage,\n\t\tacknowledge: ControlMessageAcknowledge,\n\t) => void;\n}\n\nexport interface DomainControlMessageIdentity {\n\treadonly kind: ControlMessageKind;\n\treadonly operation?: string;\n}\n\nexport interface DeliveryPolicyDerivationProps {\n\treadonly envelope: ControlEnvelope;\n\treadonly policyByOperation: Readonly<Record<string, ControlDeliveryPolicy>>;\n\treadonly policyByKind?: Partial<Record<ControlMessageKind, ControlDeliveryPolicy>>;\n}\n\nexport function assertControlEnvelopeMatchesDomainMessage(\n\tenvelope: ControlEnvelope,\n\tdomainMessage: DomainControlMessageIdentity,\n): void {\n\tif (envelope.kind !== domainMessage.kind) {\n\t\tthrow new Error(`control message kind mismatch: ${envelope.kind} !== ${domainMessage.kind}`);\n\t}\n\tif (envelope.operation !== domainMessage.operation) {\n\t\tthrow new Error(\n\t\t\t`control message operation mismatch: ${envelope.operation ?? '<none>'} !== ${domainMessage.operation ?? '<none>'}`,\n\t\t);\n\t}\n}\n\nexport function buildControlMessageReceipt(): ControlMessageReceipt {\n\treturn ControlMessageReceiptSchema.parse({ received: true });\n}\n\nexport function buildControlMessageRejectionReceipt(props: {\n\treadonly errorClass: string;\n\treadonly safeMessage?: string;\n}): ControlMessageReceipt {\n\treturn ControlMessageReceiptSchema.parse({\n\t\terrorClass: props.errorClass,\n\t\treceived: false,\n\t\t...(props.safeMessage === undefined ? {} : { safeMessage: props.safeMessage }),\n\t});\n}\n\nexport function buildControlMessageExceptionRejectionReceipt(props: {\n\treadonly error: unknown;\n\treadonly processingErrorClass: string;\n\treadonly safeMessage: string;\n\treadonly schemaErrorClass?: string;\n}): ControlMessageReceipt {\n\treturn buildControlMessageRejectionReceipt({\n\t\terrorClass:\n\t\t\tprops.error instanceof ZodError\n\t\t\t\t? (props.schemaErrorClass ?? 'schema_validation_failed')\n\t\t\t\t: props.processingErrorClass,\n\t\tsafeMessage: props.safeMessage,\n\t});\n}\n\nexport function assertControlMessageReceiptAccepted(receiptPayload: unknown): void {\n\tconst receipt = ControlMessageReceiptSchema.parse(receiptPayload);\n\tif (!receipt.received) {\n\t\tthrow new Error(receipt.safeMessage ?? receipt.errorClass);\n\t}\n}\n\nexport function extractDomainCommandResultResponseToMessageId(\n\tpayload: unknown,\n): string | undefined {\n\tconst parsed = DomainCommandResultResponseLinkSchema.safeParse(payload);\n\treturn parsed.success ? parsed.data.payload.responseToMessageId : undefined;\n}\n\nexport function buildControlHandshakeSignaturePayload(proof: ControlHandshakeCredential): string {\n\treturn JSON.stringify({\n\t\taudience: proof.audience,\n\t\tbootId: proof.bootId,\n\t\tcontrollerEpoch: proof.controllerEpoch,\n\t\tcredentialId: proof.credentialId,\n\t\texpiresAtMs: proof.expiresAtMs,\n\t\tgenerationId: proof.generationId,\n\t\tissuedAtMs: proof.issuedAtMs,\n\t\tnonce: proof.nonce,\n\t\tpeerId: proof.peerId,\n\t\tprotocolVersion: proof.protocolVersion,\n\t\tzoneId: proof.zoneId,\n\t});\n}\n\nexport function buildControlReadyRequestSignaturePayload(\n\tproof: ControlReadyRequestCredential,\n): string {\n\treturn JSON.stringify({\n\t\taudience: proof.audience,\n\t\tbootId: proof.bootId,\n\t\tcontrollerEpoch: proof.controllerEpoch,\n\t\tgenerationId: proof.generationId,\n\t\tissuedAtMs: proof.issuedAtMs,\n\t\tpeerId: proof.peerId,\n\t\tprotocolVersion: proof.protocolVersion,\n\t\trequestId: proof.requestId,\n\t\tzoneId: proof.zoneId,\n\t});\n}\n\nexport function deriveControlDeliveryPolicy(\n\tprops: DeliveryPolicyDerivationProps,\n): ControlDeliveryPolicy {\n\tif (props.envelope.operation !== undefined) {\n\t\tconst operationPolicy = props.policyByOperation[props.envelope.operation];\n\t\tif (operationPolicy !== undefined) {\n\t\t\treturn operationPolicy;\n\t\t}\n\t}\n\tconst kindPolicy = props.policyByKind?.[props.envelope.kind];\n\tif (kindPolicy !== undefined) {\n\t\treturn kindPolicy;\n\t}\n\tthrow new Error(\n\t\t`no derived delivery policy for ${props.envelope.kind}:${props.envelope.operation ?? '<none>'}`,\n\t);\n}\n\nexport function assertDerivedControlDeliveryPolicy(props: DeliveryPolicyDerivationProps): void {\n\tconst derivedPolicy = deriveControlDeliveryPolicy(props);\n\tif (props.envelope.deliveryPolicy !== derivedPolicy) {\n\t\tthrow new Error(\n\t\t\t`control delivery policy mismatch: ${props.envelope.deliveryPolicy} !== ${derivedPolicy}`,\n\t\t);\n\t}\n}\n\nexport function coalesceLatestWinsByKey<TMessage>(\n\tmessages: readonly TMessage[],\n\tkeyForMessage: (message: TMessage) => string,\n): readonly TMessage[] {\n\tconst latestByKey = new Map<string, TMessage>();\n\tfor (const message of messages) {\n\t\tlatestByKey.set(keyForMessage(message), message);\n\t}\n\treturn [...latestByKey.values()];\n}\n\nexport function shouldReplayControlEnvelope(envelope: ControlEnvelope): boolean {\n\treturn (\n\t\tenvelope.deliveryPolicy !== 'droppable' &&\n\t\tenvelope.deliveryPolicy !== 'latest_wins' &&\n\t\tenvelope.deliveryPolicy !== 'forbidden_bulk'\n\t);\n}\n\nexport interface ControlSequenceContinuityProps {\n\treadonly envelope: ControlEnvelope;\n\treadonly lastSeenSequence: number;\n}\n\nexport interface ControlEnvelopeSequencedMessage {\n\treadonly envelope: Pick<ControlEnvelope, 'sequence'>;\n}\n\nexport function orderControlMessagesByEnvelopeSequence<\n\tTControlMessage extends ControlEnvelopeSequencedMessage,\n>(messages: readonly TControlMessage[]): readonly TControlMessage[] {\n\treturn messages.toSorted((left, right) => left.envelope.sequence - right.envelope.sequence);\n}\n\nfunction controlSequenceDiagnosticSuffix(envelope: ControlEnvelope): string {\n\treturn ` kind=${envelope.kind} operation=${envelope.operation ?? '<none>'} delivery=${envelope.deliveryPolicy} sessionId=${envelope.sessionId}`;\n}\n\nexport type ControlSequenceContinuityDecision =\n\t| {\n\t\t\treadonly action: 'accept';\n\t\t\treadonly nextLastSeenSequence: number;\n\t }\n\t| {\n\t\t\treadonly action: 'drop';\n\t\t\treadonly nextLastSeenSequence: number;\n\t\t\treadonly safeMessage: string;\n\t }\n\t| {\n\t\t\treadonly action: 'stale';\n\t\t\treadonly closeReason: Extract<ControlSessionCloseReason, 'sequence_gap'>;\n\t\t\treadonly nextLastSeenSequence: number;\n\t\t\treadonly safeMessage: string;\n\t };\n\nexport function evaluateControlSequenceContinuity(\n\tprops: ControlSequenceContinuityProps,\n): ControlSequenceContinuityDecision {\n\tif (props.envelope.sequence <= props.lastSeenSequence) {\n\t\treturn {\n\t\t\taction: 'drop',\n\t\t\tnextLastSeenSequence: props.lastSeenSequence,\n\t\t\tsafeMessage: `control sequence did not advance: last=${String(props.lastSeenSequence)} received=${String(props.envelope.sequence)}${controlSequenceDiagnosticSuffix(props.envelope)}`,\n\t\t};\n\t}\n\tif (\n\t\tprops.envelope.deliveryPolicy === 'droppable' ||\n\t\tprops.envelope.deliveryPolicy === 'latest_wins'\n\t) {\n\t\treturn {\n\t\t\taction: 'accept',\n\t\t\tnextLastSeenSequence: props.lastSeenSequence,\n\t\t};\n\t}\n\tconst expectedSequence = props.lastSeenSequence + 1;\n\tif (props.envelope.sequence === expectedSequence) {\n\t\treturn {\n\t\t\taction: 'accept',\n\t\t\tnextLastSeenSequence: props.envelope.sequence,\n\t\t};\n\t}\n\treturn {\n\t\taction: 'stale',\n\t\tcloseReason: 'sequence_gap',\n\t\tnextLastSeenSequence: props.lastSeenSequence,\n\t\tsafeMessage: `control sequence gap: expected=${String(expectedSequence)} received=${String(props.envelope.sequence)}${controlSequenceDiagnosticSuffix(props.envelope)}`,\n\t};\n}\n\nexport function buildControlProtocolJsonSchemas(): Readonly<Record<string, unknown>> {\n\treturn {\n\t\tclose: z.toJSONSchema(ControlCloseSchema, { io: 'input' }),\n\t\tenvelope: z.toJSONSchema(ControlEnvelopeSchema, { io: 'input' }),\n\t\thandshakeCredential: z.toJSONSchema(ControlHandshakeCredentialSchema, { io: 'input' }),\n\t\thandshakeProof: z.toJSONSchema(ControlHandshakeProofSchema, { io: 'input' }),\n\t\thello: z.toJSONSchema(ControlHelloSchema, { io: 'input' }),\n\t\thelloResponse: z.toJSONSchema(ControlHelloResponseSchema, { io: 'input' }),\n\t\treadyRequestCredential: z.toJSONSchema(ControlReadyRequestCredentialSchema, {\n\t\t\tio: 'input',\n\t\t}),\n\t\treadyRequestProof: z.toJSONSchema(ControlReadyRequestProofSchema, { io: 'input' }),\n\t};\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@agent-vm/control-protocol-contracts",
3
+ "version": "0.0.109",
4
+ "description": "Shared Zod contracts for agent-vm Socket.IO control sessions.",
5
+ "homepage": "https://github.com/ShravanSunder/agent-vm#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/ShravanSunder/agent-vm/issues"
8
+ },
9
+ "license": "MIT",
10
+ "author": "Shravan Sunder <ShravanSunder@users.noreply.github.com>",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/ShravanSunder/agent-vm.git",
14
+ "directory": "packages/control-protocol-contracts"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "type": "module",
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js"
26
+ }
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "dependencies": {
32
+ "zod": "^4.4.3"
33
+ },
34
+ "devDependencies": {
35
+ "vitest": "^4.1.5"
36
+ },
37
+ "scripts": {
38
+ "build": "tsdown",
39
+ "typecheck": "tsc -p tsconfig.json --noEmit",
40
+ "test": "pnpm test:unit",
41
+ "test:unit": "vitest run --root ../../ --config vitest.config.ts --project unit packages/control-protocol-contracts/src"
42
+ }
43
+ }