agent-embassy 1.2.0 → 1.3.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 (91) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/CONTRIBUTING.md +25 -7
  3. package/README.md +20 -12
  4. package/README.zh-CN.md +14 -13
  5. package/SECURITY.md +55 -41
  6. package/dist/src/gateway/claude-helper-supervisor.js +0 -1
  7. package/dist/src/gateway/claude-helper-supervisor.js.map +1 -1
  8. package/dist/src/gateway/claude-runtime.d.ts +0 -2
  9. package/dist/src/gateway/claude-runtime.js +6 -17
  10. package/dist/src/gateway/claude-runtime.js.map +1 -1
  11. package/dist/src/gateway/cli-copy.d.ts +1 -1
  12. package/dist/src/gateway/cli-copy.en.d.ts +3 -1
  13. package/dist/src/gateway/cli-copy.en.js +5 -3
  14. package/dist/src/gateway/cli-copy.en.js.map +1 -1
  15. package/dist/src/gateway/cli-copy.js +2 -0
  16. package/dist/src/gateway/cli-copy.js.map +1 -1
  17. package/dist/src/gateway/cli-copy.zh-CN.d.ts +3 -1
  18. package/dist/src/gateway/cli-copy.zh-CN.js +5 -3
  19. package/dist/src/gateway/cli-copy.zh-CN.js.map +1 -1
  20. package/dist/src/gateway/cli.d.ts +2 -5
  21. package/dist/src/gateway/cli.js +30 -67
  22. package/dist/src/gateway/cli.js.map +1 -1
  23. package/dist/src/gateway/codex-app-server.d.ts +1 -7
  24. package/dist/src/gateway/codex-app-server.js +5 -52
  25. package/dist/src/gateway/codex-app-server.js.map +1 -1
  26. package/dist/src/gateway/codex-local-transport.d.ts +4 -10
  27. package/dist/src/gateway/codex-local-transport.js +13 -16
  28. package/dist/src/gateway/codex-local-transport.js.map +1 -1
  29. package/dist/src/gateway/compatibility.d.ts +0 -27
  30. package/dist/src/gateway/compatibility.js +1 -101
  31. package/dist/src/gateway/compatibility.js.map +1 -1
  32. package/dist/src/gateway/config.d.ts +0 -3
  33. package/dist/src/gateway/config.js +0 -10
  34. package/dist/src/gateway/config.js.map +1 -1
  35. package/dist/src/gateway/control.d.ts +1 -20
  36. package/dist/src/gateway/control.js +2 -33
  37. package/dist/src/gateway/control.js.map +1 -1
  38. package/dist/src/gateway/dashboard-copy.d.ts +1 -1
  39. package/dist/src/gateway/dashboard-copy.en.d.ts +6 -7
  40. package/dist/src/gateway/dashboard-copy.en.js +15 -16
  41. package/dist/src/gateway/dashboard-copy.en.js.map +1 -1
  42. package/dist/src/gateway/dashboard-copy.js +6 -7
  43. package/dist/src/gateway/dashboard-copy.js.map +1 -1
  44. package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +6 -7
  45. package/dist/src/gateway/dashboard-copy.zh-CN.js +15 -16
  46. package/dist/src/gateway/dashboard-copy.zh-CN.js.map +1 -1
  47. package/dist/src/gateway/dashboard-model.d.ts +3 -7
  48. package/dist/src/gateway/dashboard-model.js +41 -16
  49. package/dist/src/gateway/dashboard-model.js.map +1 -1
  50. package/dist/src/gateway/dashboard.js +5 -7
  51. package/dist/src/gateway/dashboard.js.map +1 -1
  52. package/dist/src/gateway/live-dashboard-app/app.js +17 -45
  53. package/dist/src/gateway/live-dashboard-command.d.ts +5 -1
  54. package/dist/src/gateway/live-dashboard-command.js +8 -6
  55. package/dist/src/gateway/live-dashboard-command.js.map +1 -1
  56. package/dist/src/gateway/live-dashboard-http.d.ts +0 -4
  57. package/dist/src/gateway/live-dashboard-http.js +19 -93
  58. package/dist/src/gateway/live-dashboard-http.js.map +1 -1
  59. package/dist/src/gateway/live-dashboard-protocol.d.ts +1 -5
  60. package/dist/src/gateway/live-dashboard-protocol.js +0 -42
  61. package/dist/src/gateway/live-dashboard-protocol.js.map +1 -1
  62. package/dist/src/gateway/live-dashboard-server.d.ts +2 -2
  63. package/dist/src/gateway/live-dashboard-server.js +18 -4
  64. package/dist/src/gateway/live-dashboard-server.js.map +1 -1
  65. package/dist/src/gateway/live-dashboard.d.ts +3 -6
  66. package/dist/src/gateway/live-dashboard.js +6 -42
  67. package/dist/src/gateway/live-dashboard.js.map +1 -1
  68. package/dist/src/gateway/provenance-envelope.js +1 -1
  69. package/dist/src/gateway/provenance-envelope.js.map +1 -1
  70. package/dist/src/gateway/providers.d.ts +1 -21
  71. package/dist/src/gateway/providers.js +15 -261
  72. package/dist/src/gateway/providers.js.map +1 -1
  73. package/dist/src/gateway/server.js +0 -3
  74. package/dist/src/gateway/server.js.map +1 -1
  75. package/dist/src/gateway/service.d.ts +3 -15
  76. package/dist/src/gateway/service.js +76 -257
  77. package/dist/src/gateway/service.js.map +1 -1
  78. package/dist/src/gateway/store.js +76 -18
  79. package/dist/src/gateway/store.js.map +1 -1
  80. package/dist/src/gateway/types.d.ts +0 -4
  81. package/dist/src/gateway/types.js.map +1 -1
  82. package/docs/GATEWAY-ARCHITECTURE.md +75 -63
  83. package/package.json +1 -1
  84. package/skills/embassy-peer/SKILL.md +25 -10
  85. package/dist/src/gateway/claude-compatibility-scratch.d.ts +0 -18
  86. package/dist/src/gateway/claude-compatibility-scratch.js +0 -158
  87. package/dist/src/gateway/claude-compatibility-scratch.js.map +0 -1
  88. package/dist/src/gateway/live-dashboard-bootstrap.d.ts +0 -36
  89. package/dist/src/gateway/live-dashboard-bootstrap.js +0 -176
  90. package/dist/src/gateway/live-dashboard-bootstrap.js.map +0 -1
  91. package/docs/DESIGN.md +0 -134
