agentxjs 0.0.6 → 0.1.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 (54) hide show
  1. package/README.md +255 -464
  2. package/dist/browser.cjs +215 -0
  3. package/dist/browser.cjs.map +1 -0
  4. package/dist/browser.d.cts +32 -0
  5. package/dist/browser.d.ts +32 -0
  6. package/dist/browser.js +153 -0
  7. package/dist/browser.js.map +1 -0
  8. package/dist/index.cjs +326 -2763
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +27 -69
  11. package/dist/index.d.ts +27 -69
  12. package/dist/index.js +255 -2760
  13. package/dist/index.js.map +1 -1
  14. package/package.json +17 -40
  15. package/dist/runtime/sse/index.cjs +0 -633
  16. package/dist/runtime/sse/index.cjs.map +0 -1
  17. package/dist/runtime/sse/index.d.cts +0 -159
  18. package/dist/runtime/sse/index.d.ts +0 -159
  19. package/dist/runtime/sse/index.js +0 -621
  20. package/dist/runtime/sse/index.js.map +0 -1
  21. package/dist/server/adapters/express.cjs +0 -81
  22. package/dist/server/adapters/express.cjs.map +0 -1
  23. package/dist/server/adapters/express.d.cts +0 -75
  24. package/dist/server/adapters/express.d.ts +0 -75
  25. package/dist/server/adapters/express.js +0 -78
  26. package/dist/server/adapters/express.js.map +0 -1
  27. package/dist/server/adapters/hono.cjs +0 -32
  28. package/dist/server/adapters/hono.cjs.map +0 -1
  29. package/dist/server/adapters/hono.d.cts +0 -96
  30. package/dist/server/adapters/hono.d.ts +0 -96
  31. package/dist/server/adapters/hono.js +0 -28
  32. package/dist/server/adapters/hono.js.map +0 -1
  33. package/dist/server/adapters/index.cjs +0 -135
  34. package/dist/server/adapters/index.cjs.map +0 -1
  35. package/dist/server/adapters/index.d.cts +0 -5
  36. package/dist/server/adapters/index.d.ts +0 -5
  37. package/dist/server/adapters/index.js +0 -125
  38. package/dist/server/adapters/index.js.map +0 -1
  39. package/dist/server/adapters/next.cjs +0 -30
  40. package/dist/server/adapters/next.cjs.map +0 -1
  41. package/dist/server/adapters/next.d.cts +0 -107
  42. package/dist/server/adapters/next.d.ts +0 -107
  43. package/dist/server/adapters/next.js +0 -25
  44. package/dist/server/adapters/next.js.map +0 -1
  45. package/dist/server/index.cjs +0 -1093
  46. package/dist/server/index.cjs.map +0 -1
  47. package/dist/server/index.d.cts +0 -131
  48. package/dist/server/index.d.ts +0 -131
  49. package/dist/server/index.js +0 -1080
  50. package/dist/server/index.js.map +0 -1
  51. package/dist/types-Cgfcw91r.d.cts +0 -282
  52. package/dist/types-Cgfcw91r.d.ts +0 -282
  53. package/dist/types-OVKV6qpE.d.cts +0 -118
  54. package/dist/types-OVKV6qpE.d.ts +0 -118
package/dist/index.js CHANGED
@@ -1,2816 +1,311 @@
1
- import { createLogger, setLoggerFactory } from '@agentxjs/common';
2
- import ky from 'ky';
3
- import { LogLevel, isStateEvent, STREAM_EVENT_TYPE_NAMES } from '@agentxjs/types';
4
- import { Subject } from 'rxjs';
5
- import { filter, take } from 'rxjs/operators';
1
+ import { createLogger } from '@agentxjs/common';
2
+ export { ConsoleLogger, LoggerFactoryImpl, createLogger, setLoggerFactory } from '@agentxjs/common';
3
+ import { isRemoteConfig } from '@agentxjs/types/agentx';
4
+ export { isLocalConfig, isRemoteConfig } from '@agentxjs/types/agentx';
5
+ export { hasIntent, isAgentEvent, isAgentMessageEvent, isAgentStateEvent, isAgentStreamEvent, isAgentTurnEvent, isCommandEvent, isCommandRequest, isCommandResponse, isFromSource, isNotification, isRequest, isResult } from '@agentxjs/types/event';
6
6
 
7
7
  var __defProp = Object.defineProperty;
8
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
10
-
11
- // src/defineAgent.ts
12
- function defineAgent(input) {
13
- const { name, description, systemPrompt } = input;
14
- return {
15
- name,
16
- description,
17
- systemPrompt
18
- };
19
- }
20
- var logger = createLogger("agentx/DefinitionManager");
21
- function generateMetaImageId(definitionName) {
22
- return `meta_${definitionName}`;
23
- }
24
- function toDefinitionRecord(definition) {
25
- const now = /* @__PURE__ */ new Date();
26
- return {
27
- name: definition.name,
28
- description: definition.description,
29
- systemPrompt: definition.systemPrompt,
30
- definition,
31
- source: "code",
32
- createdAt: now,
33
- updatedAt: now
34
- };
35
- }
36
- var DefinitionManagerImpl = class {
37
- constructor(repository) {
38
- this.repository = repository;
39
- // Local cache for sync access
40
- __publicField(this, "cache", /* @__PURE__ */ new Map());
41
- }
42
- register(definition) {
43
- if (this.cache.has(definition.name)) {
44
- throw new Error(`Definition already exists: ${definition.name}`);
45
- }
46
- this.cache.set(definition.name, definition);
47
- const definitionRecord = toDefinitionRecord(definition);
48
- this.repository.saveDefinition(definitionRecord).catch((err) => {
49
- logger.error("Failed to save definition", { name: definition.name, error: err });
50
- });
51
- const metaImageId = generateMetaImageId(definition.name);
52
- const imageRecord = {
53
- imageId: metaImageId,
54
- type: "meta",
55
- definitionName: definition.name,
56
- parentImageId: null,
57
- definition,
58
- config: {},
59
- messages: [],
60
- createdAt: /* @__PURE__ */ new Date()
61
- };
62
- this.repository.saveImage(imageRecord).catch((err) => {
63
- logger.error("Failed to save MetaImage", { definitionName: definition.name, error: err });
64
- });
65
- logger.info("Definition registered", {
66
- name: definition.name,
67
- metaImageId
68
- });
69
- }
70
- get(name) {
71
- return this.cache.get(name);
72
- }
73
- list() {
74
- return Array.from(this.cache.values());
75
- }
76
- has(name) {
77
- return this.cache.has(name);
78
- }
79
- unregister(name) {
80
- const definition = this.cache.get(name);
81
- if (!definition) {
82
- return false;
83
- }
84
- this.cache.delete(name);
85
- this.repository.deleteDefinition(name).catch((err) => {
86
- logger.error("Failed to delete definition", { name, error: err });
87
- });
88
- const metaImageId = generateMetaImageId(name);
89
- this.repository.deleteImage(metaImageId).catch((err) => {
90
- logger.error("Failed to delete MetaImage", { definitionName: name, error: err });
91
- });
92
- logger.info("Definition unregistered", { name });
93
- return true;
94
- }
95
- };
96
- var logger2 = createLogger("agentx/ImageManager");
97
- function generateMetaImageId2(definitionName) {
98
- return `meta_${definitionName}`;
99
- }
100
- function toAgentImage(record) {
101
- const definition = record.definition;
102
- if (record.type === "meta") {
103
- const metaImage = {
104
- type: "meta",
105
- imageId: record.imageId,
106
- definitionName: record.definitionName,
107
- definition,
108
- config: record.config,
109
- messages: [],
110
- createdAt: record.createdAt
111
- };
112
- return metaImage;
113
- } else {
114
- return {
115
- type: "derived",
116
- imageId: record.imageId,
117
- parentImageId: record.parentImageId,
118
- definitionName: record.definitionName,
119
- definition,
120
- config: record.config,
121
- messages: record.messages,
122
- createdAt: record.createdAt
123
- };
124
- }
125
- }
126
- var ImageManagerImpl = class {
127
- constructor(repository, containerManager, defaultContainerId) {
128
- __publicField(this, "repository");
129
- __publicField(this, "containerManager");
130
- __publicField(this, "defaultContainerId");
131
- this.repository = repository;
132
- this.containerManager = containerManager;
133
- this.defaultContainerId = defaultContainerId;
134
- }
135
- async get(imageId) {
136
- const record = await this.repository.findImageById(imageId);
137
- if (!record) {
138
- return void 0;
139
- }
140
- return toAgentImage(record);
141
- }
142
- async getMetaImage(definitionName) {
143
- const metaImageId = generateMetaImageId2(definitionName);
144
- const record = await this.repository.findImageById(metaImageId);
145
- if (!record || record.type !== "meta") {
146
- return void 0;
147
- }
148
- return toAgentImage(record);
149
- }
150
- async list() {
151
- const records = await this.repository.findAllImages();
152
- return records.map(toAgentImage);
153
- }
154
- async listByDefinition(definitionName) {
155
- const allRecords = await this.repository.findAllImages();
156
- const filtered = allRecords.filter((r) => r.definitionName === definitionName);
157
- return filtered.map(toAgentImage);
158
- }
159
- async exists(imageId) {
160
- return this.repository.imageExists(imageId);
161
- }
162
- async delete(imageId) {
163
- const record = await this.repository.findImageById(imageId);
164
- if (!record) {
165
- return false;
166
- }
167
- if (record.type === "meta") {
168
- logger2.warn("Cannot delete MetaImage directly", { imageId });
169
- return false;
170
- }
171
- await this.repository.deleteImage(imageId);
172
- logger2.info("Image deleted", { imageId });
173
- return true;
174
- }
175
- async run(imageId, options) {
176
- logger2.info("Running agent from image", { imageId, containerId: options?.containerId });
177
- const image = await this.get(imageId);
178
- if (!image) {
179
- throw new Error(`Image not found: ${imageId}`);
180
- }
181
- let containerId = options?.containerId || this.defaultContainerId;
182
- if (!containerId) {
183
- const container = await this.containerManager.create();
184
- containerId = container.containerId;
185
- this.defaultContainerId = containerId;
186
- logger2.debug("Auto-created default container", { containerId });
187
- }
188
- return this.containerManager.run(image, containerId);
189
- }
8
+ var __getOwnPropNames = Object.getOwnPropertyNames;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
190
11
  };
191
- var logger3 = createLogger("agentx/AgentManager");
192
- var AgentManager = class {
193
- constructor(containerManager) {
194
- this.containerManager = containerManager;
195
- }
196
- /**
197
- * Get an existing agent by ID
198
- */
199
- get(agentId) {
200
- return this.containerManager.getAgent(agentId);
201
- }
202
- /**
203
- * Check if an agent exists
204
- */
205
- has(agentId) {
206
- return this.containerManager.hasAgent(agentId);
207
- }
208
- /**
209
- * List all agents
210
- */
211
- list() {
212
- return this.containerManager.listAgents();
213
- }
214
- /**
215
- * Destroy an agent by ID
216
- */
217
- async destroy(agentId) {
218
- logger3.debug("Destroying agent", { agentId });
219
- await this.containerManager.destroyAgent(agentId);
220
- logger3.info("Agent destroyed", { agentId });
221
- }
222
- /**
223
- * Destroy all agents
224
- */
225
- async destroyAll() {
226
- const agents = this.containerManager.listAgents();
227
- logger3.debug("Destroying all agents", { count: agents.length });
228
- await this.containerManager.destroyAllAgents();
229
- logger3.info("All agents destroyed", { count: agents.length });
230
- }
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
231
15
  };
