@clawcrony/claw-crony 1.0.1

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 (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +82 -0
  3. package/dist/index.d.ts +17 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +720 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/agent-card.d.ts +4 -0
  8. package/dist/src/agent-card.d.ts.map +1 -0
  9. package/dist/src/agent-card.js +61 -0
  10. package/dist/src/agent-card.js.map +1 -0
  11. package/dist/src/audit.d.ts +36 -0
  12. package/dist/src/audit.d.ts.map +1 -0
  13. package/dist/src/audit.js +88 -0
  14. package/dist/src/audit.js.map +1 -0
  15. package/dist/src/client.d.ts +53 -0
  16. package/dist/src/client.d.ts.map +1 -0
  17. package/dist/src/client.js +322 -0
  18. package/dist/src/client.js.map +1 -0
  19. package/dist/src/executor.d.ts +34 -0
  20. package/dist/src/executor.d.ts.map +1 -0
  21. package/dist/src/executor.js +994 -0
  22. package/dist/src/executor.js.map +1 -0
  23. package/dist/src/file-security.d.ts +63 -0
  24. package/dist/src/file-security.d.ts.map +1 -0
  25. package/dist/src/file-security.js +350 -0
  26. package/dist/src/file-security.js.map +1 -0
  27. package/dist/src/hub-match.d.ts +73 -0
  28. package/dist/src/hub-match.d.ts.map +1 -0
  29. package/dist/src/hub-match.js +120 -0
  30. package/dist/src/hub-match.js.map +1 -0
  31. package/dist/src/hub-registration.d.ts +24 -0
  32. package/dist/src/hub-registration.d.ts.map +1 -0
  33. package/dist/src/hub-registration.js +242 -0
  34. package/dist/src/hub-registration.js.map +1 -0
  35. package/dist/src/internal/envelope.d.ts +33 -0
  36. package/dist/src/internal/envelope.d.ts.map +1 -0
  37. package/dist/src/internal/envelope.js +152 -0
  38. package/dist/src/internal/envelope.js.map +1 -0
  39. package/dist/src/internal/idempotency.d.ts +48 -0
  40. package/dist/src/internal/idempotency.d.ts.map +1 -0
  41. package/dist/src/internal/idempotency.js +82 -0
  42. package/dist/src/internal/idempotency.js.map +1 -0
  43. package/dist/src/internal/metrics.d.ts +38 -0
  44. package/dist/src/internal/metrics.d.ts.map +1 -0
  45. package/dist/src/internal/metrics.js +83 -0
  46. package/dist/src/internal/metrics.js.map +1 -0
  47. package/dist/src/internal/outbox.d.ts +49 -0
  48. package/dist/src/internal/outbox.d.ts.map +1 -0
  49. package/dist/src/internal/outbox.js +149 -0
  50. package/dist/src/internal/outbox.js.map +1 -0
  51. package/dist/src/internal/routing.d.ts +28 -0
  52. package/dist/src/internal/routing.d.ts.map +1 -0
  53. package/dist/src/internal/routing.js +57 -0
  54. package/dist/src/internal/routing.js.map +1 -0
  55. package/dist/src/internal/security.d.ts +53 -0
  56. package/dist/src/internal/security.d.ts.map +1 -0
  57. package/dist/src/internal/security.js +122 -0
  58. package/dist/src/internal/security.js.map +1 -0
  59. package/dist/src/internal/transport.d.ts +49 -0
  60. package/dist/src/internal/transport.d.ts.map +1 -0
  61. package/dist/src/internal/transport.js +207 -0
  62. package/dist/src/internal/transport.js.map +1 -0
  63. package/dist/src/internal/types-internal.d.ts +95 -0
  64. package/dist/src/internal/types-internal.d.ts.map +1 -0
  65. package/dist/src/internal/types-internal.js +9 -0
  66. package/dist/src/internal/types-internal.js.map +1 -0
  67. package/dist/src/peer-health.d.ts +47 -0
  68. package/dist/src/peer-health.d.ts.map +1 -0
  69. package/dist/src/peer-health.js +169 -0
  70. package/dist/src/peer-health.js.map +1 -0
  71. package/dist/src/peer-retry.d.ts +16 -0
  72. package/dist/src/peer-retry.d.ts.map +1 -0
  73. package/dist/src/peer-retry.js +75 -0
  74. package/dist/src/peer-retry.js.map +1 -0
  75. package/dist/src/queueing-executor.d.ts +23 -0
  76. package/dist/src/queueing-executor.d.ts.map +1 -0
  77. package/dist/src/queueing-executor.js +179 -0
  78. package/dist/src/queueing-executor.js.map +1 -0
  79. package/dist/src/routing-rules.d.ts +53 -0
  80. package/dist/src/routing-rules.d.ts.map +1 -0
  81. package/dist/src/routing-rules.js +130 -0
  82. package/dist/src/routing-rules.js.map +1 -0
  83. package/dist/src/task-cleanup.d.ts +21 -0
  84. package/dist/src/task-cleanup.d.ts.map +1 -0
  85. package/dist/src/task-cleanup.js +77 -0
  86. package/dist/src/task-cleanup.js.map +1 -0
  87. package/dist/src/task-store.d.ts +16 -0
  88. package/dist/src/task-store.d.ts.map +1 -0
  89. package/dist/src/task-store.js +80 -0
  90. package/dist/src/task-store.js.map +1 -0
  91. package/dist/src/telemetry.d.ts +88 -0
  92. package/dist/src/telemetry.d.ts.map +1 -0
  93. package/dist/src/telemetry.js +235 -0
  94. package/dist/src/telemetry.js.map +1 -0
  95. package/dist/src/transport-fallback.d.ts +29 -0
  96. package/dist/src/transport-fallback.d.ts.map +1 -0
  97. package/dist/src/transport-fallback.js +81 -0
  98. package/dist/src/transport-fallback.js.map +1 -0
  99. package/dist/src/types.d.ts +160 -0
  100. package/dist/src/types.d.ts.map +1 -0
  101. package/dist/src/types.js +7 -0
  102. package/dist/src/types.js.map +1 -0
  103. package/openclaw.plugin.json +272 -0
  104. package/package.json +56 -0
  105. package/skill/SKILL.md +230 -0
  106. package/skill/references/tools-md-template.md +57 -0
  107. package/skill/scripts/a2a-send.mjs +357 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../../src/internal/idempotency.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,MAAM,EAAE,KAAK,CAAA;CAAE,GACjB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC;AAE3B,MAAM,WAAW,sBAAsB;IACrC,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,cAAc,CAAK;gBAEf,MAAM,EAAE,sBAAsB;IAI1C;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,WAAW;IAiB3D,4EAA4E;IAC5E,KAAK,CACH,GAAG,EAAE,MAAM,EACX,kBAAkB,EAAE,MAAM,EAC1B,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI;IAaP,kCAAkC;IAClC,OAAO,IAAI,IAAI;IAUf,4BAA4B;IAC5B,QAAQ,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE;IAItD,6DAA6D;IAC7D,YAAY,CAAC,UAAU,SAAS,GAAG,IAAI;IAKvC,6BAA6B;IAC7B,WAAW,IAAI,IAAI;CAMpB"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * A2A Gateway Plugin — Idempotency Store
3
+ *
4
+ * OpenClaw gateway-internal module — NOT part of the A2A spec.
5
+ * SHA-256 payload fingerprinting and in-memory deduplication
6
+ * with configurable TTL and periodic cleanup.
7
+ */
8
+ import { createHash } from "node:crypto";
9
+ /** Create a SHA-256 hex fingerprint of the given payload string. */
10
+ export function createFingerprint(payload) {
11
+ return createHash("sha256").update(payload).digest("hex");
12
+ }
13
+ export class IdempotencyStore {
14
+ entries = new Map();
15
+ timer = null;
16
+ config;
17
+ expiredCleaned = 0;
18
+ constructor(config) {
19
+ this.config = config;
20
+ }
21
+ /**
22
+ * Check whether a key has been seen before.
23
+ * - Not found -> `{ status: 'new' }`
24
+ * - Found with same fingerprint -> `{ status: 'duplicate', response }`
25
+ * - Found with different fingerprint -> `{ status: 'conflict' }`
26
+ */
27
+ check(key, payloadFingerprint) {
28
+ const entry = this.entries.get(key);
29
+ if (!entry)
30
+ return { status: "new" };
31
+ if (entry.expires_at <= Date.now()) {
32
+ this.entries.delete(key);
33
+ this.expiredCleaned += 1;
34
+ return { status: "new" };
35
+ }
36
+ if (entry.payload_fingerprint === payloadFingerprint) {
37
+ return { status: "duplicate", response: entry.response };
38
+ }
39
+ return { status: "conflict" };
40
+ }
41
+ /** Store a response keyed by idempotency key with optional TTL override. */
42
+ store(key, payloadFingerprint, response, ttlSeconds) {
43
+ const ttl = ttlSeconds ?? this.config.defaultTtlSeconds;
44
+ const now = Date.now();
45
+ const entry = {
46
+ idempotency_key: key,
47
+ payload_fingerprint: payloadFingerprint,
48
+ response,
49
+ created_at: now,
50
+ expires_at: now + ttl * 1000,
51
+ };
52
+ this.entries.set(key, entry);
53
+ }
54
+ /** Remove all expired entries. */
55
+ cleanup() {
56
+ const now = Date.now();
57
+ for (const [key, entry] of this.entries) {
58
+ if (entry.expires_at <= now) {
59
+ this.entries.delete(key);
60
+ this.expiredCleaned += 1;
61
+ }
62
+ }
63
+ }
64
+ /** Return summary stats. */
65
+ getStats() {
66
+ return { total: this.entries.size, expired_cleaned: this.expiredCleaned };
67
+ }
68
+ /** Start periodic cleanup. Default interval is 60 000 ms. */
69
+ startCleanup(intervalMs = 60_000) {
70
+ if (this.timer)
71
+ return;
72
+ this.timer = setInterval(() => this.cleanup(), intervalMs);
73
+ }
74
+ /** Stop periodic cleanup. */
75
+ stopCleanup() {
76
+ if (this.timer) {
77
+ clearInterval(this.timer);
78
+ this.timer = null;
79
+ }
80
+ }
81
+ }
82
+ //# sourceMappingURL=idempotency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../../src/internal/idempotency.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * A2A Gateway — Metrics collector and structured logging
3
+ *
4
+ * OpenClaw gateway-internal module — NOT part of the A2A spec.
5
+ */
6
+ import type { A2AMetrics } from "./types-internal.js";
7
+ export interface StructuredLogDetails {
8
+ message_id?: string;
9
+ trace_id?: string;
10
+ source?: string;
11
+ dest?: string;
12
+ status?: string;
13
+ retry_count?: number;
14
+ latency_ms?: number;
15
+ [key: string]: unknown;
16
+ }
17
+ /** Collects and exposes A2A protocol metrics. */
18
+ export declare class A2AMetricsCollector {
19
+ private metrics;
20
+ constructor();
21
+ private emptyMetrics;
22
+ recordSend(): void;
23
+ recordReceive(): void;
24
+ recordAck(): void;
25
+ recordRetry(): void;
26
+ recordIdempotentHit(): void;
27
+ recordDeadLetter(): void;
28
+ recordError(): void;
29
+ recordSecurityRejection(): void;
30
+ recordLoopRejection(): void;
31
+ /** Return a snapshot of the current metrics. */
32
+ getMetrics(): A2AMetrics;
33
+ /** Reset all counters to zero. */
34
+ reset(): void;
35
+ /** Output a structured JSON log line to stdout. */
36
+ structuredLog(event: string, details: StructuredLogDetails): void;
37
+ }
38
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/internal/metrics.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMtD,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAMD,iDAAiD;AACjD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,OAAO,CAAa;;IAM5B,OAAO,CAAC,YAAY;IAcpB,UAAU,IAAI,IAAI;IAKlB,aAAa,IAAI,IAAI;IAKrB,SAAS,IAAI,IAAI;IAIjB,WAAW,IAAI,IAAI;IAInB,mBAAmB,IAAI,IAAI;IAI3B,gBAAgB,IAAI,IAAI;IAIxB,WAAW,IAAI,IAAI;IAInB,uBAAuB,IAAI,IAAI;IAI/B,mBAAmB,IAAI,IAAI;IAI3B,gDAAgD;IAChD,UAAU,IAAI,UAAU;IAIxB,kCAAkC;IAClC,KAAK,IAAI,IAAI;IAIb,mDAAmD;IACnD,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,IAAI;CAgBlE"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * A2A Gateway — Metrics collector and structured logging
3
+ *
4
+ * OpenClaw gateway-internal module — NOT part of the A2A spec.
5
+ */
6
+ // ---------------------------------------------------------------------------
7
+ // Metrics collector
8
+ // ---------------------------------------------------------------------------
9
+ /** Collects and exposes A2A protocol metrics. */
10
+ export class A2AMetricsCollector {
11
+ metrics;
12
+ constructor() {
13
+ this.metrics = this.emptyMetrics();
14
+ }
15
+ emptyMetrics() {
16
+ return {
17
+ messages_sent: 0,
18
+ messages_received: 0,
19
+ acks_sent: 0,
20
+ retries: 0,
21
+ idempotent_hits: 0,
22
+ dead_letters: 0,
23
+ errors: 0,
24
+ security_rejections: 0,
25
+ loop_rejections: 0,
26
+ };
27
+ }
28
+ recordSend() {
29
+ this.metrics.messages_sent++;
30
+ this.metrics.last_send_at = new Date().toISOString();
31
+ }
32
+ recordReceive() {
33
+ this.metrics.messages_received++;
34
+ this.metrics.last_receive_at = new Date().toISOString();
35
+ }
36
+ recordAck() {
37
+ this.metrics.acks_sent++;
38
+ }
39
+ recordRetry() {
40
+ this.metrics.retries++;
41
+ }
42
+ recordIdempotentHit() {
43
+ this.metrics.idempotent_hits++;
44
+ }
45
+ recordDeadLetter() {
46
+ this.metrics.dead_letters++;
47
+ }
48
+ recordError() {
49
+ this.metrics.errors++;
50
+ }
51
+ recordSecurityRejection() {
52
+ this.metrics.security_rejections++;
53
+ }
54
+ recordLoopRejection() {
55
+ this.metrics.loop_rejections++;
56
+ }
57
+ /** Return a snapshot of the current metrics. */
58
+ getMetrics() {
59
+ return { ...this.metrics };
60
+ }
61
+ /** Reset all counters to zero. */
62
+ reset() {
63
+ this.metrics = this.emptyMetrics();
64
+ }
65
+ /** Output a structured JSON log line to stdout. */
66
+ structuredLog(event, details) {
67
+ const entry = {
68
+ ts: new Date().toISOString(),
69
+ event,
70
+ message_id: details.message_id,
71
+ trace_id: details.trace_id,
72
+ source: details.source,
73
+ dest: details.dest,
74
+ status: details.status,
75
+ retry_count: details.retry_count,
76
+ latency_ms: details.latency_ms,
77
+ ...details,
78
+ };
79
+ // eslint-disable-next-line no-console
80
+ console.log(JSON.stringify(entry));
81
+ }
82
+ }
83
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/internal/metrics.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAmBH,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,iDAAiD;AACjD,MAAM,OAAO,mBAAmB;IACtB,OAAO,CAAa;IAE5B;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;IACrC,CAAC;IAEO,YAAY;QAClB,OAAO;YACL,aAAa,EAAE,CAAC;YAChB,iBAAiB,EAAE,CAAC;YACpB,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;YACV,eAAe,EAAE,CAAC;YAClB,YAAY,EAAE,CAAC;YACf,MAAM,EAAE,CAAC;YACT,mBAAmB,EAAE,CAAC;YACtB,eAAe,EAAE,CAAC;SACnB,CAAC;IACJ,CAAC;IAED,UAAU;QACR,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,CAAC,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACvD,CAAC;IAED,aAAa;QACX,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;QACjC,IAAI,CAAC,OAAO,CAAC,eAAe,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1D,CAAC;IAED,SAAS;QACP,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;IAC3B,CAAC;IAED,WAAW;QACT,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAED,mBAAmB;QACjB,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;IACjC,CAAC;IAED,gBAAgB;QACd,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;IAC9B,CAAC;IAED,WAAW;QACT,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;IACxB,CAAC;IAED,uBAAuB;QACrB,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC;IACrC,CAAC;IAED,mBAAmB;QACjB,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;IACjC,CAAC;IAED,gDAAgD;IAChD,UAAU;QACR,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAED,kCAAkC;IAClC,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;IACrC,CAAC;IAED,mDAAmD;IACnD,aAAa,CAAC,KAAa,EAAE,OAA6B;QACxD,MAAM,KAAK,GAAG;YACZ,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,KAAK;YACL,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,GAAG,OAAO;SACX,CAAC;QACF,sCAAsC;QACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACrC,CAAC;CACF"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * A2A Gateway Plugin — Outbox Pattern
3
+ *
4
+ * OpenClaw gateway-internal module — NOT part of the A2A spec.
5
+ * Reliable at-least-once delivery via an in-memory outbox with
6
+ * exponential back-off retry and dead-letter handling.
7
+ */
8
+ import type { OutboxEntry } from "./types-internal.js";
9
+ export interface OutboxConfig {
10
+ pollIntervalMs: number;
11
+ maxRetries: number;
12
+ baseDelayMs: number;
13
+ maxDelayMs: number;
14
+ }
15
+ export declare class Outbox {
16
+ private store;
17
+ private timer;
18
+ private isFlushing;
19
+ private config;
20
+ constructor(config: OutboxConfig);
21
+ /** Add a message to the outbox. Returns the generated entry id. */
22
+ enqueue(entry: Omit<OutboxEntry, "id" | "status" | "retry_count" | "next_retry_at" | "created_at">): string;
23
+ /** Return all entries eligible for sending (pending + due). */
24
+ getPending(): OutboxEntry[];
25
+ markSending(id: string): void;
26
+ markSent(id: string): void;
27
+ /**
28
+ * Record a failed delivery attempt.
29
+ * Applies exponential back-off with jitter. Moves to 'dead' after max retries.
30
+ */
31
+ markFailed(id: string, error: string): void;
32
+ /** Return all dead-letter entries. */
33
+ getDeadLetters(): OutboxEntry[];
34
+ /** Return aggregate counts by status. */
35
+ getStats(): Record<"pending" | "sending" | "sent" | "failed" | "dead", number>;
36
+ /** Remove a single entry by id. */
37
+ remove(id: string): void;
38
+ /** Remove 'sent' entries older than maxAgeMs. */
39
+ cleanup(maxAgeMs: number): void;
40
+ /**
41
+ * Start the relay polling loop.
42
+ * For each pending entry, calls `sendFn`. On success (true) marks sent,
43
+ * on failure (false or thrown error) marks failed.
44
+ */
45
+ startRelay(sendFn: (entry: OutboxEntry) => Promise<boolean>): void;
46
+ /** Stop the relay polling loop. */
47
+ stopRelay(): void;
48
+ }
49
+ //# sourceMappingURL=outbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../../src/internal/outbox.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,qBAAqB,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,EAAE,YAAY;IAIhC,mEAAmE;IACnE,OAAO,CACL,KAAK,EAAE,IAAI,CACT,WAAW,EACX,IAAI,GAAG,QAAQ,GAAG,aAAa,GAAG,eAAe,GAAG,YAAY,CACjE,GACA,MAAM;IAeT,+DAA+D;IAC/D,UAAU,IAAI,WAAW,EAAE;IAY3B,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAK7B,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAK1B;;;OAGG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAqB3C,sCAAsC;IACtC,cAAc,IAAI,WAAW,EAAE;IAQ/B,yCAAyC;IACzC,QAAQ,IAAI,MAAM,CAAC,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,EAAE,MAAM,CAAC;IAQ9E,mCAAmC;IACnC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIxB,iDAAiD;IACjD,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAS/B;;;;OAIG;IACH,UAAU,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI;IA2BlE,mCAAmC;IACnC,SAAS,IAAI,IAAI;CAMlB"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * A2A Gateway Plugin — Outbox Pattern
3
+ *
4
+ * OpenClaw gateway-internal module — NOT part of the A2A spec.
5
+ * Reliable at-least-once delivery via an in-memory outbox with
6
+ * exponential back-off retry and dead-letter handling.
7
+ */
8
+ import { randomUUID } from "node:crypto";
9
+ export class Outbox {
10
+ store = new Map();
11
+ timer = null;
12
+ isFlushing = false;
13
+ config;
14
+ constructor(config) {
15
+ this.config = config;
16
+ }
17
+ /** Add a message to the outbox. Returns the generated entry id. */
18
+ enqueue(entry) {
19
+ const id = randomUUID();
20
+ const now = Date.now();
21
+ const full = {
22
+ ...entry,
23
+ id,
24
+ status: "pending",
25
+ retry_count: 0,
26
+ next_retry_at: now,
27
+ created_at: now,
28
+ };
29
+ this.store.set(id, full);
30
+ return id;
31
+ }
32
+ /** Return all entries eligible for sending (pending + due). */
33
+ getPending() {
34
+ const now = Date.now();
35
+ const entries = [];
36
+ for (const entry of this.store.values()) {
37
+ if (entry.status === "pending" && entry.next_retry_at <= now) {
38
+ entries.push(entry);
39
+ }
40
+ }
41
+ entries.sort((a, b) => a.created_at - b.created_at);
42
+ return entries;
43
+ }
44
+ markSending(id) {
45
+ const entry = this.store.get(id);
46
+ if (entry)
47
+ entry.status = "sending";
48
+ }
49
+ markSent(id) {
50
+ const entry = this.store.get(id);
51
+ if (entry)
52
+ entry.status = "sent";
53
+ }
54
+ /**
55
+ * Record a failed delivery attempt.
56
+ * Applies exponential back-off with jitter. Moves to 'dead' after max retries.
57
+ */
58
+ markFailed(id, error) {
59
+ const entry = this.store.get(id);
60
+ if (!entry)
61
+ return;
62
+ entry.retry_count += 1;
63
+ entry.last_error = error;
64
+ if (entry.retry_count >= this.config.maxRetries) {
65
+ entry.status = "dead";
66
+ return;
67
+ }
68
+ const { baseDelayMs, maxDelayMs } = this.config;
69
+ const expDelay = baseDelayMs * Math.pow(2, entry.retry_count);
70
+ const jitter = Math.random() * baseDelayMs;
71
+ const delay = Math.min(expDelay + jitter, maxDelayMs);
72
+ entry.status = "pending";
73
+ entry.next_retry_at = Date.now() + delay;
74
+ }
75
+ /** Return all dead-letter entries. */
76
+ getDeadLetters() {
77
+ const result = [];
78
+ for (const entry of this.store.values()) {
79
+ if (entry.status === "dead")
80
+ result.push(entry);
81
+ }
82
+ return result;
83
+ }
84
+ /** Return aggregate counts by status. */
85
+ getStats() {
86
+ const stats = { pending: 0, sending: 0, sent: 0, failed: 0, dead: 0 };
87
+ for (const entry of this.store.values()) {
88
+ stats[entry.status] += 1;
89
+ }
90
+ return stats;
91
+ }
92
+ /** Remove a single entry by id. */
93
+ remove(id) {
94
+ this.store.delete(id);
95
+ }
96
+ /** Remove 'sent' entries older than maxAgeMs. */
97
+ cleanup(maxAgeMs) {
98
+ const cutoff = Date.now() - maxAgeMs;
99
+ for (const [id, entry] of this.store) {
100
+ if (entry.status === "sent" && entry.created_at < cutoff) {
101
+ this.store.delete(id);
102
+ }
103
+ }
104
+ }
105
+ /**
106
+ * Start the relay polling loop.
107
+ * For each pending entry, calls `sendFn`. On success (true) marks sent,
108
+ * on failure (false or thrown error) marks failed.
109
+ */
110
+ startRelay(sendFn) {
111
+ if (this.timer)
112
+ return;
113
+ this.timer = setInterval(async () => {
114
+ if (this.isFlushing)
115
+ return;
116
+ this.isFlushing = true;
117
+ try {
118
+ const pending = this.getPending();
119
+ for (const entry of pending) {
120
+ this.markSending(entry.id);
121
+ try {
122
+ const ok = await sendFn(entry);
123
+ if (ok) {
124
+ this.markSent(entry.id);
125
+ }
126
+ else {
127
+ this.markFailed(entry.id, "sendFn returned false");
128
+ }
129
+ }
130
+ catch (err) {
131
+ const msg = err instanceof Error ? err.message : String(err);
132
+ this.markFailed(entry.id, msg);
133
+ }
134
+ }
135
+ }
136
+ finally {
137
+ this.isFlushing = false;
138
+ }
139
+ }, this.config.pollIntervalMs);
140
+ }
141
+ /** Stop the relay polling loop. */
142
+ stopRelay() {
143
+ if (this.timer) {
144
+ clearInterval(this.timer);
145
+ this.timer = null;
146
+ }
147
+ }
148
+ }
149
+ //# sourceMappingURL=outbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../../src/internal/outbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * A2A Gateway — Message Routing
3
+ *
4
+ * OpenClaw gateway-internal module — NOT part of the A2A spec.
5
+ */
6
+ import type { A2ADestination, RouteResult, RoutingRule } from "./types-internal.js";
7
+ export declare class Router {
8
+ private rules;
9
+ private defaultAgentId;
10
+ constructor(rules: RoutingRule[], defaultAgentId?: string);
11
+ /**
12
+ * Determine which agent should handle a message based on its destination.
13
+ *
14
+ * Resolution order:
15
+ * 1. Explicit agent_id on the destination
16
+ * 2. Route key matched against configured rules
17
+ * 3. Default agent (if configured)
18
+ * 4. null (no route found)
19
+ */
20
+ route(destination: A2ADestination): RouteResult | null;
21
+ /** Add a routing rule. */
22
+ addRule(rule: RoutingRule): void;
23
+ /** Remove a routing rule by its route key. */
24
+ removeRule(routeKey: string): void;
25
+ /** Return all current routing rules. */
26
+ getRules(): RoutingRule[];
27
+ }
28
+ //# sourceMappingURL=routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../../src/internal/routing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMpF,qBAAa,MAAM;IACjB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,cAAc,CAAqB;gBAE/B,KAAK,EAAE,WAAW,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM;IAKzD;;;;;;;;OAQG;IACH,KAAK,CAAC,WAAW,EAAE,cAAc,GAAG,WAAW,GAAG,IAAI;IAuBtD,0BAA0B;IAC1B,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAIhC,8CAA8C;IAC9C,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIlC,wCAAwC;IACxC,QAAQ,IAAI,WAAW,EAAE;CAG1B"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * A2A Gateway — Message Routing
3
+ *
4
+ * OpenClaw gateway-internal module — NOT part of the A2A spec.
5
+ */
6
+ // ---------------------------------------------------------------------------
7
+ // Router
8
+ // ---------------------------------------------------------------------------
9
+ export class Router {
10
+ rules;
11
+ defaultAgentId;
12
+ constructor(rules, defaultAgentId) {
13
+ this.rules = [...rules];
14
+ this.defaultAgentId = defaultAgentId;
15
+ }
16
+ /**
17
+ * Determine which agent should handle a message based on its destination.
18
+ *
19
+ * Resolution order:
20
+ * 1. Explicit agent_id on the destination
21
+ * 2. Route key matched against configured rules
22
+ * 3. Default agent (if configured)
23
+ * 4. null (no route found)
24
+ */
25
+ route(destination) {
26
+ // 1. Direct agent_id
27
+ if (destination.agent_id) {
28
+ return { agentId: destination.agent_id, matched_by: "agent_id" };
29
+ }
30
+ // 2. Route key lookup
31
+ if (destination.route_key) {
32
+ const rule = this.rules.find((r) => r.routeKey === destination.route_key);
33
+ if (rule) {
34
+ return { agentId: rule.agentId, matched_by: "route_key" };
35
+ }
36
+ }
37
+ // 3. Default
38
+ if (this.defaultAgentId) {
39
+ return { agentId: this.defaultAgentId, matched_by: "default" };
40
+ }
41
+ // 4. No route
42
+ return null;
43
+ }
44
+ /** Add a routing rule. */
45
+ addRule(rule) {
46
+ this.rules.push(rule);
47
+ }
48
+ /** Remove a routing rule by its route key. */
49
+ removeRule(routeKey) {
50
+ this.rules = this.rules.filter((r) => r.routeKey !== routeKey);
51
+ }
52
+ /** Return all current routing rules. */
53
+ getRules() {
54
+ return [...this.rules];
55
+ }
56
+ }
57
+ //# sourceMappingURL=routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.js","sourceRoot":"","sources":["../../../src/internal/routing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,MAAM,OAAO,MAAM;IACT,KAAK,CAAgB;IACrB,cAAc,CAAqB;IAE3C,YAAY,KAAoB,EAAE,cAAuB;QACvD,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QACxB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,WAA2B;QAC/B,qBAAqB;QACrB,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YACzB,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;QACnE,CAAC;QAED,sBAAsB;QACtB,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,WAAW,CAAC,SAAS,CAAC,CAAC;YAC1E,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;YAC5D,CAAC;QACH,CAAC;QAED,aAAa;QACb,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;QACjE,CAAC;QAED,cAAc;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,0BAA0B;IAC1B,OAAO,CAAC,IAAiB;QACvB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,8CAA8C;IAC9C,UAAU,CAAC,QAAgB;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;IACjE,CAAC;IAED,wCAAwC;IACxC,QAAQ;QACN,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * A2A Gateway — HMAC-SHA256 signing, nonce cache, and peer registry
3
+ *
4
+ * OpenClaw gateway-internal module — NOT part of the A2A spec.
5
+ * A2A standard uses OAuth/API Key; this implements custom HMAC-SHA256
6
+ * for gateway-to-gateway communication.
7
+ */
8
+ import type { InternalPeerConfig } from "./types-internal.js";
9
+ export interface SignResult {
10
+ signature: string;
11
+ timestamp: number;
12
+ nonce: string;
13
+ }
14
+ export interface VerifyResult {
15
+ valid: boolean;
16
+ error?: string;
17
+ }
18
+ /** Sign a request body using HMAC-SHA256. */
19
+ export declare function signRequest(body: string, secret: string, timestamp?: number): SignResult;
20
+ /** Verify a signed request using constant-time comparison. */
21
+ export declare function verifyRequest(body: string, signature: string, timestamp: number, nonce: string, secret: string): VerifyResult;
22
+ /** Check if a timestamp is within the acceptable skew window. */
23
+ export declare function checkTimestamp(timestamp: number, skewSeconds: number): {
24
+ valid: boolean;
25
+ error?: string;
26
+ };
27
+ /** In-memory nonce cache with TTL and automatic cleanup. */
28
+ export declare class NonceCache {
29
+ private cache;
30
+ private cleanupTimer;
31
+ constructor(cleanupIntervalMs?: number);
32
+ /** Add a nonce. Returns false if it already exists and is not expired (replay detected). */
33
+ add(nonce: string, ttlMs: number): boolean;
34
+ /** Check if a nonce exists in the cache. */
35
+ has(nonce: string): boolean;
36
+ /** Remove expired entries. */
37
+ cleanup(): void;
38
+ /** Stop the automatic cleanup interval. */
39
+ destroy(): void;
40
+ }
41
+ /** Manage known peers and their HMAC secrets. */
42
+ export declare class PeerRegistry {
43
+ private peers;
44
+ /** Register a peer. */
45
+ addPeer(config: InternalPeerConfig): void;
46
+ /** Get peer config by gateway ID. */
47
+ getPeer(gatewayId: string): InternalPeerConfig | undefined;
48
+ /** Check if a peer is registered. */
49
+ isKnown(gatewayId: string): boolean;
50
+ /** Get the HMAC secret for a peer. */
51
+ getSecret(gatewayId: string): string | undefined;
52
+ }
53
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../src/internal/security.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAM9D,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,6CAA6C;AAC7C,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,UAAU,CASZ;AAED,8DAA8D;AAC9D,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,YAAY,CAoBd;AAMD,iEAAiE;AACjE,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAapC;AAUD,4DAA4D;AAC5D,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,YAAY,CAA+B;gBAEvC,iBAAiB,GAAE,MAAe;IAM9C,4FAA4F;IAC5F,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAc1C,4CAA4C;IAC5C,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAI3B,8BAA8B;IAC9B,OAAO,IAAI,IAAI;IASf,2CAA2C;IAC3C,OAAO,IAAI,IAAI;CAMhB;AAMD,iDAAiD;AACjD,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAyC;IAEtD,uBAAuB;IACvB,OAAO,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAIzC,qCAAqC;IACrC,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAI1D,qCAAqC;IACrC,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAInC,sCAAsC;IACtC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAGjD"}