@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.
- package/LICENSE +44 -0
- package/dist/a2a/adapters/index.cjs +42 -0
- package/dist/a2a/adapters/index.d.ts +10 -0
- package/dist/a2a/adapters/index.d.ts.map +1 -0
- package/dist/a2a/adapters/index.js +12 -0
- package/dist/a2a/adapters/message.cjs +193 -0
- package/dist/a2a/adapters/message.d.ts +50 -0
- package/dist/a2a/adapters/message.d.ts.map +1 -0
- package/dist/a2a/adapters/message.js +167 -0
- package/dist/a2a/adapters/state.cjs +57 -0
- package/dist/a2a/adapters/state.d.ts +36 -0
- package/dist/a2a/adapters/state.d.ts.map +1 -0
- package/dist/a2a/adapters/state.js +32 -0
- package/dist/a2a/adapters/task-view.cjs +85 -0
- package/dist/a2a/adapters/task-view.d.ts +58 -0
- package/dist/a2a/adapters/task-view.d.ts.map +1 -0
- package/dist/a2a/adapters/task-view.js +60 -0
- package/dist/a2a/index.cjs +51 -0
- package/dist/a2a/index.d.ts +15 -0
- package/dist/a2a/index.d.ts.map +1 -0
- package/dist/a2a/index.js +30 -0
- package/dist/a2a/jsonrpc/index.cjs +38 -0
- package/dist/a2a/jsonrpc/index.d.ts +11 -0
- package/dist/a2a/jsonrpc/index.d.ts.map +1 -0
- package/dist/a2a/jsonrpc/index.js +10 -0
- package/dist/a2a/jsonrpc/methods.cjs +183 -0
- package/dist/a2a/jsonrpc/methods.d.ts +110 -0
- package/dist/a2a/jsonrpc/methods.d.ts.map +1 -0
- package/dist/a2a/jsonrpc/methods.js +159 -0
- package/dist/a2a/jsonrpc/server.cjs +199 -0
- package/dist/a2a/jsonrpc/server.d.ts +100 -0
- package/dist/a2a/jsonrpc/server.d.ts.map +1 -0
- package/dist/a2a/jsonrpc/server.js +175 -0
- package/dist/a2a/jsonrpc/types.cjs +47 -0
- package/dist/a2a/jsonrpc/types.d.ts +91 -0
- package/dist/a2a/jsonrpc/types.d.ts.map +1 -0
- package/dist/a2a/jsonrpc/types.js +21 -0
- package/dist/a2a/types.cjs +16 -0
- package/dist/a2a/types.d.ts +250 -0
- package/dist/a2a/types.d.ts.map +1 -0
- package/dist/a2a/types.js +0 -0
- package/dist/approval/approval-coordinator.cjs +87 -0
- package/dist/approval/approval-coordinator.d.ts +52 -0
- package/dist/approval/approval-coordinator.d.ts.map +1 -0
- package/dist/approval/approval-coordinator.js +63 -0
- package/dist/approval/manual-approval-handler.cjs +100 -0
- package/dist/approval/manual-approval-handler.d.ts +32 -0
- package/dist/approval/manual-approval-handler.d.ts.map +1 -0
- package/dist/approval/manual-approval-handler.js +76 -0
- package/dist/events/a2a-sse-subscriber.cjs +271 -0
- package/dist/events/a2a-sse-subscriber.d.ts +94 -0
- package/dist/events/a2a-sse-subscriber.d.ts.map +1 -0
- package/dist/events/a2a-sse-subscriber.js +247 -0
- package/dist/events/types.cjs +16 -0
- package/dist/events/types.d.ts +15 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +0 -0
- package/dist/events/webhook-subscriber.cjs +301 -0
- package/dist/events/webhook-subscriber.d.ts +64 -0
- package/dist/events/webhook-subscriber.d.ts.map +1 -0
- package/dist/events/webhook-subscriber.js +269 -0
- package/dist/events/webhook-types.cjs +16 -0
- package/dist/events/webhook-types.d.ts +91 -0
- package/dist/events/webhook-types.d.ts.map +1 -0
- package/dist/events/webhook-types.js +0 -0
- package/dist/hono/__tests__/test-fixtures.cjs +236 -0
- package/dist/hono/__tests__/test-fixtures.d.ts +65 -0
- package/dist/hono/__tests__/test-fixtures.d.ts.map +1 -0
- package/dist/hono/__tests__/test-fixtures.js +197 -0
- package/dist/hono/index.cjs +166 -0
- package/dist/hono/index.d.ts +2783 -0
- package/dist/hono/index.d.ts.map +1 -0
- package/dist/hono/index.js +141 -0
- package/dist/hono/middleware/auth.cjs +75 -0
- package/dist/hono/middleware/auth.d.ts +3 -0
- package/dist/hono/middleware/auth.d.ts.map +1 -0
- package/dist/hono/middleware/auth.js +51 -0
- package/dist/hono/middleware/cors.cjs +57 -0
- package/dist/hono/middleware/cors.d.ts +9 -0
- package/dist/hono/middleware/cors.d.ts.map +1 -0
- package/dist/hono/middleware/cors.js +33 -0
- package/dist/hono/middleware/error.cjs +131 -0
- package/dist/hono/middleware/error.d.ts +5 -0
- package/dist/hono/middleware/error.d.ts.map +1 -0
- package/dist/hono/middleware/error.js +105 -0
- package/dist/hono/middleware/redaction.cjs +45 -0
- package/dist/hono/middleware/redaction.d.ts +4 -0
- package/dist/hono/middleware/redaction.d.ts.map +1 -0
- package/dist/hono/middleware/redaction.js +20 -0
- package/dist/hono/node/index.cjs +139 -0
- package/dist/hono/node/index.d.ts +19 -0
- package/dist/hono/node/index.d.ts.map +1 -0
- package/dist/hono/node/index.js +115 -0
- package/dist/hono/routes/a2a-jsonrpc.cjs +119 -0
- package/dist/hono/routes/a2a-jsonrpc.d.ts +46 -0
- package/dist/hono/routes/a2a-jsonrpc.d.ts.map +1 -0
- package/dist/hono/routes/a2a-jsonrpc.js +95 -0
- package/dist/hono/routes/a2a-tasks.cjs +315 -0
- package/dist/hono/routes/a2a-tasks.d.ts +530 -0
- package/dist/hono/routes/a2a-tasks.d.ts.map +1 -0
- package/dist/hono/routes/a2a-tasks.js +291 -0
- package/dist/hono/routes/a2a.cjs +36 -0
- package/dist/hono/routes/a2a.d.ts +4 -0
- package/dist/hono/routes/a2a.d.ts.map +1 -0
- package/dist/hono/routes/a2a.js +12 -0
- package/dist/hono/routes/agents.cjs +735 -0
- package/dist/hono/routes/agents.d.ts +650 -0
- package/dist/hono/routes/agents.d.ts.map +1 -0
- package/dist/hono/routes/agents.js +711 -0
- package/dist/hono/routes/approvals.cjs +125 -0
- package/dist/hono/routes/approvals.d.ts +89 -0
- package/dist/hono/routes/approvals.d.ts.map +1 -0
- package/dist/hono/routes/approvals.js +101 -0
- package/dist/hono/routes/greeting.cjs +60 -0
- package/dist/hono/routes/greeting.d.ts +19 -0
- package/dist/hono/routes/greeting.d.ts.map +1 -0
- package/dist/hono/routes/greeting.js +36 -0
- package/dist/hono/routes/health.cjs +45 -0
- package/dist/hono/routes/health.d.ts +17 -0
- package/dist/hono/routes/health.d.ts.map +1 -0
- package/dist/hono/routes/health.js +21 -0
- package/dist/hono/routes/llm.cjs +298 -0
- package/dist/hono/routes/llm.d.ts +294 -0
- package/dist/hono/routes/llm.d.ts.map +1 -0
- package/dist/hono/routes/llm.js +287 -0
- package/dist/hono/routes/mcp.cjs +356 -0
- package/dist/hono/routes/mcp.d.ts +246 -0
- package/dist/hono/routes/mcp.d.ts.map +1 -0
- package/dist/hono/routes/mcp.js +332 -0
- package/dist/hono/routes/memory.cjs +192 -0
- package/dist/hono/routes/memory.d.ts +146 -0
- package/dist/hono/routes/memory.d.ts.map +1 -0
- package/dist/hono/routes/memory.js +168 -0
- package/dist/hono/routes/messages.cjs +320 -0
- package/dist/hono/routes/messages.d.ts +163 -0
- package/dist/hono/routes/messages.d.ts.map +1 -0
- package/dist/hono/routes/messages.js +296 -0
- package/dist/hono/routes/prompts.cjs +228 -0
- package/dist/hono/routes/prompts.d.ts +150 -0
- package/dist/hono/routes/prompts.d.ts.map +1 -0
- package/dist/hono/routes/prompts.js +204 -0
- package/dist/hono/routes/resources.cjs +110 -0
- package/dist/hono/routes/resources.d.ts +76 -0
- package/dist/hono/routes/resources.d.ts.map +1 -0
- package/dist/hono/routes/resources.js +86 -0
- package/dist/hono/routes/search.cjs +109 -0
- package/dist/hono/routes/search.d.ts +137 -0
- package/dist/hono/routes/search.d.ts.map +1 -0
- package/dist/hono/routes/search.js +85 -0
- package/dist/hono/routes/sessions.cjs +366 -0
- package/dist/hono/routes/sessions.d.ts +229 -0
- package/dist/hono/routes/sessions.d.ts.map +1 -0
- package/dist/hono/routes/sessions.js +342 -0
- package/dist/hono/routes/webhooks.cjs +228 -0
- package/dist/hono/routes/webhooks.d.ts +127 -0
- package/dist/hono/routes/webhooks.d.ts.map +1 -0
- package/dist/hono/routes/webhooks.js +204 -0
- package/dist/hono/schemas/responses.cjs +276 -0
- package/dist/hono/schemas/responses.d.ts +1418 -0
- package/dist/hono/schemas/responses.d.ts.map +1 -0
- package/dist/hono/schemas/responses.js +227 -0
- package/dist/hono/types.cjs +16 -0
- package/dist/hono/types.d.ts +6 -0
- package/dist/hono/types.d.ts.map +1 -0
- package/dist/hono/types.js +0 -0
- package/dist/index.cjs +38 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/mcp/mcp-handler.cjs +145 -0
- package/dist/mcp/mcp-handler.d.ts +14 -0
- package/dist/mcp/mcp-handler.d.ts.map +1 -0
- package/dist/mcp/mcp-handler.js +118 -0
- 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"}
|