232
- var logger4 = createLogger("agentx/SessionManager");
233
- function generateSessionId() {
234
- const timestamp = Date.now().toString(36);
235
- const random = Math.random().toString(36).substring(2, 8);
236
- return `session_${timestamp}_${random}`;
237
- }
238
- function generateImageId() {
239
- const timestamp = Date.now().toString(36);
240
- const random = Math.random().toString(36).substring(2, 8);
241
- return `image_${timestamp}_${random}`;
242
- }
243
- var SessionImpl = class _SessionImpl {
244
- constructor(record, repository, containerManager, defaultContainerId) {
245
- __publicField(this, "sessionId");
246
- __publicField(this, "userId");
247
- __publicField(this, "imageId");
248
- __publicField(this, "createdAt");
249
- __publicField(this, "_title");
250
- __publicField(this, "_updatedAt");
251
- __publicField(this, "repository");
252
- __publicField(this, "containerManager");
253
- __publicField(this, "defaultContainerId");
254
- this.sessionId = record.sessionId;
255
- this.userId = record.userId;
256
- this.imageId = record.imageId;
257
- this._title = record.title;
258
- this.createdAt = record.createdAt.getTime();
259
- this._updatedAt = record.updatedAt.getTime();
260
- this.repository = repository;
261
- this.containerManager = containerManager;
262
- this.defaultContainerId = defaultContainerId;
263
- }
264
- get title() {
265
- return this._title;
266
- }
267
- get updatedAt() {
268
- return this._updatedAt;
269
- }
270
- async resume(options) {
271
- logger4.info("Resuming agent from session", {
272
- sessionId: this.sessionId,
273
- imageId: this.imageId,
274
- containerId: options?.containerId
275
- });
276
- let containerId = options?.containerId || this.defaultContainerId;
277
- if (!containerId) {
278
- const container = await this.containerManager.create();
279
- containerId = container.containerId;
280
- logger4.debug("Auto-created default container for session", {
281
- containerId,
282
- sessionId: this.sessionId
16
+
17
+ // src/createLocalAgentX.ts
18
+ var createLocalAgentX_exports = {};
19
+ __export(createLocalAgentX_exports, {
20
+ createLocalAgentX: () => createLocalAgentX
21
+ });
22
+ function setupConnectionHandler(ws, connections, runtime) {
23
+ connections.add(ws);
24
+ logger.info("Client connected", { totalConnections: connections.size });
25
+ ws.on("message", (data) => {
26
+ try {
27
+ const event = JSON.parse(data.toString());
28
+ logger.info("Received from client", {
29
+ type: event.type,
30
+ requestId: event.data?.requestId
283
31
  });
32
+ runtime.emit(event);
33
+ } catch {
284
34
  }
285
- const agent = await this.containerManager.resume(this, containerId);
286
- this.collect(agent);
287
- return agent;
288
- }
289
- collect(agent) {
290
- logger4.debug("Collecting messages from agent", {
291
- sessionId: this.sessionId,
292
- agentId: agent.agentId
293
- });
294
- const sessionId = this.sessionId;
295
- const repository = this.repository;
296
- const saveMessage = (data, role) => {
297
- const record = {
298
- messageId: data.id,
299
- sessionId,
300
- role,
301
- content: data,
302
- createdAt: new Date(data.timestamp ?? Date.now())
303
- };
304
- repository.saveMessage(record).catch((error) => {
305
- logger4.error("Failed to persist message", {
306
- sessionId,
307
- messageId: record.messageId,
308
- error
309
- });
310
- });
311
- };
312
- agent.on("user_message", (event) => saveMessage(event.data, "user"));
313
- agent.on("assistant_message", (event) => saveMessage(event.data, "assistant"));
314
- agent.on("tool_call_message", (event) => saveMessage(event.data, "tool"));
315
- agent.on("tool_result_message", (event) => saveMessage(event.data, "tool"));
316
- }
317
- async getMessages() {
318
- logger4.debug("Getting messages for session", { sessionId: this.sessionId });
319
- const records = await this.repository.findMessagesBySessionId(this.sessionId);
320
- return records.map((record) => record.content);
321
- }
322
- async fork() {
323
- logger4.info("Forking session", { sessionId: this.sessionId });
324
- const imageRecord = await this.repository.findImageById(this.imageId);
325
- if (!imageRecord) {
326
- throw new Error(`Image not found: ${this.imageId}`);
35
+ });
36
+ ws.on("close", () => {
37
+ connections.delete(ws);
38
+ logger.info("Client disconnected", { totalConnections: connections.size });
39
+ });
40
+ }
41
+ function setupBroadcasting(connections, runtime) {
42
+ runtime.onAny((event) => {
43
+ if (event.broadcastable === false) {
44
+ return;
327
45
  }
328
- const newImageId = generateImageId();
329
- const newImageRecord = {
330
- imageId: newImageId,
331
- type: "derived",
332
- definitionName: imageRecord.definitionName,
333
- parentImageId: imageRecord.imageId,
334
- definition: imageRecord.definition,
335
- config: imageRecord.config,
336
- messages: [...imageRecord.messages],
337
- // Copy messages
338
- createdAt: /* @__PURE__ */ new Date()
339
- };
340
- await this.repository.saveImage(newImageRecord);
341
- const newSessionId = generateSessionId();
342
- const now = /* @__PURE__ */ new Date();
343
- const newSessionRecord = {
344
- sessionId: newSessionId,
345
- userId: this.userId,
346
- imageId: newImageId,
347
- title: this._title ? `Fork of ${this._title}` : null,
348
- createdAt: now,
349
- updatedAt: now
350
- };
351
- await this.repository.saveSession(newSessionRecord);
352
- logger4.info("Session forked", {
353
- originalSessionId: this.sessionId,
354
- newSessionId,
355
- newImageId
356
- });
357
- return new _SessionImpl(
358
- newSessionRecord,
359
- this.repository,
360
- this.containerManager,
361
- this.defaultContainerId
362
- );
363
- }
364
- async setTitle(title) {
365
- logger4.debug("Setting session title", { sessionId: this.sessionId, title });
366
- const now = /* @__PURE__ */ new Date();
367
- await this.repository.saveSession({
368
- sessionId: this.sessionId,
369
- userId: this.userId,
370
- imageId: this.imageId,
371
- title,
372
- createdAt: new Date(this.createdAt),
373
- updatedAt: now
46
+ logger.info("Broadcasting to clients", {
47
+ type: event.type,
48
+ category: event.category,
49
+ requestId: event.data?.requestId
374
50
  });
375
- this._title = title;
376
- this._updatedAt = now.getTime();
377
- logger4.info("Session title updated", { sessionId: this.sessionId, title });
378
- }
379
- };
380
- var SessionManagerImpl = class {
381
- constructor(repository, containerManager, defaultContainerId) {
382
- __publicField(this, "repository");
383
- __publicField(this, "containerManager");
384
- __publicField(this, "defaultContainerId");
385
- this.repository = repository;
386
- this.containerManager = containerManager;
387
- this.defaultContainerId = defaultContainerId;
388
- }
389
- async create(imageId, userId) {
390
- const sessionId = generateSessionId();
391
- const now = /* @__PURE__ */ new Date();
392
- const record = {
393
- sessionId,
394
- userId,
395
- imageId,
396
- title: null,
397
- createdAt: now,
398
- updatedAt: now
399
- };
400
- await this.repository.saveSession(record);
401
- logger4.info("Session created", { sessionId, imageId, userId });
402
- return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
403
- }
404
- async get(sessionId) {
405
- const record = await this.repository.findSessionById(sessionId);
406
- if (!record) return void 0;
407
- return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
408
- }
409
- async has(sessionId) {
410
- return this.repository.sessionExists(sessionId);
411
- }
412
- async list() {
413
- const records = await this.repository.findAllSessions();
414
- return records.map(
415
- (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
416
- );
417
- }
418
- async listByImage(imageId) {
419
- const records = await this.repository.findSessionsByImageId(imageId);
420
- return records.map(
421
- (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
422
- );
423
- }
424
- async listByUser(userId) {
425
- const records = await this.repository.findSessionsByUserId(userId);
426
- return records.map(
427
- (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
428
- );
429
- }
430
- async destroy(sessionId) {
431
- await this.repository.deleteSession(sessionId);
432
- logger4.info("Session destroyed", { sessionId });
433
- }
434
- async destroyByImage(imageId) {
435
- await this.repository.deleteSessionsByImageId(imageId);
436
- logger4.info("Sessions destroyed by image", { imageId });
437
- }
438
- async destroyAll() {
439
- const sessions = await this.repository.findAllSessions();
440
- for (const session of sessions) {
441
- await this.repository.deleteSession(session.sessionId);
442
- }
443
- logger4.info("All sessions destroyed");
444
- }
445
- };
446
- var logger5 = createLogger("agentx/ErrorManager");
447
- var ErrorManager = class {
448
- constructor() {
449
- __publicField(this, "handlers", /* @__PURE__ */ new Set());
450
- }
451
- /**
452
- * Handle an error from any agent
453
- *
454
- * Called internally when an agent emits an error event.
455
- * 1. Default logging (always)
456
- * 2. Custom handlers (user-registered)
457
- */
458
- handle(agentId, error, event) {
459
- this.logError(agentId, error);
460
- for (const handler of this.handlers) {
461
- try {
462
- handler.handle(agentId, error, event);
463
- } catch (e) {
464
- logger5.error("ErrorHandler failed", { error: e });
51
+ const message = JSON.stringify(event);
52
+ for (const ws of connections) {
53
+ if (ws.readyState === 1) {
54
+ ws.send(message);
465
55
  }
466
56
  }
467
- }
468
- /**
469
- * Add a custom error handler
470
- */
471
- addHandler(handler) {
472
- this.handlers.add(handler);
473
- return () => {
474
- this.handlers.delete(handler);
475
- };
476
- }
477
- /**
478
- * Remove an error handler
479
- */
480
- removeHandler(handler) {
481
- this.handlers.delete(handler);
482
- }
483
- /**
484
- * Default error logging
485
- */
486
- logError(agentId, error) {
487
- const prefix = `[${agentId}] ${error.category}/${error.code}`;
488
- if (error.severity === "fatal") {
489
- logger5.error(`${prefix}: ${error.message}`, { error });
490
- } else if (error.severity === "error") {
491
- logger5.error(`${prefix}: ${error.message}`);
492
- } else {
493
- logger5.warn(`${prefix}: ${error.message}`);
494
- }
495
- }
496
- };
497
- var ApiError = class extends Error {
498
- constructor(code, message, details) {
499
- super(message);
500
- this.code = code;
501
- this.details = details;
502
- this.name = "ApiError";
503
- }
504
- };
505
- function createHttpClient(options) {
506
- return ky.create({
507
- prefixUrl: options.baseUrl.replace(/\/+$/, ""),
508
- headers: options.headers,
509
- timeout: options.timeout || 3e4,
510
- hooks: {
511
- afterResponse: [
512
- async (_request, _options, response) => {
513
- if (!response.ok) {
514
- const data = await response.json().catch(() => ({}));
515
- throw new ApiError(
516
- data.error?.code || "UNKNOWN_ERROR",
517
- data.error?.message || `Request failed: ${response.status}`,
518
- data.error?.details
519
- );
520
- }
521
- return response;
522
- }
523
- ]
524
- }
525
57
  });
526
58
  }
527
- var logger6 = createLogger("core/AgentStateMachine");
528
- var AgentStateMachine = class {
529
- constructor() {
530
- __publicField(this, "_state", "idle");
531
- __publicField(this, "handlers", /* @__PURE__ */ new Set());
532
- }
533
- /**
534
- * Current agent state
535
- */
536
- get state() {
537
- return this._state;
538
- }
539
- /**
540
- * Process a StateEvent and update internal state
541
- *
542
- * @param event - StateEvent from Engine layer
543
- */
544
- process(event) {
545
- const prev = this._state;
546
- const next = this.mapEventToState(event);
547
- if (next !== null && prev !== next) {
548
- this._state = next;
549
- logger6.debug("State transition", {
550
- eventType: event.type,
551
- from: prev,
552
- to: next
553
- });
554
- this.notifyHandlers({ prev, current: next });
555
- }
556
- }
557
- /**
558
- * Subscribe to state changes
559
- *
560
- * @param handler - Callback receiving { prev, current } state change
561
- * @returns Unsubscribe function
562
- */
563
- onStateChange(handler) {
564
- this.handlers.add(handler);
565
- return () => {
566
- this.handlers.delete(handler);
567
- };
568
- }
569
- /**
570
- * Reset state machine (used on destroy)
571
- */
572
- reset() {
573
- this._state;
574
- this._state = "idle";
575
- this.handlers.clear();
576
- }
577
- /**
578
- * Map StateEvent type to AgentState
579
- *
580
- * @param event - StateEvent from Engine
581
- * @returns New AgentState or null if no transition needed
582
- */
583
- mapEventToState(event) {
584
- switch (event.type) {
585
- // Agent lifecycle
586
- case "agent_initializing":
587
- return "initializing";
588
- case "agent_ready":
589
- return "idle";
590
- case "agent_destroyed":
591
- return "idle";
592
- // Conversation lifecycle
593
- case "conversation_queued":
594
- return "queued";
595
- case "conversation_start":
596
- return "conversation_active";
597
- case "conversation_thinking":
598
- return "thinking";
599
- case "conversation_responding":
600
- return "responding";
601
- case "conversation_end":
602
- return "idle";
603
- case "conversation_interrupted":
604
- return "idle";
605
- // Return to idle on interrupt
606
- // Tool lifecycle
607
- case "tool_planned":
608
- return "planning_tool";
609
- case "tool_executing":
610
- return "awaiting_tool_result";
611
- case "tool_completed":
612
- return "responding";
613
- // Back to responding after tool completes
614
- case "tool_failed":
615
- return "responding";
616
- // Continue responding after tool failure
617
- // Error
618
- case "error_occurred":
619
- return "idle";
620
- // Reset to idle on error
621
- default:
622
- return null;
59
+ async function createLocalAgentX(config) {
60
+ if (config.logger) {
61
+ const { LoggerFactoryImpl: LoggerFactoryImpl2, setLoggerFactory: setLoggerFactory2 } = await import('@agentxjs/common');
62
+ LoggerFactoryImpl2.configure({
63
+ defaultLevel: config.logger.level,
64
+ consoleOptions: config.logger.console
65
+ });
66
+ if (config.logger.factory) {
67
+ setLoggerFactory2(config.logger.factory);
68
+ }
69
+ }
70
+ const { createRuntime, createPersistence } = await import('@agentxjs/runtime');
71
+ const storageConfig = config.storage ?? {};
72
+ const persistence = await createPersistence(
73
+ storageConfig
74
+ );
75
+ const runtime = createRuntime({
76
+ persistence,
77
+ llmProvider: {
78
+ name: "claude",
79
+ provide: () => ({
80
+ apiKey: config.llm?.apiKey ?? "",
81
+ baseUrl: config.llm?.baseUrl,
82
+ model: config.llm?.model
83
+ })
623
84
  }
624
- }
625
- /**
626
- * Notify all registered handlers of state change
627
- */
628
- notifyHandlers(change) {
629
- for (const handler of this.handlers) {
630
- try {
631
- handler(change);
632
- } catch (error) {
633
- logger6.error("State change handler error", {
634
- from: change.prev,
635
- to: change.current,
636
- error
85
+ });
86
+ let peer = null;
87
+ const connections = /* @__PURE__ */ new Set();
88
+ let attachedToServer = false;
89
+ if (config.server) {
90
+ const { WebSocketServer } = await import('ws');
91
+ peer = new WebSocketServer({ noServer: true });
92
+ config.server.on("upgrade", (request, socket, head) => {
93
+ const url = new URL(request.url || "", `http://${request.headers.host}`);
94
+ if (url.pathname === "/ws") {
95
+ peer.handleUpgrade(request, socket, head, (ws) => {
96
+ peer.emit("connection", ws, request);
637
97
  });
638
- }
639
- }
640
- }
641
- };
642
- var logger22 = createLogger("core/AgentEventBus");
643
- var AgentEventBus = class {
644
- constructor() {
645
- __publicField(this, "subject", new Subject());
646
- __publicField(this, "typeSubscriptions", /* @__PURE__ */ new Map());
647
- __publicField(this, "globalSubscriptions", []);
648
- __publicField(this, "nextId", 0);
649
- __publicField(this, "isDestroyed", false);
650
- // Cached views
651
- __publicField(this, "producerView", null);
652
- __publicField(this, "consumerView", null);
653
- }
654
- // ===== Producer Methods =====
655
- emit(event) {
656
- if (this.isDestroyed) {
657
- logger22.warn("Emit called on destroyed EventBus", { eventType: event.type });
658
- return;
659
- }
660
- this.subject.next(event);
661
- }
662
- emitBatch(events) {
663
- for (const event of events) {
664
- this.emit(event);
665
- }
666
- }
667
- on(typeOrTypes, handler, options = {}) {
668
- if (this.isDestroyed) {
669
- logger22.warn("Subscribe called on destroyed EventBus");
670
- return () => {
671
- };
672
- }
673
- const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes];
674
- const unsubscribes = [];
675
- for (const type of types) {
676
- const unsub = this.subscribeToType(type, handler, options);
677
- unsubscribes.push(unsub);
678
- }
679
- return () => unsubscribes.forEach((u) => u());
680
- }
681
- onAny(handler, options = {}) {
682
- if (this.isDestroyed) {
683
- logger22.warn("Subscribe called on destroyed EventBus");
684
- return () => {
685
- };
686
- }
687
- return this.subscribeGlobal(handler, options);
688
- }
689
- once(type, handler) {
690
- return this.on(type, handler, { once: true });
691
- }
692
- // ===== View Methods =====
693
- asConsumer() {
694
- if (!this.consumerView) {
695
- this.consumerView = {
696
- on: this.on.bind(this),
697
- onAny: this.onAny.bind(this),
698
- once: this.once.bind(this)
699
- };
700
- }
701
- return this.consumerView;
702
- }
703
- asProducer() {
704
- if (!this.producerView) {
705
- this.producerView = {
706
- emit: this.emit.bind(this),
707
- emitBatch: this.emitBatch.bind(this)
708
- };
709
- }
710
- return this.producerView;
711
- }
712
- // ===== Lifecycle =====
713
- destroy() {
714
- if (this.isDestroyed) return;
715
- this.isDestroyed = true;
716
- for (const records of this.typeSubscriptions.values()) {
717
- for (const record of records) {
718
- record.unsubscribe();
719
- }
720
- }
721
- this.typeSubscriptions.clear();
722
- for (const record of this.globalSubscriptions) {
723
- record.unsubscribe();
724
- }
725
- this.globalSubscriptions.length = 0;
726
- this.subject.complete();
727
- logger22.debug("EventBus destroyed");
728
- }
729
- // ===== Private Methods =====
730
- subscribeToType(type, handler, options) {
731
- const { filter: filter$1, priority = 0, once = false } = options;
732
- const id = this.nextId++;
733
- let observable = this.subject.pipe(filter((e) => e.type === type));
734
- if (filter$1) {
735
- observable = observable.pipe(filter(filter$1));
736
- }
737
- if (once) {
738
- observable = observable.pipe(take(1));
739
- }
740
- const subscription = observable.subscribe({
741
- next: (event) => {
742
- this.executeWithPriority(type, event, handler, id);
98
+ } else {
99
+ socket.destroy();
743
100
  }
744
101
  });
745
- const unsubscribe = () => {
746
- subscription.unsubscribe();
747
- const records2 = this.typeSubscriptions.get(type);
748
- if (records2) {
749
- const idx = records2.findIndex((r) => r.id === id);
750
- if (idx !== -1) records2.splice(idx, 1);
751
- }
752
- };
753
- if (!this.typeSubscriptions.has(type)) {
754
- this.typeSubscriptions.set(type, []);
755
- }
756
- const record = { id, priority, handler, unsubscribe };
757
- const records = this.typeSubscriptions.get(type);
758
- records.push(record);
759
- records.sort((a, b) => b.priority - a.priority);
760
- return unsubscribe;
761
- }
762
- subscribeGlobal(handler, options) {
763
- const { filter: filter$1, priority = 0, once = false } = options;
764
- const id = this.nextId++;
765
- let observable = this.subject.asObservable();
766
- if (filter$1) {
767
- observable = observable.pipe(filter(filter$1));
768
- }
769
- if (once) {
770
- observable = observable.pipe(take(1));
771
- }
772
- const subscription = observable.subscribe({
773
- next: (event) => {
774
- this.executeGlobalWithPriority(event, handler, id);
775
- }
102
+ peer.on("connection", (ws) => {
103
+ setupConnectionHandler(ws, connections, runtime);
776
104
  });
777
- const unsubscribe = () => {
778
- subscription.unsubscribe();
779
- const idx = this.globalSubscriptions.findIndex((r) => r.id === id);
780
- if (idx !== -1) this.globalSubscriptions.splice(idx, 1);
781
- };
782
- const record = { id, priority, handler, unsubscribe };
783
- this.globalSubscriptions.push(record);
784
- this.globalSubscriptions.sort((a, b) => b.priority - a.priority);
785
- return unsubscribe;
786
- }
787
- /**
788
- * Execute handler respecting priority order for typed subscriptions
789
- */
790
- executeWithPriority(type, event, handler, handlerId) {
791
- const records = this.typeSubscriptions.get(type) || [];
792
- const record = records.find((r) => r.id === handlerId);
793
- if (record) {
794
- try {
795
- handler(event);
796
- } catch (error) {
797
- logger22.error("Event handler error", { eventType: type, error });
798
- }
799
- }
800
- }
801
- /**
802
- * Execute handler respecting priority order for global subscriptions
803
- */
804
- executeGlobalWithPriority(event, handler, handlerId) {
805
- const record = this.globalSubscriptions.find((r) => r.id === handlerId);
806
- if (record) {
807
- try {
808
- handler(event);
809
- } catch (error) {
810
- logger22.error("Global event handler error", { eventType: event.type, error });
811
- }
812
- }
813
- }
814
- };
815
- var AgentErrorClassifier = class {
816
- constructor(agentId) {
817
- this.agentId = agentId;
818
- }
819
- /**
820
- * Classify an unknown error into an AgentError
821
- */
822
- classify(error) {
823
- const err = error instanceof Error ? error : new Error(String(error));
824
- const message = err.message;
825
- if (message.includes("rate limit") || message.includes("429")) {
826
- return this.create("llm", "RATE_LIMITED", message, true, err);
827
- }
828
- if (message.includes("api key") || message.includes("401") || message.includes("unauthorized")) {
829
- return this.create("llm", "INVALID_API_KEY", message, false, err);
830
- }
831
- if (message.includes("context") && message.includes("long")) {
832
- return this.create("llm", "CONTEXT_TOO_LONG", message, true, err);
833
- }
834
- if (message.includes("overloaded") || message.includes("503")) {
835
- return this.create("llm", "OVERLOADED", message, true, err);
836
- }
837
- if (message.includes("timeout") || message.includes("ETIMEDOUT")) {
838
- return this.create("network", "TIMEOUT", message, true, err);
839
- }
840
- if (message.includes("ECONNREFUSED") || message.includes("connection")) {
841
- return this.create("network", "CONNECTION_FAILED", message, true, err);
842
- }
843
- if (message.includes("network") || message.includes("fetch")) {
844
- return this.create("network", "CONNECTION_FAILED", message, true, err);
845
- }
846
- if (message.includes("driver")) {
847
- return this.create("driver", "RECEIVE_FAILED", message, true, err);
848
- }
849
- return this.create("system", "UNKNOWN", message, true, err);
105
+ setupBroadcasting(connections, runtime);
106
+ attachedToServer = true;
107
+ logger.info("WebSocket attached to existing HTTP server on /ws path");
850
108
  }
851
- /**
852
- * Create an AgentError with the specified category and code
853
- */
854
- create(category, code, message, recoverable, cause) {
855
- return {
856
- category,
857
- code,
858
- message,
859
- severity: recoverable ? "error" : "fatal",
860
- recoverable,
861
- cause
862
- };
863
- }
864
- /**
865
- * Create an ErrorEvent from an AgentError
866
- *
867
- * ErrorEvent is independent from Message layer and transportable via SSE.
868
- */
869
- createEvent(error) {
870
- return {
871
- type: "error",
872
- uuid: `${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
873
- agentId: this.agentId,
874
- timestamp: Date.now(),
875
- data: {
876
- error
109
+ return {
110
+ // Core API - delegate to runtime
111
+ request: (type, data, timeout) => runtime.request(type, data, timeout),
112
+ on: (type, handler) => runtime.on(type, handler),
113
+ onCommand: (type, handler) => runtime.onCommand(type, handler),
114
+ emitCommand: (type, data) => runtime.emitCommand(type, data),
115
+ // Server API
116
+ async listen(port, host) {
117
+ if (attachedToServer) {
118
+ throw new Error(
119
+ "Cannot listen when attached to existing server. The server should call listen() instead."
120
+ );
877
121
  }
878
- };
879
- }
880
- };
881
- var MiddlewareChain = class {
882
- constructor() {
883
- __publicField(this, "middlewares", []);
884
- }
885
- /**
886
- * Add middleware to the chain
887
- *
888
- * @param middleware - Middleware function
889
- * @returns Unsubscribe function to remove the middleware
890
- */
891
- use(middleware) {
892
- this.middlewares.push(middleware);
893
- return () => {
894
- const index = this.middlewares.indexOf(middleware);
895
- if (index !== -1) {
896
- this.middlewares.splice(index, 1);
122
+ if (peer) {
123
+ throw new Error("Server already listening");
897
124
  }
898
- };
899
- }
900
- /**
901
- * Execute the middleware chain
902
- *
903
- * @param message - User message to process
904
- * @param finalHandler - Handler called at the end of the chain
905
- */
906
- async execute(message, finalHandler) {
907
- let index = 0;
908
- const next = async (msg) => {
909
- if (index < this.middlewares.length) {
910
- const middleware = this.middlewares[index++];
911
- await middleware(msg, next);
912
- } else {
913
- await finalHandler(msg);
125
+ const { WebSocketServer } = await import('ws');
126
+ peer = new WebSocketServer({ port, host: host ?? "0.0.0.0" });
127
+ peer.on("connection", (ws) => {
128
+ setupConnectionHandler(ws, connections, runtime);
129
+ });
130
+ setupBroadcasting(connections, runtime);
131
+ },
132
+ async close() {
133
+ if (!peer) return;
134
+ for (const ws of connections) {
135
+ ws.close();
914
136
  }
915
- };
916
- await next(message);
917
- }
918
- /**
919
- * Clear all middlewares
920
- */
921
- clear() {
922
- this.middlewares.length = 0;
923
- }
924
- /**
925
- * Get the number of middlewares
926
- */
927
- get size() {
928
- return this.middlewares.length;
929
- }
930
- };
931
- var logger32 = createLogger("core/InterceptorChain");
932
- var InterceptorChain = class {
933
- constructor(agentId) {
934
- __publicField(this, "interceptors", []);
935
- __publicField(this, "agentId");
936
- this.agentId = agentId;
937
- }
938
- /**
939
- * Add interceptor to the chain
940
- *
941
- * @param interceptor - Interceptor function
942
- * @returns Unsubscribe function to remove the interceptor
943
- */
944
- intercept(interceptor) {
945
- this.interceptors.push(interceptor);
946
- return () => {
947
- const index = this.interceptors.indexOf(interceptor);
948
- if (index !== -1) {
949
- this.interceptors.splice(index, 1);
137
+ connections.clear();
138
+ if (!attachedToServer) {
139
+ await new Promise((resolve) => {
140
+ peer.close(() => resolve());
141
+ });
950
142
  }
951
- };
952
- }
953
- /**
954
- * Execute the interceptor chain
955
- *
956
- * @param event - Event to process
957
- * @param finalHandler - Handler called at the end of the chain
958
- */
959
- execute(event, finalHandler) {
960
- let index = 0;
961
- const next = (e) => {
962
- if (index < this.interceptors.length) {
963
- const interceptor = this.interceptors[index++];
964
- try {
965
- interceptor(e, next);
966
- } catch (error) {
967
- logger32.error("Interceptor error", {
968
- agentId: this.agentId,
969
- eventType: e.type,
970
- interceptorIndex: index - 1,
971
- error
143
+ peer = null;
144
+ },
145
+ async dispose() {
146
+ if (peer) {
147
+ for (const ws of connections) {
148
+ ws.close();
149
+ }
150
+ connections.clear();
151
+ if (!attachedToServer) {
152
+ await new Promise((resolve) => {
153
+ peer.close(() => resolve());
972
154
  });
973
- next(e);
974
155
  }
975
- } else {
976
- finalHandler(e);
156
+ peer = null;
977
157
  }
978
- };
979
- next(event);
980
- }
981
- /**
982
- * Clear all interceptors
983
- */
984
- clear() {
985
- this.interceptors.length = 0;
986
- }
987
- /**
988
- * Get the number of interceptors
989
- */
990
- get size() {
991
- return this.interceptors.length;
992
- }
993
- };
994
- var REACT_TO_EVENT_MAP = {
995
- // Stream Layer Events
996
- onMessageStart: "message_start",
997
- onMessageDelta: "message_delta",
998
- onMessageStop: "message_stop",
999
- onTextContentBlockStart: "text_content_block_start",
1000
- onTextDelta: "text_delta",
1001
- onTextContentBlockStop: "text_content_block_stop",
1002
- onToolUseContentBlockStart: "tool_use_content_block_start",
1003
- onInputJsonDelta: "input_json_delta",
1004
- onToolUseContentBlockStop: "tool_use_content_block_stop",
1005
- onToolCall: "tool_call",
1006
- onToolResult: "tool_result",
1007
- // Message Layer Events
1008
- onUserMessage: "user_message",
1009
- onAssistantMessage: "assistant_message",
1010
- onToolCallMessage: "tool_call_message",
1011
- onToolResultMessage: "tool_result_message",
1012
- // Error Layer Events (independent, transportable via SSE)
1013
- onError: "error",
1014
- // Turn Layer Events
1015
- onTurnRequest: "turn_request",
1016
- onTurnResponse: "turn_response"
1017
- };
1018
- function mapReactHandlers(reactHandlers) {
1019
- const eventHandlerMap = {};
1020
- for (const [reactKey, eventKey] of Object.entries(REACT_TO_EVENT_MAP)) {
1021
- const handler = reactHandlers[reactKey];
1022
- if (handler) {
1023
- eventHandlerMap[eventKey] = handler;
158
+ await runtime.dispose();
1024
159
  }
1025
- }
1026
- return eventHandlerMap;
160
+ };
1027
161
  }
1028
- var logger42 = createLogger("core/AgentInstance");
1029
- var AgentInstance = class {
1030
- constructor(definition, context, engine, driver, sandbox) {
1031
- __publicField(this, "agentId");
1032
- __publicField(this, "definition");
1033
- __publicField(this, "context");
1034
- __publicField(this, "createdAt");
1035
- __publicField(this, "sandbox");
1036
- __publicField(this, "_lifecycle", "running");
1037
- __publicField(this, "engine");
1038
- /**
1039
- * Driver instance - created from definition.driver class
1040
- */
1041
- __publicField(this, "driver");
1042
- /**
1043
- * State machine - manages state transitions driven by StateEvents
1044
- */
1045
- __publicField(this, "stateMachine", new AgentStateMachine());
1046
- /**
1047
- * Event bus - centralized event pub/sub
1048
- */
1049
- __publicField(this, "eventBus", new AgentEventBus());
1050
- /**
1051
- * Error classifier - classifies and creates error events
1052
- */
1053
- __publicField(this, "errorClassifier");
1054
- /**
1055
- * Middleware chain for receive() interception
1056
- */
1057
- __publicField(this, "middlewareChain", new MiddlewareChain());
1058
- /**
1059
- * Interceptor chain for event dispatch interception
1060
- */
1061
- __publicField(this, "interceptorChain");
1062
- /**
1063
- * Lifecycle handlers for onReady
1064
- */
1065
- __publicField(this, "readyHandlers", /* @__PURE__ */ new Set());
1066
- /**
1067
- * Lifecycle handlers for onDestroy
1068
- */
1069
- __publicField(this, "destroyHandlers", /* @__PURE__ */ new Set());
1070
- this.agentId = context.agentId;
1071
- this.definition = definition;
1072
- this.context = context;
1073
- this.engine = engine;
1074
- this.createdAt = context.createdAt;
1075
- this.sandbox = sandbox;
1076
- this.driver = driver;
1077
- this.errorClassifier = new AgentErrorClassifier(this.agentId);
1078
- this.interceptorChain = new InterceptorChain(this.agentId);
1079
- logger42.debug("AgentInstance created", {
1080
- agentId: this.agentId,
1081
- definitionName: definition.name,
1082
- driverName: this.driver.name
1083
- });
1084
- }
1085
- /**
1086
- * Current lifecycle state
1087
- */
1088
- get lifecycle() {
1089
- return this._lifecycle;
162
+ var logger;
163
+ var init_createLocalAgentX = __esm({
164
+ "src/createLocalAgentX.ts"() {
165
+ logger = createLogger("agentx/createAgentX");
1090
166
  }
1091
- /**
1092
- * Current conversation state (delegated to StateMachine)
1093
- */
1094
- get state() {
1095
- return this.stateMachine.state;
1096
- }
1097
- /**
1098
- * Receive a message from user
1099
- *
1100
- * Runs through middleware chain before actual processing.
1101
- *
1102
- * Error Handling:
1103
- * - Errors are caught and converted to ErrorMessageEvent
1104
- * - Handlers receive the error event before re-throwing
1105
- * - This ensures UI can display errors
1106
- */
1107
- async receive(message) {
1108
- if (this._lifecycle === "destroyed") {
1109
- logger42.warn("Receive called on destroyed agent", { agentId: this.agentId });
1110
- const error = this.errorClassifier.create(
1111
- "system",
1112
- "AGENT_DESTROYED",
1113
- "Agent has been destroyed",
1114
- false
1115
- );
1116
- const errorEvent = this.errorClassifier.createEvent(error);
1117
- this.notifyHandlers(errorEvent);
1118
- throw new Error("[Agent] Agent has been destroyed");
1119
- }
1120
- if (this.state !== "idle") {
1121
- logger42.warn("Receive called while agent is busy", {
1122
- agentId: this.agentId,
1123
- currentState: this.state
1124
- });
1125
- const error = this.errorClassifier.create(
1126
- "system",
1127
- "AGENT_BUSY",
1128
- `Agent is busy (state: ${this.state}), please wait for current operation to complete`,
1129
- false
1130
- );
1131
- const errorEvent = this.errorClassifier.createEvent(error);
1132
- this.notifyHandlers(errorEvent);
1133
- throw new Error(`[Agent] Agent is busy (state: ${this.state})`);
1134
- }
1135
- const userMessage = typeof message === "string" ? {
1136
- id: `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1137
- role: "user",
1138
- subtype: "user",
1139
- content: message,
1140
- timestamp: Date.now()
1141
- } : message;
1142
- logger42.debug("Receiving message", {
1143
- agentId: this.agentId,
1144
- messageId: userMessage.id
1145
- });
1146
- const userMessageEvent = {
1147
- uuid: `evt_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1148
- type: "user_message",
1149
- agentId: this.agentId,
1150
- timestamp: Date.now(),
1151
- data: userMessage
1152
- };
1153
- this.presentOutput(userMessageEvent);
1154
- this.notifyHandlers(userMessageEvent);
1155
- await this.executeMiddlewareChain(userMessage);
1156
- }
1157
- /**
1158
- * Execute middleware chain and then process the message
1159
- */
1160
- async executeMiddlewareChain(message) {
1161
- await this.middlewareChain.execute(message, (msg) => this.doReceive(msg));
1162
- }
1163
- /**
1164
- * Process a single stream event through the engine
1165
- *
1166
- * Used by:
1167
- * - doReceive() - normal message flow
1168
- * - AgentInterrupter - interrupt event injection
1169
- *
1170
- * @param streamEvent - Stream event to process
1171
- */
1172
- processStreamEvent(streamEvent) {
1173
- const outputs = this.engine.process(this.agentId, streamEvent);
1174
- for (const output of outputs) {
1175
- this.presentOutput(output);
1176
- }
1177
- for (const output of outputs) {
1178
- this.notifyHandlers(output);
167
+ });
168
+ var remoteLogger = createLogger("agentx/RemoteClient");
169
+ async function createAgentX(config) {
170
+ if (config && isRemoteConfig(config)) {
171
+ return createRemoteAgentX(config.serverUrl);
172
+ }
173
+ const { createLocalAgentX: createLocalAgentX2 } = await Promise.resolve().then(() => (init_createLocalAgentX(), createLocalAgentX_exports));
174
+ return createLocalAgentX2(config ?? {});
175
+ }
176
+ var isBrowser = typeof window !== "undefined" && typeof window.WebSocket !== "undefined";
177
+ async function createRemoteAgentX(serverUrl) {
178
+ const WebSocketImpl = isBrowser ? window.WebSocket : (await import('ws')).WebSocket;
179
+ const ws = new WebSocketImpl(serverUrl);
180
+ const handlers = /* @__PURE__ */ new Map();
181
+ const pendingRequests = /* @__PURE__ */ new Map();
182
+ await new Promise((resolve, reject) => {
183
+ if (isBrowser) {
184
+ ws.onopen = () => resolve();
185
+ ws.onerror = () => reject(new Error("WebSocket connection failed"));
186
+ } else {
187
+ ws.on("open", () => resolve());
188
+ ws.on("error", (err) => reject(err));
1179
189
  }
1180
- }
1181
- /**
1182
- * Actual message processing logic
1183
- *
1184
- * Coordinates the flow:
1185
- * 1. Driver receives message → produces StreamEvents
1186
- * 2. Engine processes events → produces outputs
1187
- * 3. Presenters handle outputs
1188
- * 4. Handlers receive outputs
1189
- */
1190
- async doReceive(userMessage) {
190
+ });
191
+ const handleMessage = (data) => {
1191
192
  try {
1192
- logger42.debug("Processing message through driver", {
1193
- agentId: this.agentId,
1194
- messageId: userMessage.id
193
+ const text = isBrowser ? data.data : data.toString();
194
+ const event = JSON.parse(text);
195
+ remoteLogger.info("Received event", {
196
+ type: event.type,
197
+ category: event.category,
198
+ requestId: event.data?.requestId
1195
199
  });
1196
- const queuedEvent = {
1197
- type: "conversation_queued",
1198
- uuid: `${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1199
- agentId: this.agentId,
1200
- timestamp: Date.now(),
1201
- data: {
1202
- userMessage
1203
- }
1204
- };
1205
- this.notifyHandlers(queuedEvent);
1206
- const streamEvents = this.driver.receive(userMessage);
1207
- for await (const streamEvent of streamEvents) {
1208
- this.processStreamEvent(streamEvent);
200
+ if (event.type === "system_error") {
201
+ const errorData = event.data;
202
+ remoteLogger.error(errorData.message, {
203
+ severity: errorData.severity,
204
+ requestId: event.data?.requestId,
205
+ details: errorData.details
206
+ });
1209
207
  }
1210
- logger42.debug("Message processing completed", {
1211
- agentId: this.agentId,
1212
- messageId: userMessage.id
1213
- });
1214
- } catch (error) {
1215
- const agentError = this.errorClassifier.classify(error);
1216
- const errorEvent = this.errorClassifier.createEvent(agentError);
1217
- logger42.error("Message processing failed", {
1218
- agentId: this.agentId,
1219
- messageId: userMessage.id,
1220
- errorCategory: agentError.category,
1221
- errorCode: agentError.code,
1222
- error
1223
- });
1224
- this.notifyHandlers(errorEvent);
1225
- throw error;
1226
- }
1227
- }
1228
- /**
1229
- * Send output to all presenters
1230
- *
1231
- * Note: Presenters are no longer part of AgentDefinition.
1232
- * This is a placeholder for future presenter injection via Runtime or middleware.
1233
- */
1234
- presentOutput(_output) {
1235
- }
1236
- on(typeOrHandlerOrMap, handler) {
1237
- if (typeof typeOrHandlerOrMap === "function") {
1238
- return this.eventBus.onAny(typeOrHandlerOrMap);
1239
- }
1240
- if (this.isEventHandlerMap(typeOrHandlerOrMap)) {
1241
- const unsubscribes = [];
1242
- for (const [eventType, eventHandler] of Object.entries(typeOrHandlerOrMap)) {
1243
- if (eventHandler) {
1244
- unsubscribes.push(this.eventBus.on(eventType, eventHandler));
208
+ const requestId = event.data?.requestId;
209
+ if (event.category === "response" && requestId && pendingRequests.has(requestId)) {
210
+ remoteLogger.info("Resolving pending request", { requestId, eventType: event.type });
211
+ const pending = pendingRequests.get(requestId);
212
+ clearTimeout(pending.timer);
213
+ pendingRequests.delete(requestId);
214
+ pending.resolve(event);
215
+ return;
216
+ }
217
+ remoteLogger.info("Dispatching to handlers", { type: event.type });
218
+ const typeHandlers = handlers.get(event.type);
219
+ if (typeHandlers) {
220
+ for (const handler of typeHandlers) {
221
+ handler(event);
1245
222
  }
1246
223
  }
1247
- return () => {
1248
- for (const unsub of unsubscribes) {
1249
- unsub();
224
+ const allHandlers = handlers.get("*");
225
+ if (allHandlers) {
226
+ for (const handler of allHandlers) {
227
+ handler(event);
1250
228
  }
1251
- };
1252
- }
1253
- const types = Array.isArray(typeOrHandlerOrMap) ? typeOrHandlerOrMap : [typeOrHandlerOrMap];
1254
- const h = handler;
1255
- return this.eventBus.on(types, h);
1256
- }
1257
- /**
1258
- * Check if the argument is an EventHandlerMap (object with event type keys)
1259
- */
1260
- isEventHandlerMap(arg) {
1261
- if (typeof arg !== "object" || arg === null || Array.isArray(arg)) {
1262
- return false;
1263
- }
1264
- const keys = Object.keys(arg);
1265
- if (keys.length === 0) {
1266
- return false;
1267
- }
1268
- return keys.every((key) => {
1269
- const value = arg[key];
1270
- return value === void 0 || typeof value === "function";
1271
- });
1272
- }
1273
- /**
1274
- * Subscribe to state changes (delegated to StateMachine)
1275
- *
1276
- * @param handler - Callback receiving { prev, current } state change
1277
- * @returns Unsubscribe function
1278
- */
1279
- onStateChange(handler) {
1280
- return this.stateMachine.onStateChange(handler);
1281
- }
1282
- /**
1283
- * React-style fluent event subscription
1284
- *
1285
- * Converts onXxx handlers to event type keys and delegates to on(handlers)
1286
- */
1287
- react(handlers) {
1288
- const eventHandlerMap = mapReactHandlers(handlers);
1289
- return this.on(eventHandlerMap);
1290
- }
1291
- /**
1292
- * Subscribe to agent ready event
1293
- *
1294
- * If already running, handler is called immediately.
1295
- */
1296
- onReady(handler) {
1297
- if (this._lifecycle === "running") {
1298
- try {
1299
- handler();
1300
- } catch (error) {
1301
- logger42.error("onReady handler error", {
1302
- agentId: this.agentId,
1303
- error
1304
- });
1305
229
  }
230
+ } catch {
1306
231
  }
1307
- this.readyHandlers.add(handler);
1308
- return () => {
1309
- this.readyHandlers.delete(handler);
1310
- };
232
+ };
233
+ if (isBrowser) {
234
+ ws.onmessage = handleMessage;
235
+ } else {
236
+ ws.on("message", handleMessage);
1311
237
  }
1312
- /**
1313
- * Subscribe to agent destroy event
1314
- */
1315
- onDestroy(handler) {
1316
- this.destroyHandlers.add(handler);
238
+ function subscribe(type, handler) {
239
+ if (!handlers.has(type)) {
240
+ handlers.set(type, /* @__PURE__ */ new Set());
241
+ }
242
+ handlers.get(type).add(handler);
1317
243
  return () => {
1318
- this.destroyHandlers.delete(handler);
244
+ handlers.get(type)?.delete(handler);
1319
245
  };
1320
246
  }
1321
- /**
1322
- * Add middleware to intercept incoming messages
1323
- */
1324
- use(middleware) {
1325
- return this.middlewareChain.use(middleware);
1326
- }
1327
- /**
1328
- * Add interceptor to intercept outgoing events
1329
- */
1330
- intercept(interceptor) {
1331
- return this.interceptorChain.intercept(interceptor);
1332
- }
1333
- /**
1334
- * Interrupt - User-initiated stop
1335
- *
1336
- * Stops the current operation gracefully.
1337
- * Flow:
1338
- * 1. Call driver.interrupt() to abort active requests
1339
- * 2. Driver yields InterruptedStreamEvent
1340
- * 3. Event flows through engine pipeline
1341
- * 4. StateEventProcessor generates conversation_interrupted
1342
- * 5. StateMachine transitions to idle state
1343
- * 6. UI receives state change notification
1344
- */
1345
- interrupt() {
1346
- logger42.debug("User interrupt requested", { agentId: this.agentId, currentState: this.state });
1347
- this.driver.interrupt();
1348
- }
1349
- /**
1350
- * Destroy - Clean up resources
1351
- */
1352
- async destroy() {
1353
- logger42.debug("Destroying agent", { agentId: this.agentId });
1354
- for (const handler of this.destroyHandlers) {
1355
- try {
1356
- handler();
1357
- } catch (error) {
1358
- logger42.error("onDestroy handler error", {
1359
- agentId: this.agentId,
1360
- error
247
+ return {
248
+ request(type, data, timeout = 3e4) {
249
+ return new Promise((resolve, reject) => {
250
+ const requestId = `req_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
251
+ const timer = setTimeout(() => {
252
+ pendingRequests.delete(requestId);
253
+ reject(new Error(`Request timeout: ${type}`));
254
+ }, timeout);
255
+ pendingRequests.set(requestId, {
256
+ resolve,
257
+ reject,
258
+ timer
1361
259
  });
1362
- }
1363
- }
1364
- this._lifecycle = "destroyed";
1365
- this.stateMachine.reset();
1366
- this.eventBus.destroy();
1367
- this.readyHandlers.clear();
1368
- this.destroyHandlers.clear();
1369
- this.middlewareChain.clear();
1370
- this.interceptorChain.clear();
1371
- this.engine.clearState(this.agentId);
1372
- logger42.info("Agent destroyed", { agentId: this.agentId });
1373
- }
1374
- /**
1375
- * Notify all registered handlers
1376
- *
1377
- * Flow:
1378
- * 1. StateMachine processes StateEvents (for state transitions)
1379
- * 2. Interceptor chain can modify/filter events
1380
- * 3. EventBus emits to all subscribers
1381
- */
1382
- notifyHandlers(event) {
1383
- if (isStateEvent(event)) {
1384
- this.stateMachine.process(event);
1385
- }
1386
- this.executeInterceptorChain(event);
1387
- }
1388
- /**
1389
- * Execute interceptor chain and then emit to EventBus
1390
- */
1391
- executeInterceptorChain(event) {
1392
- this.interceptorChain.execute(event, (e) => this.eventBus.emit(e));
1393
- }
1394
- /**
1395
- * Get the event consumer for external subscriptions
1396
- *
1397
- * Use this to expose event subscription without emit capability.
1398
- */
1399
- getEventConsumer() {
1400
- return this.eventBus.asConsumer();
1401
- }
1402
- };
1403
- var MemoryStore = class {
1404
- constructor() {
1405
- __publicField(this, "states", /* @__PURE__ */ new Map());
1406
- }
1407
- get(id) {
1408
- return this.states.get(id);
1409
- }
1410
- set(id, state) {
1411
- this.states.set(id, state);
1412
- }
1413
- delete(id) {
1414
- this.states.delete(id);
1415
- }
1416
- has(id) {
1417
- return this.states.has(id);
1418
- }
1419
- /**
1420
- * Clear all stored states
1421
- */
1422
- clear() {
1423
- this.states.clear();
1424
- }
1425
- /**
1426
- * Get the number of stored states
1427
- */
1428
- get size() {
1429
- return this.states.size;
1430
- }
1431
- /**
1432
- * Get all stored IDs
1433
- */
1434
- keys() {
1435
- return this.states.keys();
1436
- }
1437
- };
1438
- createLogger("engine/Mealy");
1439
- function combineProcessors(processors) {
1440
- return (state, event) => {
1441
- const newState = {};
1442
- const allOutputs = [];
1443
- for (const key in processors) {
1444
- const processor = processors[key];
1445
- const subState = state[key];
1446
- const [newSubState, outputs] = processor(subState, event);
1447
- newState[key] = newSubState;
1448
- allOutputs.push(...outputs);
1449
- }
1450
- return [newState, allOutputs];
1451
- };
1452
- }
1453
- function combineInitialStates(initialStates) {
1454
- return () => {
1455
- const state = {};
1456
- for (const key in initialStates) {
1457
- state[key] = initialStates[key]();
1458
- }
1459
- return state;
1460
- };
1461
- }
1462
- function createInitialMessageAssemblerState() {
1463
- return {
1464
- currentMessageId: null,
1465
- messageStartTime: null,
1466
- pendingContents: {},
1467
- pendingToolCalls: {}
1468
- };
1469
- }
1470
- function generateId() {
1471
- return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1472
- }
1473
- var messageAssemblerProcessor = (state, input) => {
1474
- switch (input.type) {
1475
- case "message_start":
1476
- return handleMessageStart(state, input);
1477
- case "text_delta":
1478
- return handleTextDelta(state, input);
1479
- case "tool_use_content_block_start":
1480
- return handleToolUseContentBlockStart(state, input);
1481
- case "input_json_delta":
1482
- return handleInputJsonDelta(state, input);
1483
- case "tool_use_content_block_stop":
1484
- return handleToolUseContentBlockStop(state, input);
1485
- case "tool_result":
1486
- return handleToolResult(state, input);
1487
- case "message_stop":
1488
- return handleMessageStop(state, input);
1489
- default:
1490
- return [state, []];
1491
- }
1492
- };
1493
- function handleMessageStart(state, event) {
1494
- return [
1495
- {
1496
- ...state,
1497
- currentMessageId: generateId(),
1498
- messageStartTime: event.timestamp,
1499
- pendingContents: {}
1500
- },
1501
- []
1502
- ];
1503
- }
1504
- function handleTextDelta(state, event) {
1505
- const index = 0;
1506
- const existingContent = state.pendingContents[index];
1507
- const pendingContent = existingContent?.type === "text" ? {
1508
- ...existingContent,
1509
- textDeltas: [...existingContent.textDeltas || [], event.data.text]
1510
- } : {
1511
- type: "text",
1512
- index,
1513
- textDeltas: [event.data.text]
1514
- };
1515
- return [
1516
- {
1517
- ...state,
1518
- pendingContents: {
1519
- ...state.pendingContents,
1520
- [index]: pendingContent
1521
- }
1522
- },
1523
- []
1524
- ];
1525
- }
1526
- function handleToolUseContentBlockStart(state, event) {
1527
- const index = 1;
1528
- const pendingContent = {
1529
- type: "tool_use",
1530
- index,
1531
- toolId: event.data.id,
1532
- toolName: event.data.name,
1533
- toolInputJson: ""
1534
- };
1535
- return [
1536
- {
1537
- ...state,
1538
- pendingContents: {
1539
- ...state.pendingContents,
1540
- [index]: pendingContent
1541
- }
1542
- },
1543
- []
1544
- ];
1545
- }
1546
- function handleInputJsonDelta(state, event) {
1547
- const index = 1;
1548
- const existingContent = state.pendingContents[index];
1549
- if (!existingContent || existingContent.type !== "tool_use") {
1550
- return [state, []];
1551
- }
1552
- const pendingContent = {
1553
- ...existingContent,
1554
- toolInputJson: (existingContent.toolInputJson || "") + event.data.partialJson
1555
- };
1556
- return [
1557
- {
1558
- ...state,
1559
- pendingContents: {
1560
- ...state.pendingContents,
1561
- [index]: pendingContent
1562
- }
260
+ const event = {
261
+ type,
262
+ timestamp: Date.now(),
263
+ data: { ...data, requestId },
264
+ source: "command",
265
+ category: "request",
266
+ intent: "request"
267
+ };
268
+ ws.send(JSON.stringify(event));
269
+ });
1563
270
  },
1564
- []
1565
- ];
1566
- }
1567
- function handleToolUseContentBlockStop(state, event) {
1568
- const index = 1;
1569
- const pendingContent = state.pendingContents[index];
1570
- if (!pendingContent || pendingContent.type !== "tool_use") {
1571
- return [state, []];
1572
- }
1573
- let toolInput = {};
1574
- try {
1575
- toolInput = pendingContent.toolInputJson ? JSON.parse(pendingContent.toolInputJson) : {};
1576
- } catch {
1577
- toolInput = {};
1578
- }
1579
- const outputs = [];
1580
- const toolId = pendingContent.toolId;
1581
- const toolName = pendingContent.toolName;
1582
- const toolCallEvent = {
1583
- type: "tool_call",
1584
- uuid: generateId(),
1585
- agentId: event.agentId,
1586
- timestamp: Date.now(),
1587
- data: {
1588
- id: toolId,
1589
- name: toolName,
1590
- input: toolInput
1591
- }
1592
- };
1593
- outputs.push(toolCallEvent);
1594
- const toolCall = {
1595
- type: "tool-call",
1596
- id: toolId,
1597
- name: toolName,
1598
- input: toolInput
1599
- };
1600
- const toolCallMessage = {
1601
- id: generateId(),
1602
- role: "assistant",
1603
- subtype: "tool-call",
1604
- toolCall,
1605
- timestamp: Date.now()
1606
- };
1607
- const toolCallMessageEvent = {
1608
- type: "tool_call_message",
1609
- uuid: generateId(),
1610
- agentId: event.agentId,
1611
- timestamp: Date.now(),
1612
- data: toolCallMessage
1613
- };
1614
- outputs.push(toolCallMessageEvent);
1615
- const { [index]: _, ...remainingContents } = state.pendingContents;
1616
- return [
1617
- {
1618
- ...state,
1619
- pendingContents: remainingContents,
1620
- pendingToolCalls: {
1621
- ...state.pendingToolCalls,
1622
- [toolId]: { id: toolId, name: toolName }
1623
- }
271
+ on(type, handler) {
272
+ return subscribe(type, handler);
1624
273
  },
1625
- outputs
1626
- ];
1627
- }
1628
- function handleToolResult(state, event) {
1629
- const { toolId, content, isError } = event.data;
1630
- const pendingToolCall = state.pendingToolCalls[toolId];
1631
- const toolName = pendingToolCall?.name || "unknown";
1632
- const toolResult = {
1633
- type: "tool-result",
1634
- id: toolId,
1635
- name: toolName,
1636
- output: {
1637
- type: isError ? "error-text" : "text",
1638
- value: typeof content === "string" ? content : JSON.stringify(content)
1639
- }
1640
- };
1641
- const toolResultMessage = {
1642
- id: generateId(),
1643
- role: "tool",
1644
- subtype: "tool-result",
1645
- toolResult,
1646
- toolCallId: toolId,
1647
- timestamp: Date.now()
1648
- };
1649
- const toolResultMessageEvent = {
1650
- type: "tool_result_message",
1651
- uuid: generateId(),
1652
- agentId: event.agentId,
1653
- timestamp: Date.now(),
1654
- data: toolResultMessage
1655
- };
1656
- const { [toolId]: _, ...remainingToolCalls } = state.pendingToolCalls;
1657
- return [
1658
- {
1659
- ...state,
1660
- pendingToolCalls: remainingToolCalls
274
+ onCommand(type, handler) {
275
+ return subscribe(type, handler);
1661
276
  },
1662
- [toolResultMessageEvent]
1663
- ];
1664
- }
1665
- function handleMessageStop(state, event) {
1666
- if (!state.currentMessageId) {
1667
- return [state, []];
1668
- }
1669
- const textParts = [];
1670
- const sortedContents = Object.values(state.pendingContents).sort((a, b) => a.index - b.index);
1671
- for (const pending of sortedContents) {
1672
- if (pending.type === "text" && pending.textDeltas) {
1673
- textParts.push(pending.textDeltas.join(""));
1674
- }
1675
- }
1676
- const content = textParts.join("");
1677
- const stopReason = event.data.stopReason;
1678
- if (!content || content.trim().length === 0) {
1679
- const shouldPreserveToolCalls2 = stopReason === "tool_use";
1680
- return [
1681
- {
1682
- ...createInitialMessageAssemblerState(),
1683
- pendingToolCalls: shouldPreserveToolCalls2 ? state.pendingToolCalls : {}
1684
- },
1685
- []
1686
- ];
1687
- }
1688
- const assistantMessage = {
1689
- id: state.currentMessageId,
1690
- role: "assistant",
1691
- subtype: "assistant",
1692
- content,
1693
- timestamp: state.messageStartTime || Date.now(),
1694
- // Usage data is not available in message_stop event
1695
- // It would need to be tracked separately if needed
1696
- usage: void 0
1697
- };
1698
- const assistantEvent = {
1699
- type: "assistant_message",
1700
- uuid: generateId(),
1701
- agentId: event.agentId,
1702
- timestamp: Date.now(),
1703
- data: assistantMessage
1704
- };
1705
- const shouldPreserveToolCalls = stopReason === "tool_use";
1706
- return [
1707
- {
1708
- ...createInitialMessageAssemblerState(),
1709
- pendingToolCalls: shouldPreserveToolCalls ? state.pendingToolCalls : {}
277
+ emitCommand(type, data) {
278
+ const event = {
279
+ type,
280
+ timestamp: Date.now(),
281
+ data,
282
+ source: "command",
283
+ category: type.toString().endsWith("_response") ? "response" : "request",
284
+ intent: type.toString().endsWith("_response") ? "result" : "request"
285
+ };
286
+ ws.send(JSON.stringify(event));
1710
287
  },
1711
- [assistantEvent]
1712
- ];
1713
- }
1714
- var logger23 = createLogger("engine/stateEventProcessor");
1715
- function createInitialStateEventProcessorContext() {
1716
- return {};
1717
- }
1718
- function generateId2() {
1719
- return `state_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1720
- }
1721
- var stateEventProcessor = (context, input) => {
1722
- logger23.debug(`[Stream Event] ${input.type}`, {
1723
- context,
1724
- eventData: "data" in input ? input.data : void 0
1725
- });
1726
- switch (input.type) {
1727
- case "message_start":
1728
- return handleMessageStart2(context, input);
1729
- case "message_delta":
1730
- return handleMessageDelta(context);
1731
- case "message_stop":
1732
- return handleMessageStop2(context, input);
1733
- case "text_content_block_start":
1734
- return handleTextContentBlockStart(context, input);
1735
- case "tool_use_content_block_start":
1736
- return handleToolUseContentBlockStart2(context, input);
1737
- case "tool_use_content_block_stop":
1738
- return handleToolUseContentBlockStop2(context);
1739
- case "tool_call":
1740
- return handleToolCall(context);
1741
- case "interrupted":
1742
- return handleInterrupted(context, input);
1743
- default:
1744
- logger23.debug(`[Stream Event] ${input.type} (unhandled)`);
1745
- return [context, []];
1746
- }
1747
- };
1748
- function handleMessageStart2(context, event) {
1749
- const conversationStartEvent = {
1750
- type: "conversation_start",
1751
- uuid: generateId2(),
1752
- agentId: event.agentId,
1753
- timestamp: event.timestamp,
1754
- transition: {
1755
- reason: "conversation_started",
1756
- trigger: "message_start"
288
+ async listen() {
289
+ throw new Error("Cannot listen in remote mode");
1757
290
  },
1758
- data: {
1759
- userMessage: {}
1760
- // Will be populated by higher-level component
1761
- }
1762
- };
1763
- return [context, [conversationStartEvent]];
1764
- }
1765
- function handleMessageDelta(context, _event) {
1766
- return [context, []];
1767
- }
1768
- function handleMessageStop2(context, event) {
1769
- const stopReason = event.data.stopReason;
1770
- logger23.debug("message_stop received", { stopReason });
1771
- if (stopReason === "tool_use") {
1772
- logger23.debug("Skipping conversation_end (tool_use in progress)");
1773
- return [context, []];
1774
- }
1775
- const conversationEndEvent = {
1776
- type: "conversation_end",
1777
- uuid: generateId2(),
1778
- agentId: event.agentId,
1779
- timestamp: event.timestamp,
1780
- transition: {
1781
- reason: "conversation_completed",
1782
- trigger: "message_stop"
291
+ async close() {
1783
292
  },
1784
- data: {
1785
- assistantMessage: {},
1786
- // Will be populated by higher-level component
1787
- durationMs: 0,
1788
- // Will be calculated by StateMachine or TurnTracker
1789
- durationApiMs: 0,
1790
- numTurns: 0,
1791
- result: "completed",
1792
- totalCostUsd: 0,
1793
- usage: {
1794
- input: 0,
1795
- output: 0
293
+ async dispose() {
294
+ for (const pending of pendingRequests.values()) {
295
+ clearTimeout(pending.timer);
296
+ pending.reject(new Error("AgentX disposed"));
1796
297
  }
1797
- }
1798
- };
1799
- return [context, [conversationEndEvent]];
1800
- }
1801
- function handleTextContentBlockStart(context, event) {
1802
- const respondingEvent = {
1803
- type: "conversation_responding",
1804
- uuid: generateId2(),
1805
- agentId: event.agentId,
1806
- timestamp: Date.now(),
1807
- transition: {
1808
- reason: "assistant_responding",
1809
- trigger: "text_content_block_start"
1810
- },
1811
- data: {}
1812
- };
1813
- return [context, [respondingEvent]];
1814
- }
1815
- function handleToolUseContentBlockStart2(context, event) {
1816
- const outputs = [];
1817
- const toolPlannedEvent = {
1818
- type: "tool_planned",
1819
- uuid: generateId2(),
1820
- agentId: event.agentId,
1821
- timestamp: event.timestamp,
1822
- data: {
1823
- id: event.data.id,
1824
- name: event.data.name,
1825
- input: {}
1826
- }
1827
- };
1828
- outputs.push(toolPlannedEvent);
1829
- const toolExecutingEvent = {
1830
- type: "tool_executing",
1831
- uuid: generateId2(),
1832
- agentId: event.agentId,
1833
- timestamp: event.timestamp,
1834
- transition: {
1835
- reason: "tool_planning_started",
1836
- trigger: "tool_use_content_block_start"
1837
- },
1838
- data: {}
1839
- };
1840
- outputs.push(toolExecutingEvent);
1841
- return [context, outputs];
1842
- }
1843
- function handleToolUseContentBlockStop2(context, _event) {
1844
- return [context, []];
1845
- }
1846
- function handleToolCall(context, _event) {
1847
- return [context, []];
1848
- }
1849
- function handleInterrupted(context, event) {
1850
- logger23.debug("interrupted event received", { reason: event.data.reason });
1851
- const conversationInterruptedEvent = {
1852
- type: "conversation_interrupted",
1853
- uuid: generateId2(),
1854
- agentId: event.agentId,
1855
- timestamp: event.timestamp,
1856
- transition: {
1857
- reason: event.data.reason,
1858
- trigger: "interrupted"
1859
- },
1860
- data: {
1861
- reason: event.data.reason
1862
- }
1863
- };
1864
- return [context, [conversationInterruptedEvent]];
1865
- }
1866
- function createInitialTurnTrackerState() {
1867
- return {
1868
- pendingTurn: null,
1869
- costPerInputToken: 3e-6,
1870
- // $3 per 1M tokens
1871
- costPerOutputToken: 15e-6
1872
- // $15 per 1M tokens
1873
- };
1874
- }
1875
- function generateId3() {
1876
- return `turn_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1877
- }
1878
- function calculateCost(usage, costPerInputToken, costPerOutputToken) {
1879
- const inputCost = usage.input * costPerInputToken;
1880
- const outputCost = usage.output * costPerOutputToken;
1881
- return inputCost + outputCost;
1882
- }
1883
- var turnTrackerProcessor = (state, input) => {
1884
- switch (input.type) {
1885
- case "user_message":
1886
- return handleUserMessage(state, input);
1887
- case "message_stop":
1888
- return handleMessageStop3(state, input);
1889
- case "assistant_message":
1890
- return [state, []];
1891
- default:
1892
- return [state, []];
1893
- }
1894
- };
1895
- function handleUserMessage(state, event) {
1896
- const turnId = generateId3();
1897
- const pendingTurn = {
1898
- turnId,
1899
- userMessage: event.data,
1900
- requestedAt: event.timestamp
1901
- };
1902
- const turnRequestEvent = {
1903
- type: "turn_request",
1904
- uuid: generateId3(),
1905
- agentId: event.agentId,
1906
- timestamp: Date.now(),
1907
- turnId,
1908
- data: {
1909
- userMessage: event.data,
1910
- requestedAt: event.timestamp
1911
- }
1912
- };
1913
- return [
1914
- {
1915
- ...state,
1916
- pendingTurn
1917
- },
1918
- [turnRequestEvent]
1919
- ];
1920
- }
1921
- function handleMessageStop3(state, event) {
1922
- if (!state.pendingTurn) {
1923
- return [state, []];
1924
- }
1925
- const stopReason = event.data.stopReason;
1926
- if (stopReason === "end_turn" || stopReason === "max_tokens" || stopReason === "stop_sequence") {
1927
- return completeTurn(state, event.agentId, event.timestamp);
1928
- }
1929
- return [state, []];
1930
- }
1931
- function completeTurn(state, agentId, completedAt) {
1932
- if (!state.pendingTurn) {
1933
- return [state, []];
1934
- }
1935
- const { turnId, requestedAt } = state.pendingTurn;
1936
- const duration = completedAt - requestedAt;
1937
- const usage = { input: 0, output: 0 };
1938
- const cost = calculateCost(usage, state.costPerInputToken, state.costPerOutputToken);
1939
- const turnResponseEvent = {
1940
- type: "turn_response",
1941
- uuid: generateId3(),
1942
- agentId,
1943
- timestamp: Date.now(),
1944
- turnId,
1945
- data: {
1946
- assistantMessage: {
1947
- id: generateId3(),
1948
- role: "assistant",
1949
- subtype: "assistant",
1950
- content: "",
1951
- timestamp: completedAt
1952
- },
1953
- respondedAt: completedAt,
1954
- durationMs: duration,
1955
- usage,
1956
- costUsd: cost
1957
- }
1958
- };
1959
- return [
1960
- {
1961
- ...state,
1962
- pendingTurn: null
1963
- },
1964
- [turnResponseEvent]
1965
- ];
1966
- }
1967
- var agentProcessor = combineProcessors({
1968
- messageAssembler: messageAssemblerProcessor,
1969
- stateEventProcessor,
1970
- turnTracker: turnTrackerProcessor
1971
- });
1972
- var createInitialAgentEngineState = combineInitialStates({
1973
- messageAssembler: createInitialMessageAssemblerState,
1974
- stateEventProcessor: createInitialStateEventProcessorContext,
1975
- turnTracker: createInitialTurnTrackerState
1976
- });
1977
- var logger33 = createLogger("engine/AgentEngine");
1978
- var AgentEngine = class {
1979
- constructor() {
1980
- __publicField(this, "store");
1981
- this.store = new MemoryStore();
1982
- logger33.debug("AgentEngine initialized");
1983
- }
1984
- /**
1985
- * Process a single stream event and return output events
1986
- *
1987
- * This is the core Mealy Machine operation:
1988
- * process(agentId, event) → outputs[]
1989
- *
1990
- * @param agentId - The agent identifier (for state isolation)
1991
- * @param event - Stream event to process
1992
- * @returns Array of output events (state, message, turn events)
1993
- */
1994
- process(agentId, event) {
1995
- const eventType = event.type || "unknown";
1996
- logger33.debug("Processing event", { agentId, eventType });
1997
- const isNewState = !this.store.has(agentId);
1998
- let state = this.store.get(agentId) ?? createInitialAgentEngineState();
1999
- if (isNewState) {
2000
- logger33.debug("Created initial state for agent", { agentId });
2001
- }
2002
- const allOutputs = [];
2003
- allOutputs.push(event);
2004
- const [newState, outputs] = agentProcessor(state, event);
2005
- state = newState;
2006
- for (const output of outputs) {
2007
- allOutputs.push(output);
2008
- const [chainedState, chainedOutputs] = this.processChained(state, output);
2009
- state = chainedState;
2010
- allOutputs.push(...chainedOutputs);
2011
- }
2012
- this.store.set(agentId, state);
2013
- if (outputs.length > 0) {
2014
- logger33.debug("Produced outputs", {
2015
- agentId,
2016
- inputEvent: eventType,
2017
- outputCount: allOutputs.length,
2018
- processorOutputs: outputs.length
2019
- });
2020
- }
2021
- return allOutputs;
2022
- }
2023
- /**
2024
- * Process chained events recursively
2025
- *
2026
- * Some processors produce events that trigger other processors:
2027
- * - MessageAssembler produces MessageEvents
2028
- * - TurnTracker consumes MessageEvents to produce TurnEvents
2029
- */
2030
- processChained(state, event) {
2031
- const [newState, outputs] = agentProcessor(state, event);
2032
- if (outputs.length === 0) {
2033
- return [newState, []];
2034
- }
2035
- const allOutputs = [...outputs];
2036
- let currentState = newState;
2037
- for (const output of outputs) {
2038
- const [chainedState, chainedOutputs] = this.processChained(currentState, output);
2039
- currentState = chainedState;
2040
- allOutputs.push(...chainedOutputs);
2041
- }
2042
- return [currentState, allOutputs];
2043
- }
2044
- /**
2045
- * Clear state for an agent
2046
- *
2047
- * Call this when an agent is destroyed to free memory.
2048
- */
2049
- clearState(agentId) {
2050
- logger33.debug("Clearing state", { agentId });
2051
- this.store.delete(agentId);
2052
- }
2053
- /**
2054
- * Check if state exists for an agent
2055
- */
2056
- hasState(agentId) {
2057
- return this.store.has(agentId);
2058
- }
2059
- };
2060
- var logger7 = createLogger("agentx/ContainerManager");
2061
- function generateContainerId() {
2062
- const timestamp = Date.now().toString(36);
2063
- const random = Math.random().toString(36).substring(2, 8);
2064
- return `container_${timestamp}_${random}`;
2065
- }
2066
- function generateAgentId() {
2067
- const timestamp = Date.now().toString(36);
2068
- const random = Math.random().toString(36).substring(2, 8);
2069
- return `agent_${timestamp}_${random}`;
2070
- }
2071
- var ContainerManagerImpl = class {
2072
- constructor(runtime, repository) {
2073
- __publicField(this, "agents", /* @__PURE__ */ new Map());
2074
- __publicField(this, "engine");
2075
- __publicField(this, "runtime");
2076
- __publicField(this, "repository");
2077
- this.runtime = runtime;
2078
- this.repository = repository;
2079
- this.engine = new AgentEngine();
2080
- }
2081
- // ==================== Container Lifecycle ====================
2082
- async create(config) {
2083
- const containerId = generateContainerId();
2084
- const now = Date.now();
2085
- const record = {
2086
- containerId,
2087
- createdAt: now,
2088
- updatedAt: now,
2089
- config
2090
- };
2091
- await this.repository.saveContainer(record);
2092
- logger7.info("Container created", { containerId });
2093
- return record;
2094
- }
2095
- async get(containerId) {
2096
- return this.repository.findContainerById(containerId);
2097
- }
2098
- async list() {
2099
- return this.repository.findAllContainers();
2100
- }
2101
- async delete(containerId) {
2102
- const exists = await this.repository.containerExists(containerId);
2103
- if (!exists) {
2104
- return false;
2105
- }
2106
- await this.repository.deleteContainer(containerId);
2107
- logger7.info("Container deleted", { containerId });
2108
- return true;
2109
- }
2110
- async exists(containerId) {
2111
- return this.repository.containerExists(containerId);
2112
- }
2113
- // ==================== Agent Runtime ====================
2114
- async run(image, containerId) {
2115
- logger7.info("Running agent from image", {
2116
- imageId: image.imageId,
2117
- containerId
2118
- });
2119
- const container = await this.repository.findContainerById(containerId);
2120
- if (!container) {
2121
- throw new Error(`Container not found: ${containerId}`);
2122
- }
2123
- let agentId;
2124
- if (this.runtime.agentIdResolver) {
2125
- agentId = await this.runtime.agentIdResolver.resolveForRun(image.imageId, containerId);
2126
- } else {
2127
- agentId = generateAgentId();
2128
- }
2129
- const context = {
2130
- agentId,
2131
- createdAt: Date.now()
2132
- };
2133
- const sandbox = this.runtime.createSandbox(containerId);
2134
- const driver = this.runtime.createDriver(image.definition, context, sandbox);
2135
- const agent = new AgentInstance(image.definition, context, this.engine, driver, sandbox);
2136
- this.agents.set(agentId, agent);
2137
- logger7.info("Agent started", {
2138
- agentId,
2139
- imageId: image.imageId,
2140
- containerId,
2141
- definitionName: image.definition.name
2142
- });
2143
- return agent;
2144
- }
2145
- async resume(session, containerId) {
2146
- logger7.info("Resuming agent from session", {
2147
- sessionId: session.sessionId,
2148
- imageId: session.imageId,
2149
- containerId
2150
- });
2151
- const container = await this.repository.findContainerById(containerId);
2152
- if (!container) {
2153
- throw new Error(`Container not found: ${containerId}`);
2154
- }
2155
- const imageRecord = await this.repository.findImageById(session.imageId);
2156
- if (!imageRecord) {
2157
- throw new Error(`Image not found: ${session.imageId}`);
2158
- }
2159
- let agentId;
2160
- if (this.runtime.agentIdResolver) {
2161
- agentId = await this.runtime.agentIdResolver.resolveForResume(session.sessionId, containerId);
2162
- } else {
2163
- agentId = generateAgentId();
2164
- }
2165
- const context = {
2166
- agentId,
2167
- createdAt: Date.now()
2168
- };
2169
- const sandbox = this.runtime.createSandbox(containerId);
2170
- const definition = imageRecord.definition;
2171
- const driver = this.runtime.createDriver(definition, context, sandbox);
2172
- const agent = new AgentInstance(definition, context, this.engine, driver, sandbox);
2173
- this.agents.set(agentId, agent);
2174
- logger7.info("Agent resumed", {
2175
- agentId,
2176
- sessionId: session.sessionId,
2177
- imageId: session.imageId,
2178
- containerId
2179
- });
2180
- return agent;
2181
- }
2182
- async destroyAgent(agentId) {
2183
- const agent = this.agents.get(agentId);
2184
- if (!agent) {
2185
- logger7.warn("Agent not found for destroy", { agentId });
2186
- return;
2187
- }
2188
- logger7.debug("Destroying agent", { agentId });
2189
- await agent.destroy();
2190
- this.agents.delete(agentId);
2191
- logger7.info("Agent destroyed", { agentId });
2192
- }
2193
- getAgent(agentId) {
2194
- return this.agents.get(agentId);
2195
- }
2196
- hasAgent(agentId) {
2197
- return this.agents.has(agentId);
2198
- }
2199
- listAgents() {
2200
- return Array.from(this.agents.values());
2201
- }
2202
- async destroyAllAgents() {
2203
- const agentIds = Array.from(this.agents.keys());
2204
- logger7.debug("Destroying all agents", { count: agentIds.length });
2205
- await Promise.all(agentIds.map((id) => this.destroyAgent(id)));
2206
- logger7.info("All agents destroyed", { count: agentIds.length });
2207
- }
2208
- };
2209
-
2210
- // src/AgentX.ts
2211
- var logger8 = createLogger("agentx/AgentX");
2212
- function createAgentX(runtime, options) {
2213
- logger8.info("Creating AgentX instance", { runtime: runtime.name });
2214
- if (!runtime.repository) {
2215
- throw new Error("Runtime must have a repository for persistence");
2216
- }
2217
- const repository = runtime.repository;
2218
- const containerManager = new ContainerManagerImpl(runtime, repository);
2219
- const errorManager = new ErrorManager();
2220
- const definitionManager = new DefinitionManagerImpl(repository);
2221
- const agentManager = new AgentManager(containerManager);
2222
- const imageManager = new ImageManagerImpl(repository, containerManager, options?.containerId);
2223
- const sessionManager = new SessionManagerImpl(repository, containerManager, options?.containerId);
2224
- logger8.debug("AgentX instance created", { runtime: runtime.name });
2225
- return {
2226
- mode: "local",
2227
- containers: containerManager,
2228
- definitions: definitionManager,
2229
- images: imageManager,
2230
- agents: agentManager,
2231
- sessions: sessionManager,
2232
- errors: errorManager
2233
- };
2234
- }
2235
- var PersistentSSEConnection = class {
2236
- constructor(serverUrl, agentId, sseParams = {}) {
2237
- this.serverUrl = serverUrl;
2238
- this.agentId = agentId;
2239
- this.sseParams = sseParams;
2240
- __publicField(this, "eventSource", null);
2241
- __publicField(this, "messageQueue", []);
2242
- __publicField(this, "activeIterators", /* @__PURE__ */ new Set());
2243
- __publicField(this, "isDone", false);
2244
- }
2245
- /**
2246
- * Initialize SSE connection
2247
- */
2248
- connect() {
2249
- if (this.eventSource) {
2250
- return;
2251
- }
2252
- let sseUrl = `${this.serverUrl}/agents/${this.agentId}/sse`;
2253
- if (Object.keys(this.sseParams).length > 0) {
2254
- const params = new URLSearchParams(this.sseParams);
2255
- sseUrl += `?${params.toString()}`;
2256
- }
2257
- this.eventSource = new EventSource(sseUrl);
2258
- const handleEvent = (event) => {
2259
- try {
2260
- const data = JSON.parse(event.data);
2261
- if (this.activeIterators.size > 0) {
2262
- const iterator = this.activeIterators.values().next().value;
2263
- if (iterator) {
2264
- this.activeIterators.delete(iterator);
2265
- iterator.resolve({ value: data, done: false });
2266
- }
2267
- } else {
2268
- this.messageQueue.push(data);
2269
- }
2270
- } catch {
2271
- }
2272
- };
2273
- const handleError = () => {
2274
- this.isDone = true;
2275
- this.eventSource?.close();
2276
- this.eventSource = null;
2277
- for (const iterator of this.activeIterators) {
2278
- iterator.reject(new Error("SSE connection error"));
2279
- }
2280
- this.activeIterators.clear();
2281
- };
2282
- for (const eventType of STREAM_EVENT_TYPE_NAMES) {
2283
- this.eventSource.addEventListener(eventType, handleEvent);
2284
- }
2285
- this.eventSource.addEventListener("error", handleEvent);
2286
- this.eventSource.onmessage = handleEvent;
2287
- this.eventSource.onerror = handleError;
2288
- }
2289
- /**
2290
- * Create an async iterable for a single receive() call
2291
- *
2292
- * This iterator continues until a final message_stop is received (stopReason !== "tool_use").
2293
- * For tool calls, this means it will span multiple message_start/message_stop cycles.
2294
- * The SSE connection itself remains open for future receive() calls.
2295
- */
2296
- createIterator() {
2297
- const connection = this;
2298
- return {
2299
- [Symbol.asyncIterator]() {
2300
- let turnComplete = false;
2301
- return {
2302
- async next() {
2303
- if (connection.messageQueue.length > 0) {
2304
- const event = connection.messageQueue.shift();
2305
- if (event.type === "message_stop") {
2306
- const stopReason = event.data.stopReason;
2307
- if (stopReason !== "tool_use") {
2308
- turnComplete = true;
2309
- }
2310
- }
2311
- return { value: event, done: false };
2312
- }
2313
- if (turnComplete) {
2314
- return { done: true, value: void 0 };
2315
- }
2316
- if (connection.isDone) {
2317
- return { done: true, value: void 0 };
2318
- }
2319
- return new Promise((resolve, reject) => {
2320
- const wrappedResolve = (result) => {
2321
- if (!result.done) {
2322
- if (result.value.type === "message_stop") {
2323
- const stopReason = result.value.data.stopReason;
2324
- if (stopReason !== "tool_use") {
2325
- turnComplete = true;
2326
- }
2327
- }
2328
- }
2329
- resolve(result);
2330
- };
2331
- const iterator = { resolve: wrappedResolve, reject };
2332
- connection.activeIterators.add(iterator);
2333
- });
2334
- },
2335
- async return() {
2336
- return { done: true, value: void 0 };
2337
- }
2338
- };
2339
- }
2340
- };
2341
- }
2342
- /**
2343
- * Close the connection
2344
- */
2345
- close() {
2346
- this.isDone = true;
2347
- if (this.eventSource) {
2348
- this.eventSource.close();
2349
- this.eventSource = null;
2350
- }
2351
- for (const iterator of this.activeIterators) {
2352
- iterator.reject(new Error("Connection closed"));
2353
- }
2354
- this.activeIterators.clear();
2355
- this.messageQueue = [];
2356
- }
2357
- };
2358
- function createSSEDriver(config) {
2359
- const { serverUrl, agentId, headers = {}, sseParams = {} } = config;
2360
- let connection = null;
2361
- return {
2362
- name: "SSEDriver",
2363
- async *receive(message) {
2364
- if (!connection) {
2365
- connection = new PersistentSSEConnection(serverUrl, agentId, sseParams);
2366
- connection.connect();
2367
- }
2368
- const messageUrl = `${serverUrl}/agents/${agentId}/messages`;
2369
- const response = await fetch(messageUrl, {
2370
- method: "POST",
2371
- headers: {
2372
- "Content-Type": "application/json",
2373
- ...headers
2374
- },
2375
- body: JSON.stringify({
2376
- content: typeof message.content === "string" ? message.content : message.content
2377
- })
2378
- });
2379
- if (!response.ok) {
2380
- const errorBody = await response.json().catch(() => ({}));
2381
- throw new Error(errorBody.error?.message || `HTTP ${response.status}`);
2382
- }
2383
- yield* connection.createIterator();
2384
- },
2385
- interrupt() {
2386
- const interruptUrl = `${serverUrl}/agents/${agentId}/interrupt`;
2387
- fetch(interruptUrl, {
2388
- method: "POST",
2389
- headers: {
2390
- "Content-Type": "application/json",
2391
- ...headers
2392
- }
2393
- }).catch(() => {
2394
- });
2395
- }
2396
- };
2397
- }
2398
- var logger9 = createLogger("agentx/RemoteRepository");
2399
- var RemoteRepository = class {
2400
- constructor(options) {
2401
- __publicField(this, "client");
2402
- this.client = createHttpClient({
2403
- baseUrl: options.serverUrl,
2404
- headers: options.headers
2405
- });
2406
- logger9.debug("RemoteRepository created", { serverUrl: options.serverUrl });
2407
- }
2408
- // ==================== Definition ====================
2409
- async saveDefinition(record) {
2410
- await this.client.put(`definitions/${record.name}`, { json: record });
2411
- }
2412
- async findDefinitionByName(name) {
2413
- try {
2414
- const result = await this.client.get(`definitions/${name}`).json();
2415
- return this.parseDefinitionRecord(result);
2416
- } catch (error) {
2417
- if (this.isNotFound(error)) return null;
2418
- throw error;
2419
- }
2420
- }
2421
- async findAllDefinitions() {
2422
- const result = await this.client.get("definitions").json();
2423
- return result.map((r) => this.parseDefinitionRecord(r));
2424
- }
2425
- async deleteDefinition(name) {
2426
- await this.client.delete(`definitions/${name}`);
2427
- }
2428
- async definitionExists(name) {
2429
- try {
2430
- await this.client.head(`definitions/${name}`);
2431
- return true;
2432
- } catch {
2433
- return false;
2434
- }
2435
- }
2436
- // ==================== Image ====================
2437
- async saveImage(record) {
2438
- await this.client.put(`images/${record.imageId}`, { json: record });
2439
- }
2440
- async findImageById(imageId) {
2441
- try {
2442
- const result = await this.client.get(`images/${imageId}`).json();
2443
- return this.parseImageRecord(result);
2444
- } catch (error) {
2445
- if (this.isNotFound(error)) return null;
2446
- throw error;
2447
- }
2448
- }
2449
- async findAllImages() {
2450
- const result = await this.client.get("images").json();
2451
- return result.map((r) => this.parseImageRecord(r));
2452
- }
2453
- async deleteImage(imageId) {
2454
- await this.client.delete(`images/${imageId}`);
2455
- }
2456
- async imageExists(imageId) {
2457
- try {
2458
- await this.client.head(`images/${imageId}`);
2459
- return true;
2460
- } catch {
2461
- return false;
2462
- }
2463
- }
2464
- // ==================== Session ====================
2465
- async saveSession(record) {
2466
- await this.client.put(`sessions/${record.sessionId}`, { json: record });
2467
- }
2468
- async findSessionById(sessionId) {
2469
- try {
2470
- const result = await this.client.get(`sessions/${sessionId}`).json();
2471
- return this.parseSessionRecord(result);
2472
- } catch (error) {
2473
- if (this.isNotFound(error)) return null;
2474
- throw error;
2475
- }
2476
- }
2477
- async findSessionsByImageId(imageId) {
2478
- const result = await this.client.get(`images/${imageId}/sessions`).json();
2479
- return result.map((r) => this.parseSessionRecord(r));
2480
- }
2481
- async findSessionsByUserId(userId) {
2482
- const result = await this.client.get(`users/${userId}/sessions`).json();
2483
- return result.map((r) => this.parseSessionRecord(r));
2484
- }
2485
- async findAllSessions() {
2486
- const result = await this.client.get("sessions").json();
2487
- return result.map((r) => this.parseSessionRecord(r));
2488
- }
2489
- async deleteSession(sessionId) {
2490
- await this.client.delete(`sessions/${sessionId}`);
2491
- }
2492
- async deleteSessionsByImageId(imageId) {
2493
- await this.client.delete(`images/${imageId}/sessions`);
2494
- }
2495
- async sessionExists(sessionId) {
2496
- try {
2497
- await this.client.head(`sessions/${sessionId}`);
2498
- return true;
2499
- } catch {
2500
- return false;
2501
- }
2502
- }
2503
- // ==================== Message ====================
2504
- /**
2505
- * Save message - noop in browser
2506
- *
2507
- * Messages are persisted by server-side SessionCollector.
2508
- * Browser-side calls this but it does nothing to avoid duplicate saves.
2509
- */
2510
- async saveMessage(_record) {
2511
- logger9.debug("saveMessage called (noop in browser)");
2512
- }
2513
- async findMessageById(messageId) {
2514
- try {
2515
- const result = await this.client.get(`messages/${messageId}`).json();
2516
- return this.parseMessageRecord(result);
2517
- } catch (error) {
2518
- if (this.isNotFound(error)) return null;
2519
- throw error;
2520
- }
2521
- }
2522
- async findMessagesBySessionId(sessionId) {
2523
- const result = await this.client.get(`sessions/${sessionId}/messages`).json();
2524
- return result.map((r) => this.parseMessageRecord(r));
2525
- }
2526
- async deleteMessage(messageId) {
2527
- await this.client.delete(`messages/${messageId}`);
2528
- }
2529
- async deleteMessagesBySessionId(sessionId) {
2530
- await this.client.delete(`sessions/${sessionId}/messages`);
2531
- }
2532
- async countMessagesBySessionId(sessionId) {
2533
- const result = await this.client.get(`sessions/${sessionId}/messages/count`).json();
2534
- return result.count;
2535
- }
2536
- // ==================== Container ====================
2537
- async saveContainer(record) {
2538
- await this.client.put(`containers/${record.containerId}`, { json: record });
2539
- }
2540
- async findContainerById(containerId) {
2541
- try {
2542
- const result = await this.client.get(`containers/${containerId}`).json();
2543
- return this.parseContainerRecord(result);
2544
- } catch (error) {
2545
- if (this.isNotFound(error)) return null;
2546
- throw error;
2547
- }
2548
- }
2549
- async findAllContainers() {
2550
- const result = await this.client.get("containers").json();
2551
- return result.map((r) => this.parseContainerRecord(r));
2552
- }
2553
- async deleteContainer(containerId) {
2554
- await this.client.delete(`containers/${containerId}`);
2555
- }
2556
- async containerExists(containerId) {
2557
- try {
2558
- await this.client.head(`containers/${containerId}`);
2559
- return true;
2560
- } catch {
2561
- return false;
2562
- }
2563
- }
2564
- // ==================== Helpers ====================
2565
- isNotFound(error) {
2566
- return error?.response?.status === 404;
2567
- }
2568
- parseDefinitionRecord(raw) {
2569
- return {
2570
- ...raw,
2571
- createdAt: new Date(raw.createdAt),
2572
- updatedAt: new Date(raw.updatedAt)
2573
- };
2574
- }
2575
- parseImageRecord(raw) {
2576
- return {
2577
- ...raw,
2578
- createdAt: new Date(raw.createdAt)
2579
- };
2580
- }
2581
- parseSessionRecord(raw) {
2582
- return {
2583
- ...raw,
2584
- createdAt: new Date(raw.createdAt),
2585
- updatedAt: new Date(raw.updatedAt)
2586
- };
2587
- }
2588
- parseMessageRecord(raw) {
2589
- return {
2590
- ...raw,
2591
- createdAt: new Date(raw.createdAt)
2592
- };
2593
- }
2594
- parseContainerRecord(raw) {
2595
- return {
2596
- ...raw
2597
- // ContainerRecord uses number timestamps, no conversion needed
2598
- };
2599
- }
2600
- };
2601
- var _BrowserLogger = class _BrowserLogger {
2602
- constructor(name, options = {}) {
2603
- __publicField(this, "name");
2604
- __publicField(this, "level");
2605
- __publicField(this, "collapsed");
2606
- this.name = name;
2607
- this.level = options.level ?? LogLevel.INFO;
2608
- this.collapsed = options.collapsed ?? true;
2609
- }
2610
- debug(message, context) {
2611
- if (this.isDebugEnabled()) {
2612
- this.log("DEBUG", message, context);
2613
- }
2614
- }
2615
- info(message, context) {
2616
- if (this.isInfoEnabled()) {
2617
- this.log("INFO", message, context);
2618
- }
2619
- }
2620
- warn(message, context) {
2621
- if (this.isWarnEnabled()) {
2622
- this.log("WARN", message, context);
2623
- }
2624
- }
2625
- error(message, context) {
2626
- if (this.isErrorEnabled()) {
2627
- if (message instanceof Error) {
2628
- this.log("ERROR", message.message, { ...context, stack: message.stack });
298
+ pendingRequests.clear();
299
+ handlers.clear();
300
+ if (isBrowser) {
301
+ ws.close();
2629
302
  } else {
2630
- this.log("ERROR", message, context);
303
+ ws.close();
2631
304
  }
2632
305
  }
2633
- }
2634
- isDebugEnabled() {
2635
- return this.level <= LogLevel.DEBUG;
2636
- }
2637
- isInfoEnabled() {
2638
- return this.level <= LogLevel.INFO;
2639
- }
2640
- isWarnEnabled() {
2641
- return this.level <= LogLevel.WARN;
2642
- }
2643
- isErrorEnabled() {
2644
- return this.level <= LogLevel.ERROR;
2645
- }
2646
- log(level, message, context) {
2647
- const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString();
2648
- const consoleMethod = this.getConsoleMethod(level);
2649
- const badgeStyle = _BrowserLogger.BADGE_STYLES[level];
2650
- const format = `%c${timestamp} %c${level}%c %c[${this.name}]%c ${message}`;
2651
- const styles = [
2652
- _BrowserLogger.STYLES.TIMESTAMP,
2653
- badgeStyle,
2654
- "",
2655
- // reset after badge
2656
- _BrowserLogger.STYLES.NAME,
2657
- _BrowserLogger.STYLES.MESSAGE
2658
- ];
2659
- if (context && Object.keys(context).length > 0) {
2660
- const groupMethod = this.collapsed ? console.groupCollapsed : console.group;
2661
- groupMethod.call(console, format, ...styles);
2662
- console.log("Context:", context);
2663
- console.groupEnd();
2664
- } else {
2665
- consoleMethod(format, ...styles);
2666
- }
2667
- }
2668
- getConsoleMethod(level) {
2669
- switch (level) {
2670
- case "DEBUG":
2671
- return console.debug.bind(console);
2672
- case "INFO":
2673
- return console.info.bind(console);
2674
- case "WARN":
2675
- return console.warn.bind(console);
2676
- case "ERROR":
2677
- return console.error.bind(console);
2678
- default:
2679
- return console.log.bind(console);
2680
- }
2681
- }
2682
- };
2683
- // CSS styles for different log levels
2684
- __publicField(_BrowserLogger, "STYLES", {
2685
- DEBUG: "color: #6B7280; font-weight: normal;",
2686
- // gray
2687
- INFO: "color: #10B981; font-weight: normal;",
2688
- // green
2689
- WARN: "color: #F59E0B; font-weight: bold;",
2690
- // amber
2691
- ERROR: "color: #EF4444; font-weight: bold;",
2692
- // red
2693
- TIMESTAMP: "color: #9CA3AF; font-weight: normal;",
2694
- // light gray
2695
- NAME: "color: #8B5CF6; font-weight: normal;",
2696
- // purple
2697
- MESSAGE: "color: inherit; font-weight: normal;"
2698
- });
2699
- // Badge styles for level indicators
2700
- __publicField(_BrowserLogger, "BADGE_STYLES", {
2701
- DEBUG: "background: #E5E7EB; color: #374151; padding: 2px 6px; border-radius: 3px; font-size: 11px;",
2702
- INFO: "background: #D1FAE5; color: #065F46; padding: 2px 6px; border-radius: 3px; font-size: 11px;",
2703
- WARN: "background: #FEF3C7; color: #92400E; padding: 2px 6px; border-radius: 3px; font-size: 11px;",
2704
- ERROR: "background: #FEE2E2; color: #991B1B; padding: 2px 6px; border-radius: 3px; font-size: 11px;"
2705
- });
2706
- var BrowserLogger = _BrowserLogger;
2707
-
2708
- // src/runtime/sse/logger/BrowserLoggerFactory.ts
2709
- var BrowserLoggerFactory = class {
2710
- constructor(options = {}) {
2711
- __publicField(this, "options");
2712
- __publicField(this, "loggers", /* @__PURE__ */ new Map());
2713
- this.options = options;
2714
- }
2715
- getLogger(name) {
2716
- if (this.loggers.has(name)) {
2717
- return this.loggers.get(name);
2718
- }
2719
- const logger11 = new BrowserLogger(name, this.options);
2720
- this.loggers.set(name, logger11);
2721
- return logger11;
2722
- }
2723
- };
2724
- var logger10 = createLogger("agentx/RemoteAgentIdResolver");
2725
- var RemoteAgentIdResolver = class {
2726
- constructor(options) {
2727
- __publicField(this, "client");
2728
- this.client = createHttpClient({
2729
- baseUrl: options.serverUrl,
2730
- headers: options.headers
2731
- });
2732
- }
2733
- async resolveForRun(imageId, containerId) {
2734
- logger10.debug("Resolving agent ID for run", { imageId, containerId });
2735
- const response = await this.client.post(`images/${imageId}/run`, {
2736
- json: { containerId }
2737
- }).json();
2738
- logger10.info("Agent ID resolved for run", { imageId, agentId: response.agentId });
2739
- return response.agentId;
2740
- }
2741
- async resolveForResume(sessionId, containerId) {
2742
- logger10.debug("Resolving agent ID for resume", { sessionId, containerId });
2743
- const response = await this.client.post(`sessions/${sessionId}/resume`, {
2744
- json: { containerId }
2745
- }).json();
2746
- logger10.info("Agent ID resolved for resume", { sessionId, agentId: response.agentId });
2747
- return response.agentId;
2748
- }
2749
- };
2750
-
2751
- // src/runtime/sse/SSERuntime.ts
2752
- var noopSandbox = {
2753
- name: "browser-noop",
2754
- workspace: {
2755
- id: "noop",
2756
- name: "noop",
2757
- path: ""
2758
- // Browser has no local workspace
2759
- },
2760
- llm: {
2761
- name: "noop",
2762
- provide: () => ({})
2763
- }
2764
- };
2765
- var SSERuntime = class {
2766
- constructor(config) {
2767
- __publicField(this, "name", "sse");
2768
- __publicField(this, "repository");
2769
- __publicField(this, "loggerFactory");
2770
- __publicField(this, "agentIdResolver");
2771
- __publicField(this, "serverUrl");
2772
- __publicField(this, "headers");
2773
- __publicField(this, "sseParams");
2774
- this.serverUrl = config.serverUrl.replace(/\/+$/, "");
2775
- this.headers = config.headers ?? {};
2776
- this.sseParams = config.sseParams ?? {};
2777
- this.loggerFactory = new BrowserLoggerFactory({
2778
- collapsed: true
2779
- });
2780
- setLoggerFactory(this.loggerFactory);
2781
- this.repository = new RemoteRepository({
2782
- serverUrl: this.serverUrl,
2783
- headers: this.headers
2784
- });
2785
- this.agentIdResolver = new RemoteAgentIdResolver({
2786
- serverUrl: this.serverUrl,
2787
- headers: this.headers
2788
- });
2789
- }
2790
- createSandbox(_containerId) {
2791
- return noopSandbox;
2792
- }
2793
- createDriver(_definition, context, _sandbox) {
2794
- const driver = createSSEDriver({
2795
- serverUrl: this.serverUrl,
2796
- agentId: context.agentId,
2797
- headers: this.headers,
2798
- sseParams: this.sseParams
2799
- });
2800
- return {
2801
- ...driver,
2802
- sandbox: noopSandbox
2803
- };
2804
- }
2805
- createLogger(name) {
2806
- return this.loggerFactory.getLogger(name);
2807
- }
2808
- };
2809
- function sseRuntime(config) {
2810
- return new SSERuntime(config);
306
+ };
2811
307
  }
2812
- var createSSERuntime = sseRuntime;
2813
308
 
2814
- export { createAgentX, createSSERuntime, defineAgent, sseRuntime };
309
+ export { createAgentX, createRemoteAgentX };
2815
310
  //# sourceMappingURL=index.js.map
2816
311
  //# sourceMappingURL=index.js.map