@agentplat/mesh 0.3.0-beta.2 → 0.3.0-beta.4

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 (95) hide show
  1. package/README.md +133 -4
  2. package/dist/adaptive-overlay-contracts.d.ts +149 -0
  3. package/dist/adaptive-overlay-contracts.d.ts.map +1 -0
  4. package/dist/adaptive-overlay-contracts.js +3 -0
  5. package/dist/adaptive-overlay-contracts.js.map +1 -0
  6. package/dist/adaptive-overlay-runtime.d.ts +67 -0
  7. package/dist/adaptive-overlay-runtime.d.ts.map +1 -0
  8. package/dist/adaptive-overlay-runtime.js +427 -0
  9. package/dist/adaptive-overlay-runtime.js.map +1 -0
  10. package/dist/adaptive-overlay-validation.d.ts +19 -0
  11. package/dist/adaptive-overlay-validation.d.ts.map +1 -0
  12. package/dist/adaptive-overlay-validation.js +326 -0
  13. package/dist/adaptive-overlay-validation.js.map +1 -0
  14. package/dist/adaptive-overlay.d.ts +4 -0
  15. package/dist/adaptive-overlay.d.ts.map +1 -0
  16. package/dist/adaptive-overlay.js +4 -0
  17. package/dist/adaptive-overlay.js.map +1 -0
  18. package/dist/authenticated-overlay-transport.d.ts +227 -0
  19. package/dist/authenticated-overlay-transport.d.ts.map +1 -0
  20. package/dist/authenticated-overlay-transport.js +702 -0
  21. package/dist/authenticated-overlay-transport.js.map +1 -0
  22. package/dist/authority-continuity-contracts.d.ts +249 -0
  23. package/dist/authority-continuity-contracts.d.ts.map +1 -0
  24. package/dist/authority-continuity-contracts.js +11 -0
  25. package/dist/authority-continuity-contracts.js.map +1 -0
  26. package/dist/authority-continuity.d.ts +43 -0
  27. package/dist/authority-continuity.d.ts.map +1 -0
  28. package/dist/authority-continuity.js +1338 -0
  29. package/dist/authority-continuity.js.map +1 -0
  30. package/dist/continuity.d.ts +3 -0
  31. package/dist/continuity.d.ts.map +1 -0
  32. package/dist/continuity.js +3 -0
  33. package/dist/continuity.js.map +1 -0
  34. package/dist/coordination-allocation-contracts.d.ts +6 -0
  35. package/dist/coordination-allocation-contracts.d.ts.map +1 -1
  36. package/dist/coordination-allocation-state.d.ts.map +1 -1
  37. package/dist/coordination-allocation-state.js +37 -7
  38. package/dist/coordination-allocation-state.js.map +1 -1
  39. package/dist/coordination-allocation.d.ts +1 -1
  40. package/dist/coordination-allocation.d.ts.map +1 -1
  41. package/dist/coordination-allocation.js +92 -11
  42. package/dist/coordination-allocation.js.map +1 -1
  43. package/dist/coordination-discovery-state.d.ts.map +1 -1
  44. package/dist/coordination-discovery-state.js +5 -3
  45. package/dist/coordination-discovery-state.js.map +1 -1
  46. package/dist/coordination-recovery.js +5 -1
  47. package/dist/coordination-recovery.js.map +1 -1
  48. package/dist/durability.d.ts +22 -0
  49. package/dist/durability.d.ts.map +1 -1
  50. package/dist/durability.js +22 -0
  51. package/dist/durability.js.map +1 -1
  52. package/dist/overlay-transport.d.ts +7 -0
  53. package/dist/overlay-transport.d.ts.map +1 -0
  54. package/dist/overlay-transport.js +7 -0
  55. package/dist/overlay-transport.js.map +1 -0
  56. package/dist/overlay.d.ts +9 -0
  57. package/dist/overlay.d.ts.map +1 -0
  58. package/dist/overlay.js +9 -0
  59. package/dist/overlay.js.map +1 -0
  60. package/dist/sparse-overlay-contracts.d.ts +91 -0
  61. package/dist/sparse-overlay-contracts.d.ts.map +1 -0
  62. package/dist/sparse-overlay-contracts.js +2 -0
  63. package/dist/sparse-overlay-contracts.js.map +1 -0
  64. package/dist/sparse-overlay-durability.d.ts +23 -0
  65. package/dist/sparse-overlay-durability.d.ts.map +1 -0
  66. package/dist/sparse-overlay-durability.js +97 -0
  67. package/dist/sparse-overlay-durability.js.map +1 -0
  68. package/dist/sparse-overlay-runtime-contracts.d.ts +158 -0
  69. package/dist/sparse-overlay-runtime-contracts.d.ts.map +1 -0
  70. package/dist/sparse-overlay-runtime-contracts.js +2 -0
  71. package/dist/sparse-overlay-runtime-contracts.js.map +1 -0
  72. package/dist/sparse-overlay-runtime.d.ts +48 -0
  73. package/dist/sparse-overlay-runtime.d.ts.map +1 -0
  74. package/dist/sparse-overlay-runtime.js +763 -0
  75. package/dist/sparse-overlay-runtime.js.map +1 -0
  76. package/dist/sparse-overlay-transport-contracts.d.ts +183 -0
  77. package/dist/sparse-overlay-transport-contracts.d.ts.map +1 -0
  78. package/dist/sparse-overlay-transport-contracts.js +2 -0
  79. package/dist/sparse-overlay-transport-contracts.js.map +1 -0
  80. package/dist/sparse-overlay-transport-durability.d.ts +19 -0
  81. package/dist/sparse-overlay-transport-durability.d.ts.map +1 -0
  82. package/dist/sparse-overlay-transport-durability.js +91 -0
  83. package/dist/sparse-overlay-transport-durability.js.map +1 -0
  84. package/dist/sparse-overlay-transport.d.ts +97 -0
  85. package/dist/sparse-overlay-transport.d.ts.map +1 -0
  86. package/dist/sparse-overlay-transport.js +888 -0
  87. package/dist/sparse-overlay-transport.js.map +1 -0
  88. package/dist/sparse-overlay.d.ts +74 -0
  89. package/dist/sparse-overlay.d.ts.map +1 -0
  90. package/dist/sparse-overlay.js +817 -0
  91. package/dist/sparse-overlay.js.map +1 -0
  92. package/fixtures/beta1/manifest.json +4 -4
  93. package/fixtures/beta1/states/discovery-v1.json +3 -3
  94. package/fixtures/beta1/states/discovery-v2.json +3 -3
  95. package/package.json +20 -4
