@dexto/server 1.2.5

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 (174) hide show
  1. package/LICENSE +44 -0
  2. package/dist/a2a/adapters/index.cjs +42 -0
  3. package/dist/a2a/adapters/index.d.ts +10 -0
  4. package/dist/a2a/adapters/index.d.ts.map +1 -0
  5. package/dist/a2a/adapters/index.js +12 -0
  6. package/dist/a2a/adapters/message.cjs +193 -0
  7. package/dist/a2a/adapters/message.d.ts +50 -0
  8. package/dist/a2a/adapters/message.d.ts.map +1 -0
  9. package/dist/a2a/adapters/message.js +167 -0
  10. package/dist/a2a/adapters/state.cjs +57 -0
  11. package/dist/a2a/adapters/state.d.ts +36 -0
  12. package/dist/a2a/adapters/state.d.ts.map +1 -0
  13. package/dist/a2a/adapters/state.js +32 -0
  14. package/dist/a2a/adapters/task-view.cjs +85 -0
  15. package/dist/a2a/adapters/task-view.d.ts +58 -0
  16. package/dist/a2a/adapters/task-view.d.ts.map +1 -0
  17. package/dist/a2a/adapters/task-view.js +60 -0
  18. package/dist/a2a/index.cjs +51 -0
  19. package/dist/a2a/index.d.ts +15 -0
  20. package/dist/a2a/index.d.ts.map +1 -0
  21. package/dist/a2a/index.js +30 -0
  22. package/dist/a2a/jsonrpc/index.cjs +38 -0
  23. package/dist/a2a/jsonrpc/index.d.ts +11 -0
  24. package/dist/a2a/jsonrpc/index.d.ts.map +1 -0
  25. package/dist/a2a/jsonrpc/index.js +10 -0
  26. package/dist/a2a/jsonrpc/methods.cjs +183 -0
  27. package/dist/a2a/jsonrpc/methods.d.ts +110 -0
  28. package/dist/a2a/jsonrpc/methods.d.ts.map +1 -0
  29. package/dist/a2a/jsonrpc/methods.js +159 -0
  30. package/dist/a2a/jsonrpc/server.cjs +199 -0
  31. package/dist/a2a/jsonrpc/server.d.ts +100 -0
  32. package/dist/a2a/jsonrpc/server.d.ts.map +1 -0
  33. package/dist/a2a/jsonrpc/server.js +175 -0
  34. package/dist/a2a/jsonrpc/types.cjs +47 -0
  35. package/dist/a2a/jsonrpc/types.d.ts +91 -0
  36. package/dist/a2a/jsonrpc/types.d.ts.map +1 -0
  37. package/dist/a2a/jsonrpc/types.js +21 -0
  38. package/dist/a2a/types.cjs +16 -0
  39. package/dist/a2a/types.d.ts +250 -0
  40. package/dist/a2a/types.d.ts.map +1 -0
  41. package/dist/a2a/types.js +0 -0
  42. package/dist/approval/approval-coordinator.cjs +87 -0
  43. package/dist/approval/approval-coordinator.d.ts +52 -0
  44. package/dist/approval/approval-coordinator.d.ts.map +1 -0
  45. package/dist/approval/approval-coordinator.js +63 -0
  46. package/dist/approval/manual-approval-handler.cjs +100 -0
  47. package/dist/approval/manual-approval-handler.d.ts +32 -0
  48. package/dist/approval/manual-approval-handler.d.ts.map +1 -0
  49. package/dist/approval/manual-approval-handler.js +76 -0
  50. package/dist/events/a2a-sse-subscriber.cjs +271 -0
  51. package/dist/events/a2a-sse-subscriber.d.ts +94 -0
  52. package/dist/events/a2a-sse-subscriber.d.ts.map +1 -0
  53. package/dist/events/a2a-sse-subscriber.js +247 -0
  54. package/dist/events/types.cjs +16 -0
  55. package/dist/events/types.d.ts +15 -0
  56. package/dist/events/types.d.ts.map +1 -0
  57. package/dist/events/types.js +0 -0
  58. package/dist/events/webhook-subscriber.cjs +301 -0
  59. package/dist/events/webhook-subscriber.d.ts +64 -0
  60. package/dist/events/webhook-subscriber.d.ts.map +1 -0
  61. package/dist/events/webhook-subscriber.js +269 -0
  62. package/dist/events/webhook-types.cjs +16 -0
  63. package/dist/events/webhook-types.d.ts +91 -0
  64. package/dist/events/webhook-types.d.ts.map +1 -0
  65. package/dist/events/webhook-types.js +0 -0
  66. package/dist/hono/__tests__/test-fixtures.cjs +236 -0
  67. package/dist/hono/__tests__/test-fixtures.d.ts +65 -0
  68. package/dist/hono/__tests__/test-fixtures.d.ts.map +1 -0
  69. package/dist/hono/__tests__/test-fixtures.js +197 -0
  70. package/dist/hono/index.cjs +166 -0
  71. package/dist/hono/index.d.ts +2783 -0
  72. package/dist/hono/index.d.ts.map +1 -0
  73. package/dist/hono/index.js +141 -0
  74. package/dist/hono/middleware/auth.cjs +75 -0
  75. package/dist/hono/middleware/auth.d.ts +3 -0
  76. package/dist/hono/middleware/auth.d.ts.map +1 -0
  77. package/dist/hono/middleware/auth.js +51 -0
  78. package/dist/hono/middleware/cors.cjs +57 -0
  79. package/dist/hono/middleware/cors.d.ts +9 -0
  80. package/dist/hono/middleware/cors.d.ts.map +1 -0
  81. package/dist/hono/middleware/cors.js +33 -0
  82. package/dist/hono/middleware/error.cjs +131 -0
  83. package/dist/hono/middleware/error.d.ts +5 -0
  84. package/dist/hono/middleware/error.d.ts.map +1 -0
  85. package/dist/hono/middleware/error.js +105 -0
  86. package/dist/hono/middleware/redaction.cjs +45 -0
  87. package/dist/hono/middleware/redaction.d.ts +4 -0
  88. package/dist/hono/middleware/redaction.d.ts.map +1 -0
  89. package/dist/hono/middleware/redaction.js +20 -0
  90. package/dist/hono/node/index.cjs +139 -0
  91. package/dist/hono/node/index.d.ts +19 -0
  92. package/dist/hono/node/index.d.ts.map +1 -0
  93. package/dist/hono/node/index.js +115 -0
  94. package/dist/hono/routes/a2a-jsonrpc.cjs +119 -0
  95. package/dist/hono/routes/a2a-jsonrpc.d.ts +46 -0
  96. package/dist/hono/routes/a2a-jsonrpc.d.ts.map +1 -0
  97. package/dist/hono/routes/a2a-jsonrpc.js +95 -0
  98. package/dist/hono/routes/a2a-tasks.cjs +315 -0
  99. package/dist/hono/routes/a2a-tasks.d.ts +530 -0
  100. package/dist/hono/routes/a2a-tasks.d.ts.map +1 -0
  101. package/dist/hono/routes/a2a-tasks.js +291 -0
  102. package/dist/hono/routes/a2a.cjs +36 -0
  103. package/dist/hono/routes/a2a.d.ts +4 -0
  104. package/dist/hono/routes/a2a.d.ts.map +1 -0
  105. package/dist/hono/routes/a2a.js +12 -0
  106. package/dist/hono/routes/agents.cjs +735 -0
  107. package/dist/hono/routes/agents.d.ts +650 -0
  108. package/dist/hono/routes/agents.d.ts.map +1 -0
  109. package/dist/hono/routes/agents.js +711 -0
  110. package/dist/hono/routes/approvals.cjs +125 -0
  111. package/dist/hono/routes/approvals.d.ts +89 -0
  112. package/dist/hono/routes/approvals.d.ts.map +1 -0
  113. package/dist/hono/routes/approvals.js +101 -0
  114. package/dist/hono/routes/greeting.cjs +60 -0
  115. package/dist/hono/routes/greeting.d.ts +19 -0
  116. package/dist/hono/routes/greeting.d.ts.map +1 -0
  117. package/dist/hono/routes/greeting.js +36 -0
  118. package/dist/hono/routes/health.cjs +45 -0
  119. package/dist/hono/routes/health.d.ts +17 -0
  120. package/dist/hono/routes/health.d.ts.map +1 -0
  121. package/dist/hono/routes/health.js +21 -0
  122. package/dist/hono/routes/llm.cjs +298 -0
  123. package/dist/hono/routes/llm.d.ts +294 -0
  124. package/dist/hono/routes/llm.d.ts.map +1 -0
  125. package/dist/hono/routes/llm.js +287 -0
  126. package/dist/hono/routes/mcp.cjs +356 -0
  127. package/dist/hono/routes/mcp.d.ts +246 -0
  128. package/dist/hono/routes/mcp.d.ts.map +1 -0
  129. package/dist/hono/routes/mcp.js +332 -0
  130. package/dist/hono/routes/memory.cjs +192 -0
  131. package/dist/hono/routes/memory.d.ts +146 -0
  132. package/dist/hono/routes/memory.d.ts.map +1 -0
  133. package/dist/hono/routes/memory.js +168 -0
  134. package/dist/hono/routes/messages.cjs +320 -0
  135. package/dist/hono/routes/messages.d.ts +163 -0
  136. package/dist/hono/routes/messages.d.ts.map +1 -0
  137. package/dist/hono/routes/messages.js +296 -0
  138. package/dist/hono/routes/prompts.cjs +228 -0
  139. package/dist/hono/routes/prompts.d.ts +150 -0
  140. package/dist/hono/routes/prompts.d.ts.map +1 -0
  141. package/dist/hono/routes/prompts.js +204 -0
  142. package/dist/hono/routes/resources.cjs +110 -0
  143. package/dist/hono/routes/resources.d.ts +76 -0
  144. package/dist/hono/routes/resources.d.ts.map +1 -0
  145. package/dist/hono/routes/resources.js +86 -0
  146. package/dist/hono/routes/search.cjs +109 -0
  147. package/dist/hono/routes/search.d.ts +137 -0
  148. package/dist/hono/routes/search.d.ts.map +1 -0
  149. package/dist/hono/routes/search.js +85 -0
  150. package/dist/hono/routes/sessions.cjs +366 -0
  151. package/dist/hono/routes/sessions.d.ts +229 -0
  152. package/dist/hono/routes/sessions.d.ts.map +1 -0
  153. package/dist/hono/routes/sessions.js +342 -0
  154. package/dist/hono/routes/webhooks.cjs +228 -0
  155. package/dist/hono/routes/webhooks.d.ts +127 -0
  156. package/dist/hono/routes/webhooks.d.ts.map +1 -0
  157. package/dist/hono/routes/webhooks.js +204 -0
  158. package/dist/hono/schemas/responses.cjs +276 -0
  159. package/dist/hono/schemas/responses.d.ts +1418 -0
  160. package/dist/hono/schemas/responses.d.ts.map +1 -0
  161. package/dist/hono/schemas/responses.js +227 -0
  162. package/dist/hono/types.cjs +16 -0
  163. package/dist/hono/types.d.ts +6 -0
  164. package/dist/hono/types.d.ts.map +1 -0
  165. package/dist/hono/types.js +0 -0
  166. package/dist/index.cjs +38 -0
  167. package/dist/index.d.ts +11 -0
  168. package/dist/index.d.ts.map +1 -0
  169. package/dist/index.js +9 -0
  170. package/dist/mcp/mcp-handler.cjs +145 -0
  171. package/dist/mcp/mcp-handler.d.ts +14 -0
  172. package/dist/mcp/mcp-handler.d.ts.map +1 -0
  173. package/dist/mcp/mcp-handler.js +118 -0
  174. package/package.json +59 -0
