@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,122 @@
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 crypto from "node:crypto";
9
+ /** Sign a request body using HMAC-SHA256. */
10
+ export function signRequest(body, secret, timestamp) {
11
+ const ts = timestamp ?? Date.now();
12
+ const nonce = crypto.randomUUID();
13
+ const data = `${ts}.${nonce}.${body}`;
14
+ const signature = crypto
15
+ .createHmac("sha256", secret)
16
+ .update(data)
17
+ .digest("hex");
18
+ return { signature, timestamp: ts, nonce };
19
+ }
20
+ /** Verify a signed request using constant-time comparison. */
21
+ export function verifyRequest(body, signature, timestamp, nonce, secret) {
22
+ const data = `${timestamp}.${nonce}.${body}`;
23
+ const expected = crypto
24
+ .createHmac("sha256", secret)
25
+ .update(data)
26
+ .digest("hex");
27
+ // Constant-time comparison
28
+ const sigBuf = Buffer.from(signature, "utf8");
29
+ const expBuf = Buffer.from(expected, "utf8");
30
+ if (sigBuf.length !== expBuf.length) {
31
+ return { valid: false, error: "Signature length mismatch" };
32
+ }
33
+ if (!crypto.timingSafeEqual(sigBuf, expBuf)) {
34
+ return { valid: false, error: "Signature mismatch" };
35
+ }
36
+ return { valid: true };
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // Timestamp check
40
+ // ---------------------------------------------------------------------------
41
+ /** Check if a timestamp is within the acceptable skew window. */
42
+ export function checkTimestamp(timestamp, skewSeconds) {
43
+ const now = Date.now();
44
+ const diff = Math.abs(now - timestamp);
45
+ const maxDiff = skewSeconds * 1000;
46
+ if (diff > maxDiff) {
47
+ return {
48
+ valid: false,
49
+ error: `Timestamp skew ${Math.round(diff / 1000)}s exceeds limit ${skewSeconds}s`,
50
+ };
51
+ }
52
+ return { valid: true };
53
+ }
54
+ /** In-memory nonce cache with TTL and automatic cleanup. */
55
+ export class NonceCache {
56
+ cache = new Map();
57
+ cleanupTimer = null;
58
+ constructor(cleanupIntervalMs = 60_000) {
59
+ this.cleanupTimer = setInterval(() => this.cleanup(), cleanupIntervalMs);
60
+ // Allow the process to exit even if the timer is still running
61
+ this.cleanupTimer.unref();
62
+ }
63
+ /** Add a nonce. Returns false if it already exists and is not expired (replay detected). */
64
+ add(nonce, ttlMs) {
65
+ const existing = this.cache.get(nonce);
66
+ if (existing) {
67
+ if (existing.expiresAt <= Date.now()) {
68
+ // Expired entry — safe to reuse
69
+ this.cache.delete(nonce);
70
+ }
71
+ else {
72
+ return false;
73
+ }
74
+ }
75
+ this.cache.set(nonce, { expiresAt: Date.now() + ttlMs });
76
+ return true;
77
+ }
78
+ /** Check if a nonce exists in the cache. */
79
+ has(nonce) {
80
+ return this.cache.has(nonce);
81
+ }
82
+ /** Remove expired entries. */
83
+ cleanup() {
84
+ const now = Date.now();
85
+ for (const [nonce, entry] of this.cache) {
86
+ if (entry.expiresAt <= now) {
87
+ this.cache.delete(nonce);
88
+ }
89
+ }
90
+ }
91
+ /** Stop the automatic cleanup interval. */
92
+ destroy() {
93
+ if (this.cleanupTimer !== null) {
94
+ clearInterval(this.cleanupTimer);
95
+ this.cleanupTimer = null;
96
+ }
97
+ }
98
+ }
99
+ // ---------------------------------------------------------------------------
100
+ // Peer registry
101
+ // ---------------------------------------------------------------------------
102
+ /** Manage known peers and their HMAC secrets. */
103
+ export class PeerRegistry {
104
+ peers = new Map();
105
+ /** Register a peer. */
106
+ addPeer(config) {
107
+ this.peers.set(config.gatewayId, config);
108
+ }
109
+ /** Get peer config by gateway ID. */
110
+ getPeer(gatewayId) {
111
+ return this.peers.get(gatewayId);
112
+ }
113
+ /** Check if a peer is registered. */
114
+ isKnown(gatewayId) {
115
+ return this.peers.has(gatewayId);
116
+ }
117
+ /** Get the HMAC secret for a peer. */
118
+ getSecret(gatewayId) {
119
+ return this.peers.get(gatewayId)?.hmacSecret;
120
+ }
121
+ }
122
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../../src/internal/security.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * A2A Gateway — HTTP Transport Layer
3
+ *
4
+ * OpenClaw gateway-internal module — NOT part of the A2A spec.
5
+ * Uses only Node.js built-in modules (http, https).
6
+ */
7
+ import type { A2AEnvelope } from "./types-internal.js";
8
+ export interface InboundHeaders {
9
+ signature: string;
10
+ timestamp: number;
11
+ nonce: string;
12
+ sourceGatewayId: string;
13
+ }
14
+ export interface InboundHandlers {
15
+ onMessage(envelope: A2AEnvelope, rawBody: string, headers: InboundHeaders): Promise<{
16
+ statusCode: number;
17
+ body: string;
18
+ }>;
19
+ }
20
+ export declare class InboundServer {
21
+ private server;
22
+ private readonly config;
23
+ private readonly handlers;
24
+ constructor(config: {
25
+ host: string;
26
+ port: number;
27
+ }, handlers: InboundHandlers);
28
+ /** Start the HTTP server. Resolves once the server is listening. */
29
+ start(): Promise<void>;
30
+ /** Gracefully stop the server. */
31
+ stop(): Promise<void>;
32
+ private handleRequest;
33
+ private processBody;
34
+ private readBody;
35
+ private headerString;
36
+ private sendJson;
37
+ }
38
+ export interface OutboundResult {
39
+ success: boolean;
40
+ statusCode: number;
41
+ body: string;
42
+ }
43
+ export declare class OutboundClient {
44
+ /**
45
+ * Send an A2A envelope to a remote gateway.
46
+ */
47
+ send(url: string, envelope: A2AEnvelope, signature: string, timestamp: number, nonce: string, sourceGatewayId: string): Promise<OutboundResult>;
48
+ }
49
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/internal/transport.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMvD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;CACzB;AAcD,MAAM,WAAW,eAAe;IAC9B,SAAS,CACP,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;IACxD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;gBAGzC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EACtC,QAAQ,EAAE,eAAe;IAM3B,oEAAoE;IACpE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAetB,kCAAkC;IAClC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAcrB,OAAO,CAAC,aAAa;YA0CP,WAAW;IAmCzB,OAAO,CAAC,QAAQ;IAyBhB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,QAAQ;CAYjB;AAMD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,cAAc;IACzB;;OAEG;IACH,IAAI,CACF,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,cAAc,CAAC;CA4D3B"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * A2A Gateway — HTTP Transport Layer
3
+ *
4
+ * OpenClaw gateway-internal module — NOT part of the A2A spec.
5
+ * Uses only Node.js built-in modules (http, https).
6
+ */
7
+ import http from "node:http";
8
+ import https from "node:https";
9
+ // ---------------------------------------------------------------------------
10
+ // Constants
11
+ // ---------------------------------------------------------------------------
12
+ const MAX_BODY_BYTES = 2 * 1024 * 1024; // 2 MB
13
+ const INBOX_PATH = "/a2a/v1/inbox";
14
+ const OUTBOUND_TIMEOUT_MS = 30_000;
15
+ export class InboundServer {
16
+ server = null;
17
+ config;
18
+ handlers;
19
+ constructor(config, handlers) {
20
+ this.config = config;
21
+ this.handlers = handlers;
22
+ }
23
+ /** Start the HTTP server. Resolves once the server is listening. */
24
+ start() {
25
+ return new Promise((resolve, reject) => {
26
+ this.server = http.createServer((req, res) => {
27
+ this.handleRequest(req, res);
28
+ });
29
+ this.server.once("error", reject);
30
+ this.server.listen(this.config.port, this.config.host, () => {
31
+ this.server.removeListener("error", reject);
32
+ resolve();
33
+ });
34
+ });
35
+ }
36
+ /** Gracefully stop the server. */
37
+ stop() {
38
+ return new Promise((resolve) => {
39
+ if (!this.server) {
40
+ resolve();
41
+ return;
42
+ }
43
+ this.server.close(() => resolve());
44
+ });
45
+ }
46
+ // -------------------------------------------------------------------------
47
+ // Internal request handler
48
+ // -------------------------------------------------------------------------
49
+ handleRequest(req, res) {
50
+ // Route check
51
+ let url;
52
+ try {
53
+ url = new URL(req.url ?? "/", "http://localhost");
54
+ }
55
+ catch {
56
+ this.sendJson(res, 400, { error: "Malformed URL" });
57
+ return;
58
+ }
59
+ if (url.pathname !== INBOX_PATH) {
60
+ this.sendJson(res, 404, { error: "Not found" });
61
+ return;
62
+ }
63
+ // Method check
64
+ if (req.method !== "POST") {
65
+ this.sendJson(res, 405, { error: "Method not allowed" });
66
+ return;
67
+ }
68
+ // Content-Type check
69
+ const contentType = req.headers["content-type"] ?? "";
70
+ if (!contentType.includes("application/json")) {
71
+ this.sendJson(res, 400, { error: "Content-Type must be application/json" });
72
+ return;
73
+ }
74
+ // Read body with size limit
75
+ this.readBody(req)
76
+ .then((rawBody) => this.processBody(rawBody, req, res))
77
+ .catch((err) => {
78
+ if (err.code === "PAYLOAD_TOO_LARGE") {
79
+ this.sendJson(res, 413, { error: "Payload too large" });
80
+ }
81
+ else {
82
+ this.sendJson(res, 500, { error: "Internal server error" });
83
+ }
84
+ });
85
+ }
86
+ async processBody(rawBody, req, res) {
87
+ // Parse JSON
88
+ let envelope;
89
+ try {
90
+ envelope = JSON.parse(rawBody);
91
+ }
92
+ catch {
93
+ this.sendJson(res, 400, { error: "Invalid JSON" });
94
+ return;
95
+ }
96
+ // Extract security headers
97
+ const headers = {
98
+ signature: this.headerString(req, "x-a2a-signature"),
99
+ timestamp: Number(this.headerString(req, "x-a2a-timestamp")) || 0,
100
+ nonce: this.headerString(req, "x-a2a-nonce"),
101
+ sourceGatewayId: this.headerString(req, "x-a2a-source-gateway"),
102
+ };
103
+ // Delegate to handler
104
+ try {
105
+ const result = await this.handlers.onMessage(envelope, rawBody, headers);
106
+ this.sendJson(res, result.statusCode, JSON.parse(result.body));
107
+ }
108
+ catch {
109
+ this.sendJson(res, 500, { error: "Internal server error" });
110
+ }
111
+ }
112
+ // -------------------------------------------------------------------------
113
+ // Helpers
114
+ // -------------------------------------------------------------------------
115
+ readBody(req) {
116
+ return new Promise((resolve, reject) => {
117
+ const chunks = [];
118
+ let totalBytes = 0;
119
+ req.on("data", (chunk) => {
120
+ totalBytes += chunk.length;
121
+ if (totalBytes > MAX_BODY_BYTES) {
122
+ req.destroy();
123
+ const err = new Error("Payload too large");
124
+ err.code = "PAYLOAD_TOO_LARGE";
125
+ reject(err);
126
+ return;
127
+ }
128
+ chunks.push(chunk);
129
+ });
130
+ req.on("end", () => {
131
+ resolve(Buffer.concat(chunks).toString("utf8"));
132
+ });
133
+ req.on("error", reject);
134
+ });
135
+ }
136
+ headerString(req, name) {
137
+ const value = req.headers[name];
138
+ if (Array.isArray(value))
139
+ return value[0] ?? "";
140
+ return value ?? "";
141
+ }
142
+ sendJson(res, statusCode, body) {
143
+ const payload = JSON.stringify(body);
144
+ res.writeHead(statusCode, {
145
+ "Content-Type": "application/json",
146
+ "Content-Length": Buffer.byteLength(payload, "utf8"),
147
+ });
148
+ res.end(payload);
149
+ }
150
+ }
151
+ export class OutboundClient {
152
+ /**
153
+ * Send an A2A envelope to a remote gateway.
154
+ */
155
+ send(url, envelope, signature, timestamp, nonce, sourceGatewayId) {
156
+ return new Promise((resolve) => {
157
+ const parsed = new URL(url);
158
+ const isHttps = parsed.protocol === "https:";
159
+ const transport = isHttps ? https : http;
160
+ const body = JSON.stringify(envelope);
161
+ const options = {
162
+ hostname: parsed.hostname,
163
+ port: parsed.port || (isHttps ? 443 : 80),
164
+ path: parsed.pathname + parsed.search,
165
+ method: "POST",
166
+ headers: {
167
+ "Content-Type": "application/json",
168
+ "Content-Length": Buffer.byteLength(body, "utf8"),
169
+ "X-A2A-Signature": signature,
170
+ "X-A2A-Timestamp": String(timestamp),
171
+ "X-A2A-Nonce": nonce,
172
+ "X-A2A-Source-Gateway": sourceGatewayId,
173
+ },
174
+ timeout: OUTBOUND_TIMEOUT_MS,
175
+ };
176
+ const req = transport.request(options, (res) => {
177
+ const chunks = [];
178
+ res.on("data", (chunk) => chunks.push(chunk));
179
+ res.on("end", () => {
180
+ const responseBody = Buffer.concat(chunks).toString("utf8");
181
+ const statusCode = res.statusCode ?? 0;
182
+ resolve({
183
+ success: statusCode >= 200 && statusCode < 300,
184
+ statusCode,
185
+ body: responseBody,
186
+ });
187
+ });
188
+ res.on("error", () => {
189
+ resolve({ success: false, statusCode: 0, body: "Response read error" });
190
+ });
191
+ });
192
+ req.on("timeout", () => {
193
+ req.destroy();
194
+ resolve({ success: false, statusCode: 0, body: "Request timeout" });
195
+ });
196
+ req.on("error", (err) => {
197
+ resolve({
198
+ success: false,
199
+ statusCode: 0,
200
+ body: err.message || "Connection error",
201
+ });
202
+ });
203
+ req.end(body);
204
+ });
205
+ }
206
+ }
207
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../src/internal/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Gateway-internal types — NOT part of the A2A spec.
3
+ *
4
+ * These types support the OpenClaw gateway-to-gateway protocol layer
5
+ * (custom envelope format, HMAC signing, routing, outbox, idempotency, metrics).
6
+ * They are separate from the standard A2A types used by the SDK integration.
7
+ */
8
+ export interface A2ASource {
9
+ gateway_id: string;
10
+ agent_id?: string;
11
+ }
12
+ export interface A2ADestination {
13
+ gateway_id?: string;
14
+ agent_id?: string;
15
+ route_key?: string;
16
+ }
17
+ export type MessageType = "command" | "event" | "response" | "error" | "ack";
18
+ export interface A2AEnvelope {
19
+ protocol_version: string;
20
+ message_id: string;
21
+ idempotency_key: string;
22
+ correlation_id?: string;
23
+ timestamp: string;
24
+ ttl_seconds: number;
25
+ trace_id?: string;
26
+ span_id?: string;
27
+ source: A2ASource;
28
+ destination: A2ADestination;
29
+ message_type: MessageType;
30
+ hop_count: number;
31
+ route_path: string[];
32
+ payload: unknown;
33
+ }
34
+ export interface A2AAck {
35
+ protocol_version: string;
36
+ message_id: string;
37
+ correlation_id: string;
38
+ source: {
39
+ gateway_id: string;
40
+ };
41
+ message_type: "ack";
42
+ timestamp: string;
43
+ status: "accepted" | "rejected";
44
+ reason?: string;
45
+ }
46
+ export interface A2AConfig {
47
+ gatewayId: string;
48
+ limits: {
49
+ maxHops: number;
50
+ maxPayloadBytes: number;
51
+ };
52
+ }
53
+ export interface RoutingRule {
54
+ routeKey: string;
55
+ agentId: string;
56
+ }
57
+ export interface RouteResult {
58
+ agentId: string;
59
+ matched_by: "agent_id" | "route_key" | "default";
60
+ }
61
+ export type OutboxStatus = "pending" | "sending" | "sent" | "failed" | "dead";
62
+ export interface OutboxEntry {
63
+ id: string;
64
+ status: OutboxStatus;
65
+ retry_count: number;
66
+ next_retry_at: number;
67
+ created_at: number;
68
+ last_error?: string;
69
+ [key: string]: unknown;
70
+ }
71
+ export interface IdempotencyEntry {
72
+ idempotency_key: string;
73
+ payload_fingerprint: string;
74
+ response: string;
75
+ created_at: number;
76
+ expires_at: number;
77
+ }
78
+ export interface A2AMetrics {
79
+ messages_sent: number;
80
+ messages_received: number;
81
+ acks_sent: number;
82
+ retries: number;
83
+ idempotent_hits: number;
84
+ dead_letters: number;
85
+ errors: number;
86
+ security_rejections: number;
87
+ loop_rejections: number;
88
+ last_send_at?: string;
89
+ last_receive_at?: string;
90
+ }
91
+ export interface InternalPeerConfig {
92
+ gatewayId: string;
93
+ hmacSecret: string;
94
+ }
95
+ //# sourceMappingURL=types-internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-internal.d.ts","sourceRoot":"","sources":["../../../src/internal/types-internal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Gateway-internal types — NOT part of the A2A spec.
3
+ *
4
+ * These types support the OpenClaw gateway-to-gateway protocol layer
5
+ * (custom envelope format, HMAC signing, routing, outbox, idempotency, metrics).
6
+ * They are separate from the standard A2A types used by the SDK integration.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types-internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-internal.js","sourceRoot":"","sources":["../../../src/internal/types-internal.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,47 @@
1
+ import type { PeerConfig, HealthCheckConfig, CircuitBreakerConfig, PeerState } from "./types.js";
2
+ type LogFn = (level: "info" | "warn" | "error", msg: string, details?: Record<string, unknown>) => void;
3
+ type HealthProbe = (peer: PeerConfig) => Promise<boolean>;
4
+ /**
5
+ * Manages per-peer health checks and circuit breaker state.
6
+ *
7
+ * Health checks periodically probe each peer's Agent Card endpoint.
8
+ * The circuit breaker follows the standard three-state pattern:
9
+ * closed → open → half-open → closed
10
+ */
11
+ export declare class PeerHealthManager {
12
+ private readonly states;
13
+ private readonly peers;
14
+ private readonly healthConfig;
15
+ private readonly cbConfig;
16
+ private readonly probe;
17
+ private readonly log;
18
+ private timer;
19
+ private halfOpenInFlight;
20
+ /** Cached skills per peer, refreshed on each successful health check probe. */
21
+ private readonly peerSkills;
22
+ constructor(peers: PeerConfig[], healthConfig: HealthCheckConfig, cbConfig: CircuitBreakerConfig, probe: HealthProbe, log: LogFn);
23
+ /** Start periodic health checks. */
24
+ start(): void;
25
+ /** Stop periodic health checks. */
26
+ stop(): void;
27
+ /** Check if a peer is available for requests (circuit is not open). */
28
+ isAvailable(peerName: string): boolean;
29
+ /** Record a successful call to a peer. */
30
+ recordSuccess(peerName: string): void;
31
+ /** Record a failed call to a peer. May trigger circuit open. */
32
+ recordFailure(peerName: string): void;
33
+ /** Get state for a single peer. */
34
+ getState(peerName: string): PeerState | undefined;
35
+ /** Get states for all peers. */
36
+ getAllStates(): Map<string, PeerState>;
37
+ /** Get cached skills for all peers (populated during health checks). */
38
+ getPeerSkills(): Map<string, string[]>;
39
+ /** Update cached skills for a peer (called by the health probe). */
40
+ setPeerSkills(peerName: string, skills: string[]): void;
41
+ /** Run health checks for all peers. */
42
+ private runHealthChecks;
43
+ /** Probe a single peer and update its state. */
44
+ private checkPeer;
45
+ }
46
+ export {};
47
+ //# sourceMappingURL=peer-health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer-health.d.ts","sourceRoot":"","sources":["../../src/peer-health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,oBAAoB,EAGpB,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AACxG,KAAK,WAAW,GAAG,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE1D;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoB;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAChD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA+B;gBAGxD,KAAK,EAAE,UAAU,EAAE,EACnB,YAAY,EAAE,iBAAiB,EAC/B,QAAQ,EAAE,oBAAoB,EAC9B,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,KAAK;IAoBZ,oCAAoC;IACpC,KAAK,IAAI,IAAI;IAab,mCAAmC;IACnC,IAAI,IAAI,IAAI;IAOZ,uEAAuE;IACvE,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IA0BtC,0CAA0C;IAC1C,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAkBrC,gEAAgE;IAChE,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAkCrC,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAIjD,gCAAgC;IAChC,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;IAItC,wEAAwE;IACxE,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAItC,oEAAoE;IACpE,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAIvD,uCAAuC;IACvC,OAAO,CAAC,eAAe;IAWvB,gDAAgD;YAClC,SAAS;CAcxB"}