agentxjs 0.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 (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +602 -0
  3. package/dist/index.cjs +1292 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +88 -0
  6. package/dist/index.d.ts +88 -0
  7. package/dist/index.js +1283 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/runtime/sse/index.cjs +633 -0
  10. package/dist/runtime/sse/index.cjs.map +1 -0
  11. package/dist/runtime/sse/index.d.cts +159 -0
  12. package/dist/runtime/sse/index.d.ts +159 -0
  13. package/dist/runtime/sse/index.js +621 -0
  14. package/dist/runtime/sse/index.js.map +1 -0
  15. package/dist/server/adapters/express.cjs +81 -0
  16. package/dist/server/adapters/express.cjs.map +1 -0
  17. package/dist/server/adapters/express.d.cts +75 -0
  18. package/dist/server/adapters/express.d.ts +75 -0
  19. package/dist/server/adapters/express.js +78 -0
  20. package/dist/server/adapters/express.js.map +1 -0
  21. package/dist/server/adapters/hono.cjs +32 -0
  22. package/dist/server/adapters/hono.cjs.map +1 -0
  23. package/dist/server/adapters/hono.d.cts +96 -0
  24. package/dist/server/adapters/hono.d.ts +96 -0
  25. package/dist/server/adapters/hono.js +28 -0
  26. package/dist/server/adapters/hono.js.map +1 -0
  27. package/dist/server/adapters/index.cjs +135 -0
  28. package/dist/server/adapters/index.cjs.map +1 -0
  29. package/dist/server/adapters/index.d.cts +5 -0
  30. package/dist/server/adapters/index.d.ts +5 -0
  31. package/dist/server/adapters/index.js +125 -0
  32. package/dist/server/adapters/index.js.map +1 -0
  33. package/dist/server/adapters/next.cjs +30 -0
  34. package/dist/server/adapters/next.cjs.map +1 -0
  35. package/dist/server/adapters/next.d.cts +107 -0
  36. package/dist/server/adapters/next.d.ts +107 -0
  37. package/dist/server/adapters/next.js +25 -0
  38. package/dist/server/adapters/next.js.map +1 -0
  39. package/dist/server/index.cjs +1093 -0
  40. package/dist/server/index.cjs.map +1 -0
  41. package/dist/server/index.d.cts +131 -0
  42. package/dist/server/index.d.ts +131 -0
  43. package/dist/server/index.js +1080 -0
  44. package/dist/server/index.js.map +1 -0
  45. package/dist/types-Cgfcw91r.d.cts +282 -0
  46. package/dist/types-Cgfcw91r.d.ts +282 -0
  47. package/dist/types-OVKV6qpE.d.cts +118 -0
  48. package/dist/types-OVKV6qpE.d.ts +118 -0
  49. package/package.json +78 -0
@@ -0,0 +1,1093 @@
1
+ 'use strict';
2
+
3
+ var types = require('@agentxjs/types');
4
+ var common = require('@agentxjs/common');
5
+
6
+ var __defProp = Object.defineProperty;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
9
+ var logger = common.createLogger("agentx/SSEServerTransport");
10
+ var SSEConnection = class {
11
+ constructor(connectionId, agentId) {
12
+ __publicField(this, "connectionId");
13
+ __publicField(this, "agentId");
14
+ __publicField(this, "_state", "connecting");
15
+ __publicField(this, "_controller", null);
16
+ __publicField(this, "_encoder", new TextEncoder());
17
+ __publicField(this, "_closeHandlers", []);
18
+ __publicField(this, "_unsubscribe", null);
19
+ __publicField(this, "_heartbeatInterval", null);
20
+ this.connectionId = connectionId;
21
+ this.agentId = agentId;
22
+ logger.debug("SSE connection created", {
23
+ connectionId,
24
+ agentId
25
+ });
26
+ }
27
+ get state() {
28
+ return this._state;
29
+ }
30
+ /**
31
+ * Create SSE Response stream
32
+ */
33
+ createResponse(agent) {
34
+ const stream = new ReadableStream({
35
+ start: (controller) => {
36
+ this._controller = controller;
37
+ this._state = "open";
38
+ this._unsubscribe = agent.on((event) => {
39
+ if (types.isStreamEvent(event)) {
40
+ this.send(event);
41
+ } else if (types.isErrorEvent(event)) {
42
+ this.sendError(event);
43
+ }
44
+ });
45
+ this._heartbeatInterval = setInterval(() => {
46
+ this.sendHeartbeat();
47
+ }, 3e4);
48
+ },
49
+ cancel: () => {
50
+ this.close();
51
+ }
52
+ });
53
+ return new Response(stream, {
54
+ headers: {
55
+ "Content-Type": "text/event-stream",
56
+ "Cache-Control": "no-cache",
57
+ Connection: "keep-alive",
58
+ "X-Accel-Buffering": "no"
59
+ // Disable nginx buffering
60
+ }
61
+ });
62
+ }
63
+ /**
64
+ * Send a Stream event to the client
65
+ */
66
+ send(event) {
67
+ if (this._state !== "open" || !this._controller) {
68
+ return;
69
+ }
70
+ try {
71
+ const eventType = event.type;
72
+ const data = JSON.stringify(event);
73
+ const message = `event: ${eventType}
74
+ data: ${data}
75
+
76
+ `;
77
+ this._controller.enqueue(this._encoder.encode(message));
78
+ } catch {
79
+ this.close();
80
+ }
81
+ }
82
+ /**
83
+ * Send an Error event to the client
84
+ *
85
+ * ErrorEvent is independent from Stream events but also transported via SSE.
86
+ */
87
+ sendError(event) {
88
+ if (this._state !== "open" || !this._controller) {
89
+ return;
90
+ }
91
+ try {
92
+ const eventType = event.type;
93
+ const data = JSON.stringify(event);
94
+ const message = `event: ${eventType}
95
+ data: ${data}
96
+
97
+ `;
98
+ this._controller.enqueue(this._encoder.encode(message));
99
+ } catch {
100
+ this.close();
101
+ }
102
+ }
103
+ /**
104
+ * Send heartbeat to keep connection alive
105
+ */
106
+ sendHeartbeat() {
107
+ if (this._state !== "open" || !this._controller) {
108
+ return;
109
+ }
110
+ try {
111
+ const message = `: heartbeat ${Date.now()}
112
+
113
+ `;
114
+ this._controller.enqueue(this._encoder.encode(message));
115
+ } catch {
116
+ this.close();
117
+ }
118
+ }
119
+ /**
120
+ * Close the connection
121
+ */
122
+ close() {
123
+ if (this._state === "closed" || this._state === "closing") {
124
+ return;
125
+ }
126
+ logger.debug("Closing SSE connection", {
127
+ connectionId: this.connectionId,
128
+ agentId: this.agentId
129
+ });
130
+ this._state = "closing";
131
+ if (this._heartbeatInterval) {
132
+ clearInterval(this._heartbeatInterval);
133
+ this._heartbeatInterval = null;
134
+ }
135
+ if (this._unsubscribe) {
136
+ this._unsubscribe();
137
+ this._unsubscribe = null;
138
+ }
139
+ if (this._controller) {
140
+ try {
141
+ this._controller.close();
142
+ } catch {
143
+ }
144
+ this._controller = null;
145
+ }
146
+ this._state = "closed";
147
+ for (const handler of this._closeHandlers) {
148
+ try {
149
+ handler();
150
+ } catch {
151
+ }
152
+ }
153
+ this._closeHandlers = [];
154
+ }
155
+ /**
156
+ * Register close handler
157
+ */
158
+ onClose(handler) {
159
+ if (this._state === "closed") {
160
+ handler();
161
+ } else {
162
+ this._closeHandlers.push(handler);
163
+ }
164
+ }
165
+ };
166
+ var SSEConnectionManager = class {
167
+ constructor() {
168
+ __publicField(this, "_connections", /* @__PURE__ */ new Map());
169
+ __publicField(this, "_idCounter", 0);
170
+ }
171
+ /**
172
+ * Create a new SSE connection for an agent
173
+ */
174
+ createConnection(agent) {
175
+ const connectionId = `conn_${++this._idCounter}_${Date.now()}`;
176
+ const connection = new SSEConnection(connectionId, agent.agentId);
177
+ const response = connection.createResponse(agent);
178
+ this._connections.set(connectionId, connection);
179
+ connection.onClose(() => {
180
+ this._connections.delete(connectionId);
181
+ });
182
+ return { connection, response };
183
+ }
184
+ /**
185
+ * Get connection by ID
186
+ */
187
+ getConnection(connectionId) {
188
+ return this._connections.get(connectionId);
189
+ }
190
+ /**
191
+ * Get all connections for an agent
192
+ */
193
+ getConnectionsForAgent(agentId) {
194
+ return Array.from(this._connections.values()).filter((conn) => conn.agentId === agentId);
195
+ }
196
+ /**
197
+ * Close all connections for an agent
198
+ */
199
+ closeConnectionsForAgent(agentId) {
200
+ for (const conn of this.getConnectionsForAgent(agentId)) {
201
+ conn.close();
202
+ }
203
+ }
204
+ /**
205
+ * Close all connections
206
+ */
207
+ closeAll() {
208
+ for (const conn of this._connections.values()) {
209
+ conn.close();
210
+ }
211
+ this._connections.clear();
212
+ }
213
+ /**
214
+ * Get active connection count
215
+ */
216
+ get connectionCount() {
217
+ return this._connections.size;
218
+ }
219
+ };
220
+ var logger2 = common.createLogger("agentx/AgentXHandler");
221
+ var VERSION = "0.1.0";
222
+ function createAgentXHandler(agentx, options = {}) {
223
+ const {
224
+ basePath = "",
225
+ allowDynamicCreation = false,
226
+ allowedDefinitions = [],
227
+ repository,
228
+ hooks = {}
229
+ } = options;
230
+ const sseManager = new SSEConnectionManager();
231
+ const definitions = /* @__PURE__ */ new Map();
232
+ function registerDefinition(name, definition, defaultConfig) {
233
+ definitions.set(name, { definition, defaultConfig });
234
+ }
235
+ function parseRequest(request) {
236
+ const url = new URL(request.url);
237
+ const method = request.method;
238
+ let path = url.pathname;
239
+ if (basePath && path.startsWith(basePath)) {
240
+ path = path.slice(basePath.length);
241
+ }
242
+ path = "/" + path.replace(/^\/+|\/+$/g, "");
243
+ if (method === "GET" && path === "/info") {
244
+ return { type: "platform_info" };
245
+ }
246
+ if (method === "GET" && path === "/health") {
247
+ return { type: "platform_health" };
248
+ }
249
+ if (method === "GET" && path === "/agents") {
250
+ return { type: "list_agents" };
251
+ }
252
+ if (method === "POST" && path === "/agents") {
253
+ return { type: "create_agent" };
254
+ }
255
+ const agentMatch = path.match(/^\/agents\/([^/]+)(\/.*)?$/);
256
+ if (agentMatch) {
257
+ const agentId = agentMatch[1];
258
+ const subPath = agentMatch[2] || "";
259
+ if (method === "GET" && subPath === "") {
260
+ return { type: "get_agent", agentId };
261
+ }
262
+ if (method === "DELETE" && subPath === "") {
263
+ return { type: "delete_agent", agentId };
264
+ }
265
+ if (method === "GET" && subPath === "/sse") {
266
+ return { type: "connect_sse", agentId };
267
+ }
268
+ if (method === "POST" && subPath === "/messages") {
269
+ return { type: "send_message", agentId };
270
+ }
271
+ if (method === "POST" && subPath === "/interrupt") {
272
+ return { type: "interrupt", agentId };
273
+ }
274
+ }
275
+ if (method === "GET" && path === "/definitions") {
276
+ return { type: "list_definitions" };
277
+ }
278
+ const definitionMatch = path.match(/^\/definitions\/([^/]+)$/);
279
+ if (definitionMatch) {
280
+ const definitionName = definitionMatch[1];
281
+ if (method === "GET") {
282
+ return { type: "get_definition", definitionName };
283
+ }
284
+ if (method === "PUT") {
285
+ return { type: "save_definition", definitionName };
286
+ }
287
+ if (method === "DELETE") {
288
+ return { type: "delete_definition", definitionName };
289
+ }
290
+ if (method === "HEAD") {
291
+ return { type: "head_definition", definitionName };
292
+ }
293
+ }
294
+ if (method === "GET" && path === "/images") {
295
+ return { type: "list_images" };
296
+ }
297
+ const imageMatch = path.match(/^\/images\/([^/]+)(\/.*)?$/);
298
+ if (imageMatch) {
299
+ const imageId = imageMatch[1];
300
+ const subPath = imageMatch[2] || "";
301
+ if (method === "GET" && subPath === "") {
302
+ return { type: "get_image", imageId };
303
+ }
304
+ if (method === "PUT" && subPath === "") {
305
+ return { type: "save_image", imageId };
306
+ }
307
+ if (method === "DELETE" && subPath === "") {
308
+ return { type: "delete_image", imageId };
309
+ }
310
+ if (method === "HEAD" && subPath === "") {
311
+ return { type: "head_image", imageId };
312
+ }
313
+ if (method === "GET" && subPath === "/sessions") {
314
+ return { type: "list_image_sessions", imageId };
315
+ }
316
+ if (method === "DELETE" && subPath === "/sessions") {
317
+ return { type: "delete_image_sessions", imageId };
318
+ }
319
+ if (method === "POST" && subPath === "/run") {
320
+ return { type: "run_image", imageId };
321
+ }
322
+ }
323
+ if (method === "GET" && path === "/sessions") {
324
+ return { type: "list_sessions" };
325
+ }
326
+ const sessionMatch = path.match(/^\/sessions\/([^/]+)(\/.*)?$/);
327
+ if (sessionMatch) {
328
+ const sessionId = sessionMatch[1];
329
+ const subPath = sessionMatch[2] || "";
330
+ if (method === "GET" && subPath === "") {
331
+ return { type: "get_session", sessionId };
332
+ }
333
+ if (method === "PUT" && subPath === "") {
334
+ return { type: "save_session", sessionId };
335
+ }
336
+ if (method === "DELETE" && subPath === "") {
337
+ return { type: "delete_session", sessionId };
338
+ }
339
+ if (method === "HEAD" && subPath === "") {
340
+ return { type: "head_session", sessionId };
341
+ }
342
+ if (method === "GET" && subPath === "/messages") {
343
+ return { type: "list_session_messages", sessionId };
344
+ }
345
+ if (method === "DELETE" && subPath === "/messages") {
346
+ return { type: "delete_session_messages", sessionId };
347
+ }
348
+ if (method === "GET" && subPath === "/messages/count") {
349
+ return { type: "count_session_messages", sessionId };
350
+ }
351
+ if (method === "POST" && subPath === "/resume") {
352
+ return { type: "resume_session", sessionId };
353
+ }
354
+ }
355
+ const userMatch = path.match(/^\/users\/([^/]+)\/sessions$/);
356
+ if (userMatch && method === "GET") {
357
+ return { type: "list_user_sessions", userId: userMatch[1] };
358
+ }
359
+ const messageMatch = path.match(/^\/messages\/([^/]+)$/);
360
+ if (messageMatch) {
361
+ const messageId = messageMatch[1];
362
+ if (method === "GET") {
363
+ return { type: "get_message", messageId };
364
+ }
365
+ if (method === "PUT") {
366
+ return { type: "save_message", messageId };
367
+ }
368
+ if (method === "DELETE") {
369
+ return { type: "delete_message", messageId };
370
+ }
371
+ }
372
+ if (method === "GET" && path === "/containers") {
373
+ return { type: "list_containers" };
374
+ }
375
+ if (method === "POST" && path === "/containers") {
376
+ return { type: "create_container" };
377
+ }
378
+ const containerMatch = path.match(/^\/containers\/([^/]+)$/);
379
+ if (containerMatch) {
380
+ const containerId = containerMatch[1];
381
+ if (method === "GET") {
382
+ return { type: "get_container", containerId };
383
+ }
384
+ if (method === "PUT") {
385
+ return { type: "save_container", containerId };
386
+ }
387
+ if (method === "DELETE") {
388
+ return { type: "delete_container", containerId };
389
+ }
390
+ if (method === "HEAD") {
391
+ return { type: "head_container", containerId };
392
+ }
393
+ }
394
+ return { type: "not_found" };
395
+ }
396
+ function jsonResponse(data, status = 200) {
397
+ return new Response(JSON.stringify(data), {
398
+ status,
399
+ headers: {
400
+ "Content-Type": "application/json"
401
+ }
402
+ });
403
+ }
404
+ function errorResponse(code, message, status) {
405
+ const body = {
406
+ error: { code, message }
407
+ };
408
+ return jsonResponse(body, status);
409
+ }
410
+ function getAgentOrError(agentId) {
411
+ const agent = agentx.agents.get(agentId);
412
+ if (!agent) {
413
+ return errorResponse("AGENT_NOT_FOUND", `Agent ${agentId} not found`, 404);
414
+ }
415
+ if (agent.lifecycle === "destroyed") {
416
+ return errorResponse("AGENT_DESTROYED", `Agent ${agentId} has been destroyed`, 410);
417
+ }
418
+ return agent;
419
+ }
420
+ function buildAgentInfo(agent) {
421
+ return {
422
+ agentId: agent.agentId,
423
+ name: agent.definition.name,
424
+ description: agent.definition.description,
425
+ lifecycle: agent.lifecycle,
426
+ state: agent.state,
427
+ createdAt: agent.createdAt
428
+ };
429
+ }
430
+ async function handlePlatformInfo() {
431
+ const response = {
432
+ platform: "AgentX",
433
+ version: VERSION,
434
+ agentCount: agentx.agents.list().length
435
+ };
436
+ return jsonResponse(response);
437
+ }
438
+ async function handleHealth() {
439
+ const response = {
440
+ status: "healthy",
441
+ timestamp: Date.now(),
442
+ agentCount: agentx.agents.list().length
443
+ };
444
+ return jsonResponse(response);
445
+ }
446
+ async function handleListAgents() {
447
+ const allAgents = agentx.agents.list();
448
+ const agents = allAgents.map((agent) => buildAgentInfo(agent));
449
+ const response = { agents };
450
+ return jsonResponse(response);
451
+ }
452
+ async function handleCreateAgent(request) {
453
+ if (!allowDynamicCreation) {
454
+ return errorResponse("DYNAMIC_CREATION_DISABLED", "Dynamic agent creation is disabled", 403);
455
+ }
456
+ let body;
457
+ try {
458
+ body = await request.json();
459
+ } catch {
460
+ return errorResponse("INVALID_REQUEST", "Invalid JSON body", 400);
461
+ }
462
+ if (!body.definition) {
463
+ return errorResponse("INVALID_REQUEST", "Missing 'definition' field", 400);
464
+ }
465
+ if (allowedDefinitions.length > 0 && !allowedDefinitions.includes(body.definition)) {
466
+ return errorResponse(
467
+ "DEFINITION_NOT_FOUND",
468
+ `Definition '${body.definition}' is not allowed`,
469
+ 403
470
+ );
471
+ }
472
+ const registered = definitions.get(body.definition);
473
+ if (!registered) {
474
+ return errorResponse(
475
+ "DEFINITION_NOT_FOUND",
476
+ `Definition '${body.definition}' not found`,
477
+ 404
478
+ );
479
+ }
480
+ const metaImage = await agentx.images.getMetaImage(body.definition);
481
+ if (!metaImage) {
482
+ return errorResponse(
483
+ "IMAGE_NOT_FOUND",
484
+ `MetaImage for definition '${body.definition}' not found`,
485
+ 404
486
+ );
487
+ }
488
+ const agent = await agentx.images.run(metaImage.imageId);
489
+ const response = {
490
+ agentId: agent.agentId,
491
+ name: agent.definition.name,
492
+ lifecycle: agent.lifecycle,
493
+ state: agent.state,
494
+ createdAt: agent.createdAt,
495
+ endpoints: {
496
+ sse: `${basePath}/agents/${agent.agentId}/sse`,
497
+ messages: `${basePath}/agents/${agent.agentId}/messages`,
498
+ interrupt: `${basePath}/agents/${agent.agentId}/interrupt`
499
+ }
500
+ };
501
+ return jsonResponse(response, 201);
502
+ }
503
+ async function handleGetAgent(agentId) {
504
+ const result = getAgentOrError(agentId);
505
+ if (result instanceof Response) return result;
506
+ return jsonResponse(buildAgentInfo(result));
507
+ }
508
+ async function handleDeleteAgent(agentId) {
509
+ const result = getAgentOrError(agentId);
510
+ if (result instanceof Response) return result;
511
+ sseManager.closeConnectionsForAgent(agentId);
512
+ await agentx.agents.destroy(agentId);
513
+ return new Response(null, { status: 204 });
514
+ }
515
+ async function handleConnectSSE(agentId) {
516
+ const result = getAgentOrError(agentId);
517
+ if (result instanceof Response) return result;
518
+ const agent = result;
519
+ const { connection, response } = sseManager.createConnection(agent);
520
+ if (hooks.onConnect) {
521
+ try {
522
+ await hooks.onConnect(agentId, connection.connectionId);
523
+ } catch {
524
+ }
525
+ }
526
+ connection.onClose(() => {
527
+ if (hooks.onDisconnect) {
528
+ const result2 = hooks.onDisconnect(agentId, connection.connectionId);
529
+ if (result2 instanceof Promise) {
530
+ result2.catch(() => {
531
+ });
532
+ }
533
+ }
534
+ });
535
+ return response;
536
+ }
537
+ async function handleSendMessage(agentId, request) {
538
+ const result = getAgentOrError(agentId);
539
+ if (result instanceof Response) return result;
540
+ const agent = result;
541
+ if (agent.state !== "idle") {
542
+ return errorResponse("AGENT_BUSY", `Agent is currently ${agent.state}`, 409);
543
+ }
544
+ let body;
545
+ try {
546
+ body = await request.json();
547
+ } catch {
548
+ return errorResponse("INVALID_REQUEST", "Invalid JSON body", 400);
549
+ }
550
+ if (!body.content) {
551
+ return errorResponse("INVALID_REQUEST", "Missing 'content' field", 400);
552
+ }
553
+ const message = {
554
+ id: `msg_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
555
+ role: "user",
556
+ subtype: "user",
557
+ content: typeof body.content === "string" ? body.content : body.content,
558
+ timestamp: Date.now()
559
+ };
560
+ if (hooks.onMessage) {
561
+ try {
562
+ await hooks.onMessage(agentId, message);
563
+ } catch {
564
+ }
565
+ }
566
+ agent.receive(message).catch((error) => {
567
+ if (hooks.onError) {
568
+ const result2 = hooks.onError(agentId, error);
569
+ if (result2 instanceof Promise) {
570
+ result2.catch(() => {
571
+ });
572
+ }
573
+ }
574
+ });
575
+ const response = {
576
+ status: "processing"
577
+ };
578
+ return jsonResponse(response, 202);
579
+ }
580
+ async function handleInterrupt(agentId) {
581
+ const result = getAgentOrError(agentId);
582
+ if (result instanceof Response) return result;
583
+ const agent = result;
584
+ agent.interrupt();
585
+ const response = {
586
+ interrupted: true
587
+ };
588
+ return jsonResponse(response);
589
+ }
590
+ function getRepository() {
591
+ if (!repository) {
592
+ throw new Error(
593
+ "Repository not configured. Pass 'repository' option to createAgentXHandler."
594
+ );
595
+ }
596
+ return repository;
597
+ }
598
+ async function handleListDefinitions() {
599
+ const repo = getRepository();
600
+ const definitions2 = await repo.findAllDefinitions();
601
+ return jsonResponse(definitions2);
602
+ }
603
+ async function handleGetDefinition(name) {
604
+ const repo = getRepository();
605
+ const definition = await repo.findDefinitionByName(name);
606
+ if (!definition) {
607
+ return errorResponse("INVALID_REQUEST", `Definition ${name} not found`, 404);
608
+ }
609
+ return jsonResponse(definition);
610
+ }
611
+ async function handleSaveDefinition(name, request) {
612
+ const repo = getRepository();
613
+ let body;
614
+ try {
615
+ body = await request.json();
616
+ } catch {
617
+ return errorResponse("INVALID_REQUEST", "Invalid JSON body", 400);
618
+ }
619
+ await repo.saveDefinition({ ...body, name });
620
+ return new Response(null, { status: 204 });
621
+ }
622
+ async function handleDeleteDefinition(name) {
623
+ const repo = getRepository();
624
+ await repo.deleteDefinition(name);
625
+ return new Response(null, { status: 204 });
626
+ }
627
+ async function handleHeadDefinition(name) {
628
+ const repo = getRepository();
629
+ const exists = await repo.definitionExists(name);
630
+ return new Response(null, { status: exists ? 200 : 404 });
631
+ }
632
+ async function handleListImages() {
633
+ const repo = getRepository();
634
+ const images = await repo.findAllImages();
635
+ return jsonResponse(images);
636
+ }
637
+ async function handleGetImage(imageId) {
638
+ const repo = getRepository();
639
+ const image = await repo.findImageById(imageId);
640
+ if (!image) {
641
+ return errorResponse("INVALID_REQUEST", `Image ${imageId} not found`, 404);
642
+ }
643
+ return jsonResponse(image);
644
+ }
645
+ async function handleSaveImage(imageId, request) {
646
+ const repo = getRepository();
647
+ let body;
648
+ try {
649
+ body = await request.json();
650
+ } catch {
651
+ return errorResponse("INVALID_REQUEST", "Invalid JSON body", 400);
652
+ }
653
+ await repo.saveImage({ ...body, imageId });
654
+ return new Response(null, { status: 204 });
655
+ }
656
+ async function handleDeleteImage(imageId) {
657
+ const repo = getRepository();
658
+ await repo.deleteImage(imageId);
659
+ return new Response(null, { status: 204 });
660
+ }
661
+ async function handleHeadImage(imageId) {
662
+ const repo = getRepository();
663
+ const exists = await repo.imageExists(imageId);
664
+ return new Response(null, { status: exists ? 200 : 404 });
665
+ }
666
+ async function handleListImageSessions(imageId) {
667
+ const repo = getRepository();
668
+ const sessions = await repo.findSessionsByImageId(imageId);
669
+ return jsonResponse(sessions);
670
+ }
671
+ async function handleDeleteImageSessions(imageId) {
672
+ const repo = getRepository();
673
+ await repo.deleteSessionsByImageId(imageId);
674
+ return new Response(null, { status: 204 });
675
+ }
676
+ async function handleRunImage(imageId, request) {
677
+ let containerId;
678
+ try {
679
+ const body = await request.json();
680
+ containerId = body.containerId;
681
+ } catch {
682
+ }
683
+ const agent = await agentx.images.run(imageId, { containerId });
684
+ const response = {
685
+ agentId: agent.agentId,
686
+ name: agent.definition.name,
687
+ lifecycle: agent.lifecycle,
688
+ state: agent.state,
689
+ createdAt: agent.createdAt,
690
+ endpoints: {
691
+ sse: `${basePath}/agents/${agent.agentId}/sse`,
692
+ messages: `${basePath}/agents/${agent.agentId}/messages`,
693
+ interrupt: `${basePath}/agents/${agent.agentId}/interrupt`
694
+ }
695
+ };
696
+ return jsonResponse(response, 201);
697
+ }
698
+ async function handleListSessions() {
699
+ const repo = getRepository();
700
+ const sessions = await repo.findAllSessions();
701
+ return jsonResponse(sessions);
702
+ }
703
+ async function handleGetSession(sessionId) {
704
+ const repo = getRepository();
705
+ const session = await repo.findSessionById(sessionId);
706
+ if (!session) {
707
+ return errorResponse("INVALID_REQUEST", `Session ${sessionId} not found`, 404);
708
+ }
709
+ return jsonResponse(session);
710
+ }
711
+ async function handleSaveSession(sessionId, request) {
712
+ const repo = getRepository();
713
+ let body;
714
+ try {
715
+ body = await request.json();
716
+ } catch {
717
+ return errorResponse("INVALID_REQUEST", "Invalid JSON body", 400);
718
+ }
719
+ await repo.saveSession({ ...body, sessionId });
720
+ return new Response(null, { status: 204 });
721
+ }
722
+ async function handleDeleteSession(sessionId) {
723
+ const repo = getRepository();
724
+ await repo.deleteSession(sessionId);
725
+ return new Response(null, { status: 204 });
726
+ }
727
+ async function handleHeadSession(sessionId) {
728
+ const repo = getRepository();
729
+ const exists = await repo.sessionExists(sessionId);
730
+ return new Response(null, { status: exists ? 200 : 404 });
731
+ }
732
+ async function handleListSessionMessages(sessionId) {
733
+ const repo = getRepository();
734
+ const messages = await repo.findMessagesBySessionId(sessionId);
735
+ return jsonResponse(messages);
736
+ }
737
+ async function handleDeleteSessionMessages(sessionId) {
738
+ const repo = getRepository();
739
+ await repo.deleteMessagesBySessionId(sessionId);
740
+ return new Response(null, { status: 204 });
741
+ }
742
+ async function handleCountSessionMessages(sessionId) {
743
+ const repo = getRepository();
744
+ const count = await repo.countMessagesBySessionId(sessionId);
745
+ return jsonResponse({ count });
746
+ }
747
+ async function handleResumeSession(sessionId, request) {
748
+ const session = await agentx.sessions.get(sessionId);
749
+ if (!session) {
750
+ return errorResponse("INVALID_REQUEST", `Session ${sessionId} not found`, 404);
751
+ }
752
+ let containerId;
753
+ try {
754
+ const body = await request.json();
755
+ containerId = body.containerId;
756
+ } catch {
757
+ }
758
+ const agent = await session.resume({ containerId });
759
+ const response = {
760
+ agentId: agent.agentId,
761
+ name: agent.definition.name,
762
+ lifecycle: agent.lifecycle,
763
+ state: agent.state,
764
+ createdAt: agent.createdAt,
765
+ endpoints: {
766
+ sse: `${basePath}/agents/${agent.agentId}/sse`,
767
+ messages: `${basePath}/agents/${agent.agentId}/messages`,
768
+ interrupt: `${basePath}/agents/${agent.agentId}/interrupt`
769
+ }
770
+ };
771
+ return jsonResponse(response, 201);
772
+ }
773
+ async function handleListUserSessions(userId) {
774
+ const repo = getRepository();
775
+ const sessions = await repo.findSessionsByUserId(userId);
776
+ return jsonResponse(sessions);
777
+ }
778
+ async function handleGetMessage(messageId) {
779
+ const repo = getRepository();
780
+ const message = await repo.findMessageById(messageId);
781
+ if (!message) {
782
+ return errorResponse("INVALID_REQUEST", `Message ${messageId} not found`, 404);
783
+ }
784
+ return jsonResponse(message);
785
+ }
786
+ async function handleSaveMessage(messageId, request) {
787
+ const repo = getRepository();
788
+ let body;
789
+ try {
790
+ body = await request.json();
791
+ } catch {
792
+ return errorResponse("INVALID_REQUEST", "Invalid JSON body", 400);
793
+ }
794
+ await repo.saveMessage({ ...body, messageId });
795
+ return new Response(null, { status: 204 });
796
+ }
797
+ async function handleDeleteMessage(messageId) {
798
+ const repo = getRepository();
799
+ await repo.deleteMessage(messageId);
800
+ return new Response(null, { status: 204 });
801
+ }
802
+ async function handleListContainers() {
803
+ const repo = getRepository();
804
+ const containers = await repo.findAllContainers();
805
+ return jsonResponse(containers);
806
+ }
807
+ async function handleCreateContainer(request) {
808
+ let config;
809
+ try {
810
+ const body = await request.json();
811
+ config = body.config;
812
+ } catch {
813
+ }
814
+ const container = await agentx.containers.create(config);
815
+ return jsonResponse(container, 201);
816
+ }
817
+ async function handleGetContainer(containerId) {
818
+ const container = await agentx.containers.get(containerId);
819
+ if (!container) {
820
+ return errorResponse("INVALID_REQUEST", `Container ${containerId} not found`, 404);
821
+ }
822
+ return jsonResponse(container);
823
+ }
824
+ async function handleDeleteContainer(containerId) {
825
+ const deleted = await agentx.containers.delete(containerId);
826
+ if (!deleted) {
827
+ return errorResponse("INVALID_REQUEST", `Container ${containerId} not found`, 404);
828
+ }
829
+ return new Response(null, { status: 204 });
830
+ }
831
+ async function handleHeadContainer(containerId) {
832
+ const exists = await agentx.containers.exists(containerId);
833
+ return new Response(null, { status: exists ? 200 : 404 });
834
+ }
835
+ async function handleSaveContainer(containerId, request) {
836
+ const repo = getRepository();
837
+ let body;
838
+ try {
839
+ body = await request.json();
840
+ } catch {
841
+ return errorResponse("INVALID_REQUEST", "Invalid JSON body", 400);
842
+ }
843
+ await repo.saveContainer({ ...body, containerId });
844
+ return new Response(null, { status: 204 });
845
+ }
846
+ const handler = async (request) => {
847
+ try {
848
+ const parsed = parseRequest(request);
849
+ switch (parsed.type) {
850
+ // Platform
851
+ case "platform_info":
852
+ return handlePlatformInfo();
853
+ case "platform_health":
854
+ return handleHealth();
855
+ // Agents
856
+ case "list_agents":
857
+ return handleListAgents();
858
+ case "create_agent":
859
+ return handleCreateAgent(request);
860
+ case "get_agent":
861
+ return handleGetAgent(parsed.agentId);
862
+ case "delete_agent":
863
+ return handleDeleteAgent(parsed.agentId);
864
+ case "connect_sse":
865
+ return handleConnectSSE(parsed.agentId);
866
+ case "send_message":
867
+ return handleSendMessage(parsed.agentId, request);
868
+ case "interrupt":
869
+ return handleInterrupt(parsed.agentId);
870
+ // Definitions
871
+ case "list_definitions":
872
+ return handleListDefinitions();
873
+ case "get_definition":
874
+ return handleGetDefinition(parsed.definitionName);
875
+ case "save_definition":
876
+ return handleSaveDefinition(parsed.definitionName, request);
877
+ case "delete_definition":
878
+ return handleDeleteDefinition(parsed.definitionName);
879
+ case "head_definition":
880
+ return handleHeadDefinition(parsed.definitionName);
881
+ // Images
882
+ case "list_images":
883
+ return handleListImages();
884
+ case "get_image":
885
+ return handleGetImage(parsed.imageId);
886
+ case "save_image":
887
+ return handleSaveImage(parsed.imageId, request);
888
+ case "delete_image":
889
+ return handleDeleteImage(parsed.imageId);
890
+ case "head_image":
891
+ return handleHeadImage(parsed.imageId);
892
+ case "list_image_sessions":
893
+ return handleListImageSessions(parsed.imageId);
894
+ case "delete_image_sessions":
895
+ return handleDeleteImageSessions(parsed.imageId);
896
+ case "run_image":
897
+ return handleRunImage(parsed.imageId, request);
898
+ // Sessions
899
+ case "list_sessions":
900
+ return handleListSessions();
901
+ case "get_session":
902
+ return handleGetSession(parsed.sessionId);
903
+ case "save_session":
904
+ return handleSaveSession(parsed.sessionId, request);
905
+ case "delete_session":
906
+ return handleDeleteSession(parsed.sessionId);
907
+ case "head_session":
908
+ return handleHeadSession(parsed.sessionId);
909
+ case "list_session_messages":
910
+ return handleListSessionMessages(parsed.sessionId);
911
+ case "delete_session_messages":
912
+ return handleDeleteSessionMessages(parsed.sessionId);
913
+ case "count_session_messages":
914
+ return handleCountSessionMessages(parsed.sessionId);
915
+ case "resume_session":
916
+ return handleResumeSession(parsed.sessionId, request);
917
+ // Users
918
+ case "list_user_sessions":
919
+ return handleListUserSessions(parsed.userId);
920
+ // Messages
921
+ case "get_message":
922
+ return handleGetMessage(parsed.messageId);
923
+ case "save_message":
924
+ return handleSaveMessage(parsed.messageId, request);
925
+ case "delete_message":
926
+ return handleDeleteMessage(parsed.messageId);
927
+ // Containers
928
+ case "list_containers":
929
+ return handleListContainers();
930
+ case "create_container":
931
+ return handleCreateContainer(request);
932
+ case "get_container":
933
+ return handleGetContainer(parsed.containerId);
934
+ case "save_container":
935
+ return handleSaveContainer(parsed.containerId, request);
936
+ case "delete_container":
937
+ return handleDeleteContainer(parsed.containerId);
938
+ case "head_container":
939
+ return handleHeadContainer(parsed.containerId);
940
+ case "not_found":
941
+ default:
942
+ return errorResponse("INVALID_REQUEST", "Not found", 404);
943
+ }
944
+ } catch (error) {
945
+ logger2.error("Unhandled error in request handler", { error });
946
+ return errorResponse(
947
+ "INTERNAL_ERROR",
948
+ error instanceof Error ? error.message : "Internal server error",
949
+ 500
950
+ );
951
+ }
952
+ };
953
+ handler.registerDefinition = registerDefinition;
954
+ handler.sseManager = sseManager;
955
+ return handler;
956
+ }
957
+
958
+ // src/server/adapters/express.ts
959
+ function toWebRequest(req) {
960
+ const protocol = req.protocol || "http";
961
+ const host = req.hostname || req.headers.host || "localhost";
962
+ const url = `${protocol}://${host}${req.originalUrl || req.url}`;
963
+ const headers = new Headers();
964
+ for (const [key, value] of Object.entries(req.headers)) {
965
+ if (value !== void 0) {
966
+ if (Array.isArray(value)) {
967
+ value.forEach((v) => headers.append(key, v));
968
+ } else {
969
+ headers.set(key, value);
970
+ }
971
+ }
972
+ }
973
+ const init = {
974
+ method: req.method,
975
+ headers
976
+ };
977
+ if (req.method !== "GET" && req.method !== "HEAD") {
978
+ if (req.body !== void 0) {
979
+ init.body = JSON.stringify(req.body);
980
+ }
981
+ }
982
+ return new Request(url, init);
983
+ }
984
+ async function sendWebResponse(res, webResponse) {
985
+ res.status(webResponse.status);
986
+ webResponse.headers.forEach((value, key) => {
987
+ if (key.toLowerCase() !== "content-encoding") {
988
+ res.setHeader(key, value);
989
+ }
990
+ });
991
+ const contentType = webResponse.headers.get("content-type");
992
+ if (contentType?.includes("text/event-stream")) {
993
+ res.setHeader("Cache-Control", "no-cache");
994
+ res.setHeader("Connection", "keep-alive");
995
+ if (res.flushHeaders) {
996
+ res.flushHeaders();
997
+ }
998
+ const reader = webResponse.body?.getReader();
999
+ if (reader) {
1000
+ const decoder = new TextDecoder();
1001
+ try {
1002
+ while (true) {
1003
+ const { done, value } = await reader.read();
1004
+ if (done) break;
1005
+ res.write(decoder.decode(value, { stream: true }));
1006
+ }
1007
+ } catch {
1008
+ } finally {
1009
+ reader.releaseLock();
1010
+ }
1011
+ }
1012
+ res.end();
1013
+ } else {
1014
+ const body = await webResponse.text();
1015
+ res.end(body);
1016
+ }
1017
+ }
1018
+ function toExpressHandler(handler) {
1019
+ return async (req, res, next) => {
1020
+ try {
1021
+ const webRequest = toWebRequest(req);
1022
+ const webResponse = await handler(webRequest);
1023
+ await sendWebResponse(res, webResponse);
1024
+ } catch (error) {
1025
+ next(error);
1026
+ }
1027
+ };
1028
+ }
1029
+ function createExpressAdapter(handler) {
1030
+ return toExpressHandler(handler);
1031
+ }
1032
+
1033
+ // src/server/adapters/hono.ts
1034
+ function toHonoHandler(handler) {
1035
+ return async (c) => {
1036
+ return handler(c.req.raw);
1037
+ };
1038
+ }
1039
+ function createHonoRoutes(handler, HonoClass) {
1040
+ const app = new HonoClass();
1041
+ const honoHandler = toHonoHandler(handler);
1042
+ app.get("/info", honoHandler);
1043
+ app.get("/health", honoHandler);
1044
+ app.get("/agents", honoHandler);
1045
+ app.post("/agents", honoHandler);
1046
+ app.get("/agents/:agentId", honoHandler);
1047
+ app.delete("/agents/:agentId", honoHandler);
1048
+ app.get("/agents/:agentId/sse", honoHandler);
1049
+ app.post("/agents/:agentId/messages", honoHandler);
1050
+ app.post("/agents/:agentId/interrupt", honoHandler);
1051
+ app.all("/*", honoHandler);
1052
+ return app;
1053
+ }
1054
+ function createHonoAdapter(handler) {
1055
+ return toHonoHandler(handler);
1056
+ }
1057
+
1058
+ // src/server/adapters/next.ts
1059
+ function createNextHandler(handler) {
1060
+ const routeHandler = async (request) => {
1061
+ return handler(request);
1062
+ };
1063
+ return {
1064
+ GET: routeHandler,
1065
+ POST: routeHandler,
1066
+ DELETE: routeHandler,
1067
+ PUT: routeHandler,
1068
+ PATCH: routeHandler,
1069
+ HEAD: routeHandler,
1070
+ OPTIONS: routeHandler
1071
+ };
1072
+ }
1073
+ function toNextHandler(handler) {
1074
+ return async (request) => handler(request);
1075
+ }
1076
+ function createNextEdgeHandler(handler) {
1077
+ return createNextHandler(handler);
1078
+ }
1079
+
1080
+ exports.SSEConnection = SSEConnection;
1081
+ exports.SSEConnectionManager = SSEConnectionManager;
1082
+ exports.createAgentXHandler = createAgentXHandler;
1083
+ exports.createAgentXRoutes = createNextHandler;
1084
+ exports.createExpressAdapter = createExpressAdapter;
1085
+ exports.createHonoAdapter = createHonoAdapter;
1086
+ exports.createHonoRoutes = createHonoRoutes;
1087
+ exports.createNextEdgeHandler = createNextEdgeHandler;
1088
+ exports.createNextHandler = createNextHandler;
1089
+ exports.toExpressHandler = toExpressHandler;
1090
+ exports.toHonoHandler = toHonoHandler;
1091
+ exports.toNextHandler = toNextHandler;
1092
+ //# sourceMappingURL=index.cjs.map
1093
+ //# sourceMappingURL=index.cjs.map