@@ -0,0 +1,269 @@
1
+ import crypto from "crypto";
2
+ import { setMaxListeners } from "events";
3
+ import {
4
+ INTEGRATION_EVENTS
5
+ } from "@dexto/core";
6
+ import { logger } from "@dexto/core";
7
+ const DEFAULT_DELIVERY_OPTIONS = {
8
+ maxRetries: 3,
9
+ timeout: 1e4,
10
+ // 10 seconds
11
+ includeSignature: true
12
+ };
13
+ class WebhookEventSubscriber {
14
+ webhooks = /* @__PURE__ */ new Map();
15
+ abortController;
16
+ deliveryOptions;
17
+ fetchFn;
18
+ constructor({
19
+ fetchFn,
20
+ ...deliveryOptions
21
+ } = {}) {
22
+ this.deliveryOptions = { ...DEFAULT_DELIVERY_OPTIONS, ...deliveryOptions };
23
+ this.fetchFn = fetchFn || fetch;
24
+ logger.debug("WebhookEventSubscriber initialized");
25
+ }
26
+ /**
27
+ * Subscribe to agent events and deliver them to registered webhooks
28
+ */
29
+ subscribe(eventBus) {
30
+ this.abortController?.abort();
31
+ this.abortController = new AbortController();
32
+ const { signal } = this.abortController;
33
+ const MAX_SHARED_SIGNAL_LISTENERS = 20;
34
+ setMaxListeners(MAX_SHARED_SIGNAL_LISTENERS, signal);
35
+ INTEGRATION_EVENTS.forEach((eventName) => {
36
+ eventBus.on(
37
+ eventName,
38
+ (payload) => {
39
+ this.deliverEvent(eventName, payload);
40
+ },
41
+ { signal }
42
+ );
43
+ });
44
+ logger.info(`Webhook subscriber active with ${this.webhooks.size} registered webhooks`);
45
+ }
46
+ /**
47
+ * Register a new webhook endpoint
48
+ */
49
+ addWebhook(webhook) {
50
+ this.webhooks.set(webhook.id, webhook);
51
+ logger.info(`Webhook registered: ${webhook.id} -> ${webhook.url}`);
52
+ }
53
+ /**
54
+ * Remove a webhook endpoint
55
+ */
56
+ removeWebhook(webhookId) {
57
+ const removed = this.webhooks.delete(webhookId);
58
+ if (removed) {
59
+ logger.info(`Webhook removed: ${webhookId}`);
60
+ } else {
61
+ logger.warn(`Attempted to remove non-existent webhook: ${webhookId}`);
62
+ }
63
+ return removed;
64
+ }
65
+ /**
66
+ * Get all registered webhooks
67
+ */
68
+ getWebhooks() {
69
+ return Array.from(this.webhooks.values());
70
+ }
71
+ /**
72
+ * Get a specific webhook by ID
73
+ */
74
+ getWebhook(webhookId) {
75
+ return this.webhooks.get(webhookId);
76
+ }
77
+ /**
78
+ * Test a webhook by sending a sample event
79
+ */
80
+ async testWebhook(webhookId) {
81
+ const webhook = this.webhooks.get(webhookId);
82
+ if (!webhook) {
83
+ throw new Error(`Webhook not found: ${webhookId}`);
84
+ }
85
+ const testEvent = {
86
+ id: `evt_test_${Date.now()}`,
87
+ type: "tools:available-updated",
88
+ data: {
89
+ tools: ["test-tool"],
90
+ source: "mcp"
91
+ },
92
+ created: (/* @__PURE__ */ new Date()).toISOString(),
93
+ apiVersion: "2025-07-03"
94
+ };
95
+ return this.deliverToWebhook(webhook, testEvent);
96
+ }
97
+ /**
98
+ * Clean up event listeners and resources
99
+ */
100
+ cleanup() {
101
+ if (this.abortController) {
102
+ this.abortController.abort();
103
+ delete this.abortController;
104
+ }
105
+ this.webhooks.clear();
106
+ logger.debug("Webhook event subscriber cleaned up");
107
+ }
108
+ /**
109
+ * Unsubscribe from current event bus without clearing registered webhooks
110
+ */
111
+ unsubscribe() {
112
+ if (this.abortController) {
113
+ const controller = this.abortController;
114
+ delete this.abortController;
115
+ try {
116
+ controller.abort();
117
+ } catch (error) {
118
+ logger.debug(
119
+ `Error aborting controller during unsubscribe: ${error instanceof Error ? error.message : String(error)}`,
120
+ {
121
+ location: "WebhookEventSubscriber.unsubscribe",
122
+ ...error instanceof Error ? { stack: error.stack } : { value: String(error) }
123
+ }
124
+ );
125
+ }
126
+ }
127
+ }
128
+ /**
129
+ * Deliver an event to all registered webhooks
130
+ */
131
+ async deliverEvent(eventType, eventData) {
132
+ if (this.webhooks.size === 0) {
133
+ return;
134
+ }
135
+ const webhookEvent = {
136
+ id: `evt_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,
137
+ type: eventType,
138
+ data: eventData,
139
+ created: (/* @__PURE__ */ new Date()).toISOString(),
140
+ apiVersion: "2025-07-03"
141
+ };
142
+ logger.debug(`Delivering webhook event: ${eventType} to ${this.webhooks.size} webhooks`);
143
+ const deliveryPromises = Array.from(this.webhooks.values()).map((webhook) => ({
144
+ webhook,
145
+ promise: this.deliverToWebhook(webhook, webhookEvent)
146
+ }));
147
+ const handleSettled = (results) => {
148
+ results.forEach((result, i) => {
149
+ if (result.status === "rejected") {
150
+ const webhook = deliveryPromises[i]?.webhook;
151
+ if (webhook) {
152
+ logger.error(
153
+ `Webhook delivery failed for ${webhook.id}: ${result.reason instanceof Error ? result.reason.message : String(result.reason)}`
154
+ );
155
+ }
156
+ }
157
+ });
158
+ };
159
+ if (process.env.NODE_ENV === "test") {
160
+ const results = await Promise.allSettled(deliveryPromises.map((p) => p.promise));
161
+ handleSettled(results);
162
+ } else {
163
+ Promise.allSettled(deliveryPromises.map((p) => p.promise)).then(handleSettled);
164
+ }
165
+ }
166
+ /**
167
+ * Deliver an event to a specific webhook with retry logic
168
+ */
169
+ async deliverToWebhook(webhook, event) {
170
+ const startTime = Date.now();
171
+ let lastError;
172
+ let lastStatusCode;
173
+ for (let attempt = 1; attempt <= this.deliveryOptions.maxRetries; attempt++) {
174
+ try {
175
+ const result2 = await this.sendWebhookRequest(webhook, event, attempt);
176
+ if (result2.success) {
177
+ return result2;
178
+ }
179
+ lastError = new Error(result2.error || `HTTP ${result2.statusCode}`);
180
+ lastStatusCode = result2.statusCode;
181
+ } catch (error) {
182
+ lastError = error instanceof Error ? error : new Error(String(error));
183
+ logger.warn(
184
+ `Webhook delivery attempt ${attempt}/${this.deliveryOptions.maxRetries} failed for ${webhook.id}: ${lastError.message}`
185
+ );
186
+ }
187
+ if (attempt < this.deliveryOptions.maxRetries) {
188
+ const baseDelay = process.env.NODE_ENV === "test" ? 1 : 1e3;
189
+ const exp = baseDelay * Math.pow(2, attempt - 1);
190
+ const jitter = exp * 0.2 * Math.random();
191
+ const backoffMs = Math.min(exp + jitter, 1e4);
192
+ await new Promise((resolve) => setTimeout(resolve, backoffMs));
193
+ }
194
+ }
195
+ const totalTime = Date.now() - startTime;
196
+ const result = {
197
+ success: false,
198
+ error: lastError?.message || "Unknown error",
199
+ responseTime: totalTime,
200
+ attempt: this.deliveryOptions.maxRetries,
201
+ ...lastStatusCode !== void 0 && { statusCode: lastStatusCode }
202
+ };
203
+ logger.error(
204
+ `Webhook delivery failed after ${this.deliveryOptions.maxRetries} attempts for ${webhook.id}: ${result.error}`
205
+ );
206
+ return result;
207
+ }
208
+ /**
209
+ * Send HTTP request to webhook endpoint
210
+ */
211
+ async sendWebhookRequest(webhook, event, attempt) {
212
+ const startTime = Date.now();
213
+ const payload = JSON.stringify(event);
214
+ const headers = {
215
+ "Content-Type": "application/json",
216
+ "User-Agent": "DextoAgent/1.0",
217
+ "X-Dexto-Event-Type": event.type,
218
+ "X-Dexto-Event-Id": event.id,
219
+ "X-Dexto-Delivery-Attempt": attempt.toString()
220
+ };
221
+ if (webhook.secret && this.deliveryOptions.includeSignature) {
222
+ const signature = this.generateSignature(payload, webhook.secret);
223
+ headers["X-Dexto-Signature-256"] = signature;
224
+ }
225
+ try {
226
+ const response = await this.fetchFn(webhook.url, {
227
+ method: "POST",
228
+ headers,
229
+ body: payload,
230
+ signal: AbortSignal.timeout(this.deliveryOptions.timeout)
231
+ });
232
+ const responseTime = Date.now() - startTime;
233
+ const success = response.ok;
234
+ const result = {
235
+ success,
236
+ statusCode: response.status,
237
+ responseTime,
238
+ attempt
239
+ };
240
+ if (!success) {
241
+ result.error = `HTTP ${response.status}: ${response.statusText}`;
242
+ }
243
+ logger.debug(
244
+ `Webhook delivery ${success ? "succeeded" : "failed"} for ${webhook.id}: ${response.status} in ${responseTime}ms`
245
+ );
246
+ return result;
247
+ } catch (error) {
248
+ const responseTime = Date.now() - startTime;
249
+ const errorMessage = error instanceof Error ? error.message : String(error);
250
+ return {
251
+ success: false,
252
+ error: errorMessage,
253
+ responseTime,
254
+ attempt
255
+ };
256
+ }
257
+ }
258
+ /**
259
+ * Generate HMAC signature for webhook verification
260
+ */
261
+ generateSignature(payload, secret) {
262
+ const hmac = crypto.createHmac("sha256", secret);
263
+ hmac.update(payload, "utf8");
264
+ return `sha256=${hmac.digest("hex")}`;
265
+ }
266
+ }
267
+ export {
268
+ WebhookEventSubscriber
269
+ };
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+ var webhook_types_exports = {};
16
+ module.exports = __toCommonJS(webhook_types_exports);
@@ -0,0 +1,91 @@
1
+ import type { AgentEventMap, AgentEventName } from '@dexto/core';
2
+ /**
3
+ * TODO: temporarily DUPE OF cli
4
+ * Webhook configuration interface
5
+ * Represents a registered webhook endpoint
6
+ */
7
+ export interface WebhookConfig {
8
+ /** Unique identifier for the webhook */
9
+ id: string;
10
+ /** The URL to send webhook events to */
11
+ url: string;
12
+ /** Optional secret for signature verification */
13
+ secret?: string;
14
+ /** When the webhook was registered */
15
+ createdAt: Date;
16
+ /** Optional description for the webhook */
17
+ description?: string;
18
+ }
19
+ /**
20
+ * Webhook event payload interface
21
+ * Mirrors Stripe.Event structure for familiar developer experience
22
+ */
23
+ export interface DextoWebhookEvent<T extends AgentEventName = AgentEventName> {
24
+ /** Unique identifier for this webhook event */
25
+ id: string;
26
+ /** The type of event - provides IDE autocomplete */
27
+ type: T;
28
+ /** The event data payload - typed based on event type */
29
+ data: AgentEventMap[T];
30
+ /** When the event was created */
31
+ created: string;
32
+ /** API version for future compatibility */
33
+ apiVersion: string;
34
+ }
35
+ /**
36
+ * Webhook delivery attempt result
37
+ */
38
+ export interface WebhookDeliveryResult {
39
+ /** Whether the delivery was successful */
40
+ success: boolean;
41
+ /** HTTP status code received */
42
+ statusCode?: number;
43
+ /** Error message if delivery failed */
44
+ error?: string;
45
+ /** Response time in milliseconds */
46
+ responseTime: number;
47
+ /** Number of delivery attempts */
48
+ attempt: number;
49
+ }
50
+ /**
51
+ * Webhook registration request body
52
+ */
53
+ export interface WebhookRegistrationRequest {
54
+ /** The URL to send webhook events to */
55
+ url: string;
56
+ /** Optional secret for signature verification */
57
+ secret?: string;
58
+ /** Optional description for the webhook */
59
+ description?: string;
60
+ }
61
+ /**
62
+ * Webhook test event payload
63
+ */
64
+ export interface WebhookTestEvent extends DextoWebhookEvent<'tools:available-updated'> {
65
+ /** Indicates this is a test event */
66
+ test: true;
67
+ }
68
+ /**
69
+ * Type-safe webhook handler function signature
70
+ * Provides autocomplete for event types and typed data payloads
71
+ */
72
+ export type WebhookHandler<T extends AgentEventName = AgentEventName> = (event: DextoWebhookEvent<T>) => Promise<void> | void;
73
+ /**
74
+ * Webhook handler mapping for type-safe event routing
75
+ * Provides IDE autocomplete for event names like Stripe webhooks
76
+ */
77
+ export type WebhookEventHandlers = {
78
+ [K in AgentEventName]?: WebhookHandler<K>;
79
+ };
80
+ /**
81
+ * Webhook delivery options
82
+ */
83
+ export interface WebhookDeliveryOptions {
84
+ /** Maximum number of retry attempts */
85
+ maxRetries?: number;
86
+ /** Timeout in milliseconds */
87
+ timeout?: number;
88
+ /** Include signature verification header */
89
+ includeSignature?: boolean;
90
+ }
91
+ //# sourceMappingURL=webhook-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-types.d.ts","sourceRoot":"","sources":["../../src/events/webhook-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEjE;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC1B,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,SAAS,EAAE,IAAI,CAAC;IAChB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc;IACxE,+CAA+C;IAC/C,EAAE,EAAE,MAAM,CAAC;IACX,oDAAoD;IACpD,IAAI,EAAE,CAAC,CAAC;IACR,yDAAyD;IACzD,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IACvB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACvC,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB,CAAC,yBAAyB,CAAC;IAClF,qCAAqC;IACrC,IAAI,EAAE,IAAI,CAAC;CACd;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,IAAI,CACpE,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAC1B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1B;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;KAC9B,CAAC,IAAI,cAAc,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;CAC5C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B"}
File without changes
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var test_fixtures_exports = {};
30
+ __export(test_fixtures_exports, {
31
+ createTestAgent: () => createTestAgent,
32
+ createTestAgentConfig: () => createTestAgentConfig,
33
+ expectResponseStructure: () => expectResponseStructure,
34
+ httpRequest: () => httpRequest,
35
+ startTestServer: () => startTestServer,
36
+ validators: () => validators
37
+ });
38
+ module.exports = __toCommonJS(test_fixtures_exports);
39
+ var import_core = require("@dexto/core");
40
+ var import__ = require("../index.js");
41
+ var import_node = require("../node/index.js");
42
+ function createTestAgentConfig() {
43
+ return {
44
+ systemPrompt: "You are a test assistant.",
45
+ llm: {
46
+ provider: "openai",
47
+ model: "gpt-5-nano",
48
+ apiKey: "test-key-123",
49
+ // Mock key for testing
50
+ router: "vercel",
51
+ maxIterations: 10
52
+ },
53
+ mcpServers: {},
54
+ storage: {
55
+ cache: { type: "in-memory" },
56
+ database: { type: "in-memory" },
57
+ blob: { type: "local", storePath: "/tmp/test-blobs" }
58
+ },
59
+ sessions: {
60
+ maxSessions: 10,
61
+ sessionTTL: 3600
62
+ },
63
+ toolConfirmation: {
64
+ mode: "auto-approve",
65
+ timeout: 12e4
66
+ },
67
+ elicitation: {
68
+ enabled: false,
69
+ timeout: 12e4
70
+ }
71
+ };
72
+ }
73
+ async function createTestAgent(config) {
74
+ const agentConfig = config ?? createTestAgentConfig();
75
+ const agent = new import_core.DextoAgent(agentConfig);
76
+ await agent.start();
77
+ return agent;
78
+ }
79
+ async function startTestServer(agent, port, agentsContext) {
80
+ const serverPort = port ?? await findAvailablePort();
81
+ const agentCard = (0, import_core.createAgentCard)({
82
+ defaultName: "test-agent",
83
+ defaultVersion: "1.0.0",
84
+ defaultBaseUrl: `http://localhost:${serverPort}`
85
+ });
86
+ const getAgent = () => agent;
87
+ const getAgentCard = () => agentCard;
88
+ const { WebhookEventSubscriber } = await import("../../events/webhook-subscriber.js");
89
+ const { A2ASseEventSubscriber } = await import("../../events/a2a-sse-subscriber.js");
90
+ const { ApprovalCoordinator } = await import("../../approval/approval-coordinator.js");
91
+ const webhookSubscriber = new WebhookEventSubscriber();
92
+ const sseSubscriber = new A2ASseEventSubscriber();
93
+ const approvalCoordinator = new ApprovalCoordinator();
94
+ webhookSubscriber.subscribe(agent.agentEventBus);
95
+ sseSubscriber.subscribe(agent.agentEventBus);
96
+ const app = (0, import__.createDextoApp)({
97
+ getAgent,
98
+ getAgentCard,
99
+ approvalCoordinator,
100
+ webhookSubscriber,
101
+ sseSubscriber,
102
+ ...agentsContext ? { agentsContext } : {}
103
+ // Include agentsContext only if provided
104
+ });
105
+ const bridge = (0, import_node.createNodeServer)(app, {
106
+ getAgent: () => agent,
107
+ port: serverPort
108
+ });
109
+ const updatedAgentCard = (0, import_core.createAgentCard)({
110
+ defaultName: "test-agent",
111
+ defaultVersion: "1.0.0",
112
+ defaultBaseUrl: `http://localhost:${serverPort}`
113
+ });
114
+ await new Promise((resolve, reject) => {
115
+ bridge.server.listen(serverPort, "0.0.0.0", () => {
116
+ resolve();
117
+ });
118
+ bridge.server.on("error", reject);
119
+ });
120
+ const baseUrl = `http://localhost:${serverPort}`;
121
+ return {
122
+ server: bridge.server,
123
+ app,
124
+ bridge,
125
+ agent,
126
+ agentCard: updatedAgentCard,
127
+ baseUrl,
128
+ port: serverPort,
129
+ cleanup: async () => {
130
+ webhookSubscriber.cleanup();
131
+ sseSubscriber.cleanup();
132
+ approvalCoordinator.removeAllListeners();
133
+ await new Promise((resolve, reject) => {
134
+ bridge.server.close((err) => {
135
+ if (err) reject(err);
136
+ else resolve();
137
+ });
138
+ });
139
+ if (agent.isStarted()) {
140
+ await agent.stop();
141
+ }
142
+ }
143
+ };
144
+ }
145
+ async function findAvailablePort() {
146
+ const { createServer } = await import("node:http");
147
+ const startPort = 49152 + Math.floor(Math.random() * 1e3);
148
+ for (let port = startPort; port < 65535; port++) {
149
+ try {
150
+ await new Promise((resolve, reject) => {
151
+ const server = createServer();
152
+ server.on("error", (err) => {
153
+ if (err.code === "EADDRINUSE") {
154
+ reject(new Error(`Port ${port} is in use`));
155
+ } else {
156
+ reject(err);
157
+ }
158
+ });
159
+ server.listen(port, () => {
160
+ server.close(() => resolve());
161
+ });
162
+ });
163
+ return port;
164
+ } catch {
165
+ continue;
166
+ }
167
+ }
168
+ throw new Error(`Could not find an available port starting from ${startPort}`);
169
+ }
170
+ async function httpRequest(baseUrl, method, path, body, headers) {
171
+ const url = `${baseUrl}${path}`;
172
+ const options = {
173
+ method,
174
+ headers: {
175
+ "Content-Type": "application/json",
176
+ ...headers
177
+ }
178
+ };
179
+ if (body !== void 0) {
180
+ options.body = JSON.stringify(body);
181
+ }
182
+ const response = await fetch(url, options);
183
+ const text = await response.text();
184
+ let parsedBody;
185
+ try {
186
+ parsedBody = JSON.parse(text);
187
+ } catch {
188
+ parsedBody = text;
189
+ }
190
+ const headersObject = {};
191
+ response.headers.forEach((value, key) => {
192
+ headersObject[key] = value;
193
+ });
194
+ return {
195
+ status: response.status,
196
+ headers: headersObject,
197
+ body: parsedBody,
198
+ text
199
+ };
200
+ }
201
+ function expectResponseStructure(body, schema) {
202
+ if (typeof body !== "object" || body === null) {
203
+ throw new Error(`Expected object response, got ${typeof body}`);
204
+ }
205
+ const bodyObj = body;
206
+ for (const [key, validator] of Object.entries(schema)) {
207
+ if (!(key in bodyObj)) {
208
+ throw new Error(`Missing required field: ${key}`);
209
+ }
210
+ if (!validator(bodyObj[key])) {
211
+ throw new Error(
212
+ `Invalid type for field '${key}': expected validator to return true, got false`
213
+ );
214
+ }
215
+ }
216
+ }
217
+ const validators = {
218
+ string: (value) => typeof value === "string",
219
+ number: (value) => typeof value === "number",
220
+ boolean: (value) => typeof value === "boolean",
221
+ array: (value) => Array.isArray(value),
222
+ object: (value) => typeof value === "object" && value !== null && !Array.isArray(value),
223
+ optionalString: (value) => value === void 0 || typeof value === "string",
224
+ optionalNumber: (value) => value === void 0 || typeof value === "number",
225
+ optionalArray: (value) => value === void 0 || Array.isArray(value),
226
+ optionalObject: (value) => value === void 0 || typeof value === "object" && value !== null && !Array.isArray(value)
227
+ };
228
+ // Annotate the CommonJS export names for ESM import in node:
229
+ 0 && (module.exports = {
230
+ createTestAgent,
231
+ createTestAgentConfig,
232
+ expectResponseStructure,
233
+ httpRequest,
234
+ startTestServer,
235
+ validators
236
+ });
@@ -0,0 +1,65 @@
1
+ import { DextoAgent } from '@dexto/core';
2
+ import type { AgentConfig, AgentCard } from '@dexto/core';
3
+ import type { Server as HttpServer } from 'node:http';
4
+ import type { DextoApp } from '../types.js';
5
+ import { type NodeBridgeResult } from '../node/index.js';
6
+ import type { CreateDextoAppOptions } from '../index.js';
7
+ /**
8
+ * Test configuration for integration tests
9
+ * Uses in-memory storage to avoid side effects
10
+ */
11
+ export declare function createTestAgentConfig(): AgentConfig;
12
+ /**
13
+ * Creates a real DextoAgent instance with in-memory storage
14
+ * No mocks - uses real implementations
15
+ */
16
+ export declare function createTestAgent(config?: AgentConfig): Promise<DextoAgent>;
17
+ /**
18
+ * Test server setup result
19
+ */
20
+ export interface TestServer {
21
+ server: HttpServer;
22
+ app: DextoApp;
23
+ bridge: NodeBridgeResult;
24
+ agent: DextoAgent;
25
+ agentCard: AgentCard;
26
+ baseUrl: string;
27
+ port: number;
28
+ cleanup: () => Promise<void>;
29
+ }
30
+ /**
31
+ * Starts a real HTTP server for testing
32
+ * Uses createDextoApp and createNodeServer directly
33
+ * @param agent - The agent instance to use
34
+ * @param port - Optional port (auto-selected if not provided)
35
+ * @param agentsContext - Optional agent switching context (enables /api/agents routes)
36
+ */
37
+ export declare function startTestServer(agent: DextoAgent, port?: number, agentsContext?: CreateDextoAppOptions['agentsContext']): Promise<TestServer>;
38
+ /**
39
+ * Helper to make HTTP requests to the test server
40
+ */
41
+ export declare function httpRequest(baseUrl: string, method: string, path: string, body?: unknown, headers?: Record<string, string>): Promise<{
42
+ status: number;
43
+ headers: Record<string, string>;
44
+ body: unknown;
45
+ text: string;
46
+ }>;
47
+ /**
48
+ * Validates that a response has the expected structure
49
+ */
50
+ export declare function expectResponseStructure(body: unknown, schema: Record<string, (value: unknown) => boolean>): void;
51
+ /**
52
+ * Common response validators
53
+ */
54
+ export declare const validators: {
55
+ string: (value: unknown) => boolean;
56
+ number: (value: unknown) => boolean;
57
+ boolean: (value: unknown) => boolean;
58
+ array: (value: unknown) => boolean;
59
+ object: (value: unknown) => boolean;
60
+ optionalString: (value: unknown) => boolean;
61
+ optionalNumber: (value: unknown) => boolean;
62
+ optionalArray: (value: unknown) => boolean;
63
+ optionalObject: (value: unknown) => boolean;
64
+ };
65
+ //# sourceMappingURL=test-fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-fixtures.d.ts","sourceRoot":"","sources":["../../../src/hono/__tests__/test-fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,WAAW,CA6BnD;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAK/E;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,QAAQ,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACjC,KAAK,EAAE,UAAU,EACjB,IAAI,CAAC,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,qBAAqB,CAAC,eAAe,CAAC,GACvD,OAAO,CAAC,UAAU,CAAC,CAwFrB;AAmCD;;GAEG;AACH,wBAAsB,WAAW,CAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,OAAO,CAAC;IACP,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC,CAmCD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACnC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,GACpD,IAAI,CAgBN;AAED;;GAEG;AACH,eAAO,MAAM,UAAU;oBACH,OAAO,KAAG,OAAO;oBACjB,OAAO,KAAG,OAAO;qBAChB,OAAO,KAAG,OAAO;mBACnB,OAAO,KAAG,OAAO;oBAChB,OAAO,KAAG,OAAO;4BAET,OAAO,KAAG,OAAO;4BACjB,OAAO,KAAG,OAAO;2BAClB,OAAO,KAAG,OAAO;4BAChB,OAAO,KAAG,OAAO;CAG5C,CAAC"}