agentxjs 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,10 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var common = require('@agentxjs/common');
4
- var ky = require('ky');
5
- var agent = require('@agentxjs/agent');
6
- var engine = require('@agentxjs/engine');
7
3
  var types = require('@agentxjs/types');
4
+ var ky = require('ky');
5
+ var rxjs = require('rxjs');
6
+ var operators = require('rxjs/operators');
8
7
 
9
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
9
 
@@ -23,7 +22,171 @@ function defineAgent(input) {
23
22
  systemPrompt
24
23
  };
25
24
  }
26
- var logger = common.createLogger("agentx/DefinitionManager");
25
+ var __defProp2 = Object.defineProperty;
26
+ var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
27
+ var __publicField2 = (obj, key, value) => __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
28
+ var _ConsoleLogger = class _ConsoleLogger2 {
29
+ constructor(name, options = {}) {
30
+ __publicField2(this, "name");
31
+ __publicField2(this, "level");
32
+ __publicField2(this, "colors");
33
+ __publicField2(this, "timestamps");
34
+ this.name = name;
35
+ this.level = options.level ?? types.LogLevel.INFO;
36
+ this.colors = options.colors ?? this.isNodeEnvironment();
37
+ this.timestamps = options.timestamps ?? true;
38
+ }
39
+ debug(message, context) {
40
+ if (this.isDebugEnabled()) {
41
+ this.log("DEBUG", message, context);
42
+ }
43
+ }
44
+ info(message, context) {
45
+ if (this.isInfoEnabled()) {
46
+ this.log("INFO", message, context);
47
+ }
48
+ }
49
+ warn(message, context) {
50
+ if (this.isWarnEnabled()) {
51
+ this.log("WARN", message, context);
52
+ }
53
+ }
54
+ error(message, context) {
55
+ if (this.isErrorEnabled()) {
56
+ if (message instanceof Error) {
57
+ this.log("ERROR", message.message, { ...context, stack: message.stack });
58
+ } else {
59
+ this.log("ERROR", message, context);
60
+ }
61
+ }
62
+ }
63
+ isDebugEnabled() {
64
+ return this.level <= types.LogLevel.DEBUG;
65
+ }
66
+ isInfoEnabled() {
67
+ return this.level <= types.LogLevel.INFO;
68
+ }
69
+ isWarnEnabled() {
70
+ return this.level <= types.LogLevel.WARN;
71
+ }
72
+ isErrorEnabled() {
73
+ return this.level <= types.LogLevel.ERROR;
74
+ }
75
+ log(level, message, context) {
76
+ const parts = [];
77
+ if (this.timestamps) {
78
+ parts.push((/* @__PURE__ */ new Date()).toISOString());
79
+ }
80
+ if (this.colors) {
81
+ const color = _ConsoleLogger2.COLORS[level];
82
+ parts.push(`${color}${level.padEnd(5)}${_ConsoleLogger2.COLORS.RESET}`);
83
+ } else {
84
+ parts.push(level.padEnd(5));
85
+ }
86
+ parts.push(`[${this.name}]`);
87
+ parts.push(message);
88
+ const logLine = parts.join(" ");
89
+ const consoleMethod = this.getConsoleMethod(level);
90
+ if (context && Object.keys(context).length > 0) {
91
+ consoleMethod(logLine, context);
92
+ } else {
93
+ consoleMethod(logLine);
94
+ }
95
+ }
96
+ getConsoleMethod(level) {
97
+ switch (level) {
98
+ case "DEBUG":
99
+ return console.debug.bind(console);
100
+ case "INFO":
101
+ return console.info.bind(console);
102
+ case "WARN":
103
+ return console.warn.bind(console);
104
+ case "ERROR":
105
+ return console.error.bind(console);
106
+ default:
107
+ return console.log.bind(console);
108
+ }
109
+ }
110
+ isNodeEnvironment() {
111
+ return typeof process !== "undefined" && process.versions?.node !== void 0;
112
+ }
113
+ };
114
+ __publicField2(_ConsoleLogger, "COLORS", {
115
+ DEBUG: "\x1B[36m",
116
+ INFO: "\x1B[32m",
117
+ WARN: "\x1B[33m",
118
+ ERROR: "\x1B[31m",
119
+ RESET: "\x1B[0m"
120
+ });
121
+ var ConsoleLogger = _ConsoleLogger;
122
+ var externalFactory = null;
123
+ var LoggerFactoryImpl = class {
124
+ static getLogger(nameOrClass) {
125
+ const name = typeof nameOrClass === "string" ? nameOrClass : nameOrClass.name;
126
+ if (this.loggers.has(name)) {
127
+ return this.loggers.get(name);
128
+ }
129
+ const lazyLogger = this.createLazyLogger(name);
130
+ this.loggers.set(name, lazyLogger);
131
+ return lazyLogger;
132
+ }
133
+ static configure(config) {
134
+ this.config = { ...this.config, ...config };
135
+ }
136
+ static reset() {
137
+ this.loggers.clear();
138
+ this.config = { defaultLevel: types.LogLevel.INFO };
139
+ externalFactory = null;
140
+ }
141
+ static createLazyLogger(name) {
142
+ let realLogger = null;
143
+ const getRealLogger = () => {
144
+ if (!realLogger) {
145
+ realLogger = this.createLogger(name);
146
+ }
147
+ return realLogger;
148
+ };
149
+ return {
150
+ name,
151
+ level: this.config.defaultLevel || types.LogLevel.INFO,
152
+ debug: (message, context) => getRealLogger().debug(message, context),
153
+ info: (message, context) => getRealLogger().info(message, context),
154
+ warn: (message, context) => getRealLogger().warn(message, context),
155
+ error: (message, context) => getRealLogger().error(message, context),
156
+ isDebugEnabled: () => getRealLogger().isDebugEnabled(),
157
+ isInfoEnabled: () => getRealLogger().isInfoEnabled(),
158
+ isWarnEnabled: () => getRealLogger().isWarnEnabled(),
159
+ isErrorEnabled: () => getRealLogger().isErrorEnabled()
160
+ };
161
+ }
162
+ static createLogger(name) {
163
+ if (externalFactory) {
164
+ return externalFactory.getLogger(name);
165
+ }
166
+ if (this.config.defaultImplementation) {
167
+ return this.config.defaultImplementation(name);
168
+ }
169
+ return new ConsoleLogger(name, {
170
+ level: this.config.defaultLevel,
171
+ ...this.config.consoleOptions
172
+ });
173
+ }
174
+ };
175
+ __publicField2(LoggerFactoryImpl, "loggers", /* @__PURE__ */ new Map());
176
+ __publicField2(LoggerFactoryImpl, "config", {
177
+ defaultLevel: types.LogLevel.INFO
178
+ });
179
+ function setLoggerFactory(factory) {
180
+ externalFactory = factory;
181
+ LoggerFactoryImpl.reset();
182
+ externalFactory = factory;
183
+ }
184
+ function createLogger(name) {
185
+ return LoggerFactoryImpl.getLogger(name);
186
+ }
187
+
188
+ // src/managers/definition/DefinitionManagerImpl.ts
189
+ var logger = createLogger("agentx/DefinitionManager");
27
190
  function generateMetaImageId(definitionName) {
28
191
  return `meta_${definitionName}`;
29
192
  }
@@ -99,7 +262,9 @@ var DefinitionManagerImpl = class {
99
262
  return true;
100
263
  }
101
264
  };
102
- var logger2 = common.createLogger("agentx/ImageManager");
265
+
266
+ // src/managers/image/ImageManagerImpl.ts
267
+ var logger2 = createLogger("agentx/ImageManager");
103
268
  function generateMetaImageId2(definitionName) {
104
269
  return `meta_${definitionName}`;
105
270
  }
@@ -194,7 +359,9 @@ var ImageManagerImpl = class {
194
359
  return this.containerManager.run(image, containerId);
195
360
  }
196
361
  };