@@ -1,6 +1,6 @@
1
1
  import type { MeshAllocationBidSelection, MeshAllocationCommand, MeshAllocationDecision, MeshAllocationRuntimeState, MeshAllocationSelectionInput, MeshAllocationTimerDecision, MeshAllocationTimerInput, MeshVerifiedAllocationRequest } from "./coordination-allocation-contracts.js";
2
2
  /** Commits a prepared local offer or award; signing and delivery stay outside. */
3
- export declare function evaluateMeshAllocationCommand(state: MeshAllocationRuntimeState, command: MeshAllocationCommand, verifiedAt: string, receivedAt: number): MeshAllocationDecision;
3
+ export declare function evaluateMeshAllocationCommand(state: MeshAllocationRuntimeState, command: MeshAllocationCommand, verifiedAt: string, receivedAt: number, supportedCriticalExtensions?: readonly string[], eligibleRecipientPeerIds?: readonly string[]): MeshAllocationDecision;
4
4
  /** Evaluates a verified direct bid at the local offer owner. */
5
5
  export declare function evaluateVerifiedMeshAllocationEnvelope(state: MeshAllocationRuntimeState, request: MeshVerifiedAllocationRequest): MeshAllocationDecision;
6
6
  /** Selects a currently valid bid deterministically while the window is open. */