@@ -392,7 +392,6 @@ function isQueuedMetadata(value) {
392
392
  "enqueuedAt",
393
393
  "deadlineAt",
394
394
  "bytes",
395
- "hopCount",
396
395
  ], ["conversationIdSuffix", "body", "pair", "transientTarget", "steer"])) {
397
396
  return false;
398
397
  }
@@ -417,7 +416,6 @@ function isQueuedMetadata(value) {
417
416
  value.body.length > 0 &&
418
417
  !value.body.includes("\u0000") &&
419
418
  Buffer.byteLength(value.body, "utf8") === value.bytes)) &&
420
- isNonNegativeInteger(value.hopCount) &&
421
419
  (value.pair === undefined || value.pair === true) &&
422
420
  (value.transientTarget === undefined || value.transientTarget === true) &&
423
421
  (value.steer === undefined || value.steer === true));
@@ -439,7 +437,6 @@ function isEvent(value) {
439
437
  "targetAlias",
440
438
  "state",
441
439
  "bytes",
442
- "hopCount",
443
440
  ], ["conversationIdSuffix", "body", "latencyMs", "safeErrorCode", "steer"])) {
444
441
  return false;
445
442
  }
@@ -464,7 +461,6 @@ function isEvent(value) {
464
461
  value.body.length > 0 &&
465
462
  !value.body.includes("\u0000") &&
466
463
  Buffer.byteLength(value.body, "utf8") === value.bytes)) &&
467
- isNonNegativeInteger(value.hopCount) &&
468
464
  (value.latencyMs === undefined || isNonNegativeInteger(value.latencyMs)) &&
469
465
  (value.safeErrorCode === undefined || isSafeCode(value.safeErrorCode)) &&
470
466
  (value.steer === undefined || value.steer === true));
@@ -717,6 +713,80 @@ function migratePreCodexOrphanRemovalJournal(value) {
717
713
  codexOrphanRemovalEvents: [],
718
714
  };
719
715
  }