197
- var logger3 = common.createLogger("agentx/AgentManager");
362
+
363
+ // src/managers/agent/AgentManager.ts
364
+ var logger3 = createLogger("agentx/AgentManager");
198
365
  var AgentManager = class {
199
366
  constructor(containerManager) {
200
367
  this.containerManager = containerManager;
@@ -235,7 +402,9 @@ var AgentManager = class {
235
402
  logger3.info("All agents destroyed", { count: agents.length });
236
403
  }
237
404
  };
238
- var logger4 = common.createLogger("agentx/SessionManager");
405
+
406
+ // src/managers/session/SessionManagerImpl.ts
407
+ var logger4 = createLogger("agentx/SessionManager");
239
408
  function generateSessionId() {
240
409
  const timestamp = Date.now().toString(36);
241
410
  const random = Math.random().toString(36).substring(2, 8);
@@ -367,170 +536,1709 @@ var SessionImpl = class _SessionImpl {
367
536
  this.defaultContainerId
368
537
  );
369
538
  }
370
- async setTitle(title) {
371
- logger4.debug("Setting session title", { sessionId: this.sessionId, title });
372
- const now = /* @__PURE__ */ new Date();
373
- await this.repository.saveSession({
374
- sessionId: this.sessionId,
375
- userId: this.userId,
376
- imageId: this.imageId,
377
- title,
378
- createdAt: new Date(this.createdAt),
379
- updatedAt: now
380
- });
381
- this._title = title;
382
- this._updatedAt = now.getTime();
383
- logger4.info("Session title updated", { sessionId: this.sessionId, title });
539
+ async setTitle(title) {
540
+ logger4.debug("Setting session title", { sessionId: this.sessionId, title });
541
+ const now = /* @__PURE__ */ new Date();
542
+ await this.repository.saveSession({
543
+ sessionId: this.sessionId,
544
+ userId: this.userId,
545
+ imageId: this.imageId,
546
+ title,
547
+ createdAt: new Date(this.createdAt),
548
+ updatedAt: now
549
+ });
550
+ this._title = title;
551
+ this._updatedAt = now.getTime();
552
+ logger4.info("Session title updated", { sessionId: this.sessionId, title });
553
+ }
554
+ };
555
+ var SessionManagerImpl = class {
556
+ constructor(repository, containerManager, defaultContainerId) {
557
+ __publicField(this, "repository");
558
+ __publicField(this, "containerManager");
559
+ __publicField(this, "defaultContainerId");
560
+ this.repository = repository;
561
+ this.containerManager = containerManager;
562
+ this.defaultContainerId = defaultContainerId;
563
+ }
564
+ async create(imageId, userId) {
565
+ const sessionId = generateSessionId();
566
+ const now = /* @__PURE__ */ new Date();
567
+ const record = {
568
+ sessionId,
569
+ userId,
570
+ imageId,
571
+ title: null,
572
+ createdAt: now,
573
+ updatedAt: now
574
+ };
575
+ await this.repository.saveSession(record);
576
+ logger4.info("Session created", { sessionId, imageId, userId });
577
+ return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
578
+ }
579
+ async get(sessionId) {
580
+ const record = await this.repository.findSessionById(sessionId);
581
+ if (!record) return void 0;
582
+ return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
583
+ }
584
+ async has(sessionId) {
585
+ return this.repository.sessionExists(sessionId);
586
+ }
587
+ async list() {
588
+ const records = await this.repository.findAllSessions();
589
+ return records.map(
590
+ (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
591
+ );
592
+ }
593
+ async listByImage(imageId) {
594
+ const records = await this.repository.findSessionsByImageId(imageId);
595
+ return records.map(
596
+ (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
597
+ );
598
+ }
599
+ async listByUser(userId) {
600
+ const records = await this.repository.findSessionsByUserId(userId);
601
+ return records.map(
602
+ (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
603
+ );
604
+ }
605
+ async destroy(sessionId) {
606
+ await this.repository.deleteSession(sessionId);
607
+ logger4.info("Session destroyed", { sessionId });
608
+ }
609
+ async destroyByImage(imageId) {
610
+ await this.repository.deleteSessionsByImageId(imageId);
611
+ logger4.info("Sessions destroyed by image", { imageId });
612
+ }
613
+ async destroyAll() {
614
+ const sessions = await this.repository.findAllSessions();
615
+ for (const session of sessions) {
616
+ await this.repository.deleteSession(session.sessionId);
617
+ }
618
+ logger4.info("All sessions destroyed");
619
+ }
620
+ };
621
+
622
+ // src/managers/error/ErrorManager.ts
623
+ var logger5 = createLogger("agentx/ErrorManager");
624
+ var ErrorManager = class {
625
+ constructor() {
626
+ __publicField(this, "handlers", /* @__PURE__ */ new Set());
627
+ }
628
+ /**
629
+ * Handle an error from any agent
630
+ *
631
+ * Called internally when an agent emits an error event.
632
+ * 1. Default logging (always)
633
+ * 2. Custom handlers (user-registered)
634
+ */
635
+ handle(agentId, error, event) {
636
+ this.logError(agentId, error);
637
+ for (const handler of this.handlers) {
638
+ try {
639
+ handler.handle(agentId, error, event);
640
+ } catch (e) {
641
+ logger5.error("ErrorHandler failed", { error: e });
642
+ }
643
+ }
644
+ }
645
+ /**
646
+ * Add a custom error handler
647
+ */
648
+ addHandler(handler) {
649
+ this.handlers.add(handler);
650
+ return () => {
651
+ this.handlers.delete(handler);
652
+ };
653
+ }
654
+ /**
655
+ * Remove an error handler
656
+ */
657
+ removeHandler(handler) {
658
+ this.handlers.delete(handler);
659
+ }
660
+ /**
661
+ * Default error logging
662
+ */
663
+ logError(agentId, error) {
664
+ const prefix = `[${agentId}] ${error.category}/${error.code}`;
665
+ if (error.severity === "fatal") {
666
+ logger5.error(`${prefix}: ${error.message}`, { error });
667
+ } else if (error.severity === "error") {
668
+ logger5.error(`${prefix}: ${error.message}`);
669
+ } else {
670
+ logger5.warn(`${prefix}: ${error.message}`);
671
+ }
672
+ }
673
+ };
674
+ var ApiError = class extends Error {
675
+ constructor(code, message, details) {
676
+ super(message);
677
+ this.code = code;
678
+ this.details = details;
679
+ this.name = "ApiError";
680
+ }
681
+ };
682
+ function createHttpClient(options) {
683
+ return ky__default.default.create({
684
+ prefixUrl: options.baseUrl.replace(/\/+$/, ""),
685
+ headers: options.headers,
686
+ timeout: options.timeout || 3e4,
687
+ hooks: {
688
+ afterResponse: [
689
+ async (_request, _options, response) => {
690
+ if (!response.ok) {
691
+ const data = await response.json().catch(() => ({}));
692
+ throw new ApiError(
693
+ data.error?.code || "UNKNOWN_ERROR",
694
+ data.error?.message || `Request failed: ${response.status}`,
695
+ data.error?.details
696
+ );
697
+ }
698
+ return response;
699
+ }
700
+ ]
701
+ }
702
+ });
703
+ }
704
+ var logger6 = createLogger("core/AgentStateMachine");
705
+ var AgentStateMachine = class {
706
+ constructor() {
707
+ __publicField(this, "_state", "idle");
708
+ __publicField(this, "handlers", /* @__PURE__ */ new Set());
709
+ }
710
+ /**
711
+ * Current agent state
712
+ */
713
+ get state() {
714
+ return this._state;
715
+ }
716
+ /**
717
+ * Process a StateEvent and update internal state
718
+ *
719
+ * @param event - StateEvent from Engine layer
720
+ */
721
+ process(event) {
722
+ const prev = this._state;
723
+ const next = this.mapEventToState(event);
724
+ if (next !== null && prev !== next) {
725
+ this._state = next;
726
+ logger6.debug("State transition", {
727
+ eventType: event.type,
728
+ from: prev,
729
+ to: next
730
+ });
731
+ this.notifyHandlers({ prev, current: next });
732
+ }
733
+ }
734
+ /**
735
+ * Subscribe to state changes
736
+ *
737
+ * @param handler - Callback receiving { prev, current } state change
738
+ * @returns Unsubscribe function
739
+ */
740
+ onStateChange(handler) {
741
+ this.handlers.add(handler);
742
+ return () => {
743
+ this.handlers.delete(handler);
744
+ };
745
+ }
746
+ /**
747
+ * Reset state machine (used on destroy)
748
+ */
749
+ reset() {
750
+ this._state;
751
+ this._state = "idle";
752
+ this.handlers.clear();
753
+ }
754
+ /**
755
+ * Map StateEvent type to AgentState
756
+ *
757
+ * @param event - StateEvent from Engine
758
+ * @returns New AgentState or null if no transition needed
759
+ */
760
+ mapEventToState(event) {
761
+ switch (event.type) {
762
+ // Agent lifecycle
763
+ case "agent_initializing":
764
+ return "initializing";
765
+ case "agent_ready":
766
+ return "idle";
767
+ case "agent_destroyed":
768
+ return "idle";
769
+ // Conversation lifecycle
770
+ case "conversation_queued":
771
+ return "queued";
772
+ case "conversation_start":
773
+ return "conversation_active";
774
+ case "conversation_thinking":
775
+ return "thinking";
776
+ case "conversation_responding":
777
+ return "responding";
778
+ case "conversation_end":
779
+ return "idle";
780
+ case "conversation_interrupted":
781
+ return "idle";
782
+ // Return to idle on interrupt
783
+ // Tool lifecycle
784
+ case "tool_planned":
785
+ return "planning_tool";
786
+ case "tool_executing":
787
+ return "awaiting_tool_result";
788
+ case "tool_completed":
789
+ return "responding";
790
+ // Back to responding after tool completes
791
+ case "tool_failed":
792
+ return "responding";
793
+ // Continue responding after tool failure
794
+ // Error
795
+ case "error_occurred":
796
+ return "idle";
797
+ // Reset to idle on error
798
+ default:
799
+ return null;
800
+ }
801
+ }
802
+ /**
803
+ * Notify all registered handlers of state change
804
+ */
805
+ notifyHandlers(change) {
806
+ for (const handler of this.handlers) {
807
+ try {
808
+ handler(change);
809
+ } catch (error) {
810
+ logger6.error("State change handler error", {
811
+ from: change.prev,
812
+ to: change.current,
813
+ error
814
+ });
815
+ }
816
+ }
817
+ }
818
+ };
819
+ var logger22 = createLogger("core/AgentEventBus");
820
+ var AgentEventBus = class {
821
+ constructor() {
822
+ __publicField(this, "subject", new rxjs.Subject());
823
+ __publicField(this, "typeSubscriptions", /* @__PURE__ */ new Map());
824
+ __publicField(this, "globalSubscriptions", []);
825
+ __publicField(this, "nextId", 0);
826
+ __publicField(this, "isDestroyed", false);
827
+ // Cached views
828
+ __publicField(this, "producerView", null);
829
+ __publicField(this, "consumerView", null);
830
+ }
831
+ // ===== Producer Methods =====
832
+ emit(event) {
833
+ if (this.isDestroyed) {
834
+ logger22.warn("Emit called on destroyed EventBus", { eventType: event.type });
835
+ return;
836
+ }
837
+ this.subject.next(event);
838
+ }
839
+ emitBatch(events) {
840
+ for (const event of events) {
841
+ this.emit(event);
842
+ }
843
+ }
844
+ on(typeOrTypes, handler, options = {}) {
845
+ if (this.isDestroyed) {
846
+ logger22.warn("Subscribe called on destroyed EventBus");
847
+ return () => {
848
+ };
849
+ }
850
+ const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes];
851
+ const unsubscribes = [];
852
+ for (const type of types) {
853
+ const unsub = this.subscribeToType(type, handler, options);
854
+ unsubscribes.push(unsub);
855
+ }
856
+ return () => unsubscribes.forEach((u) => u());
857
+ }
858
+ onAny(handler, options = {}) {
859
+ if (this.isDestroyed) {
860
+ logger22.warn("Subscribe called on destroyed EventBus");
861
+ return () => {
862
+ };
863
+ }
864
+ return this.subscribeGlobal(handler, options);
865
+ }
866
+ once(type, handler) {
867
+ return this.on(type, handler, { once: true });
868
+ }
869
+ // ===== View Methods =====
870
+ asConsumer() {
871
+ if (!this.consumerView) {
872
+ this.consumerView = {
873
+ on: this.on.bind(this),
874
+ onAny: this.onAny.bind(this),
875
+ once: this.once.bind(this)
876
+ };
877
+ }
878
+ return this.consumerView;
879
+ }
880
+ asProducer() {
881
+ if (!this.producerView) {
882
+ this.producerView = {
883
+ emit: this.emit.bind(this),
884
+ emitBatch: this.emitBatch.bind(this)
885
+ };
886
+ }
887
+ return this.producerView;
888
+ }
889
+ // ===== Lifecycle =====
890
+ destroy() {
891
+ if (this.isDestroyed) return;
892
+ this.isDestroyed = true;
893
+ for (const records of this.typeSubscriptions.values()) {
894
+ for (const record of records) {
895
+ record.unsubscribe();
896
+ }
897
+ }
898
+ this.typeSubscriptions.clear();
899
+ for (const record of this.globalSubscriptions) {
900
+ record.unsubscribe();
901
+ }
902
+ this.globalSubscriptions.length = 0;
903
+ this.subject.complete();
904
+ logger22.debug("EventBus destroyed");
905
+ }
906
+ // ===== Private Methods =====
907
+ subscribeToType(type, handler, options) {
908
+ const { filter: filter$1, priority = 0, once = false } = options;
909
+ const id = this.nextId++;
910
+ let observable = this.subject.pipe(operators.filter((e) => e.type === type));
911
+ if (filter$1) {
912
+ observable = observable.pipe(operators.filter(filter$1));
913
+ }
914
+ if (once) {
915
+ observable = observable.pipe(operators.take(1));
916
+ }
917
+ const subscription = observable.subscribe({
918
+ next: (event) => {
919
+ this.executeWithPriority(type, event, handler, id);
920
+ }
921
+ });
922
+ const unsubscribe = () => {
923
+ subscription.unsubscribe();
924
+ const records2 = this.typeSubscriptions.get(type);
925
+ if (records2) {
926
+ const idx = records2.findIndex((r) => r.id === id);
927
+ if (idx !== -1) records2.splice(idx, 1);
928
+ }
929
+ };
930
+ if (!this.typeSubscriptions.has(type)) {
931
+ this.typeSubscriptions.set(type, []);
932
+ }
933
+ const record = { id, priority, handler, unsubscribe };
934
+ const records = this.typeSubscriptions.get(type);
935
+ records.push(record);
936
+ records.sort((a, b) => b.priority - a.priority);
937
+ return unsubscribe;
938
+ }
939
+ subscribeGlobal(handler, options) {
940
+ const { filter: filter$1, priority = 0, once = false } = options;
941
+ const id = this.nextId++;
942
+ let observable = this.subject.asObservable();
943
+ if (filter$1) {
944
+ observable = observable.pipe(operators.filter(filter$1));
945
+ }
946
+ if (once) {
947
+ observable = observable.pipe(operators.take(1));
948
+ }
949
+ const subscription = observable.subscribe({
950
+ next: (event) => {
951
+ this.executeGlobalWithPriority(event, handler, id);
952
+ }
953
+ });
954
+ const unsubscribe = () => {
955
+ subscription.unsubscribe();
956
+ const idx = this.globalSubscriptions.findIndex((r) => r.id === id);
957
+ if (idx !== -1) this.globalSubscriptions.splice(idx, 1);
958
+ };
959
+ const record = { id, priority, handler, unsubscribe };
960
+ this.globalSubscriptions.push(record);
961
+ this.globalSubscriptions.sort((a, b) => b.priority - a.priority);
962
+ return unsubscribe;
963
+ }
964
+ /**
965
+ * Execute handler respecting priority order for typed subscriptions
966
+ */
967
+ executeWithPriority(type, event, handler, handlerId) {
968
+ const records = this.typeSubscriptions.get(type) || [];
969
+ const record = records.find((r) => r.id === handlerId);
970
+ if (record) {
971
+ try {
972
+ handler(event);
973
+ } catch (error) {
974
+ logger22.error("Event handler error", { eventType: type, error });
975
+ }
976
+ }
977
+ }
978
+ /**
979
+ * Execute handler respecting priority order for global subscriptions
980
+ */
981
+ executeGlobalWithPriority(event, handler, handlerId) {
982
+ const record = this.globalSubscriptions.find((r) => r.id === handlerId);
983
+ if (record) {
984
+ try {
985
+ handler(event);
986
+ } catch (error) {
987
+ logger22.error("Global event handler error", { eventType: event.type, error });
988
+ }
989
+ }
990
+ }
991
+ };
992
+ var AgentErrorClassifier = class {
993
+ constructor(agentId) {
994
+ this.agentId = agentId;
995
+ }
996
+ /**
997
+ * Classify an unknown error into an AgentError
998
+ */
999
+ classify(error) {
1000
+ const err = error instanceof Error ? error : new Error(String(error));
1001
+ const message = err.message;
1002
+ if (message.includes("rate limit") || message.includes("429")) {
1003
+ return this.create("llm", "RATE_LIMITED", message, true, err);
1004
+ }
1005
+ if (message.includes("api key") || message.includes("401") || message.includes("unauthorized")) {
1006
+ return this.create("llm", "INVALID_API_KEY", message, false, err);
1007
+ }
1008
+ if (message.includes("context") && message.includes("long")) {
1009
+ return this.create("llm", "CONTEXT_TOO_LONG", message, true, err);
1010
+ }
1011
+ if (message.includes("overloaded") || message.includes("503")) {
1012
+ return this.create("llm", "OVERLOADED", message, true, err);
1013
+ }
1014
+ if (message.includes("timeout") || message.includes("ETIMEDOUT")) {
1015
+ return this.create("network", "TIMEOUT", message, true, err);
1016
+ }
1017
+ if (message.includes("ECONNREFUSED") || message.includes("connection")) {
1018
+ return this.create("network", "CONNECTION_FAILED", message, true, err);
1019
+ }
1020
+ if (message.includes("network") || message.includes("fetch")) {
1021
+ return this.create("network", "CONNECTION_FAILED", message, true, err);
1022
+ }
1023
+ if (message.includes("driver")) {
1024
+ return this.create("driver", "RECEIVE_FAILED", message, true, err);
1025
+ }
1026
+ return this.create("system", "UNKNOWN", message, true, err);
1027
+ }
1028
+ /**
1029
+ * Create an AgentError with the specified category and code
1030
+ */
1031
+ create(category, code, message, recoverable, cause) {
1032
+ return {
1033
+ category,
1034
+ code,
1035
+ message,
1036
+ severity: recoverable ? "error" : "fatal",
1037
+ recoverable,
1038
+ cause
1039
+ };
1040
+ }
1041
+ /**
1042
+ * Create an ErrorEvent from an AgentError
1043
+ *
1044
+ * ErrorEvent is independent from Message layer and transportable via SSE.
1045
+ */
1046
+ createEvent(error) {
1047
+ return {
1048
+ type: "error",
1049
+ uuid: `${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1050
+ agentId: this.agentId,
1051
+ timestamp: Date.now(),
1052
+ data: {
1053
+ error
1054
+ }
1055
+ };
1056
+ }
1057
+ };
1058
+ var MiddlewareChain = class {
1059
+ constructor() {
1060
+ __publicField(this, "middlewares", []);
1061
+ }
1062
+ /**
1063
+ * Add middleware to the chain
1064
+ *
1065
+ * @param middleware - Middleware function
1066
+ * @returns Unsubscribe function to remove the middleware
1067
+ */
1068
+ use(middleware) {
1069
+ this.middlewares.push(middleware);
1070
+ return () => {
1071
+ const index = this.middlewares.indexOf(middleware);
1072
+ if (index !== -1) {
1073
+ this.middlewares.splice(index, 1);
1074
+ }
1075
+ };
1076
+ }
1077
+ /**
1078
+ * Execute the middleware chain
1079
+ *
1080
+ * @param message - User message to process
1081
+ * @param finalHandler - Handler called at the end of the chain
1082
+ */
1083
+ async execute(message, finalHandler) {
1084
+ let index = 0;
1085
+ const next = async (msg) => {
1086
+ if (index < this.middlewares.length) {
1087
+ const middleware = this.middlewares[index++];
1088
+ await middleware(msg, next);
1089
+ } else {
1090
+ await finalHandler(msg);
1091
+ }
1092
+ };
1093
+ await next(message);
1094
+ }
1095
+ /**
1096
+ * Clear all middlewares
1097
+ */
1098
+ clear() {
1099
+ this.middlewares.length = 0;
1100
+ }
1101
+ /**
1102
+ * Get the number of middlewares
1103
+ */
1104
+ get size() {
1105
+ return this.middlewares.length;
1106
+ }
1107
+ };
1108
+ var logger32 = createLogger("core/InterceptorChain");
1109
+ var InterceptorChain = class {
1110
+ constructor(agentId) {
1111
+ __publicField(this, "interceptors", []);
1112
+ __publicField(this, "agentId");
1113
+ this.agentId = agentId;
1114
+ }
1115
+ /**
1116
+ * Add interceptor to the chain
1117
+ *
1118
+ * @param interceptor - Interceptor function
1119
+ * @returns Unsubscribe function to remove the interceptor
1120
+ */
1121
+ intercept(interceptor) {
1122
+ this.interceptors.push(interceptor);
1123
+ return () => {
1124
+ const index = this.interceptors.indexOf(interceptor);
1125
+ if (index !== -1) {
1126
+ this.interceptors.splice(index, 1);
1127
+ }
1128
+ };
1129
+ }
1130
+ /**
1131
+ * Execute the interceptor chain
1132
+ *
1133
+ * @param event - Event to process
1134
+ * @param finalHandler - Handler called at the end of the chain
1135
+ */
1136
+ execute(event, finalHandler) {
1137
+ let index = 0;
1138
+ const next = (e) => {
1139
+ if (index < this.interceptors.length) {
1140
+ const interceptor = this.interceptors[index++];
1141
+ try {
1142
+ interceptor(e, next);
1143
+ } catch (error) {
1144
+ logger32.error("Interceptor error", {
1145
+ agentId: this.agentId,
1146
+ eventType: e.type,
1147
+ interceptorIndex: index - 1,
1148
+ error
1149
+ });
1150
+ next(e);
1151
+ }
1152
+ } else {
1153
+ finalHandler(e);
1154
+ }
1155
+ };
1156
+ next(event);
1157
+ }
1158
+ /**
1159
+ * Clear all interceptors
1160
+ */
1161
+ clear() {
1162
+ this.interceptors.length = 0;
1163
+ }
1164
+ /**
1165
+ * Get the number of interceptors
1166
+ */
1167
+ get size() {
1168
+ return this.interceptors.length;
1169
+ }
1170
+ };
1171
+ var REACT_TO_EVENT_MAP = {
1172
+ // Stream Layer Events
1173
+ onMessageStart: "message_start",
1174
+ onMessageDelta: "message_delta",
1175
+ onMessageStop: "message_stop",
1176
+ onTextContentBlockStart: "text_content_block_start",
1177
+ onTextDelta: "text_delta",
1178
+ onTextContentBlockStop: "text_content_block_stop",
1179
+ onToolUseContentBlockStart: "tool_use_content_block_start",
1180
+ onInputJsonDelta: "input_json_delta",
1181
+ onToolUseContentBlockStop: "tool_use_content_block_stop",
1182
+ onToolCall: "tool_call",
1183
+ onToolResult: "tool_result",
1184
+ // Message Layer Events
1185
+ onUserMessage: "user_message",
1186
+ onAssistantMessage: "assistant_message",
1187
+ onToolCallMessage: "tool_call_message",
1188
+ onToolResultMessage: "tool_result_message",
1189
+ // Error Layer Events (independent, transportable via SSE)
1190
+ onError: "error",
1191
+ // Turn Layer Events
1192
+ onTurnRequest: "turn_request",
1193
+ onTurnResponse: "turn_response"
1194
+ };
1195
+ function mapReactHandlers(reactHandlers) {
1196
+ const eventHandlerMap = {};
1197
+ for (const [reactKey, eventKey] of Object.entries(REACT_TO_EVENT_MAP)) {
1198
+ const handler = reactHandlers[reactKey];
1199
+ if (handler) {
1200
+ eventHandlerMap[eventKey] = handler;
1201
+ }
1202
+ }
1203
+ return eventHandlerMap;
1204
+ }
1205
+ var logger42 = createLogger("core/AgentInstance");
1206
+ var AgentInstance = class {
1207
+ constructor(definition, context, engine, driver, sandbox) {
1208
+ __publicField(this, "agentId");
1209
+ __publicField(this, "definition");
1210
+ __publicField(this, "context");
1211
+ __publicField(this, "createdAt");
1212
+ __publicField(this, "sandbox");
1213
+ __publicField(this, "_lifecycle", "running");
1214
+ __publicField(this, "engine");
1215
+ /**
1216
+ * Driver instance - created from definition.driver class
1217
+ */
1218
+ __publicField(this, "driver");
1219
+ /**
1220
+ * State machine - manages state transitions driven by StateEvents
1221
+ */
1222
+ __publicField(this, "stateMachine", new AgentStateMachine());
1223
+ /**
1224
+ * Event bus - centralized event pub/sub
1225
+ */
1226
+ __publicField(this, "eventBus", new AgentEventBus());
1227
+ /**
1228
+ * Error classifier - classifies and creates error events
1229
+ */
1230
+ __publicField(this, "errorClassifier");
1231
+ /**
1232
+ * Middleware chain for receive() interception
1233
+ */
1234
+ __publicField(this, "middlewareChain", new MiddlewareChain());
1235
+ /**
1236
+ * Interceptor chain for event dispatch interception
1237
+ */
1238
+ __publicField(this, "interceptorChain");
1239
+ /**
1240
+ * Lifecycle handlers for onReady
1241
+ */
1242
+ __publicField(this, "readyHandlers", /* @__PURE__ */ new Set());
1243
+ /**
1244
+ * Lifecycle handlers for onDestroy
1245
+ */
1246
+ __publicField(this, "destroyHandlers", /* @__PURE__ */ new Set());
1247
+ this.agentId = context.agentId;
1248
+ this.definition = definition;
1249
+ this.context = context;
1250
+ this.engine = engine;
1251
+ this.createdAt = context.createdAt;
1252
+ this.sandbox = sandbox;
1253
+ this.driver = driver;
1254
+ this.errorClassifier = new AgentErrorClassifier(this.agentId);
1255
+ this.interceptorChain = new InterceptorChain(this.agentId);
1256
+ logger42.debug("AgentInstance created", {
1257
+ agentId: this.agentId,
1258
+ definitionName: definition.name,
1259
+ driverName: this.driver.name
1260
+ });
1261
+ }
1262
+ /**
1263
+ * Current lifecycle state
1264
+ */
1265
+ get lifecycle() {
1266
+ return this._lifecycle;
1267
+ }
1268
+ /**
1269
+ * Current conversation state (delegated to StateMachine)
1270
+ */
1271
+ get state() {
1272
+ return this.stateMachine.state;
1273
+ }
1274
+ /**
1275
+ * Receive a message from user
1276
+ *
1277
+ * Runs through middleware chain before actual processing.
1278
+ *
1279
+ * Error Handling:
1280
+ * - Errors are caught and converted to ErrorMessageEvent
1281
+ * - Handlers receive the error event before re-throwing
1282
+ * - This ensures UI can display errors
1283
+ */
1284
+ async receive(message) {
1285
+ if (this._lifecycle === "destroyed") {
1286
+ logger42.warn("Receive called on destroyed agent", { agentId: this.agentId });
1287
+ const error = this.errorClassifier.create(
1288
+ "system",
1289
+ "AGENT_DESTROYED",
1290
+ "Agent has been destroyed",
1291
+ false
1292
+ );
1293
+ const errorEvent = this.errorClassifier.createEvent(error);
1294
+ this.notifyHandlers(errorEvent);
1295
+ throw new Error("[Agent] Agent has been destroyed");
1296
+ }
1297
+ if (this.state !== "idle") {
1298
+ logger42.warn("Receive called while agent is busy", {
1299
+ agentId: this.agentId,
1300
+ currentState: this.state
1301
+ });
1302
+ const error = this.errorClassifier.create(
1303
+ "system",
1304
+ "AGENT_BUSY",
1305
+ `Agent is busy (state: ${this.state}), please wait for current operation to complete`,
1306
+ false
1307
+ );
1308
+ const errorEvent = this.errorClassifier.createEvent(error);
1309
+ this.notifyHandlers(errorEvent);
1310
+ throw new Error(`[Agent] Agent is busy (state: ${this.state})`);
1311
+ }
1312
+ const userMessage = typeof message === "string" ? {
1313
+ id: `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1314
+ role: "user",
1315
+ subtype: "user",
1316
+ content: message,
1317
+ timestamp: Date.now()
1318
+ } : message;
1319
+ logger42.debug("Receiving message", {
1320
+ agentId: this.agentId,
1321
+ messageId: userMessage.id
1322
+ });
1323
+ const userMessageEvent = {
1324
+ uuid: `evt_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1325
+ type: "user_message",
1326
+ agentId: this.agentId,
1327
+ timestamp: Date.now(),
1328
+ data: userMessage
1329
+ };
1330
+ this.presentOutput(userMessageEvent);
1331
+ this.notifyHandlers(userMessageEvent);
1332
+ await this.executeMiddlewareChain(userMessage);
1333
+ }
1334
+ /**
1335
+ * Execute middleware chain and then process the message
1336
+ */
1337
+ async executeMiddlewareChain(message) {
1338
+ await this.middlewareChain.execute(message, (msg) => this.doReceive(msg));
1339
+ }
1340
+ /**
1341
+ * Process a single stream event through the engine
1342
+ *
1343
+ * Used by:
1344
+ * - doReceive() - normal message flow
1345
+ * - AgentInterrupter - interrupt event injection
1346
+ *
1347
+ * @param streamEvent - Stream event to process
1348
+ */
1349
+ processStreamEvent(streamEvent) {
1350
+ const outputs = this.engine.process(this.agentId, streamEvent);
1351
+ for (const output of outputs) {
1352
+ this.presentOutput(output);
1353
+ }
1354
+ for (const output of outputs) {
1355
+ this.notifyHandlers(output);
1356
+ }
1357
+ }
1358
+ /**
1359
+ * Actual message processing logic
1360
+ *
1361
+ * Coordinates the flow:
1362
+ * 1. Driver receives message → produces StreamEvents
1363
+ * 2. Engine processes events → produces outputs
1364
+ * 3. Presenters handle outputs
1365
+ * 4. Handlers receive outputs
1366
+ */
1367
+ async doReceive(userMessage) {
1368
+ try {
1369
+ logger42.debug("Processing message through driver", {
1370
+ agentId: this.agentId,
1371
+ messageId: userMessage.id
1372
+ });
1373
+ const queuedEvent = {
1374
+ type: "conversation_queued",
1375
+ uuid: `${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1376
+ agentId: this.agentId,
1377
+ timestamp: Date.now(),
1378
+ data: {
1379
+ userMessage
1380
+ }
1381
+ };
1382
+ this.notifyHandlers(queuedEvent);
1383
+ const streamEvents = this.driver.receive(userMessage);
1384
+ for await (const streamEvent of streamEvents) {
1385
+ this.processStreamEvent(streamEvent);
1386
+ }
1387
+ logger42.debug("Message processing completed", {
1388
+ agentId: this.agentId,
1389
+ messageId: userMessage.id
1390
+ });
1391
+ } catch (error) {
1392
+ const agentError = this.errorClassifier.classify(error);
1393
+ const errorEvent = this.errorClassifier.createEvent(agentError);
1394
+ logger42.error("Message processing failed", {
1395
+ agentId: this.agentId,
1396
+ messageId: userMessage.id,
1397
+ errorCategory: agentError.category,
1398
+ errorCode: agentError.code,
1399
+ error
1400
+ });
1401
+ this.notifyHandlers(errorEvent);
1402
+ throw error;
1403
+ }
1404
+ }
1405
+ /**
1406
+ * Send output to all presenters
1407
+ *
1408
+ * Note: Presenters are no longer part of AgentDefinition.
1409
+ * This is a placeholder for future presenter injection via Runtime or middleware.
1410
+ */
1411
+ presentOutput(_output) {
1412
+ }
1413
+ on(typeOrHandlerOrMap, handler) {
1414
+ if (typeof typeOrHandlerOrMap === "function") {
1415
+ return this.eventBus.onAny(typeOrHandlerOrMap);
1416
+ }
1417
+ if (this.isEventHandlerMap(typeOrHandlerOrMap)) {
1418
+ const unsubscribes = [];
1419
+ for (const [eventType, eventHandler] of Object.entries(typeOrHandlerOrMap)) {
1420
+ if (eventHandler) {
1421
+ unsubscribes.push(this.eventBus.on(eventType, eventHandler));
1422
+ }
1423
+ }
1424
+ return () => {
1425
+ for (const unsub of unsubscribes) {
1426
+ unsub();
1427
+ }
1428
+ };
1429
+ }
1430
+ const types = Array.isArray(typeOrHandlerOrMap) ? typeOrHandlerOrMap : [typeOrHandlerOrMap];
1431
+ const h = handler;
1432
+ return this.eventBus.on(types, h);
1433
+ }
1434
+ /**
1435
+ * Check if the argument is an EventHandlerMap (object with event type keys)
1436
+ */
1437
+ isEventHandlerMap(arg) {
1438
+ if (typeof arg !== "object" || arg === null || Array.isArray(arg)) {
1439
+ return false;
1440
+ }
1441
+ const keys = Object.keys(arg);
1442
+ if (keys.length === 0) {
1443
+ return false;
1444
+ }
1445
+ return keys.every((key) => {
1446
+ const value = arg[key];
1447
+ return value === void 0 || typeof value === "function";
1448
+ });
1449
+ }
1450
+ /**
1451
+ * Subscribe to state changes (delegated to StateMachine)
1452
+ *
1453
+ * @param handler - Callback receiving { prev, current } state change
1454
+ * @returns Unsubscribe function
1455
+ */
1456
+ onStateChange(handler) {
1457
+ return this.stateMachine.onStateChange(handler);
1458
+ }
1459
+ /**
1460
+ * React-style fluent event subscription
1461
+ *
1462
+ * Converts onXxx handlers to event type keys and delegates to on(handlers)
1463
+ */
1464
+ react(handlers) {
1465
+ const eventHandlerMap = mapReactHandlers(handlers);
1466
+ return this.on(eventHandlerMap);
1467
+ }
1468
+ /**
1469
+ * Subscribe to agent ready event
1470
+ *
1471
+ * If already running, handler is called immediately.
1472
+ */
1473
+ onReady(handler) {
1474
+ if (this._lifecycle === "running") {
1475
+ try {
1476
+ handler();
1477
+ } catch (error) {
1478
+ logger42.error("onReady handler error", {
1479
+ agentId: this.agentId,
1480
+ error
1481
+ });
1482
+ }
1483
+ }
1484
+ this.readyHandlers.add(handler);
1485
+ return () => {
1486
+ this.readyHandlers.delete(handler);
1487
+ };
1488
+ }
1489
+ /**
1490
+ * Subscribe to agent destroy event
1491
+ */
1492
+ onDestroy(handler) {
1493
+ this.destroyHandlers.add(handler);
1494
+ return () => {
1495
+ this.destroyHandlers.delete(handler);
1496
+ };
1497
+ }
1498
+ /**
1499
+ * Add middleware to intercept incoming messages
1500
+ */
1501
+ use(middleware) {
1502
+ return this.middlewareChain.use(middleware);
1503
+ }
1504
+ /**
1505
+ * Add interceptor to intercept outgoing events
1506
+ */
1507
+ intercept(interceptor) {
1508
+ return this.interceptorChain.intercept(interceptor);
1509
+ }
1510
+ /**
1511
+ * Interrupt - User-initiated stop
1512
+ *
1513
+ * Stops the current operation gracefully.
1514
+ * Flow:
1515
+ * 1. Call driver.interrupt() to abort active requests
1516
+ * 2. Driver yields InterruptedStreamEvent
1517
+ * 3. Event flows through engine pipeline
1518
+ * 4. StateEventProcessor generates conversation_interrupted
1519
+ * 5. StateMachine transitions to idle state
1520
+ * 6. UI receives state change notification
1521
+ */
1522
+ interrupt() {
1523
+ logger42.debug("User interrupt requested", { agentId: this.agentId, currentState: this.state });
1524
+ this.driver.interrupt();
1525
+ }
1526
+ /**
1527
+ * Destroy - Clean up resources
1528
+ */
1529
+ async destroy() {
1530
+ logger42.debug("Destroying agent", { agentId: this.agentId });
1531
+ for (const handler of this.destroyHandlers) {
1532
+ try {
1533
+ handler();
1534
+ } catch (error) {
1535
+ logger42.error("onDestroy handler error", {
1536
+ agentId: this.agentId,
1537
+ error
1538
+ });
1539
+ }
1540
+ }
1541
+ this._lifecycle = "destroyed";
1542
+ this.stateMachine.reset();
1543
+ this.eventBus.destroy();
1544
+ this.readyHandlers.clear();
1545
+ this.destroyHandlers.clear();
1546
+ this.middlewareChain.clear();
1547
+ this.interceptorChain.clear();
1548
+ this.engine.clearState(this.agentId);
1549
+ logger42.info("Agent destroyed", { agentId: this.agentId });
1550
+ }
1551
+ /**
1552
+ * Notify all registered handlers
1553
+ *
1554
+ * Flow:
1555
+ * 1. StateMachine processes StateEvents (for state transitions)
1556
+ * 2. Interceptor chain can modify/filter events
1557
+ * 3. EventBus emits to all subscribers
1558
+ */
1559
+ notifyHandlers(event) {
1560
+ if (types.isStateEvent(event)) {
1561
+ this.stateMachine.process(event);
1562
+ }
1563
+ this.executeInterceptorChain(event);
1564
+ }
1565
+ /**
1566
+ * Execute interceptor chain and then emit to EventBus
1567
+ */
1568
+ executeInterceptorChain(event) {
1569
+ this.interceptorChain.execute(event, (e) => this.eventBus.emit(e));
1570
+ }
1571
+ /**
1572
+ * Get the event consumer for external subscriptions
1573
+ *
1574
+ * Use this to expose event subscription without emit capability.
1575
+ */
1576
+ getEventConsumer() {
1577
+ return this.eventBus.asConsumer();
384
1578
  }
385
1579
  };
386
- var SessionManagerImpl = class {
387
- constructor(repository, containerManager, defaultContainerId) {
388
- __publicField(this, "repository");
389
- __publicField(this, "containerManager");
390
- __publicField(this, "defaultContainerId");
391
- this.repository = repository;
392
- this.containerManager = containerManager;
393
- this.defaultContainerId = defaultContainerId;
1580
+
1581
+ // ../engine/dist/index.js
1582
+ var MemoryStore = class {
1583
+ constructor() {
1584
+ __publicField(this, "states", /* @__PURE__ */ new Map());
394
1585
  }
395
- async create(imageId, userId) {
396
- const sessionId = generateSessionId();
397
- const now = /* @__PURE__ */ new Date();
398
- const record = {
399
- sessionId,
400
- userId,
401
- imageId,
402
- title: null,
403
- createdAt: now,
404
- updatedAt: now
405
- };
406
- await this.repository.saveSession(record);
407
- logger4.info("Session created", { sessionId, imageId, userId });
408
- return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
1586
+ get(id) {
1587
+ return this.states.get(id);
409
1588
  }
410
- async get(sessionId) {
411
- const record = await this.repository.findSessionById(sessionId);
412
- if (!record) return void 0;
413
- return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
1589
+ set(id, state) {
1590
+ this.states.set(id, state);
414
1591
  }
415
- async has(sessionId) {
416
- return this.repository.sessionExists(sessionId);
1592
+ delete(id) {
1593
+ this.states.delete(id);
417
1594
  }
418
- async list() {
419
- const records = await this.repository.findAllSessions();
420
- return records.map(
421
- (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
422
- );
1595
+ has(id) {
1596
+ return this.states.has(id);
423
1597
  }
424
- async listByImage(imageId) {
425
- const records = await this.repository.findSessionsByImageId(imageId);
426
- return records.map(
427
- (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
428
- );
1598
+ /**
1599
+ * Clear all stored states
1600
+ */
1601
+ clear() {
1602
+ this.states.clear();
429
1603
  }
430
- async listByUser(userId) {
431
- const records = await this.repository.findSessionsByUserId(userId);
432
- return records.map(
433
- (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
434
- );
1604
+ /**
1605
+ * Get the number of stored states
1606
+ */
1607
+ get size() {
1608
+ return this.states.size;
435
1609
  }
436
- async destroy(sessionId) {
437
- await this.repository.deleteSession(sessionId);
438
- logger4.info("Session destroyed", { sessionId });
1610
+ /**
1611
+ * Get all stored IDs
1612
+ */
1613
+ keys() {
1614
+ return this.states.keys();
439
1615
  }
440
- async destroyByImage(imageId) {
441
- await this.repository.deleteSessionsByImageId(imageId);
442
- logger4.info("Sessions destroyed by image", { imageId });
1616
+ };
1617
+ createLogger("engine/Mealy");
1618
+ function combineProcessors(processors) {
1619
+ return (state, event) => {
1620
+ const newState = {};
1621
+ const allOutputs = [];
1622
+ for (const key in processors) {
1623
+ const processor = processors[key];
1624
+ const subState = state[key];
1625
+ const [newSubState, outputs] = processor(subState, event);
1626
+ newState[key] = newSubState;
1627
+ allOutputs.push(...outputs);
1628
+ }
1629
+ return [newState, allOutputs];
1630
+ };
1631
+ }
1632
+ function combineInitialStates(initialStates) {
1633
+ return () => {
1634
+ const state = {};
1635
+ for (const key in initialStates) {
1636
+ state[key] = initialStates[key]();
1637
+ }
1638
+ return state;
1639
+ };
1640
+ }
1641
+ function createInitialMessageAssemblerState() {
1642
+ return {
1643
+ currentMessageId: null,
1644
+ messageStartTime: null,
1645
+ pendingContents: {},
1646
+ pendingToolCalls: {}
1647
+ };
1648
+ }
1649
+ function generateId() {
1650
+ return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1651
+ }
1652
+ var messageAssemblerProcessor = (state, input) => {
1653
+ switch (input.type) {
1654
+ case "message_start":
1655
+ return handleMessageStart(state, input);
1656
+ case "text_delta":
1657
+ return handleTextDelta(state, input);
1658
+ case "tool_use_content_block_start":
1659
+ return handleToolUseContentBlockStart(state, input);
1660
+ case "input_json_delta":
1661
+ return handleInputJsonDelta(state, input);
1662
+ case "tool_use_content_block_stop":
1663
+ return handleToolUseContentBlockStop(state, input);
1664
+ case "tool_result":
1665
+ return handleToolResult(state, input);
1666
+ case "message_stop":
1667
+ return handleMessageStop(state, input);
1668
+ default:
1669
+ return [state, []];
443
1670
  }
444
- async destroyAll() {
445
- const sessions = await this.repository.findAllSessions();
446
- for (const session of sessions) {
447
- await this.repository.deleteSession(session.sessionId);
1671
+ };
1672
+ function handleMessageStart(state, event) {
1673
+ return [
1674
+ {
1675
+ ...state,
1676
+ currentMessageId: generateId(),
1677
+ messageStartTime: event.timestamp,
1678
+ pendingContents: {}
1679
+ },
1680
+ []
1681
+ ];
1682
+ }
1683
+ function handleTextDelta(state, event) {
1684
+ const index = 0;
1685
+ const existingContent = state.pendingContents[index];
1686
+ const pendingContent = existingContent?.type === "text" ? {
1687
+ ...existingContent,
1688
+ textDeltas: [...existingContent.textDeltas || [], event.data.text]
1689
+ } : {
1690
+ type: "text",
1691
+ index,
1692
+ textDeltas: [event.data.text]
1693
+ };
1694
+ return [
1695
+ {
1696
+ ...state,
1697
+ pendingContents: {
1698
+ ...state.pendingContents,
1699
+ [index]: pendingContent
1700
+ }
1701
+ },
1702
+ []
1703
+ ];
1704
+ }
1705
+ function handleToolUseContentBlockStart(state, event) {
1706
+ const index = 1;
1707
+ const pendingContent = {
1708
+ type: "tool_use",
1709
+ index,
1710
+ toolId: event.data.id,
1711
+ toolName: event.data.name,
1712
+ toolInputJson: ""
1713
+ };
1714
+ return [
1715
+ {
1716
+ ...state,
1717
+ pendingContents: {
1718
+ ...state.pendingContents,
1719
+ [index]: pendingContent
1720
+ }
1721
+ },
1722
+ []
1723
+ ];
1724
+ }
1725
+ function handleInputJsonDelta(state, event) {
1726
+ const index = 1;
1727
+ const existingContent = state.pendingContents[index];
1728
+ if (!existingContent || existingContent.type !== "tool_use") {
1729
+ return [state, []];
1730
+ }
1731
+ const pendingContent = {
1732
+ ...existingContent,
1733
+ toolInputJson: (existingContent.toolInputJson || "") + event.data.partialJson
1734
+ };
1735
+ return [
1736
+ {
1737
+ ...state,
1738
+ pendingContents: {
1739
+ ...state.pendingContents,
1740
+ [index]: pendingContent
1741
+ }
1742
+ },
1743
+ []
1744
+ ];
1745
+ }
1746
+ function handleToolUseContentBlockStop(state, event) {
1747
+ const index = 1;
1748
+ const pendingContent = state.pendingContents[index];
1749
+ if (!pendingContent || pendingContent.type !== "tool_use") {
1750
+ return [state, []];
1751
+ }
1752
+ let toolInput = {};
1753
+ try {
1754
+ toolInput = pendingContent.toolInputJson ? JSON.parse(pendingContent.toolInputJson) : {};
1755
+ } catch {
1756
+ toolInput = {};
1757
+ }
1758
+ const outputs = [];
1759
+ const toolId = pendingContent.toolId;
1760
+ const toolName = pendingContent.toolName;
1761
+ const toolCallEvent = {
1762
+ type: "tool_call",
1763
+ uuid: generateId(),
1764
+ agentId: event.agentId,
1765
+ timestamp: Date.now(),
1766
+ data: {
1767
+ id: toolId,
1768
+ name: toolName,
1769
+ input: toolInput
448
1770
  }
449
- logger4.info("All sessions destroyed");
1771
+ };
1772
+ outputs.push(toolCallEvent);
1773
+ const toolCall = {
1774
+ type: "tool-call",
1775
+ id: toolId,
1776
+ name: toolName,
1777
+ input: toolInput
1778
+ };
1779
+ const toolCallMessage = {
1780
+ id: generateId(),
1781
+ role: "assistant",
1782
+ subtype: "tool-call",
1783
+ toolCall,
1784
+ timestamp: Date.now()
1785
+ };
1786
+ const toolCallMessageEvent = {
1787
+ type: "tool_call_message",
1788
+ uuid: generateId(),
1789
+ agentId: event.agentId,
1790
+ timestamp: Date.now(),
1791
+ data: toolCallMessage
1792
+ };
1793
+ outputs.push(toolCallMessageEvent);
1794
+ const { [index]: _, ...remainingContents } = state.pendingContents;
1795
+ return [
1796
+ {
1797
+ ...state,
1798
+ pendingContents: remainingContents,
1799
+ pendingToolCalls: {
1800
+ ...state.pendingToolCalls,
1801
+ [toolId]: { id: toolId, name: toolName }
1802
+ }
1803
+ },
1804
+ outputs
1805
+ ];
1806
+ }
1807
+ function handleToolResult(state, event) {
1808
+ const { toolId, content, isError } = event.data;
1809
+ const pendingToolCall = state.pendingToolCalls[toolId];
1810
+ const toolName = pendingToolCall?.name || "unknown";
1811
+ const toolResult = {
1812
+ type: "tool-result",
1813
+ id: toolId,
1814
+ name: toolName,
1815
+ output: {
1816
+ type: isError ? "error-text" : "text",
1817
+ value: typeof content === "string" ? content : JSON.stringify(content)
1818
+ }
1819
+ };
1820
+ const toolResultMessage = {
1821
+ id: generateId(),
1822
+ role: "tool",
1823
+ subtype: "tool-result",
1824
+ toolResult,
1825
+ toolCallId: toolId,
1826
+ timestamp: Date.now()
1827
+ };
1828
+ const toolResultMessageEvent = {
1829
+ type: "tool_result_message",
1830
+ uuid: generateId(),
1831
+ agentId: event.agentId,
1832
+ timestamp: Date.now(),
1833
+ data: toolResultMessage
1834
+ };
1835
+ const { [toolId]: _, ...remainingToolCalls } = state.pendingToolCalls;
1836
+ return [
1837
+ {
1838
+ ...state,
1839
+ pendingToolCalls: remainingToolCalls
1840
+ },
1841
+ [toolResultMessageEvent]
1842
+ ];
1843
+ }
1844
+ function handleMessageStop(state, event) {
1845
+ if (!state.currentMessageId) {
1846
+ return [state, []];
1847
+ }
1848
+ const textParts = [];
1849
+ const sortedContents = Object.values(state.pendingContents).sort((a, b) => a.index - b.index);
1850
+ for (const pending of sortedContents) {
1851
+ if (pending.type === "text" && pending.textDeltas) {
1852
+ textParts.push(pending.textDeltas.join(""));
1853
+ }
1854
+ }
1855
+ const content = textParts.join("");
1856
+ const stopReason = event.data.stopReason;
1857
+ if (!content || content.trim().length === 0) {
1858
+ const shouldPreserveToolCalls2 = stopReason === "tool_use";
1859
+ return [
1860
+ {
1861
+ ...createInitialMessageAssemblerState(),
1862
+ pendingToolCalls: shouldPreserveToolCalls2 ? state.pendingToolCalls : {}
1863
+ },
1864
+ []
1865
+ ];
1866
+ }
1867
+ const assistantMessage = {
1868
+ id: state.currentMessageId,
1869
+ role: "assistant",
1870
+ subtype: "assistant",
1871
+ content,
1872
+ timestamp: state.messageStartTime || Date.now(),
1873
+ // Usage data is not available in message_stop event
1874
+ // It would need to be tracked separately if needed
1875
+ usage: void 0
1876
+ };
1877
+ const assistantEvent = {
1878
+ type: "assistant_message",
1879
+ uuid: generateId(),
1880
+ agentId: event.agentId,
1881
+ timestamp: Date.now(),
1882
+ data: assistantMessage
1883
+ };
1884
+ const shouldPreserveToolCalls = stopReason === "tool_use";
1885
+ return [
1886
+ {
1887
+ ...createInitialMessageAssemblerState(),
1888
+ pendingToolCalls: shouldPreserveToolCalls ? state.pendingToolCalls : {}
1889
+ },
1890
+ [assistantEvent]
1891
+ ];
1892
+ }
1893
+ var logger23 = createLogger("engine/stateEventProcessor");
1894
+ function createInitialStateEventProcessorContext() {
1895
+ return {};
1896
+ }
1897
+ function generateId2() {
1898
+ return `state_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1899
+ }
1900
+ var stateEventProcessor = (context, input) => {
1901
+ logger23.debug(`[Stream Event] ${input.type}`, {
1902
+ context,
1903
+ eventData: "data" in input ? input.data : void 0
1904
+ });
1905
+ switch (input.type) {
1906
+ case "message_start":
1907
+ return handleMessageStart2(context, input);
1908
+ case "message_delta":
1909
+ return handleMessageDelta(context);
1910
+ case "message_stop":
1911
+ return handleMessageStop2(context, input);
1912
+ case "text_content_block_start":
1913
+ return handleTextContentBlockStart(context, input);
1914
+ case "tool_use_content_block_start":
1915
+ return handleToolUseContentBlockStart2(context, input);
1916
+ case "tool_use_content_block_stop":
1917
+ return handleToolUseContentBlockStop2(context);
1918
+ case "tool_call":
1919
+ return handleToolCall(context);
1920
+ case "interrupted":
1921
+ return handleInterrupted(context, input);
1922
+ default:
1923
+ logger23.debug(`[Stream Event] ${input.type} (unhandled)`);
1924
+ return [context, []];
450
1925
  }
451
1926
  };
452
- var logger5 = common.createLogger("agentx/ErrorManager");
453
- var ErrorManager = class {
1927
+ function handleMessageStart2(context, event) {
1928
+ const conversationStartEvent = {
1929
+ type: "conversation_start",
1930
+ uuid: generateId2(),
1931
+ agentId: event.agentId,
1932
+ timestamp: event.timestamp,
1933
+ transition: {
1934
+ reason: "conversation_started",
1935
+ trigger: "message_start"
1936
+ },
1937
+ data: {
1938
+ userMessage: {}
1939
+ // Will be populated by higher-level component
1940
+ }
1941
+ };
1942
+ return [context, [conversationStartEvent]];
1943
+ }
1944
+ function handleMessageDelta(context, _event) {
1945
+ return [context, []];
1946
+ }
1947
+ function handleMessageStop2(context, event) {
1948
+ const stopReason = event.data.stopReason;
1949
+ logger23.debug("message_stop received", { stopReason });
1950
+ if (stopReason === "tool_use") {
1951
+ logger23.debug("Skipping conversation_end (tool_use in progress)");
1952
+ return [context, []];
1953
+ }
1954
+ const conversationEndEvent = {
1955
+ type: "conversation_end",
1956
+ uuid: generateId2(),
1957
+ agentId: event.agentId,
1958
+ timestamp: event.timestamp,
1959
+ transition: {
1960
+ reason: "conversation_completed",
1961
+ trigger: "message_stop"
1962
+ },
1963
+ data: {
1964
+ assistantMessage: {},
1965
+ // Will be populated by higher-level component
1966
+ durationMs: 0,
1967
+ // Will be calculated by StateMachine or TurnTracker
1968
+ durationApiMs: 0,
1969
+ numTurns: 0,
1970
+ result: "completed",
1971
+ totalCostUsd: 0,
1972
+ usage: {
1973
+ input: 0,
1974
+ output: 0
1975
+ }
1976
+ }
1977
+ };
1978
+ return [context, [conversationEndEvent]];
1979
+ }
1980
+ function handleTextContentBlockStart(context, event) {
1981
+ const respondingEvent = {
1982
+ type: "conversation_responding",
1983
+ uuid: generateId2(),
1984
+ agentId: event.agentId,
1985
+ timestamp: Date.now(),
1986
+ transition: {
1987
+ reason: "assistant_responding",
1988
+ trigger: "text_content_block_start"
1989
+ },
1990
+ data: {}
1991
+ };
1992
+ return [context, [respondingEvent]];
1993
+ }
1994
+ function handleToolUseContentBlockStart2(context, event) {
1995
+ const outputs = [];
1996
+ const toolPlannedEvent = {
1997
+ type: "tool_planned",
1998
+ uuid: generateId2(),
1999
+ agentId: event.agentId,
2000
+ timestamp: event.timestamp,
2001
+ data: {
2002
+ id: event.data.id,
2003
+ name: event.data.name,
2004
+ input: {}
2005
+ }
2006
+ };
2007
+ outputs.push(toolPlannedEvent);
2008
+ const toolExecutingEvent = {
2009
+ type: "tool_executing",
2010
+ uuid: generateId2(),
2011
+ agentId: event.agentId,
2012
+ timestamp: event.timestamp,
2013
+ transition: {
2014
+ reason: "tool_planning_started",
2015
+ trigger: "tool_use_content_block_start"
2016
+ },
2017
+ data: {}
2018
+ };
2019
+ outputs.push(toolExecutingEvent);
2020
+ return [context, outputs];
2021
+ }
2022
+ function handleToolUseContentBlockStop2(context, _event) {
2023
+ return [context, []];
2024
+ }
2025
+ function handleToolCall(context, _event) {
2026
+ return [context, []];
2027
+ }
2028
+ function handleInterrupted(context, event) {
2029
+ logger23.debug("interrupted event received", { reason: event.data.reason });
2030
+ const conversationInterruptedEvent = {
2031
+ type: "conversation_interrupted",
2032
+ uuid: generateId2(),
2033
+ agentId: event.agentId,
2034
+ timestamp: event.timestamp,
2035
+ transition: {
2036
+ reason: event.data.reason,
2037
+ trigger: "interrupted"
2038
+ },
2039
+ data: {
2040
+ reason: event.data.reason
2041
+ }
2042
+ };
2043
+ return [context, [conversationInterruptedEvent]];
2044
+ }
2045
+ function createInitialTurnTrackerState() {
2046
+ return {
2047
+ pendingTurn: null,
2048
+ costPerInputToken: 3e-6,
2049
+ // $3 per 1M tokens
2050
+ costPerOutputToken: 15e-6
2051
+ // $15 per 1M tokens
2052
+ };
2053
+ }
2054
+ function generateId3() {
2055
+ return `turn_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
2056
+ }
2057
+ function calculateCost(usage, costPerInputToken, costPerOutputToken) {
2058
+ const inputCost = usage.input * costPerInputToken;
2059
+ const outputCost = usage.output * costPerOutputToken;
2060
+ return inputCost + outputCost;
2061
+ }
2062
+ var turnTrackerProcessor = (state, input) => {
2063
+ switch (input.type) {
2064
+ case "user_message":
2065
+ return handleUserMessage(state, input);
2066
+ case "message_stop":
2067
+ return handleMessageStop3(state, input);
2068
+ case "assistant_message":
2069
+ return [state, []];
2070
+ default:
2071
+ return [state, []];
2072
+ }
2073
+ };
2074
+ function handleUserMessage(state, event) {
2075
+ const turnId = generateId3();
2076
+ const pendingTurn = {
2077
+ turnId,
2078
+ userMessage: event.data,
2079
+ requestedAt: event.timestamp
2080
+ };
2081
+ const turnRequestEvent = {
2082
+ type: "turn_request",
2083
+ uuid: generateId3(),
2084
+ agentId: event.agentId,
2085
+ timestamp: Date.now(),
2086
+ turnId,
2087
+ data: {
2088
+ userMessage: event.data,
2089
+ requestedAt: event.timestamp
2090
+ }
2091
+ };
2092
+ return [
2093
+ {
2094
+ ...state,
2095
+ pendingTurn
2096
+ },
2097
+ [turnRequestEvent]
2098
+ ];
2099
+ }
2100
+ function handleMessageStop3(state, event) {
2101
+ if (!state.pendingTurn) {
2102
+ return [state, []];
2103
+ }
2104
+ const stopReason = event.data.stopReason;
2105
+ if (stopReason === "end_turn" || stopReason === "max_tokens" || stopReason === "stop_sequence") {
2106
+ return completeTurn(state, event.agentId, event.timestamp);
2107
+ }
2108
+ return [state, []];
2109
+ }
2110
+ function completeTurn(state, agentId, completedAt) {
2111
+ if (!state.pendingTurn) {
2112
+ return [state, []];
2113
+ }
2114
+ const { turnId, requestedAt } = state.pendingTurn;
2115
+ const duration = completedAt - requestedAt;
2116
+ const usage = { input: 0, output: 0 };
2117
+ const cost = calculateCost(usage, state.costPerInputToken, state.costPerOutputToken);
2118
+ const turnResponseEvent = {
2119
+ type: "turn_response",
2120
+ uuid: generateId3(),
2121
+ agentId,
2122
+ timestamp: Date.now(),
2123
+ turnId,
2124
+ data: {
2125
+ assistantMessage: {
2126
+ id: generateId3(),
2127
+ role: "assistant",
2128
+ subtype: "assistant",
2129
+ content: "",
2130
+ timestamp: completedAt
2131
+ },
2132
+ respondedAt: completedAt,
2133
+ durationMs: duration,
2134
+ usage,
2135
+ costUsd: cost
2136
+ }
2137
+ };
2138
+ return [
2139
+ {
2140
+ ...state,
2141
+ pendingTurn: null
2142
+ },
2143
+ [turnResponseEvent]
2144
+ ];
2145
+ }
2146
+ var agentProcessor = combineProcessors({
2147
+ messageAssembler: messageAssemblerProcessor,
2148
+ stateEventProcessor,
2149
+ turnTracker: turnTrackerProcessor
2150
+ });
2151
+ var createInitialAgentEngineState = combineInitialStates({
2152
+ messageAssembler: createInitialMessageAssemblerState,
2153
+ stateEventProcessor: createInitialStateEventProcessorContext,
2154
+ turnTracker: createInitialTurnTrackerState
2155
+ });
2156
+ var logger33 = createLogger("engine/AgentEngine");
2157
+ var AgentEngine = class {
454
2158
  constructor() {
455
- __publicField(this, "handlers", /* @__PURE__ */ new Set());
2159
+ __publicField(this, "store");
2160
+ this.store = new MemoryStore();
2161
+ logger33.debug("AgentEngine initialized");
456
2162
  }
457
2163
  /**
458
- * Handle an error from any agent
2164
+ * Process a single stream event and return output events
459
2165
  *
460
- * Called internally when an agent emits an error event.
461
- * 1. Default logging (always)
462
- * 2. Custom handlers (user-registered)
2166
+ * This is the core Mealy Machine operation:
2167
+ * process(agentId, event) outputs[]
2168
+ *
2169
+ * @param agentId - The agent identifier (for state isolation)
2170
+ * @param event - Stream event to process
2171
+ * @returns Array of output events (state, message, turn events)
463
2172
  */
464
- handle(agentId, error, event) {
465
- this.logError(agentId, error);
466
- for (const handler of this.handlers) {
467
- try {
468
- handler.handle(agentId, error, event);
469
- } catch (e) {
470
- logger5.error("ErrorHandler failed", { error: e });
471
- }
2173
+ process(agentId, event) {
2174
+ const eventType = event.type || "unknown";
2175
+ logger33.debug("Processing event", { agentId, eventType });
2176
+ const isNewState = !this.store.has(agentId);
2177
+ let state = this.store.get(agentId) ?? createInitialAgentEngineState();
2178
+ if (isNewState) {
2179
+ logger33.debug("Created initial state for agent", { agentId });
2180
+ }
2181
+ const allOutputs = [];
2182
+ allOutputs.push(event);
2183
+ const [newState, outputs] = agentProcessor(state, event);
2184
+ state = newState;
2185
+ for (const output of outputs) {
2186
+ allOutputs.push(output);
2187
+ const [chainedState, chainedOutputs] = this.processChained(state, output);
2188
+ state = chainedState;
2189
+ allOutputs.push(...chainedOutputs);
472
2190
  }
2191
+ this.store.set(agentId, state);
2192
+ if (outputs.length > 0) {
2193
+ logger33.debug("Produced outputs", {
2194
+ agentId,
2195
+ inputEvent: eventType,
2196
+ outputCount: allOutputs.length,
2197
+ processorOutputs: outputs.length
2198
+ });
2199
+ }
2200
+ return allOutputs;
473
2201
  }
474
2202
  /**
475
- * Add a custom error handler
2203
+ * Process chained events recursively
2204
+ *
2205
+ * Some processors produce events that trigger other processors:
2206
+ * - MessageAssembler produces MessageEvents
2207
+ * - TurnTracker consumes MessageEvents to produce TurnEvents
476
2208
  */
477
- addHandler(handler) {
478
- this.handlers.add(handler);
479
- return () => {
480
- this.handlers.delete(handler);
481
- };
2209
+ processChained(state, event) {
2210
+ const [newState, outputs] = agentProcessor(state, event);
2211
+ if (outputs.length === 0) {
2212
+ return [newState, []];
2213
+ }
2214
+ const allOutputs = [...outputs];
2215
+ let currentState = newState;
2216
+ for (const output of outputs) {
2217
+ const [chainedState, chainedOutputs] = this.processChained(currentState, output);
2218
+ currentState = chainedState;
2219
+ allOutputs.push(...chainedOutputs);
2220
+ }
2221
+ return [currentState, allOutputs];
482
2222
  }
483
2223
  /**
484
- * Remove an error handler
2224
+ * Clear state for an agent
2225
+ *
2226
+ * Call this when an agent is destroyed to free memory.
485
2227
  */
486
- removeHandler(handler) {
487
- this.handlers.delete(handler);
2228
+ clearState(agentId) {
2229
+ logger33.debug("Clearing state", { agentId });
2230
+ this.store.delete(agentId);
488
2231
  }
489
2232
  /**
490
- * Default error logging
2233
+ * Check if state exists for an agent
491
2234
  */
492
- logError(agentId, error) {
493
- const prefix = `[${agentId}] ${error.category}/${error.code}`;
494
- if (error.severity === "fatal") {
495
- logger5.error(`${prefix}: ${error.message}`, { error });
496
- } else if (error.severity === "error") {
497
- logger5.error(`${prefix}: ${error.message}`);
498
- } else {
499
- logger5.warn(`${prefix}: ${error.message}`);
500
- }
501
- }
502
- };
503
- var ApiError = class extends Error {
504
- constructor(code, message, details) {
505
- super(message);
506
- this.code = code;
507
- this.details = details;
508
- this.name = "ApiError";
2235
+ hasState(agentId) {
2236
+ return this.store.has(agentId);
509
2237
  }
510
2238
  };
511
- function createHttpClient(options) {
512
- return ky__default.default.create({
513
- prefixUrl: options.baseUrl.replace(/\/+$/, ""),
514
- headers: options.headers,
515
- timeout: options.timeout || 3e4,
516
- hooks: {
517
- afterResponse: [
518
- async (_request, _options, response) => {
519
- if (!response.ok) {
520
- const data = await response.json().catch(() => ({}));
521
- throw new ApiError(
522
- data.error?.code || "UNKNOWN_ERROR",
523
- data.error?.message || `Request failed: ${response.status}`,
524
- data.error?.details
525
- );
526
- }
527
- return response;
528
- }
529
- ]
530
- }
531
- });
532
- }
533
- var logger6 = common.createLogger("agentx/ContainerManager");
2239
+
2240
+ // src/container/ContainerManagerImpl.ts
2241
+ var logger7 = createLogger("agentx/ContainerManager");
534
2242
  function generateContainerId() {
535
2243
  const timestamp = Date.now().toString(36);
536
2244
  const random = Math.random().toString(36).substring(2, 8);
@@ -549,7 +2257,7 @@ var ContainerManagerImpl = class {
549
2257
  __publicField(this, "repository");
550
2258
  this.runtime = runtime;
551
2259
  this.repository = repository;
552
- this.engine = new engine.AgentEngine();
2260
+ this.engine = new AgentEngine();
553
2261
  }
554
2262
  // ==================== Container Lifecycle ====================
555
2263
  async create(config) {
@@ -562,7 +2270,7 @@ var ContainerManagerImpl = class {
562
2270
  config
563
2271
  };
564
2272
  await this.repository.saveContainer(record);
565
- logger6.info("Container created", { containerId });
2273
+ logger7.info("Container created", { containerId });
566
2274
  return record;
567
2275
  }
568
2276
  async get(containerId) {
@@ -577,7 +2285,7 @@ var ContainerManagerImpl = class {
577
2285
  return false;
578
2286
  }
579
2287
  await this.repository.deleteContainer(containerId);
580
- logger6.info("Container deleted", { containerId });
2288
+ logger7.info("Container deleted", { containerId });
581
2289
  return true;
582
2290
  }
583
2291
  async exists(containerId) {
@@ -585,7 +2293,7 @@ var ContainerManagerImpl = class {
585
2293
  }
586
2294
  // ==================== Agent Runtime ====================
587
2295
  async run(image, containerId) {
588
- logger6.info("Running agent from image", {
2296
+ logger7.info("Running agent from image", {
589
2297
  imageId: image.imageId,
590
2298
  containerId
591
2299
  });
@@ -605,18 +2313,18 @@ var ContainerManagerImpl = class {
605
2313
  };
606
2314
  const sandbox = this.runtime.createSandbox(containerId);
607
2315
  const driver = this.runtime.createDriver(image.definition, context, sandbox);
608
- const agent$1 = new agent.AgentInstance(image.definition, context, this.engine, driver, sandbox);
609
- this.agents.set(agentId, agent$1);
610
- logger6.info("Agent started", {
2316
+ const agent = new AgentInstance(image.definition, context, this.engine, driver, sandbox);
2317
+ this.agents.set(agentId, agent);
2318
+ logger7.info("Agent started", {
611
2319
  agentId,
612
2320
  imageId: image.imageId,
613
2321
  containerId,
614
2322
  definitionName: image.definition.name
615
2323
  });
616
- return agent$1;
2324
+ return agent;
617
2325
  }
618
2326
  async resume(session, containerId) {
619
- logger6.info("Resuming agent from session", {
2327
+ logger7.info("Resuming agent from session", {
620
2328
  sessionId: session.sessionId,
621
2329
  imageId: session.imageId,
622
2330
  containerId
@@ -642,26 +2350,26 @@ var ContainerManagerImpl = class {
642
2350
  const sandbox = this.runtime.createSandbox(containerId);
643
2351
  const definition = imageRecord.definition;
644
2352
  const driver = this.runtime.createDriver(definition, context, sandbox);
645
- const agent$1 = new agent.AgentInstance(definition, context, this.engine, driver, sandbox);
646
- this.agents.set(agentId, agent$1);
647
- logger6.info("Agent resumed", {
2353
+ const agent = new AgentInstance(definition, context, this.engine, driver, sandbox);
2354
+ this.agents.set(agentId, agent);
2355
+ logger7.info("Agent resumed", {
648
2356
  agentId,
649
2357
  sessionId: session.sessionId,
650
2358
  imageId: session.imageId,
651
2359
  containerId
652
2360
  });
653
- return agent$1;
2361
+ return agent;
654
2362
  }
655
2363
  async destroyAgent(agentId) {
656
2364
  const agent = this.agents.get(agentId);
657
2365
  if (!agent) {
658
- logger6.warn("Agent not found for destroy", { agentId });
2366
+ logger7.warn("Agent not found for destroy", { agentId });
659
2367
  return;
660
2368
  }
661
- logger6.debug("Destroying agent", { agentId });
2369
+ logger7.debug("Destroying agent", { agentId });
662
2370
  await agent.destroy();
663
2371
  this.agents.delete(agentId);
664
- logger6.info("Agent destroyed", { agentId });
2372
+ logger7.info("Agent destroyed", { agentId });
665
2373
  }
666
2374
  getAgent(agentId) {
667
2375
  return this.agents.get(agentId);
@@ -674,16 +2382,16 @@ var ContainerManagerImpl = class {
674
2382
  }
675
2383
  async destroyAllAgents() {
676
2384
  const agentIds = Array.from(this.agents.keys());
677
- logger6.debug("Destroying all agents", { count: agentIds.length });
2385
+ logger7.debug("Destroying all agents", { count: agentIds.length });
678
2386
  await Promise.all(agentIds.map((id) => this.destroyAgent(id)));
679
- logger6.info("All agents destroyed", { count: agentIds.length });
2387
+ logger7.info("All agents destroyed", { count: agentIds.length });
680
2388
  }
681
2389
  };
682
2390
 
683
2391
  // src/AgentX.ts
684
- var logger7 = common.createLogger("agentx/AgentX");
2392
+ var logger8 = createLogger("agentx/AgentX");
685
2393
  function createAgentX(runtime, options) {
686
- logger7.info("Creating AgentX instance", { runtime: runtime.name });
2394
+ logger8.info("Creating AgentX instance", { runtime: runtime.name });
687
2395
  if (!runtime.repository) {
688
2396
  throw new Error("Runtime must have a repository for persistence");
689
2397
  }
@@ -694,7 +2402,7 @@ function createAgentX(runtime, options) {
694
2402
  const agentManager = new AgentManager(containerManager);
695
2403
  const imageManager = new ImageManagerImpl(repository, containerManager, options?.containerId);
696
2404
  const sessionManager = new SessionManagerImpl(repository, containerManager, options?.containerId);
697
- logger7.debug("AgentX instance created", { runtime: runtime.name });
2405
+ logger8.debug("AgentX instance created", { runtime: runtime.name });
698
2406
  return {
699
2407
  mode: "local",
700
2408
  containers: containerManager,
@@ -868,7 +2576,9 @@ function createSSEDriver(config) {
868
2576
  }
869
2577
  };
870
2578
  }
871
- var logger8 = common.createLogger("agentx/RemoteRepository");
2579
+
2580
+ // src/runtime/sse/repository/RemoteRepository.ts
2581
+ var logger9 = createLogger("agentx/RemoteRepository");
872
2582
  var RemoteRepository = class {
873
2583
  constructor(options) {
874
2584
  __publicField(this, "client");
@@ -876,7 +2586,7 @@ var RemoteRepository = class {
876
2586
  baseUrl: options.serverUrl,
877
2587
  headers: options.headers
878
2588
  });
879
- logger8.debug("RemoteRepository created", { serverUrl: options.serverUrl });
2589
+ logger9.debug("RemoteRepository created", { serverUrl: options.serverUrl });
880
2590
  }
881
2591
  // ==================== Definition ====================
882
2592
  async saveDefinition(record) {
@@ -981,7 +2691,7 @@ var RemoteRepository = class {
981
2691
  * Browser-side calls this but it does nothing to avoid duplicate saves.
982
2692
  */
983
2693
  async saveMessage(_record) {
984
- logger8.debug("saveMessage called (noop in browser)");
2694
+ logger9.debug("saveMessage called (noop in browser)");
985
2695
  }
986
2696
  async findMessageById(messageId) {
987
2697
  try {
@@ -1189,12 +2899,14 @@ var BrowserLoggerFactory = class {
1189
2899
  if (this.loggers.has(name)) {
1190
2900
  return this.loggers.get(name);
1191
2901
  }
1192
- const logger10 = new BrowserLogger(name, this.options);
1193
- this.loggers.set(name, logger10);
1194
- return logger10;
2902
+ const logger11 = new BrowserLogger(name, this.options);
2903
+ this.loggers.set(name, logger11);
2904
+ return logger11;
1195
2905
  }
1196
2906
  };
1197
- var logger9 = common.createLogger("agentx/RemoteAgentIdResolver");
2907
+
2908
+ // src/runtime/sse/RemoteAgentIdResolver.ts
2909
+ var logger10 = createLogger("agentx/RemoteAgentIdResolver");
1198
2910
  var RemoteAgentIdResolver = class {
1199
2911
  constructor(options) {
1200
2912
  __publicField(this, "client");
@@ -1204,19 +2916,19 @@ var RemoteAgentIdResolver = class {
1204
2916
  });
1205
2917
  }
1206
2918
  async resolveForRun(imageId, containerId) {
1207
- logger9.debug("Resolving agent ID for run", { imageId, containerId });
2919
+ logger10.debug("Resolving agent ID for run", { imageId, containerId });
1208
2920
  const response = await this.client.post(`images/${imageId}/run`, {
1209
2921
  json: { containerId }
1210
2922
  }).json();
1211
- logger9.info("Agent ID resolved for run", { imageId, agentId: response.agentId });
2923
+ logger10.info("Agent ID resolved for run", { imageId, agentId: response.agentId });
1212
2924
  return response.agentId;
1213
2925
  }
1214
2926
  async resolveForResume(sessionId, containerId) {
1215
- logger9.debug("Resolving agent ID for resume", { sessionId, containerId });
2927
+ logger10.debug("Resolving agent ID for resume", { sessionId, containerId });
1216
2928
  const response = await this.client.post(`sessions/${sessionId}/resume`, {
1217
2929
  json: { containerId }
1218
2930
  }).json();
1219
- logger9.info("Agent ID resolved for resume", { sessionId, agentId: response.agentId });
2931
+ logger10.info("Agent ID resolved for resume", { sessionId, agentId: response.agentId });
1220
2932
  return response.agentId;
1221
2933
  }
1222
2934
  };
@@ -1250,7 +2962,7 @@ var SSERuntime = class {
1250
2962
  this.loggerFactory = new BrowserLoggerFactory({
1251
2963
  collapsed: true
1252
2964
  });
1253
- common.setLoggerFactory(this.loggerFactory);
2965
+ setLoggerFactory(this.loggerFactory);
1254
2966
  this.repository = new RemoteRepository({
1255
2967
  serverUrl: this.serverUrl,
1256
2968
  headers: this.headers