@@ -1 +1 @@
1
- {"version":3,"file":"coordination-allocation.d.ts","sourceRoot":"","sources":["../src/coordination-allocation.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAIV,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EAGtB,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,EAC3B,wBAAwB,EASxB,6BAA6B,EAE9B,MAAM,wCAAwC,CAAC;AAsChD,kFAAkF;AAClF,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,0BAA0B,EACjC,OAAO,EAAE,qBAAqB,EAC9B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAmVxB;AA2gCD,gEAAgE;AAChE,wBAAgB,sCAAsC,CACpD,KAAK,EAAE,0BAA0B,EACjC,OAAO,EAAE,6BAA6B,GACrC,sBAAsB,CA6PxB;AA03BD,gFAAgF;AAChF,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,0BAA0B,EACjC,KAAK,EAAE,4BAA4B,GAClC,0BAA0B,CA2E5B;AAED,6DAA6D;AAC7D,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,0BAA0B,EACjC,KAAK,EAAE,wBAAwB,EAC/B,WAAW,EAAE,MAAM,GAClB,2BAA2B,CAqJ7B"}
1
+ {"version":3,"file":"coordination-allocation.d.ts","sourceRoot":"","sources":["../src/coordination-allocation.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAIV,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EAGtB,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,EAC3B,wBAAwB,EASxB,6BAA6B,EAE9B,MAAM,wCAAwC,CAAC;AAsChD,kFAAkF;AAClF,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,0BAA0B,EACjC,OAAO,EAAE,qBAAqB,EAC9B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,2BAA2B,GAAE,SAAS,MAAM,EAAO,EACnD,wBAAwB,CAAC,EAAE,SAAS,MAAM,EAAE,GAC3C,sBAAsB,CAkWxB;AAghCD,gEAAgE;AAChE,wBAAgB,sCAAsC,CACpD,KAAK,EAAE,0BAA0B,EACjC,OAAO,EAAE,6BAA6B,GACrC,sBAAsB,CA6PxB;AA03BD,gFAAgF;AAChF,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,0BAA0B,EACjC,KAAK,EAAE,4BAA4B,GAClC,0BAA0B,CAwF5B;AAED,6DAA6D;AAC7D,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,0BAA0B,EACjC,KAAK,EAAE,wBAAwB,EAC/B,WAAW,EAAE,MAAM,GAClB,2BAA2B,CAqJ7B"}
@@ -1,4 +1,4 @@
1
- import { canonicalizeMeshPayload, compareMeshTimestamps, validateMeshEnvelopeContext, validateSignedMeshEnvelope, } from "@agentplat/mesh-protocol";
1
+ import { DEFAULT_MESH_PROTOCOL_LIMITS, canonicalizeMeshPayload, compareMeshTimestamps, validateMeshEnvelopeContext, validateSignedMeshEnvelope, } from "@agentplat/mesh-protocol";
2
2
  import { createMeshAllocationRuntimeState, meshAllocationRetainsMessageId, meshAssignmentFenceKey, restoreMeshAllocationState, } from "./coordination-allocation-state.js";
3
3
  import { matchMeshDiscoveryCapabilities } from "./coordination-discovery.js";
4
4
  import { evaluateMeshExecutionCommand, evaluateVerifiedMeshExecutionEnvelope, } from "./coordination-execution.js";
@@ -10,8 +10,10 @@ import { sha256Base64Url } from "./sha256.js";
10
10
  import { assertMeshLogicalTime, createFrozenRecord, recordEntries, } from "./state.js";
11
11
  const utf8Encoder = new TextEncoder();
12
12
  /** Commits a prepared local offer or award; signing and delivery stay outside. */
13
- export function evaluateMeshAllocationCommand(state, command, verifiedAt, receivedAt) {
13
+ export function evaluateMeshAllocationCommand(state, command, verifiedAt, receivedAt, supportedCriticalExtensions = [], eligibleRecipientPeerIds) {
14
14
  assertRuntime(state, receivedAt);
15
+ assertSupportedCriticalExtensions(supportedCriticalExtensions);
16
+ assertEligibleRecipientPeerIds(eligibleRecipientPeerIds, state.allocation.limits.maximumRecipientsPerOffer, supportedCriticalExtensions.length > 0);
15
17
  if (!command ||
16
18
  ![
17
19
  "allocation.offer",
@@ -81,7 +83,7 @@ export function evaluateMeshAllocationCommand(state, command, verifiedAt, receiv
81
83
  .filter((offer) => offer.objectiveId === work.objectiveId &&
82
84
  offer.work.workItemId === work.workItemId)
83
85
  .sort((a, b) => a.offerAttempt - b.offerAttempt);
84
- const prepared = validatePrepared(command.recipients, state, work, verifiedAt, receivedAt, priorOffers.at(-1));
86
+ const prepared = validatePrepared(command.recipients, state, work, verifiedAt, receivedAt, priorOffers.at(-1), supportedCriticalExtensions, eligibleRecipientPeerIds);
85
87
  if ("code" in prepared)
86
88
  return reject(state, prepared.code);
87
89
  const { payload, entries, bidDeadlineAt } = prepared;
@@ -155,6 +157,13 @@ export function evaluateMeshAllocationCommand(state, command, verifiedAt, receiv
155
157
  bidDeadlineTimerGeneration: generation,
156
158
  createdAt: receivedAt,
157
159
  validityVerifiedAt: verifiedAt,
160
+ ...(supportedCriticalExtensions.length === 0
161
+ ? {}
162
+ : {
163
+ supportedCriticalExtensions: Object.freeze([
164
+ ...supportedCriticalExtensions,
165
+ ]),
166
+ }),
158
167
  reservationId,
159
168
  recipientOffers: createFrozenRecord(entries.map(({ recipientPeerId, preparedAt, envelope }) => [
160
169
  recipientPeerId,
@@ -275,8 +284,10 @@ export function evaluateMeshAllocationCommand(state, command, verifiedAt, receiv
275
284
  });
276
285
  }
277
286
  function evaluateAwardCommand(state, command, verifiedAt, receivedAt) {
278
- if (Object.keys(command).sort().join(",") !==
279
- "bidId,bidRevision,kind,offerId,recipient" ||
287
+ const commandKeys = Object.keys(command).sort().join(",");
288
+ if ((commandKeys !== "bidId,bidRevision,kind,offerId,recipient" &&
289
+ commandKeys !==
290
+ "bidId,bidRevision,excludedBidderPeerIds,kind,offerId,recipient") ||
280
291
  !command.recipient ||
281
292
  Object.keys(command.recipient).sort().join(",") !==
282
293
  "envelope,preparedAt,recipientPeerId")
@@ -292,6 +303,9 @@ function evaluateAwardCommand(state, command, verifiedAt, receivedAt) {
292
303
  const selected = selectMeshAllocationBid(state, {
293
304
  offerId: offer.offerId,
294
305
  evaluatedAt: receivedAt,
306
+ ...(command.excludedBidderPeerIds === undefined
307
+ ? {}
308
+ : { excludedBidderPeerIds: command.excludedBidderPeerIds }),
295
309
  });
296
310
  if (selected.reason !== "selected" ||
297
311
  !selected.bid ||
@@ -1942,12 +1956,21 @@ function isWitnessCopy(state, request) {
1942
1956
  }
1943
1957
  /** Selects a currently valid bid deterministically while the window is open. */
1944
1958
  export function selectMeshAllocationBid(state, input) {
1959
+ const inputKeys = input && typeof input === "object"
1960
+ ? Object.keys(input).sort().join(",")
1961
+ : "";
1962
+ const excludedBidderPeerIds = input?.excludedBidderPeerIds ?? [];
1945
1963
  if (!input ||
1946
1964
  typeof input !== "object" ||
1947
- Object.keys(input).sort().join(",") !== "evaluatedAt,offerId" ||
1965
+ (inputKeys !== "evaluatedAt,offerId" &&
1966
+ inputKeys !== "evaluatedAt,excludedBidderPeerIds,offerId") ||
1948
1967
  typeof input.offerId !== "string" ||
1949
1968
  !Number.isSafeInteger(input.evaluatedAt) ||
1950
- input.evaluatedAt < 0)
1969
+ input.evaluatedAt < 0 ||
1970
+ !Array.isArray(excludedBidderPeerIds) ||
1971
+ excludedBidderPeerIds.length > 256 ||
1972
+ new Set(excludedBidderPeerIds).size !== excludedBidderPeerIds.length ||
1973
+ excludedBidderPeerIds.some((peerId) => typeof peerId !== "string" || peerId.length === 0))
1951
1974
  throw new TypeError("Invalid Mesh allocation selection input");
1952
1975
  assertRuntime(state, input.evaluatedAt);
1953
1976
  const offer = state.allocation.localOffers[input.offerId];
@@ -1976,6 +1999,8 @@ export function selectMeshAllocationBid(state, input) {
1976
1999
  const eligible = Object.values(state.allocation.bidHeads).filter((bid) => {
1977
2000
  if (bid.offerId !== input.offerId)
1978
2001
  return false;
2002
+ if (excludedBidderPeerIds.includes(bid.bidderPeerId))
2003
+ return false;
1979
2004
  const evidence = state.allocation.acceptedBidEvidence[bid.bidId];
1980
2005
  if (!evidence)
1981
2006
  return false;
@@ -2317,7 +2342,7 @@ function evaluateAcceptanceDeadline(state, timer, logicalTime) {
2317
2342
  state: createMeshAllocationRuntimeState(coordination, Object.freeze({ ...state.discovery, lastLogicalTime: logicalTime }), objectives, allocation),
2318
2343
  });
2319
2344
  }
2320
- function validatePrepared(recipients, state, work, verifiedAt, receivedAt, previousOffer) {
2345
+ function validatePrepared(recipients, state, work, verifiedAt, receivedAt, previousOffer, supportedCriticalExtensions = [], eligibleRecipientPeerIds) {
2321
2346
  if (!Array.isArray(recipients) ||
2322
2347
  !recipients.length ||
2323
2348
  recipients.length > state.allocation.limits.maximumRecipientsPerOffer)
@@ -2327,6 +2352,13 @@ function validatePrepared(recipients, state, work, verifiedAt, receivedAt, previ
2327
2352
  if (!parsed?.ok || parsed.value.payload.type !== "work.offer")
2328
2353
  return { code: "offer_invalid" };
2329
2354
  const payload = parsed.value.payload;
2355
+ const firstEnvelope = parsed.value;
2356
+ const priorEnvelope = previousOffer
2357
+ ? Object.values(previousOffer.recipientOffers)[0]?.envelope
2358
+ : undefined;
2359
+ if (priorEnvelope !== undefined &&
2360
+ !preservesCriticalSemantics(firstEnvelope, priorEnvelope))
2361
+ return { code: "offer_invalid" };
2330
2362
  const bidDeadlineAt = logicalDeadline(payload.bidDeadline, verifiedAt, receivedAt);
2331
2363
  if (bidDeadlineAt === undefined)
2332
2364
  return { code: "offer_invalid" };
@@ -2335,10 +2367,15 @@ function validatePrepared(recipients, state, work, verifiedAt, receivedAt, previ
2335
2367
  attributes: work.matchingAttributes,
2336
2368
  fanout: Math.min(state.allocation.limits.maximumRecipientsPerOffer, state.discovery.limits.maximumFanout),
2337
2369
  }, receivedAt).matches.map((match) => match.peerId);
2370
+ const constrainedMatches = eligibleRecipientPeerIds === undefined
2371
+ ? matches
2372
+ : matches.filter((peerId) => eligibleRecipientPeerIds.includes(peerId));
2338
2373
  const ids = recipients.map((item) => item.recipientPeerId);
2339
- if (new Set(ids).size !== ids.length ||
2340
- ids.length !== matches.length ||
2341
- ids.some((id, index) => id !== matches[index]))
2374
+ if ((eligibleRecipientPeerIds !== undefined &&
2375
+ eligibleRecipientPeerIds.some((peerId) => !matches.includes(peerId))) ||
2376
+ new Set(ids).size !== ids.length ||
2377
+ ids.length !== constrainedMatches.length ||
2378
+ ids.some((id, index) => id !== constrainedMatches[index]))
2342
2379
  return { code: "offer_invalid" };
2343
2380
  const entries = [];
2344
2381
  const retainedMessageIds = new Set([
@@ -2353,6 +2390,7 @@ function validatePrepared(recipients, state, work, verifiedAt, receivedAt, previ
2353
2390
  meshId: state.allocation.identity.meshId,
2354
2391
  peerId: item.recipientPeerId,
2355
2392
  receivedAt: verifiedAt,
2393
+ supportedCriticalExtensions,
2356
2394
  });
2357
2395
  if (!result.ok ||
2358
2396
  result.value.payload.type !== "work.offer" ||
@@ -2367,6 +2405,7 @@ function validatePrepared(recipients, state, work, verifiedAt, receivedAt, previ
2367
2405
  : result.value.causationId !==
2368
2406
  previousOffer?.recipientOffers[item.recipientPeerId]?.messageId) ||
2369
2407
  !samePayload(result.value.payload, payload) ||
2408
+ !sameCriticalSemantics(result.value, firstEnvelope) ||
2370
2409
  !canonicalDigest(result.value))
2371
2410
  return { code: "offer_invalid" };
2372
2411
  if (retainedMessageIds.has(result.value.messageId) ||
@@ -2381,6 +2420,48 @@ function validatePrepared(recipients, state, work, verifiedAt, receivedAt, previ
2381
2420
  }
2382
2421
  return { payload, entries: Object.freeze(entries), bidDeadlineAt };
2383
2422
  }
2423
+ function assertSupportedCriticalExtensions(value) {
2424
+ const descriptors = Array.isArray(value)
2425
+ ? Object.getOwnPropertyDescriptors(value)
2426
+ : undefined;
2427
+ if (!Array.isArray(value) ||
2428
+ value.length > DEFAULT_MESH_PROTOCOL_LIMITS.maximumCriticalExtensions ||
2429
+ Reflect.ownKeys(value).length !== value.length + 1 ||
2430
+ Object.values(descriptors ?? {}).some((descriptor) => "get" in descriptor || "set" in descriptor))
2431
+ throw new TypeError("Invalid Mesh supported critical extensions");
2432
+ const seen = new Set();
2433
+ for (let index = 0; index < value.length; index += 1) {
2434
+ if (!Object.prototype.hasOwnProperty.call(value, index))
2435
+ throw new TypeError("Invalid Mesh supported critical extensions");
2436
+ const extension = value[index];
2437
+ if (typeof extension !== "string" ||
2438
+ extension.length < 1 ||
2439
+ seen.has(extension))
2440
+ throw new TypeError("Invalid Mesh supported critical extensions");
2441
+ seen.add(extension);
2442
+ }
2443
+ }
2444
+ function assertEligibleRecipientPeerIds(value, maximumRecipients, criticalExtensionEnabled) {
2445
+ if (value === undefined)
2446
+ return;
2447
+ if (!criticalExtensionEnabled ||
2448
+ !Array.isArray(value) ||
2449
+ value.length < 1 ||
2450
+ value.length > maximumRecipients ||
2451
+ new Set(value).size !== value.length ||
2452
+ value.some((peerId) => typeof peerId !== "string" || peerId.length < 1))
2453
+ throw new TypeError("Invalid Mesh eligible recipient peer IDs");
2454
+ }
2455
+ function sameCriticalSemantics(left, right) {
2456
+ if (!sameData(left.criticalExtensions ?? [], right.criticalExtensions ?? []))
2457
+ return false;
2458
+ return (left.criticalExtensions ?? []).every((key) => sameData(left.extensions?.[key], right.extensions?.[key]));
2459
+ }
2460
+ function preservesCriticalSemantics(current, previous) {
2461
+ const currentCritical = new Set(current.criticalExtensions ?? []);
2462
+ return (previous.criticalExtensions ?? []).every((key) => currentCritical.has(key) &&
2463
+ sameData(current.extensions?.[key], previous.extensions?.[key]));
2464
+ }
2384
2465
  function validateContext(state, request) {
2385
2466
  if (!request ||
2386
2467
  typeof request !== "object" ||