716
+ /**
717
+ * v1.2.0 persisted hop counters on queue, in-flight, and event rows. Hop
718
+ * policy no longer exists; accept only the old bounded shape and discard the
719
+ * obsolete field before strict current-schema validation and persistence.
720
+ */
721
+ function migrateLegacyHopCounts(value) {
722
+ if (!isObject(value) ||
723
+ value.schemaVersion !== 1 ||
724
+ !Array.isArray(value.queue) ||
725
+ !Array.isArray(value.inFlight) ||
726
+ !Array.isArray(value.events)) {
727
+ return value;
728
+ }
729
+ const strip = (entry) => {
730
+ if (!isObject(entry) || !Object.hasOwn(entry, "hopCount"))
731
+ return entry;
732
+ if (!isNonNegativeInteger(entry.hopCount) || entry.hopCount > 64) {
733
+ return entry;
734
+ }
735
+ const { hopCount: _legacyHopCount, ...current } = entry;
736
+ return current;
737
+ };
738
+ return {
739
+ ...value,
740
+ queue: value.queue.map(strip),
741
+ inFlight: value.inFlight.map(strip),
742
+ events: value.events.map(strip),
743
+ };
744
+ }
745
+ function isLegacyCompatibilityCertification(value) {
746
+ if (!isObject(value))
747
+ return false;
748
+ const required = ["depth", "outcome", "certifiedAt"];
749
+ if (!hasOnlyKeys(value, required, ["safeErrorCode"]))
750
+ return false;
751
+ if ((value.depth !== "wire" &&
752
+ value.depth !== "thread_ops" &&
753
+ value.depth !== "turn") ||
754
+ (value.outcome !== "pass" && value.outcome !== "fail") ||
755
+ !isIsoTimestamp(value.certifiedAt) ||
756
+ new Date(Date.parse(value.certifiedAt)).toISOString() !==
757
+ value.certifiedAt ||
758
+ (value.safeErrorCode !== undefined && !isSafeCode(value.safeErrorCode))) {
759
+ return false;
760
+ }
761
+ return (value.outcome === "pass") === (value.safeErrorCode === undefined);
762
+ }
763
+ /**
764
+ * v1.1-v1.2 compatibility rows could contain manual live-certification
765
+ * evidence. The ceremony is gone: accept only its exact old shape, discard
766
+ * it, and retain the automatic bounded probe evidence.
767
+ */
768
+ function migrateLegacyCompatibilityCertifications(value) {
769
+ if (!isObject(value) ||
770
+ value.schemaVersion !== 1 ||
771
+ !Array.isArray(value.compatibilityAttestations)) {
772
+ return value;
773
+ }
774
+ let changed = false;
775
+ const compatibilityAttestations = value.compatibilityAttestations.map((entry) => {
776
+ if (!isObject(entry) || !Object.hasOwn(entry, "certification")) {
777
+ return entry;
778
+ }
779
+ if (!isLegacyCompatibilityCertification(entry.certification)) {
780
+ return entry;
781
+ }
782
+ const { certification: _legacyCertification, ...current } = entry;
783
+ if (!isCompatibilityAttestation(current))
784
+ return entry;
785
+ changed = true;
786
+ return current;
787
+ });
788
+ return changed ? { ...value, compatibilityAttestations } : value;
789
+ }
720
790
  function isPersistedState(value) {
721
791
  if (!isObject(value) ||
722
792
  !hasOnlyKeys(value, [
@@ -2735,7 +2805,6 @@ export class GatewayStore {
2735
2805
  state: "dispatching",
2736
2806
  bytes: metadata.bytes,
2737
2807
  body,
2738
- hopCount: metadata.hopCount,
2739
2808
  ...(metadata.steer === true ? { steer: true } : {}),
2740
2809
  latencyMs: Math.max(0, now.getTime() - Date.parse(metadata.enqueuedAt)),
2741
2810
  });
@@ -2864,7 +2933,6 @@ export class GatewayStore {
2864
2933
  state: "held",
2865
2934
  bytes: metadata.bytes,
2866
2935
  body,
2867
- hopCount: metadata.hopCount,
2868
2936
  ...(metadata.steer === true ? { steer: true } : {}),
2869
2937
  ...(safeErrorCode === undefined ? {} : { safeErrorCode }),
2870
2938
  latencyMs: Math.max(0, now.getTime() - Date.parse(metadata.enqueuedAt)),
@@ -2896,7 +2964,6 @@ export class GatewayStore {
2896
2964
  state: progress,
2897
2965
  bytes: metadata.bytes,
2898
2966
  ...(metadata.body === undefined ? {} : { body: metadata.body }),
2899
- hopCount: metadata.hopCount,
2900
2967
  ...(metadata.steer === true ? { steer: true } : {}),
2901
2968
  latencyMs: Math.max(0, now.getTime() - Date.parse(metadata.enqueuedAt)),
2902
2969
  });
@@ -3443,12 +3510,6 @@ export class GatewayStore {
3443
3510
  this.recordRejection(state, sides, bytes, now, "MESSAGE_TOO_LARGE", input.steer, input.conversationIdSuffix);
3444
3511
  throw new BridgeError("MESSAGE_TOO_LARGE", "The transient message exceeds the configured byte limit.");
3445
3512
  }
3446
- const hopCount = input.hopCount ?? 0;
3447
- if (!isNonNegativeInteger(hopCount) ||
3448
- hopCount > this.config.limits.maxHopCount) {
3449
- this.recordRejection(state, sides, bytes, now, "HOP_LIMIT_EXCEEDED", input.steer, input.conversationIdSuffix);
3450
- throw new BridgeError("HOP_LIMIT_EXCEEDED", "The message exceeds the configured gateway hop limit.");
3451
- }
3452
3513
  if (typeof input.dedupeKey !== "string" ||
3453
3514
  input.dedupeKey.length === 0 ||
3454
3515
  Buffer.byteLength(input.dedupeKey) > 512) {
@@ -3476,7 +3537,6 @@ export class GatewayStore {
3476
3537
  ? {}
3477
3538
  : { conversationIdSuffix: duplicate.conversationIdSuffix }),
3478
3539
  bytes,
3479
- hopCount,
3480
3540
  ...(input.steer === true ? { steer: true } : {}),
3481
3541
  });
3482
3542
  return {
@@ -3566,7 +3626,6 @@ export class GatewayStore {
3566
3626
  deadlineAt: deadline.toISOString(),
3567
3627
  bytes,
3568
3628
  body: input.body,
3569
- hopCount,
3570
3629
  ...(sides.pair === true ? { pair: true } : {}),
3571
3630
  ...(sides.transientTarget === true
3572
3631
  ? { transientTarget: true }
@@ -3618,7 +3677,6 @@ export class GatewayStore {
3618
3677
  state: "queued",
3619
3678
  bytes,
3620
3679
  body: input.body,
3621
- hopCount,
3622
3680
  ...(input.steer === true ? { steer: true } : {}),
3623
3681
  });
3624
3682
  return {
@@ -3684,7 +3742,6 @@ export class GatewayStore {
3684
3742
  targetAlias: sides.targetAlias,
3685
3743
  state: "rejected",
3686
3744
  bytes: Math.max(1, bytes),
3687
- hopCount: 0,
3688
3745
  safeErrorCode,
3689
3746
  ...(steer === true ? { steer: true } : {}),
3690
3747
  });
@@ -3966,7 +4023,6 @@ export class GatewayStore {
3966
4023
  state: deliveryState,
3967
4024
  bytes: metadata.bytes,
3968
4025
  ...(metadata.body === undefined ? {} : { body: metadata.body }),
3969
- hopCount: metadata.hopCount,
3970
4026
  ...(metadata.steer === true ? { steer: true } : {}),
3971
4027
  latencyMs: Math.max(0, now.getTime() - Date.parse(metadata.enqueuedAt)),
3972
4028
  ...(safeErrorCode ? { safeErrorCode } : {}),
@@ -4444,6 +4500,8 @@ export class GatewayStore {
4444
4500
  parsed = migratePreCompatibilityAttestations(parsed);
4445
4501
  parsed = migratePreCodexEndpointRefreshJournal(parsed);
4446
4502
  parsed = migratePreCodexOrphanRemovalJournal(parsed);
4503
+ parsed = migrateLegacyHopCounts(parsed);
4504
+ parsed = migrateLegacyCompatibilityCertifications(parsed);
4447
4505
  if (!isPersistedState(parsed)) {
4448
4506
  throw new BridgeError("CORRUPT_GATEWAY_STATE", "The gateway controller state failed strict schema validation.");
4449
4507
  }