@agentxjs/ui 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,4 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { c as createLogger, i as isStateEvent, L as LogLevel } from "./index-CyXGvO5F.js";
1
+ import { L as LogLevel, i as isStateEvent } from "./index-O2e5VGwL.js";
5
2
  var extendStatics = function(d, b) {
6
3
  extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
7
4
  d2.__proto__ = b2;
@@ -745,2019 +742,2152 @@ function take(count) {
745
742
  }));
746
743
  });
747
744
  }
748
- var logger$1 = createLogger("core/AgentStateMachine");
749
- var AgentStateMachine = class {
750
- constructor() {
751
- __publicField(this, "_state", "idle");
752
- __publicField(this, "handlers", /* @__PURE__ */ new Set());
753
- }
754
- /**
755
- * Current agent state
756
- */
757
- get state() {
758
- return this._state;
745
+ var __defProp = Object.defineProperty;
746
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
747
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
748
+ var __defProp2 = Object.defineProperty;
749
+ var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
750
+ var __publicField2 = (obj, key, value) => __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
751
+ var _ConsoleLogger = class _ConsoleLogger2 {
752
+ constructor(name, options = {}) {
753
+ __publicField2(this, "name");
754
+ __publicField2(this, "level");
755
+ __publicField2(this, "colors");
756
+ __publicField2(this, "timestamps");
757
+ this.name = name;
758
+ this.level = options.level ?? LogLevel.INFO;
759
+ this.colors = options.colors ?? this.isNodeEnvironment();
760
+ this.timestamps = options.timestamps ?? true;
759
761
  }
760
- /**
761
- * Process a StateEvent and update internal state
762
- *
763
- * @param event - StateEvent from Engine layer
764
- */
765
- process(event) {
766
- const prev = this._state;
767
- const next = this.mapEventToState(event);
768
- if (next !== null && prev !== next) {
769
- this._state = next;
770
- logger$1.debug("State transition", {
771
- eventType: event.type,
772
- from: prev,
773
- to: next
774
- });
775
- this.notifyHandlers({ prev, current: next });
762
+ debug(message, context) {
763
+ if (this.isDebugEnabled()) {
764
+ this.log("DEBUG", message, context);
776
765
  }
777
766
  }
778
- /**
779
- * Subscribe to state changes
780
- *
781
- * @param handler - Callback receiving { prev, current } state change
782
- * @returns Unsubscribe function
783
- */
784
- onStateChange(handler) {
785
- this.handlers.add(handler);
786
- return () => {
787
- this.handlers.delete(handler);
788
- };
789
- }
790
- /**
791
- * Reset state machine (used on destroy)
792
- */
793
- reset() {
794
- this._state;
795
- this._state = "idle";
796
- this.handlers.clear();
767
+ info(message, context) {
768
+ if (this.isInfoEnabled()) {
769
+ this.log("INFO", message, context);
770
+ }
797
771
  }
798
- /**
799
- * Map StateEvent type to AgentState
800
- *
801
- * @param event - StateEvent from Engine
802
- * @returns New AgentState or null if no transition needed
803
- */
804
- mapEventToState(event) {
805
- switch (event.type) {
806
- // Agent lifecycle
807
- case "agent_initializing":
808
- return "initializing";
809
- case "agent_ready":
810
- return "idle";
811
- case "agent_destroyed":
812
- return "idle";
813
- // Conversation lifecycle
814
- case "conversation_queued":
815
- return "queued";
816
- case "conversation_start":
817
- return "conversation_active";
818
- case "conversation_thinking":
819
- return "thinking";
820
- case "conversation_responding":
821
- return "responding";
822
- case "conversation_end":
823
- return "idle";
824
- case "conversation_interrupted":
825
- return "idle";
826
- // Return to idle on interrupt
827
- // Tool lifecycle
828
- case "tool_planned":
829
- return "planning_tool";
830
- case "tool_executing":
831
- return "awaiting_tool_result";
832
- case "tool_completed":
833
- return "responding";
834
- // Back to responding after tool completes
835
- case "tool_failed":
836
- return "responding";
837
- // Continue responding after tool failure
838
- // Error
839
- case "error_occurred":
840
- return "idle";
841
- // Reset to idle on error
842
- default:
843
- return null;
772
+ warn(message, context) {
773
+ if (this.isWarnEnabled()) {
774
+ this.log("WARN", message, context);
844
775
  }
845
776
  }
846
- /**
847
- * Notify all registered handlers of state change
848
- */
849
- notifyHandlers(change) {
850
- for (const handler of this.handlers) {
851
- try {
852
- handler(change);
853
- } catch (error) {
854
- logger$1.error("State change handler error", {
855
- from: change.prev,
856
- to: change.current,
857
- error
858
- });
777
+ error(message, context) {
778
+ if (this.isErrorEnabled()) {
779
+ if (message instanceof Error) {
780
+ this.log("ERROR", message.message, { ...context, stack: message.stack });
781
+ } else {
782
+ this.log("ERROR", message, context);
859
783
  }
860
784
  }
861
785
  }
862
- };
863
- var logger2$2 = createLogger("core/AgentEventBus");
864
- var AgentEventBus = class {
865
- constructor() {
866
- __publicField(this, "subject", new Subject());
867
- __publicField(this, "typeSubscriptions", /* @__PURE__ */ new Map());
868
- __publicField(this, "globalSubscriptions", []);
869
- __publicField(this, "nextId", 0);
870
- __publicField(this, "isDestroyed", false);
871
- // Cached views
872
- __publicField(this, "producerView", null);
873
- __publicField(this, "consumerView", null);
786
+ isDebugEnabled() {
787
+ return this.level <= LogLevel.DEBUG;
874
788
  }
875
- // ===== Producer Methods =====
876
- emit(event) {
877
- if (this.isDestroyed) {
878
- logger2$2.warn("Emit called on destroyed EventBus", { eventType: event.type });
879
- return;
880
- }
881
- this.subject.next(event);
789
+ isInfoEnabled() {
790
+ return this.level <= LogLevel.INFO;
882
791
  }
883
- emitBatch(events) {
884
- for (const event of events) {
885
- this.emit(event);
886
- }
792
+ isWarnEnabled() {
793
+ return this.level <= LogLevel.WARN;
887
794
  }
888
- on(typeOrTypes, handler, options = {}) {
889
- if (this.isDestroyed) {
890
- logger2$2.warn("Subscribe called on destroyed EventBus");
891
- return () => {
892
- };
795
+ isErrorEnabled() {
796
+ return this.level <= LogLevel.ERROR;
797
+ }
798
+ log(level, message, context) {
799
+ const parts = [];
800
+ if (this.timestamps) {
801
+ parts.push((/* @__PURE__ */ new Date()).toISOString());
893
802
  }
894
- const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes];
895
- const unsubscribes = [];
896
- for (const type of types) {
897
- const unsub = this.subscribeToType(type, handler, options);
898
- unsubscribes.push(unsub);
803
+ if (this.colors) {
804
+ const color = _ConsoleLogger2.COLORS[level];
805
+ parts.push(`${color}${level.padEnd(5)}${_ConsoleLogger2.COLORS.RESET}`);
806
+ } else {
807
+ parts.push(level.padEnd(5));
899
808
  }
900
- return () => unsubscribes.forEach((u) => u());
901
- }
902
- onAny(handler, options = {}) {
903
- if (this.isDestroyed) {
904
- logger2$2.warn("Subscribe called on destroyed EventBus");
905
- return () => {
906
- };
809
+ parts.push(`[${this.name}]`);
810
+ parts.push(message);
811
+ const logLine = parts.join(" ");
812
+ const consoleMethod = this.getConsoleMethod(level);
813
+ if (context && Object.keys(context).length > 0) {
814
+ consoleMethod(logLine, context);
815
+ } else {
816
+ consoleMethod(logLine);
907
817
  }
908
- return this.subscribeGlobal(handler, options);
909
- }
910
- once(type, handler) {
911
- return this.on(type, handler, { once: true });
912
818
  }
913
- // ===== View Methods =====
914
- asConsumer() {
915
- if (!this.consumerView) {
916
- this.consumerView = {
917
- on: this.on.bind(this),
918
- onAny: this.onAny.bind(this),
919
- once: this.once.bind(this)
920
- };
819
+ getConsoleMethod(level) {
820
+ switch (level) {
821
+ case "DEBUG":
822
+ return console.debug.bind(console);
823
+ case "INFO":
824
+ return console.info.bind(console);
825
+ case "WARN":
826
+ return console.warn.bind(console);
827
+ case "ERROR":
828
+ return console.error.bind(console);
829
+ default:
830
+ return console.log.bind(console);
921
831
  }
922
- return this.consumerView;
923
832
  }
924
- asProducer() {
925
- if (!this.producerView) {
926
- this.producerView = {
927
- emit: this.emit.bind(this),
928
- emitBatch: this.emitBatch.bind(this)
929
- };
930
- }
931
- return this.producerView;
833
+ isNodeEnvironment() {
834
+ var _a;
835
+ return typeof process !== "undefined" && ((_a = process.versions) == null ? void 0 : _a.node) !== void 0;
932
836
  }
933
- // ===== Lifecycle =====
934
- destroy() {
935
- if (this.isDestroyed) return;
936
- this.isDestroyed = true;
937
- for (const records of this.typeSubscriptions.values()) {
938
- for (const record of records) {
939
- record.unsubscribe();
837
+ };
838
+ __publicField2(_ConsoleLogger, "COLORS", {
839
+ DEBUG: "\x1B[36m",
840
+ INFO: "\x1B[32m",
841
+ WARN: "\x1B[33m",
842
+ ERROR: "\x1B[31m",
843
+ RESET: "\x1B[0m"
844
+ });
845
+ var ConsoleLogger = _ConsoleLogger;
846
+ var externalFactory = null;
847
+ var LoggerFactoryImpl = class {
848
+ static getLogger(nameOrClass) {
849
+ const name = typeof nameOrClass === "string" ? nameOrClass : nameOrClass.name;
850
+ if (this.loggers.has(name)) {
851
+ return this.loggers.get(name);
852
+ }
853
+ const lazyLogger = this.createLazyLogger(name);
854
+ this.loggers.set(name, lazyLogger);
855
+ return lazyLogger;
856
+ }
857
+ static configure(config2) {
858
+ this.config = { ...this.config, ...config2 };
859
+ }
860
+ static reset() {
861
+ this.loggers.clear();
862
+ this.config = { defaultLevel: LogLevel.INFO };
863
+ externalFactory = null;
864
+ }
865
+ static createLazyLogger(name) {
866
+ let realLogger = null;
867
+ const getRealLogger = () => {
868
+ if (!realLogger) {
869
+ realLogger = this.createLogger(name);
940
870
  }
941
- }
942
- this.typeSubscriptions.clear();
943
- for (const record of this.globalSubscriptions) {
944
- record.unsubscribe();
945
- }
946
- this.globalSubscriptions.length = 0;
947
- this.subject.complete();
948
- logger2$2.debug("EventBus destroyed");
871
+ return realLogger;
872
+ };
873
+ return {
874
+ name,
875
+ level: this.config.defaultLevel || LogLevel.INFO,
876
+ debug: (message, context) => getRealLogger().debug(message, context),
877
+ info: (message, context) => getRealLogger().info(message, context),
878
+ warn: (message, context) => getRealLogger().warn(message, context),
879
+ error: (message, context) => getRealLogger().error(message, context),
880
+ isDebugEnabled: () => getRealLogger().isDebugEnabled(),
881
+ isInfoEnabled: () => getRealLogger().isInfoEnabled(),
882
+ isWarnEnabled: () => getRealLogger().isWarnEnabled(),
883
+ isErrorEnabled: () => getRealLogger().isErrorEnabled()
884
+ };
949
885
  }
950
- // ===== Private Methods =====
951
- subscribeToType(type, handler, options) {
952
- const { filter: filter$1, priority = 0, once = false } = options;
953
- const id = this.nextId++;
954
- let observable2 = this.subject.pipe(filter((e) => e.type === type));
955
- if (filter$1) {
956
- observable2 = observable2.pipe(filter(filter$1));
886
+ static createLogger(name) {
887
+ if (externalFactory) {
888
+ return externalFactory.getLogger(name);
957
889
  }
958
- if (once) {
959
- observable2 = observable2.pipe(take(1));
890
+ if (this.config.defaultImplementation) {
891
+ return this.config.defaultImplementation(name);
960
892
  }
961
- const subscription = observable2.subscribe({
962
- next: (event) => {
963
- this.executeWithPriority(type, event, handler, id);
964
- }
893
+ return new ConsoleLogger(name, {
894
+ level: this.config.defaultLevel,
895
+ ...this.config.consoleOptions
965
896
  });
966
- const unsubscribe = () => {
967
- subscription.unsubscribe();
968
- const records2 = this.typeSubscriptions.get(type);
969
- if (records2) {
970
- const idx = records2.findIndex((r) => r.id === id);
971
- if (idx !== -1) records2.splice(idx, 1);
972
- }
973
- };
974
- if (!this.typeSubscriptions.has(type)) {
975
- this.typeSubscriptions.set(type, []);
976
- }
977
- const record = { id, priority, handler, unsubscribe };
978
- const records = this.typeSubscriptions.get(type);
979
- records.push(record);
980
- records.sort((a, b) => b.priority - a.priority);
981
- return unsubscribe;
982
897
  }
983
- subscribeGlobal(handler, options) {
984
- const { filter: filter$1, priority = 0, once = false } = options;
985
- const id = this.nextId++;
986
- let observable2 = this.subject.asObservable();
987
- if (filter$1) {
988
- observable2 = observable2.pipe(filter(filter$1));
989
- }
990
- if (once) {
991
- observable2 = observable2.pipe(take(1));
898
+ };
899
+ __publicField2(LoggerFactoryImpl, "loggers", /* @__PURE__ */ new Map());
900
+ __publicField2(LoggerFactoryImpl, "config", {
901
+ defaultLevel: LogLevel.INFO
902
+ });
903
+ function createLogger(name) {
904
+ return LoggerFactoryImpl.getLogger(name);
905
+ }
906
+ var logger = createLogger("agentx/DefinitionManager");
907
+ function generateMetaImageId(definitionName) {
908
+ return `meta_${definitionName}`;
909
+ }
910
+ function toDefinitionRecord(definition) {
911
+ const now = /* @__PURE__ */ new Date();
912
+ return {
913
+ name: definition.name,
914
+ description: definition.description,
915
+ systemPrompt: definition.systemPrompt,
916
+ definition,
917
+ source: "code",
918
+ createdAt: now,
919
+ updatedAt: now
920
+ };
921
+ }
922
+ var DefinitionManagerImpl = class {
923
+ constructor(repository) {
924
+ this.repository = repository;
925
+ __publicField(this, "cache", /* @__PURE__ */ new Map());
926
+ }
927
+ register(definition) {
928
+ if (this.cache.has(definition.name)) {
929
+ throw new Error(`Definition already exists: ${definition.name}`);
992
930
  }
993
- const subscription = observable2.subscribe({
994
- next: (event) => {
995
- this.executeGlobalWithPriority(event, handler, id);
996
- }
931
+ this.cache.set(definition.name, definition);
932
+ const definitionRecord = toDefinitionRecord(definition);
933
+ this.repository.saveDefinition(definitionRecord).catch((err) => {
934
+ logger.error("Failed to save definition", { name: definition.name, error: err });
997
935
  });
998
- const unsubscribe = () => {
999
- subscription.unsubscribe();
1000
- const idx = this.globalSubscriptions.findIndex((r) => r.id === id);
1001
- if (idx !== -1) this.globalSubscriptions.splice(idx, 1);
936
+ const metaImageId = generateMetaImageId(definition.name);
937
+ const imageRecord = {
938
+ imageId: metaImageId,
939
+ type: "meta",
940
+ definitionName: definition.name,
941
+ parentImageId: null,
942
+ definition,
943
+ config: {},
944
+ messages: [],
945
+ createdAt: /* @__PURE__ */ new Date()
1002
946
  };
1003
- const record = { id, priority, handler, unsubscribe };
1004
- this.globalSubscriptions.push(record);
1005
- this.globalSubscriptions.sort((a, b) => b.priority - a.priority);
1006
- return unsubscribe;
947
+ this.repository.saveImage(imageRecord).catch((err) => {
948
+ logger.error("Failed to save MetaImage", { definitionName: definition.name, error: err });
949
+ });
950
+ logger.info("Definition registered", {
951
+ name: definition.name,
952
+ metaImageId
953
+ });
1007
954
  }
1008
- /**
1009
- * Execute handler respecting priority order for typed subscriptions
1010
- */
1011
- executeWithPriority(type, event, handler, handlerId) {
1012
- const records = this.typeSubscriptions.get(type) || [];
1013
- const record = records.find((r) => r.id === handlerId);
1014
- if (record) {
1015
- try {
1016
- handler(event);
1017
- } catch (error) {
1018
- logger2$2.error("Event handler error", { eventType: type, error });
1019
- }
1020
- }
955
+ get(name) {
956
+ return this.cache.get(name);
1021
957
  }
1022
- /**
1023
- * Execute handler respecting priority order for global subscriptions
1024
- */
1025
- executeGlobalWithPriority(event, handler, handlerId) {
1026
- const record = this.globalSubscriptions.find((r) => r.id === handlerId);
1027
- if (record) {
1028
- try {
1029
- handler(event);
1030
- } catch (error) {
1031
- logger2$2.error("Global event handler error", { eventType: event.type, error });
1032
- }
958
+ list() {
959
+ return Array.from(this.cache.values());
960
+ }
961
+ has(name) {
962
+ return this.cache.has(name);
963
+ }
964
+ unregister(name) {
965
+ const definition = this.cache.get(name);
966
+ if (!definition) {
967
+ return false;
1033
968
  }
969
+ this.cache.delete(name);
970
+ this.repository.deleteDefinition(name).catch((err) => {
971
+ logger.error("Failed to delete definition", { name, error: err });
972
+ });
973
+ const metaImageId = generateMetaImageId(name);
974
+ this.repository.deleteImage(metaImageId).catch((err) => {
975
+ logger.error("Failed to delete MetaImage", { definitionName: name, error: err });
976
+ });
977
+ logger.info("Definition unregistered", { name });
978
+ return true;
1034
979
  }
1035
980
  };
1036
- var AgentErrorClassifier = class {
1037
- constructor(agentId) {
1038
- this.agentId = agentId;
981
+ var logger2 = createLogger("agentx/ImageManager");
982
+ function generateMetaImageId2(definitionName) {
983
+ return `meta_${definitionName}`;
984
+ }
985
+ function toAgentImage(record) {
986
+ const definition = record.definition;
987
+ if (record.type === "meta") {
988
+ const metaImage = {
989
+ type: "meta",
990
+ imageId: record.imageId,
991
+ definitionName: record.definitionName,
992
+ definition,
993
+ config: record.config,
994
+ messages: [],
995
+ createdAt: record.createdAt
996
+ };
997
+ return metaImage;
998
+ } else {
999
+ return {
1000
+ type: "derived",
1001
+ imageId: record.imageId,
1002
+ parentImageId: record.parentImageId,
1003
+ definitionName: record.definitionName,
1004
+ definition,
1005
+ config: record.config,
1006
+ messages: record.messages,
1007
+ createdAt: record.createdAt
1008
+ };
1039
1009
  }
1040
- /**
1041
- * Classify an unknown error into an AgentError
1042
- */
1043
- classify(error) {
1044
- const err = error instanceof Error ? error : new Error(String(error));
1045
- const message = err.message;
1046
- if (message.includes("rate limit") || message.includes("429")) {
1047
- return this.create("llm", "RATE_LIMITED", message, true, err);
1048
- }
1049
- if (message.includes("api key") || message.includes("401") || message.includes("unauthorized")) {
1050
- return this.create("llm", "INVALID_API_KEY", message, false, err);
1051
- }
1052
- if (message.includes("context") && message.includes("long")) {
1053
- return this.create("llm", "CONTEXT_TOO_LONG", message, true, err);
1010
+ }
1011
+ var ImageManagerImpl = class {
1012
+ constructor(repository, containerManager, defaultContainerId) {
1013
+ __publicField(this, "repository");
1014
+ __publicField(this, "containerManager");
1015
+ __publicField(this, "defaultContainerId");
1016
+ this.repository = repository;
1017
+ this.containerManager = containerManager;
1018
+ this.defaultContainerId = defaultContainerId;
1019
+ }
1020
+ async get(imageId) {
1021
+ const record = await this.repository.findImageById(imageId);
1022
+ if (!record) {
1023
+ return void 0;
1054
1024
  }
1055
- if (message.includes("overloaded") || message.includes("503")) {
1056
- return this.create("llm", "OVERLOADED", message, true, err);
1025
+ return toAgentImage(record);
1026
+ }
1027
+ async getMetaImage(definitionName) {
1028
+ const metaImageId = generateMetaImageId2(definitionName);
1029
+ const record = await this.repository.findImageById(metaImageId);
1030
+ if (!record || record.type !== "meta") {
1031
+ return void 0;
1057
1032
  }
1058
- if (message.includes("timeout") || message.includes("ETIMEDOUT")) {
1059
- return this.create("network", "TIMEOUT", message, true, err);
1033
+ return toAgentImage(record);
1034
+ }
1035
+ async list() {
1036
+ const records = await this.repository.findAllImages();
1037
+ return records.map(toAgentImage);
1038
+ }
1039
+ async listByDefinition(definitionName) {
1040
+ const allRecords = await this.repository.findAllImages();
1041
+ const filtered = allRecords.filter((r) => r.definitionName === definitionName);
1042
+ return filtered.map(toAgentImage);
1043
+ }
1044
+ async exists(imageId) {
1045
+ return this.repository.imageExists(imageId);
1046
+ }
1047
+ async delete(imageId) {
1048
+ const record = await this.repository.findImageById(imageId);
1049
+ if (!record) {
1050
+ return false;
1060
1051
  }
1061
- if (message.includes("ECONNREFUSED") || message.includes("connection")) {
1062
- return this.create("network", "CONNECTION_FAILED", message, true, err);
1052
+ if (record.type === "meta") {
1053
+ logger2.warn("Cannot delete MetaImage directly", { imageId });
1054
+ return false;
1063
1055
  }
1064
- if (message.includes("network") || message.includes("fetch")) {
1065
- return this.create("network", "CONNECTION_FAILED", message, true, err);
1056
+ await this.repository.deleteImage(imageId);
1057
+ logger2.info("Image deleted", { imageId });
1058
+ return true;
1059
+ }
1060
+ async run(imageId, options) {
1061
+ logger2.info("Running agent from image", { imageId, containerId: options == null ? void 0 : options.containerId });
1062
+ const image = await this.get(imageId);
1063
+ if (!image) {
1064
+ throw new Error(`Image not found: ${imageId}`);
1066
1065
  }
1067
- if (message.includes("driver")) {
1068
- return this.create("driver", "RECEIVE_FAILED", message, true, err);
1066
+ let containerId = (options == null ? void 0 : options.containerId) || this.defaultContainerId;
1067
+ if (!containerId) {
1068
+ const container = await this.containerManager.create();
1069
+ containerId = container.containerId;
1070
+ this.defaultContainerId = containerId;
1071
+ logger2.debug("Auto-created default container", { containerId });
1069
1072
  }
1070
- return this.create("system", "UNKNOWN", message, true, err);
1073
+ return this.containerManager.run(image, containerId);
1074
+ }
1075
+ };
1076
+ var logger3 = createLogger("agentx/AgentManager");
1077
+ var AgentManager = class {
1078
+ constructor(containerManager) {
1079
+ this.containerManager = containerManager;
1071
1080
  }
1072
1081
  /**
1073
- * Create an AgentError with the specified category and code
1082
+ * Get an existing agent by ID
1074
1083
  */
1075
- create(category, code, message, recoverable, cause) {
1076
- return {
1077
- category,
1078
- code,
1079
- message,
1080
- severity: recoverable ? "error" : "fatal",
1081
- recoverable,
1082
- cause
1083
- };
1084
+ get(agentId) {
1085
+ return this.containerManager.getAgent(agentId);
1084
1086
  }
1085
1087
  /**
1086
- * Create an ErrorEvent from an AgentError
1087
- *
1088
- * ErrorEvent is independent from Message layer and transportable via SSE.
1088
+ * Check if an agent exists
1089
1089
  */
1090
- createEvent(error) {
1091
- return {
1092
- type: "error",
1093
- uuid: `${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1094
- agentId: this.agentId,
1095
- timestamp: Date.now(),
1096
- data: {
1097
- error
1098
- }
1099
- };
1100
- }
1101
- };
1102
- var MiddlewareChain = class {
1103
- constructor() {
1104
- __publicField(this, "middlewares", []);
1105
- }
1106
- /**
1107
- * Add middleware to the chain
1108
- *
1109
- * @param middleware - Middleware function
1110
- * @returns Unsubscribe function to remove the middleware
1111
- */
1112
- use(middleware) {
1113
- this.middlewares.push(middleware);
1114
- return () => {
1115
- const index = this.middlewares.indexOf(middleware);
1116
- if (index !== -1) {
1117
- this.middlewares.splice(index, 1);
1118
- }
1119
- };
1090
+ has(agentId) {
1091
+ return this.containerManager.hasAgent(agentId);
1120
1092
  }
1121
1093
  /**
1122
- * Execute the middleware chain
1123
- *
1124
- * @param message - User message to process
1125
- * @param finalHandler - Handler called at the end of the chain
1094
+ * List all agents
1126
1095
  */
1127
- async execute(message, finalHandler) {
1128
- let index = 0;
1129
- const next = async (msg) => {
1130
- if (index < this.middlewares.length) {
1131
- const middleware = this.middlewares[index++];
1132
- await middleware(msg, next);
1133
- } else {
1134
- await finalHandler(msg);
1135
- }
1136
- };
1137
- await next(message);
1096
+ list() {
1097
+ return this.containerManager.listAgents();
1138
1098
  }
1139
1099
  /**
1140
- * Clear all middlewares
1100
+ * Destroy an agent by ID
1141
1101
  */
1142
- clear() {
1143
- this.middlewares.length = 0;
1102
+ async destroy(agentId) {
1103
+ logger3.debug("Destroying agent", { agentId });
1104
+ await this.containerManager.destroyAgent(agentId);
1105
+ logger3.info("Agent destroyed", { agentId });
1144
1106
  }
1145
1107
  /**
1146
- * Get the number of middlewares
1108
+ * Destroy all agents
1147
1109
  */
1148
- get size() {
1149
- return this.middlewares.length;
1110
+ async destroyAll() {
1111
+ const agents = this.containerManager.listAgents();
1112
+ logger3.debug("Destroying all agents", { count: agents.length });
1113
+ await this.containerManager.destroyAllAgents();
1114
+ logger3.info("All agents destroyed", { count: agents.length });
1150
1115
  }
1151
1116
  };
1152
- var logger3$2 = createLogger("core/InterceptorChain");
1153
- var InterceptorChain = class {
1154
- constructor(agentId) {
1155
- __publicField(this, "interceptors", []);
1156
- __publicField(this, "agentId");
1157
- this.agentId = agentId;
1158
- }
1159
- /**
1160
- * Add interceptor to the chain
1161
- *
1162
- * @param interceptor - Interceptor function
1163
- * @returns Unsubscribe function to remove the interceptor
1164
- */
1165
- intercept(interceptor) {
1166
- this.interceptors.push(interceptor);
1167
- return () => {
1168
- const index = this.interceptors.indexOf(interceptor);
1169
- if (index !== -1) {
1170
- this.interceptors.splice(index, 1);
1171
- }
1172
- };
1173
- }
1174
- /**
1175
- * Execute the interceptor chain
1176
- *
1177
- * @param event - Event to process
1178
- * @param finalHandler - Handler called at the end of the chain
1179
- */
1180
- execute(event, finalHandler) {
1181
- let index = 0;
1182
- const next = (e) => {
1183
- if (index < this.interceptors.length) {
1184
- const interceptor = this.interceptors[index++];
1185
- try {
1186
- interceptor(e, next);
1187
- } catch (error) {
1188
- logger3$2.error("Interceptor error", {
1189
- agentId: this.agentId,
1190
- eventType: e.type,
1191
- interceptorIndex: index - 1,
1192
- error
1193
- });
1194
- next(e);
1195
- }
1196
- } else {
1197
- finalHandler(e);
1198
- }
1199
- };
1200
- next(event);
1117
+ var logger4 = createLogger("agentx/SessionManager");
1118
+ function generateSessionId() {
1119
+ const timestamp = Date.now().toString(36);
1120
+ const random = Math.random().toString(36).substring(2, 8);
1121
+ return `session_${timestamp}_${random}`;
1122
+ }
1123
+ function generateImageId() {
1124
+ const timestamp = Date.now().toString(36);
1125
+ const random = Math.random().toString(36).substring(2, 8);
1126
+ return `image_${timestamp}_${random}`;
1127
+ }
1128
+ var SessionImpl = class _SessionImpl {
1129
+ constructor(record, repository, containerManager, defaultContainerId) {
1130
+ __publicField(this, "sessionId");
1131
+ __publicField(this, "userId");
1132
+ __publicField(this, "imageId");
1133
+ __publicField(this, "createdAt");
1134
+ __publicField(this, "_title");
1135
+ __publicField(this, "_updatedAt");
1136
+ __publicField(this, "repository");
1137
+ __publicField(this, "containerManager");
1138
+ __publicField(this, "defaultContainerId");
1139
+ this.sessionId = record.sessionId;
1140
+ this.userId = record.userId;
1141
+ this.imageId = record.imageId;
1142
+ this._title = record.title;
1143
+ this.createdAt = record.createdAt.getTime();
1144
+ this._updatedAt = record.updatedAt.getTime();
1145
+ this.repository = repository;
1146
+ this.containerManager = containerManager;
1147
+ this.defaultContainerId = defaultContainerId;
1201
1148
  }
1202
- /**
1203
- * Clear all interceptors
1204
- */
1205
- clear() {
1206
- this.interceptors.length = 0;
1149
+ get title() {
1150
+ return this._title;
1207
1151
  }
1208
- /**
1209
- * Get the number of interceptors
1210
- */
1211
- get size() {
1212
- return this.interceptors.length;
1152
+ get updatedAt() {
1153
+ return this._updatedAt;
1213
1154
  }
1214
- };
1215
- var REACT_TO_EVENT_MAP = {
1216
- // Stream Layer Events
1217
- onMessageStart: "message_start",
1218
- onMessageDelta: "message_delta",
1219
- onMessageStop: "message_stop",
1220
- onTextContentBlockStart: "text_content_block_start",
1221
- onTextDelta: "text_delta",
1222
- onTextContentBlockStop: "text_content_block_stop",
1223
- onToolUseContentBlockStart: "tool_use_content_block_start",
1224
- onInputJsonDelta: "input_json_delta",
1225
- onToolUseContentBlockStop: "tool_use_content_block_stop",
1226
- onToolCall: "tool_call",
1227
- onToolResult: "tool_result",
1228
- // Message Layer Events
1229
- onUserMessage: "user_message",
1230
- onAssistantMessage: "assistant_message",
1231
- onToolCallMessage: "tool_call_message",
1232
- onToolResultMessage: "tool_result_message",
1233
- // Error Layer Events (independent, transportable via SSE)
1234
- onError: "error",
1235
- // Turn Layer Events
1236
- onTurnRequest: "turn_request",
1237
- onTurnResponse: "turn_response"
1238
- };
1239
- function mapReactHandlers(reactHandlers) {
1240
- const eventHandlerMap = {};
1241
- for (const [reactKey, eventKey] of Object.entries(REACT_TO_EVENT_MAP)) {
1242
- const handler = reactHandlers[reactKey];
1243
- if (handler) {
1244
- eventHandlerMap[eventKey] = handler;
1155
+ async resume(options) {
1156
+ logger4.info("Resuming agent from session", {
1157
+ sessionId: this.sessionId,
1158
+ imageId: this.imageId,
1159
+ containerId: options == null ? void 0 : options.containerId
1160
+ });
1161
+ let containerId = (options == null ? void 0 : options.containerId) || this.defaultContainerId;
1162
+ if (!containerId) {
1163
+ const container = await this.containerManager.create();
1164
+ containerId = container.containerId;
1165
+ logger4.debug("Auto-created default container for session", {
1166
+ containerId,
1167
+ sessionId: this.sessionId
1168
+ });
1245
1169
  }
1170
+ const agent = await this.containerManager.resume(this, containerId);
1171
+ this.collect(agent);
1172
+ return agent;
1246
1173
  }
1247
- return eventHandlerMap;
1248
- }
1249
- var logger4$1 = createLogger("core/AgentInstance");
1250
- var AgentInstance = class {
1251
- constructor(definition, context, engine, driver, sandbox) {
1252
- __publicField(this, "agentId");
1253
- __publicField(this, "definition");
1254
- __publicField(this, "context");
1255
- __publicField(this, "createdAt");
1256
- __publicField(this, "sandbox");
1257
- __publicField(this, "_lifecycle", "running");
1258
- __publicField(this, "engine");
1259
- /**
1260
- * Driver instance - created from definition.driver class
1261
- */
1262
- __publicField(this, "driver");
1263
- /**
1264
- * State machine - manages state transitions driven by StateEvents
1265
- */
1266
- __publicField(this, "stateMachine", new AgentStateMachine());
1267
- /**
1268
- * Event bus - centralized event pub/sub
1269
- */
1270
- __publicField(this, "eventBus", new AgentEventBus());
1271
- /**
1272
- * Error classifier - classifies and creates error events
1273
- */
1274
- __publicField(this, "errorClassifier");
1275
- /**
1276
- * Middleware chain for receive() interception
1277
- */
1278
- __publicField(this, "middlewareChain", new MiddlewareChain());
1279
- /**
1280
- * Interceptor chain for event dispatch interception
1281
- */
1282
- __publicField(this, "interceptorChain");
1283
- /**
1284
- * Lifecycle handlers for onReady
1285
- */
1286
- __publicField(this, "readyHandlers", /* @__PURE__ */ new Set());
1287
- /**
1288
- * Lifecycle handlers for onDestroy
1289
- */
1290
- __publicField(this, "destroyHandlers", /* @__PURE__ */ new Set());
1291
- this.agentId = context.agentId;
1292
- this.definition = definition;
1293
- this.context = context;
1294
- this.engine = engine;
1295
- this.createdAt = context.createdAt;
1296
- this.sandbox = sandbox;
1297
- this.driver = driver;
1298
- this.errorClassifier = new AgentErrorClassifier(this.agentId);
1299
- this.interceptorChain = new InterceptorChain(this.agentId);
1300
- logger4$1.debug("AgentInstance created", {
1301
- agentId: this.agentId,
1302
- definitionName: definition.name,
1303
- driverName: this.driver.name
1174
+ collect(agent) {
1175
+ logger4.debug("Collecting messages from agent", {
1176
+ sessionId: this.sessionId,
1177
+ agentId: agent.agentId
1304
1178
  });
1179
+ const sessionId = this.sessionId;
1180
+ const repository = this.repository;
1181
+ const saveMessage = (data, role) => {
1182
+ const record = {
1183
+ messageId: data.id,
1184
+ sessionId,
1185
+ role,
1186
+ content: data,
1187
+ createdAt: new Date(data.timestamp ?? Date.now())
1188
+ };
1189
+ repository.saveMessage(record).catch((error) => {
1190
+ logger4.error("Failed to persist message", {
1191
+ sessionId,
1192
+ messageId: record.messageId,
1193
+ error
1194
+ });
1195
+ });
1196
+ };
1197
+ agent.on("user_message", (event) => saveMessage(event.data, "user"));
1198
+ agent.on("assistant_message", (event) => saveMessage(event.data, "assistant"));
1199
+ agent.on("tool_call_message", (event) => saveMessage(event.data, "tool"));
1200
+ agent.on("tool_result_message", (event) => saveMessage(event.data, "tool"));
1305
1201
  }
1306
- /**
1307
- * Current lifecycle state
1308
- */
1309
- get lifecycle() {
1310
- return this._lifecycle;
1202
+ async getMessages() {
1203
+ logger4.debug("Getting messages for session", { sessionId: this.sessionId });
1204
+ const records = await this.repository.findMessagesBySessionId(this.sessionId);
1205
+ return records.map((record) => record.content);
1311
1206
  }
1312
- /**
1313
- * Current conversation state (delegated to StateMachine)
1314
- */
1315
- get state() {
1316
- return this.stateMachine.state;
1207
+ async fork() {
1208
+ logger4.info("Forking session", { sessionId: this.sessionId });
1209
+ const imageRecord = await this.repository.findImageById(this.imageId);
1210
+ if (!imageRecord) {
1211
+ throw new Error(`Image not found: ${this.imageId}`);
1212
+ }
1213
+ const newImageId = generateImageId();
1214
+ const newImageRecord = {
1215
+ imageId: newImageId,
1216
+ type: "derived",
1217
+ definitionName: imageRecord.definitionName,
1218
+ parentImageId: imageRecord.imageId,
1219
+ definition: imageRecord.definition,
1220
+ config: imageRecord.config,
1221
+ messages: [...imageRecord.messages],
1222
+ // Copy messages
1223
+ createdAt: /* @__PURE__ */ new Date()
1224
+ };
1225
+ await this.repository.saveImage(newImageRecord);
1226
+ const newSessionId = generateSessionId();
1227
+ const now = /* @__PURE__ */ new Date();
1228
+ const newSessionRecord = {
1229
+ sessionId: newSessionId,
1230
+ userId: this.userId,
1231
+ imageId: newImageId,
1232
+ title: this._title ? `Fork of ${this._title}` : null,
1233
+ createdAt: now,
1234
+ updatedAt: now
1235
+ };
1236
+ await this.repository.saveSession(newSessionRecord);
1237
+ logger4.info("Session forked", {
1238
+ originalSessionId: this.sessionId,
1239
+ newSessionId,
1240
+ newImageId
1241
+ });
1242
+ return new _SessionImpl(
1243
+ newSessionRecord,
1244
+ this.repository,
1245
+ this.containerManager,
1246
+ this.defaultContainerId
1247
+ );
1248
+ }
1249
+ async setTitle(title) {
1250
+ logger4.debug("Setting session title", { sessionId: this.sessionId, title });
1251
+ const now = /* @__PURE__ */ new Date();
1252
+ await this.repository.saveSession({
1253
+ sessionId: this.sessionId,
1254
+ userId: this.userId,
1255
+ imageId: this.imageId,
1256
+ title,
1257
+ createdAt: new Date(this.createdAt),
1258
+ updatedAt: now
1259
+ });
1260
+ this._title = title;
1261
+ this._updatedAt = now.getTime();
1262
+ logger4.info("Session title updated", { sessionId: this.sessionId, title });
1263
+ }
1264
+ };
1265
+ var SessionManagerImpl = class {
1266
+ constructor(repository, containerManager, defaultContainerId) {
1267
+ __publicField(this, "repository");
1268
+ __publicField(this, "containerManager");
1269
+ __publicField(this, "defaultContainerId");
1270
+ this.repository = repository;
1271
+ this.containerManager = containerManager;
1272
+ this.defaultContainerId = defaultContainerId;
1273
+ }
1274
+ async create(imageId, userId) {
1275
+ const sessionId = generateSessionId();
1276
+ const now = /* @__PURE__ */ new Date();
1277
+ const record = {
1278
+ sessionId,
1279
+ userId,
1280
+ imageId,
1281
+ title: null,
1282
+ createdAt: now,
1283
+ updatedAt: now
1284
+ };
1285
+ await this.repository.saveSession(record);
1286
+ logger4.info("Session created", { sessionId, imageId, userId });
1287
+ return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
1288
+ }
1289
+ async get(sessionId) {
1290
+ const record = await this.repository.findSessionById(sessionId);
1291
+ if (!record) return void 0;
1292
+ return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
1293
+ }
1294
+ async has(sessionId) {
1295
+ return this.repository.sessionExists(sessionId);
1296
+ }
1297
+ async list() {
1298
+ const records = await this.repository.findAllSessions();
1299
+ return records.map(
1300
+ (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
1301
+ );
1302
+ }
1303
+ async listByImage(imageId) {
1304
+ const records = await this.repository.findSessionsByImageId(imageId);
1305
+ return records.map(
1306
+ (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
1307
+ );
1308
+ }
1309
+ async listByUser(userId) {
1310
+ const records = await this.repository.findSessionsByUserId(userId);
1311
+ return records.map(
1312
+ (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
1313
+ );
1314
+ }
1315
+ async destroy(sessionId) {
1316
+ await this.repository.deleteSession(sessionId);
1317
+ logger4.info("Session destroyed", { sessionId });
1318
+ }
1319
+ async destroyByImage(imageId) {
1320
+ await this.repository.deleteSessionsByImageId(imageId);
1321
+ logger4.info("Sessions destroyed by image", { imageId });
1322
+ }
1323
+ async destroyAll() {
1324
+ const sessions = await this.repository.findAllSessions();
1325
+ for (const session of sessions) {
1326
+ await this.repository.deleteSession(session.sessionId);
1327
+ }
1328
+ logger4.info("All sessions destroyed");
1329
+ }
1330
+ };
1331
+ var logger5 = createLogger("agentx/ErrorManager");
1332
+ var ErrorManager = class {
1333
+ constructor() {
1334
+ __publicField(this, "handlers", /* @__PURE__ */ new Set());
1317
1335
  }
1318
1336
  /**
1319
- * Receive a message from user
1320
- *
1321
- * Runs through middleware chain before actual processing.
1337
+ * Handle an error from any agent
1322
1338
  *
1323
- * Error Handling:
1324
- * - Errors are caught and converted to ErrorMessageEvent
1325
- * - Handlers receive the error event before re-throwing
1326
- * - This ensures UI can display errors
1339
+ * Called internally when an agent emits an error event.
1340
+ * 1. Default logging (always)
1341
+ * 2. Custom handlers (user-registered)
1327
1342
  */
1328
- async receive(message) {
1329
- if (this._lifecycle === "destroyed") {
1330
- logger4$1.warn("Receive called on destroyed agent", { agentId: this.agentId });
1331
- const error = this.errorClassifier.create(
1332
- "system",
1333
- "AGENT_DESTROYED",
1334
- "Agent has been destroyed",
1335
- false
1336
- );
1337
- const errorEvent = this.errorClassifier.createEvent(error);
1338
- this.notifyHandlers(errorEvent);
1339
- throw new Error("[Agent] Agent has been destroyed");
1340
- }
1341
- if (this.state !== "idle") {
1342
- logger4$1.warn("Receive called while agent is busy", {
1343
- agentId: this.agentId,
1344
- currentState: this.state
1345
- });
1346
- const error = this.errorClassifier.create(
1347
- "system",
1348
- "AGENT_BUSY",
1349
- `Agent is busy (state: ${this.state}), please wait for current operation to complete`,
1350
- false
1351
- );
1352
- const errorEvent = this.errorClassifier.createEvent(error);
1353
- this.notifyHandlers(errorEvent);
1354
- throw new Error(`[Agent] Agent is busy (state: ${this.state})`);
1343
+ handle(agentId, error, event) {
1344
+ this.logError(agentId, error);
1345
+ for (const handler of this.handlers) {
1346
+ try {
1347
+ handler.handle(agentId, error, event);
1348
+ } catch (e) {
1349
+ logger5.error("ErrorHandler failed", { error: e });
1350
+ }
1355
1351
  }
1356
- const userMessage = typeof message === "string" ? {
1357
- id: `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1358
- role: "user",
1359
- subtype: "user",
1360
- content: message,
1361
- timestamp: Date.now()
1362
- } : message;
1363
- logger4$1.debug("Receiving message", {
1364
- agentId: this.agentId,
1365
- messageId: userMessage.id
1366
- });
1367
- const userMessageEvent = {
1368
- uuid: `evt_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1369
- type: "user_message",
1370
- agentId: this.agentId,
1371
- timestamp: Date.now(),
1372
- data: userMessage
1352
+ }
1353
+ /**
1354
+ * Add a custom error handler
1355
+ */
1356
+ addHandler(handler) {
1357
+ this.handlers.add(handler);
1358
+ return () => {
1359
+ this.handlers.delete(handler);
1373
1360
  };
1374
- this.presentOutput(userMessageEvent);
1375
- this.notifyHandlers(userMessageEvent);
1376
- await this.executeMiddlewareChain(userMessage);
1377
1361
  }
1378
1362
  /**
1379
- * Execute middleware chain and then process the message
1363
+ * Remove an error handler
1380
1364
  */
1381
- async executeMiddlewareChain(message) {
1382
- await this.middlewareChain.execute(message, (msg) => this.doReceive(msg));
1365
+ removeHandler(handler) {
1366
+ this.handlers.delete(handler);
1383
1367
  }
1384
1368
  /**
1385
- * Process a single stream event through the engine
1386
- *
1387
- * Used by:
1388
- * - doReceive() - normal message flow
1389
- * - AgentInterrupter - interrupt event injection
1390
- *
1391
- * @param streamEvent - Stream event to process
1369
+ * Default error logging
1392
1370
  */
1393
- processStreamEvent(streamEvent) {
1394
- const outputs = this.engine.process(this.agentId, streamEvent);
1395
- for (const output of outputs) {
1396
- this.presentOutput(output);
1397
- }
1398
- for (const output of outputs) {
1399
- this.notifyHandlers(output);
1371
+ logError(agentId, error) {
1372
+ const prefix = `[${agentId}] ${error.category}/${error.code}`;
1373
+ if (error.severity === "fatal") {
1374
+ logger5.error(`${prefix}: ${error.message}`, { error });
1375
+ } else if (error.severity === "error") {
1376
+ logger5.error(`${prefix}: ${error.message}`);
1377
+ } else {
1378
+ logger5.warn(`${prefix}: ${error.message}`);
1400
1379
  }
1401
1380
  }
1381
+ };
1382
+ var logger6 = createLogger("core/AgentStateMachine");
1383
+ var AgentStateMachine = class {
1384
+ constructor() {
1385
+ __publicField(this, "_state", "idle");
1386
+ __publicField(this, "handlers", /* @__PURE__ */ new Set());
1387
+ }
1402
1388
  /**
1403
- * Actual message processing logic
1389
+ * Current agent state
1390
+ */
1391
+ get state() {
1392
+ return this._state;
1393
+ }
1394
+ /**
1395
+ * Process a StateEvent and update internal state
1404
1396
  *
1405
- * Coordinates the flow:
1406
- * 1. Driver receives message → produces StreamEvents
1407
- * 2. Engine processes events → produces outputs
1408
- * 3. Presenters handle outputs
1409
- * 4. Handlers receive outputs
1397
+ * @param event - StateEvent from Engine layer
1410
1398
  */
1411
- async doReceive(userMessage) {
1412
- try {
1413
- logger4$1.debug("Processing message through driver", {
1414
- agentId: this.agentId,
1415
- messageId: userMessage.id
1416
- });
1417
- const queuedEvent = {
1418
- type: "conversation_queued",
1419
- uuid: `${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1420
- agentId: this.agentId,
1421
- timestamp: Date.now(),
1422
- data: {
1423
- userMessage
1424
- }
1425
- };
1426
- this.notifyHandlers(queuedEvent);
1427
- const streamEvents = this.driver.receive(userMessage);
1428
- for await (const streamEvent of streamEvents) {
1429
- this.processStreamEvent(streamEvent);
1430
- }
1431
- logger4$1.debug("Message processing completed", {
1432
- agentId: this.agentId,
1433
- messageId: userMessage.id
1434
- });
1435
- } catch (error) {
1436
- const agentError = this.errorClassifier.classify(error);
1437
- const errorEvent = this.errorClassifier.createEvent(agentError);
1438
- logger4$1.error("Message processing failed", {
1439
- agentId: this.agentId,
1440
- messageId: userMessage.id,
1441
- errorCategory: agentError.category,
1442
- errorCode: agentError.code,
1443
- error
1399
+ process(event) {
1400
+ const prev = this._state;
1401
+ const next = this.mapEventToState(event);
1402
+ if (next !== null && prev !== next) {
1403
+ this._state = next;
1404
+ logger6.debug("State transition", {
1405
+ eventType: event.type,
1406
+ from: prev,
1407
+ to: next
1444
1408
  });
1445
- this.notifyHandlers(errorEvent);
1446
- throw error;
1447
- }
1448
- }
1449
- /**
1450
- * Send output to all presenters
1451
- *
1452
- * Note: Presenters are no longer part of AgentDefinition.
1453
- * This is a placeholder for future presenter injection via Runtime or middleware.
1454
- */
1455
- presentOutput(_output) {
1456
- }
1457
- on(typeOrHandlerOrMap, handler) {
1458
- if (typeof typeOrHandlerOrMap === "function") {
1459
- return this.eventBus.onAny(typeOrHandlerOrMap);
1460
- }
1461
- if (this.isEventHandlerMap(typeOrHandlerOrMap)) {
1462
- const unsubscribes = [];
1463
- for (const [eventType, eventHandler] of Object.entries(typeOrHandlerOrMap)) {
1464
- if (eventHandler) {
1465
- unsubscribes.push(this.eventBus.on(eventType, eventHandler));
1466
- }
1467
- }
1468
- return () => {
1469
- for (const unsub of unsubscribes) {
1470
- unsub();
1471
- }
1472
- };
1473
- }
1474
- const types = Array.isArray(typeOrHandlerOrMap) ? typeOrHandlerOrMap : [typeOrHandlerOrMap];
1475
- const h = handler;
1476
- return this.eventBus.on(types, h);
1477
- }
1478
- /**
1479
- * Check if the argument is an EventHandlerMap (object with event type keys)
1480
- */
1481
- isEventHandlerMap(arg) {
1482
- if (typeof arg !== "object" || arg === null || Array.isArray(arg)) {
1483
- return false;
1484
- }
1485
- const keys = Object.keys(arg);
1486
- if (keys.length === 0) {
1487
- return false;
1409
+ this.notifyHandlers({ prev, current: next });
1488
1410
  }
1489
- return keys.every((key) => {
1490
- const value = arg[key];
1491
- return value === void 0 || typeof value === "function";
1492
- });
1493
1411
  }
1494
1412
  /**
1495
- * Subscribe to state changes (delegated to StateMachine)
1413
+ * Subscribe to state changes
1496
1414
  *
1497
1415
  * @param handler - Callback receiving { prev, current } state change
1498
1416
  * @returns Unsubscribe function
1499
1417
  */
1500
1418
  onStateChange(handler) {
1501
- return this.stateMachine.onStateChange(handler);
1502
- }
1503
- /**
1504
- * React-style fluent event subscription
1505
- *
1506
- * Converts onXxx handlers to event type keys and delegates to on(handlers)
1507
- */
1508
- react(handlers) {
1509
- const eventHandlerMap = mapReactHandlers(handlers);
1510
- return this.on(eventHandlerMap);
1511
- }
1512
- /**
1513
- * Subscribe to agent ready event
1514
- *
1515
- * If already running, handler is called immediately.
1516
- */
1517
- onReady(handler) {
1518
- if (this._lifecycle === "running") {
1519
- try {
1520
- handler();
1521
- } catch (error) {
1522
- logger4$1.error("onReady handler error", {
1523
- agentId: this.agentId,
1524
- error
1525
- });
1526
- }
1527
- }
1528
- this.readyHandlers.add(handler);
1529
- return () => {
1530
- this.readyHandlers.delete(handler);
1531
- };
1532
- }
1533
- /**
1534
- * Subscribe to agent destroy event
1535
- */
1536
- onDestroy(handler) {
1537
- this.destroyHandlers.add(handler);
1419
+ this.handlers.add(handler);
1538
1420
  return () => {
1539
- this.destroyHandlers.delete(handler);
1421
+ this.handlers.delete(handler);
1540
1422
  };
1541
1423
  }
1542
1424
  /**
1543
- * Add middleware to intercept incoming messages
1544
- */
1545
- use(middleware) {
1546
- return this.middlewareChain.use(middleware);
1547
- }
1548
- /**
1549
- * Add interceptor to intercept outgoing events
1425
+ * Reset state machine (used on destroy)
1550
1426
  */
1551
- intercept(interceptor) {
1552
- return this.interceptorChain.intercept(interceptor);
1427
+ reset() {
1428
+ this._state;
1429
+ this._state = "idle";
1430
+ this.handlers.clear();
1553
1431
  }
1554
1432
  /**
1555
- * Interrupt - User-initiated stop
1433
+ * Map StateEvent type to AgentState
1556
1434
  *
1557
- * Stops the current operation gracefully.
1558
- * Flow:
1559
- * 1. Call driver.interrupt() to abort active requests
1560
- * 2. Driver yields InterruptedStreamEvent
1561
- * 3. Event flows through engine pipeline
1562
- * 4. StateEventProcessor generates conversation_interrupted
1563
- * 5. StateMachine transitions to idle state
1564
- * 6. UI receives state change notification
1435
+ * @param event - StateEvent from Engine
1436
+ * @returns New AgentState or null if no transition needed
1565
1437
  */
1566
- interrupt() {
1567
- logger4$1.debug("User interrupt requested", { agentId: this.agentId, currentState: this.state });
1568
- this.driver.interrupt();
1438
+ mapEventToState(event) {
1439
+ switch (event.type) {
1440
+ // Agent lifecycle
1441
+ case "agent_initializing":
1442
+ return "initializing";
1443
+ case "agent_ready":
1444
+ return "idle";
1445
+ case "agent_destroyed":
1446
+ return "idle";
1447
+ // Conversation lifecycle
1448
+ case "conversation_queued":
1449
+ return "queued";
1450
+ case "conversation_start":
1451
+ return "conversation_active";
1452
+ case "conversation_thinking":
1453
+ return "thinking";
1454
+ case "conversation_responding":
1455
+ return "responding";
1456
+ case "conversation_end":
1457
+ return "idle";
1458
+ case "conversation_interrupted":
1459
+ return "idle";
1460
+ // Return to idle on interrupt
1461
+ // Tool lifecycle
1462
+ case "tool_planned":
1463
+ return "planning_tool";
1464
+ case "tool_executing":
1465
+ return "awaiting_tool_result";
1466
+ case "tool_completed":
1467
+ return "responding";
1468
+ // Back to responding after tool completes
1469
+ case "tool_failed":
1470
+ return "responding";
1471
+ // Continue responding after tool failure
1472
+ // Error
1473
+ case "error_occurred":
1474
+ return "idle";
1475
+ // Reset to idle on error
1476
+ default:
1477
+ return null;
1478
+ }
1569
1479
  }
1570
1480
  /**
1571
- * Destroy - Clean up resources
1481
+ * Notify all registered handlers of state change
1572
1482
  */
1573
- async destroy() {
1574
- logger4$1.debug("Destroying agent", { agentId: this.agentId });
1575
- for (const handler of this.destroyHandlers) {
1483
+ notifyHandlers(change) {
1484
+ for (const handler of this.handlers) {
1576
1485
  try {
1577
- handler();
1486
+ handler(change);
1578
1487
  } catch (error) {
1579
- logger4$1.error("onDestroy handler error", {
1580
- agentId: this.agentId,
1488
+ logger6.error("State change handler error", {
1489
+ from: change.prev,
1490
+ to: change.current,
1581
1491
  error
1582
1492
  });
1583
1493
  }
1584
1494
  }
1585
- this._lifecycle = "destroyed";
1586
- this.stateMachine.reset();
1587
- this.eventBus.destroy();
1588
- this.readyHandlers.clear();
1589
- this.destroyHandlers.clear();
1590
- this.middlewareChain.clear();
1591
- this.interceptorChain.clear();
1592
- this.engine.clearState(this.agentId);
1593
- logger4$1.info("Agent destroyed", { agentId: this.agentId });
1594
- }
1595
- /**
1596
- * Notify all registered handlers
1597
- *
1598
- * Flow:
1599
- * 1. StateMachine processes StateEvents (for state transitions)
1600
- * 2. Interceptor chain can modify/filter events
1601
- * 3. EventBus emits to all subscribers
1602
- */
1603
- notifyHandlers(event) {
1604
- if (isStateEvent(event)) {
1605
- this.stateMachine.process(event);
1606
- }
1607
- this.executeInterceptorChain(event);
1608
- }
1609
- /**
1610
- * Execute interceptor chain and then emit to EventBus
1611
- */
1612
- executeInterceptorChain(event) {
1613
- this.interceptorChain.execute(event, (e) => this.eventBus.emit(e));
1614
- }
1615
- /**
1616
- * Get the event consumer for external subscriptions
1617
- *
1618
- * Use this to expose event subscription without emit capability.
1619
- */
1620
- getEventConsumer() {
1621
- return this.eventBus.asConsumer();
1622
1495
  }
1623
1496
  };
1624
- var MemoryStore = class {
1497
+ var logger22 = createLogger("core/AgentEventBus");
1498
+ var AgentEventBus = class {
1625
1499
  constructor() {
1626
- __publicField(this, "states", /* @__PURE__ */ new Map());
1627
- }
1628
- get(id) {
1629
- return this.states.get(id);
1500
+ __publicField(this, "subject", new Subject());
1501
+ __publicField(this, "typeSubscriptions", /* @__PURE__ */ new Map());
1502
+ __publicField(this, "globalSubscriptions", []);
1503
+ __publicField(this, "nextId", 0);
1504
+ __publicField(this, "isDestroyed", false);
1505
+ __publicField(this, "producerView", null);
1506
+ __publicField(this, "consumerView", null);
1630
1507
  }
1631
- set(id, state) {
1632
- this.states.set(id, state);
1508
+ // ===== Producer Methods =====
1509
+ emit(event) {
1510
+ if (this.isDestroyed) {
1511
+ logger22.warn("Emit called on destroyed EventBus", { eventType: event.type });
1512
+ return;
1513
+ }
1514
+ this.subject.next(event);
1633
1515
  }
1634
- delete(id) {
1635
- this.states.delete(id);
1516
+ emitBatch(events) {
1517
+ for (const event of events) {
1518
+ this.emit(event);
1519
+ }
1636
1520
  }
1637
- has(id) {
1638
- return this.states.has(id);
1521
+ on(typeOrTypes, handler, options = {}) {
1522
+ if (this.isDestroyed) {
1523
+ logger22.warn("Subscribe called on destroyed EventBus");
1524
+ return () => {
1525
+ };
1526
+ }
1527
+ const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes];
1528
+ const unsubscribes = [];
1529
+ for (const type of types) {
1530
+ const unsub = this.subscribeToType(type, handler, options);
1531
+ unsubscribes.push(unsub);
1532
+ }
1533
+ return () => unsubscribes.forEach((u) => u());
1639
1534
  }
1640
- /**
1641
- * Clear all stored states
1642
- */
1643
- clear() {
1644
- this.states.clear();
1535
+ onAny(handler, options = {}) {
1536
+ if (this.isDestroyed) {
1537
+ logger22.warn("Subscribe called on destroyed EventBus");
1538
+ return () => {
1539
+ };
1540
+ }
1541
+ return this.subscribeGlobal(handler, options);
1542
+ }
1543
+ once(type, handler) {
1544
+ return this.on(type, handler, { once: true });
1545
+ }
1546
+ // ===== View Methods =====
1547
+ asConsumer() {
1548
+ if (!this.consumerView) {
1549
+ this.consumerView = {
1550
+ on: this.on.bind(this),
1551
+ onAny: this.onAny.bind(this),
1552
+ once: this.once.bind(this)
1553
+ };
1554
+ }
1555
+ return this.consumerView;
1556
+ }
1557
+ asProducer() {
1558
+ if (!this.producerView) {
1559
+ this.producerView = {
1560
+ emit: this.emit.bind(this),
1561
+ emitBatch: this.emitBatch.bind(this)
1562
+ };
1563
+ }
1564
+ return this.producerView;
1565
+ }
1566
+ // ===== Lifecycle =====
1567
+ destroy() {
1568
+ if (this.isDestroyed) return;
1569
+ this.isDestroyed = true;
1570
+ for (const records of this.typeSubscriptions.values()) {
1571
+ for (const record of records) {
1572
+ record.unsubscribe();
1573
+ }
1574
+ }
1575
+ this.typeSubscriptions.clear();
1576
+ for (const record of this.globalSubscriptions) {
1577
+ record.unsubscribe();
1578
+ }
1579
+ this.globalSubscriptions.length = 0;
1580
+ this.subject.complete();
1581
+ logger22.debug("EventBus destroyed");
1582
+ }
1583
+ // ===== Private Methods =====
1584
+ subscribeToType(type, handler, options) {
1585
+ const { filter: filter$1, priority = 0, once = false } = options;
1586
+ const id = this.nextId++;
1587
+ let observable2 = this.subject.pipe(filter((e) => e.type === type));
1588
+ if (filter$1) {
1589
+ observable2 = observable2.pipe(filter(filter$1));
1590
+ }
1591
+ if (once) {
1592
+ observable2 = observable2.pipe(take(1));
1593
+ }
1594
+ const subscription = observable2.subscribe({
1595
+ next: (event) => {
1596
+ this.executeWithPriority(type, event, handler, id);
1597
+ }
1598
+ });
1599
+ const unsubscribe = () => {
1600
+ subscription.unsubscribe();
1601
+ const records2 = this.typeSubscriptions.get(type);
1602
+ if (records2) {
1603
+ const idx = records2.findIndex((r) => r.id === id);
1604
+ if (idx !== -1) records2.splice(idx, 1);
1605
+ }
1606
+ };
1607
+ if (!this.typeSubscriptions.has(type)) {
1608
+ this.typeSubscriptions.set(type, []);
1609
+ }
1610
+ const record = { id, priority, handler, unsubscribe };
1611
+ const records = this.typeSubscriptions.get(type);
1612
+ records.push(record);
1613
+ records.sort((a, b) => b.priority - a.priority);
1614
+ return unsubscribe;
1615
+ }
1616
+ subscribeGlobal(handler, options) {
1617
+ const { filter: filter$1, priority = 0, once = false } = options;
1618
+ const id = this.nextId++;
1619
+ let observable2 = this.subject.asObservable();
1620
+ if (filter$1) {
1621
+ observable2 = observable2.pipe(filter(filter$1));
1622
+ }
1623
+ if (once) {
1624
+ observable2 = observable2.pipe(take(1));
1625
+ }
1626
+ const subscription = observable2.subscribe({
1627
+ next: (event) => {
1628
+ this.executeGlobalWithPriority(event, handler, id);
1629
+ }
1630
+ });
1631
+ const unsubscribe = () => {
1632
+ subscription.unsubscribe();
1633
+ const idx = this.globalSubscriptions.findIndex((r) => r.id === id);
1634
+ if (idx !== -1) this.globalSubscriptions.splice(idx, 1);
1635
+ };
1636
+ const record = { id, priority, handler, unsubscribe };
1637
+ this.globalSubscriptions.push(record);
1638
+ this.globalSubscriptions.sort((a, b) => b.priority - a.priority);
1639
+ return unsubscribe;
1645
1640
  }
1646
1641
  /**
1647
- * Get the number of stored states
1642
+ * Execute handler respecting priority order for typed subscriptions
1648
1643
  */
1649
- get size() {
1650
- return this.states.size;
1644
+ executeWithPriority(type, event, handler, handlerId) {
1645
+ const records = this.typeSubscriptions.get(type) || [];
1646
+ const record = records.find((r) => r.id === handlerId);
1647
+ if (record) {
1648
+ try {
1649
+ handler(event);
1650
+ } catch (error) {
1651
+ logger22.error("Event handler error", { eventType: type, error });
1652
+ }
1653
+ }
1651
1654
  }
1652
1655
  /**
1653
- * Get all stored IDs
1656
+ * Execute handler respecting priority order for global subscriptions
1654
1657
  */
1655
- keys() {
1656
- return this.states.keys();
1658
+ executeGlobalWithPriority(event, handler, handlerId) {
1659
+ const record = this.globalSubscriptions.find((r) => r.id === handlerId);
1660
+ if (record) {
1661
+ try {
1662
+ handler(event);
1663
+ } catch (error) {
1664
+ logger22.error("Global event handler error", { eventType: event.type, error });
1665
+ }
1666
+ }
1657
1667
  }
1658
1668
  };
1659
- createLogger("engine/Mealy");
1660
- function combineProcessors(processors) {
1661
- return (state, event) => {
1662
- const newState = {};
1663
- const allOutputs = [];
1664
- for (const key in processors) {
1665
- const processor = processors[key];
1666
- const subState = state[key];
1667
- const [newSubState, outputs] = processor(subState, event);
1668
- newState[key] = newSubState;
1669
- allOutputs.push(...outputs);
1669
+ var AgentErrorClassifier = class {
1670
+ constructor(agentId) {
1671
+ this.agentId = agentId;
1672
+ }
1673
+ /**
1674
+ * Classify an unknown error into an AgentError
1675
+ */
1676
+ classify(error) {
1677
+ const err = error instanceof Error ? error : new Error(String(error));
1678
+ const message = err.message;
1679
+ if (message.includes("rate limit") || message.includes("429")) {
1680
+ return this.create("llm", "RATE_LIMITED", message, true, err);
1670
1681
  }
1671
- return [newState, allOutputs];
1672
- };
1673
- }
1674
- function combineInitialStates(initialStates) {
1675
- return () => {
1676
- const state = {};
1677
- for (const key in initialStates) {
1678
- state[key] = initialStates[key]();
1682
+ if (message.includes("api key") || message.includes("401") || message.includes("unauthorized")) {
1683
+ return this.create("llm", "INVALID_API_KEY", message, false, err);
1679
1684
  }
1680
- return state;
1681
- };
1682
- }
1683
- function createInitialMessageAssemblerState() {
1684
- return {
1685
- currentMessageId: null,
1686
- messageStartTime: null,
1687
- pendingContents: {},
1688
- pendingToolCalls: {}
1689
- };
1690
- }
1691
- function generateId() {
1692
- return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1693
- }
1694
- var messageAssemblerProcessor = (state, input) => {
1695
- switch (input.type) {
1696
- case "message_start":
1697
- return handleMessageStart(state, input);
1698
- case "text_delta":
1699
- return handleTextDelta(state, input);
1700
- case "tool_use_content_block_start":
1701
- return handleToolUseContentBlockStart(state, input);
1702
- case "input_json_delta":
1703
- return handleInputJsonDelta(state, input);
1704
- case "tool_use_content_block_stop":
1705
- return handleToolUseContentBlockStop(state, input);
1706
- case "tool_result":
1707
- return handleToolResult(state, input);
1708
- case "message_stop":
1709
- return handleMessageStop(state, input);
1710
- default:
1711
- return [state, []];
1685
+ if (message.includes("context") && message.includes("long")) {
1686
+ return this.create("llm", "CONTEXT_TOO_LONG", message, true, err);
1687
+ }
1688
+ if (message.includes("overloaded") || message.includes("503")) {
1689
+ return this.create("llm", "OVERLOADED", message, true, err);
1690
+ }
1691
+ if (message.includes("timeout") || message.includes("ETIMEDOUT")) {
1692
+ return this.create("network", "TIMEOUT", message, true, err);
1693
+ }
1694
+ if (message.includes("ECONNREFUSED") || message.includes("connection")) {
1695
+ return this.create("network", "CONNECTION_FAILED", message, true, err);
1696
+ }
1697
+ if (message.includes("network") || message.includes("fetch")) {
1698
+ return this.create("network", "CONNECTION_FAILED", message, true, err);
1699
+ }
1700
+ if (message.includes("driver")) {
1701
+ return this.create("driver", "RECEIVE_FAILED", message, true, err);
1702
+ }
1703
+ return this.create("system", "UNKNOWN", message, true, err);
1712
1704
  }
1713
- };
1714
- function handleMessageStart(state, event) {
1715
- return [
1716
- {
1717
- ...state,
1718
- currentMessageId: generateId(),
1719
- messageStartTime: event.timestamp,
1720
- pendingContents: {}
1721
- },
1722
- []
1723
- ];
1724
- }
1725
- function handleTextDelta(state, event) {
1726
- const index = 0;
1727
- const existingContent = state.pendingContents[index];
1728
- const pendingContent = (existingContent == null ? void 0 : existingContent.type) === "text" ? {
1729
- ...existingContent,
1730
- textDeltas: [...existingContent.textDeltas || [], event.data.text]
1731
- } : {
1732
- type: "text",
1733
- index,
1734
- textDeltas: [event.data.text]
1735
- };
1736
- return [
1737
- {
1738
- ...state,
1739
- pendingContents: {
1740
- ...state.pendingContents,
1741
- [index]: pendingContent
1742
- }
1743
- },
1744
- []
1745
- ];
1746
- }
1747
- function handleToolUseContentBlockStart(state, event) {
1748
- const index = 1;
1749
- const pendingContent = {
1750
- type: "tool_use",
1751
- index,
1752
- toolId: event.data.id,
1753
- toolName: event.data.name,
1754
- toolInputJson: ""
1755
- };
1756
- return [
1757
- {
1758
- ...state,
1759
- pendingContents: {
1760
- ...state.pendingContents,
1761
- [index]: pendingContent
1762
- }
1763
- },
1764
- []
1765
- ];
1766
- }
1767
- function handleInputJsonDelta(state, event) {
1768
- const index = 1;
1769
- const existingContent = state.pendingContents[index];
1770
- if (!existingContent || existingContent.type !== "tool_use") {
1771
- return [state, []];
1705
+ /**
1706
+ * Create an AgentError with the specified category and code
1707
+ */
1708
+ create(category, code, message, recoverable, cause) {
1709
+ return {
1710
+ category,
1711
+ code,
1712
+ message,
1713
+ severity: recoverable ? "error" : "fatal",
1714
+ recoverable,
1715
+ cause
1716
+ };
1772
1717
  }
1773
- const pendingContent = {
1774
- ...existingContent,
1775
- toolInputJson: (existingContent.toolInputJson || "") + event.data.partialJson
1776
- };
1777
- return [
1778
- {
1779
- ...state,
1780
- pendingContents: {
1781
- ...state.pendingContents,
1782
- [index]: pendingContent
1718
+ /**
1719
+ * Create an ErrorEvent from an AgentError
1720
+ *
1721
+ * ErrorEvent is independent from Message layer and transportable via SSE.
1722
+ */
1723
+ createEvent(error) {
1724
+ return {
1725
+ type: "error",
1726
+ uuid: `${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1727
+ agentId: this.agentId,
1728
+ timestamp: Date.now(),
1729
+ data: {
1730
+ error
1783
1731
  }
1784
- },
1785
- []
1786
- ];
1787
- }
1788
- function handleToolUseContentBlockStop(state, event) {
1789
- const index = 1;
1790
- const pendingContent = state.pendingContents[index];
1791
- if (!pendingContent || pendingContent.type !== "tool_use") {
1792
- return [state, []];
1732
+ };
1793
1733
  }
1794
- let toolInput = {};
1795
- try {
1796
- toolInput = pendingContent.toolInputJson ? JSON.parse(pendingContent.toolInputJson) : {};
1797
- } catch {
1798
- toolInput = {};
1734
+ };
1735
+ var MiddlewareChain = class {
1736
+ constructor() {
1737
+ __publicField(this, "middlewares", []);
1799
1738
  }
1800
- const outputs = [];
1801
- const toolId = pendingContent.toolId;
1802
- const toolName = pendingContent.toolName;
1803
- const toolCallEvent = {
1804
- type: "tool_call",
1805
- uuid: generateId(),
1806
- agentId: event.agentId,
1807
- timestamp: Date.now(),
1808
- data: {
1809
- id: toolId,
1810
- name: toolName,
1811
- input: toolInput
1812
- }
1813
- };
1814
- outputs.push(toolCallEvent);
1815
- const toolCall = {
1816
- type: "tool-call",
1817
- id: toolId,
1818
- name: toolName,
1819
- input: toolInput
1820
- };
1821
- const toolCallMessage = {
1822
- id: generateId(),
1823
- role: "assistant",
1824
- subtype: "tool-call",
1825
- toolCall,
1826
- timestamp: Date.now()
1827
- };
1828
- const toolCallMessageEvent = {
1829
- type: "tool_call_message",
1830
- uuid: generateId(),
1831
- agentId: event.agentId,
1832
- timestamp: Date.now(),
1833
- data: toolCallMessage
1834
- };
1835
- outputs.push(toolCallMessageEvent);
1836
- const { [index]: _, ...remainingContents } = state.pendingContents;
1837
- return [
1838
- {
1839
- ...state,
1840
- pendingContents: remainingContents,
1841
- pendingToolCalls: {
1842
- ...state.pendingToolCalls,
1843
- [toolId]: { id: toolId, name: toolName }
1739
+ /**
1740
+ * Add middleware to the chain
1741
+ *
1742
+ * @param middleware - Middleware function
1743
+ * @returns Unsubscribe function to remove the middleware
1744
+ */
1745
+ use(middleware) {
1746
+ this.middlewares.push(middleware);
1747
+ return () => {
1748
+ const index = this.middlewares.indexOf(middleware);
1749
+ if (index !== -1) {
1750
+ this.middlewares.splice(index, 1);
1844
1751
  }
1845
- },
1846
- outputs
1847
- ];
1848
- }
1849
- function handleToolResult(state, event) {
1850
- const { toolId, content, isError } = event.data;
1851
- const pendingToolCall = state.pendingToolCalls[toolId];
1852
- const toolName = (pendingToolCall == null ? void 0 : pendingToolCall.name) || "unknown";
1853
- const toolResult = {
1854
- type: "tool-result",
1855
- id: toolId,
1856
- name: toolName,
1857
- output: {
1858
- type: isError ? "error-text" : "text",
1859
- value: typeof content === "string" ? content : JSON.stringify(content)
1860
- }
1861
- };
1862
- const toolResultMessage = {
1863
- id: generateId(),
1864
- role: "tool",
1865
- subtype: "tool-result",
1866
- toolResult,
1867
- toolCallId: toolId,
1868
- timestamp: Date.now()
1869
- };
1870
- const toolResultMessageEvent = {
1871
- type: "tool_result_message",
1872
- uuid: generateId(),
1873
- agentId: event.agentId,
1874
- timestamp: Date.now(),
1875
- data: toolResultMessage
1876
- };
1877
- const { [toolId]: _, ...remainingToolCalls } = state.pendingToolCalls;
1878
- return [
1879
- {
1880
- ...state,
1881
- pendingToolCalls: remainingToolCalls
1882
- },
1883
- [toolResultMessageEvent]
1884
- ];
1885
- }
1886
- function handleMessageStop(state, event) {
1887
- if (!state.currentMessageId) {
1888
- return [state, []];
1752
+ };
1889
1753
  }
1890
- const textParts = [];
1891
- const sortedContents = Object.values(state.pendingContents).sort((a, b) => a.index - b.index);
1892
- for (const pending of sortedContents) {
1893
- if (pending.type === "text" && pending.textDeltas) {
1894
- textParts.push(pending.textDeltas.join(""));
1895
- }
1754
+ /**
1755
+ * Execute the middleware chain
1756
+ *
1757
+ * @param message - User message to process
1758
+ * @param finalHandler - Handler called at the end of the chain
1759
+ */
1760
+ async execute(message, finalHandler) {
1761
+ let index = 0;
1762
+ const next = async (msg) => {
1763
+ if (index < this.middlewares.length) {
1764
+ const middleware = this.middlewares[index++];
1765
+ await middleware(msg, next);
1766
+ } else {
1767
+ await finalHandler(msg);
1768
+ }
1769
+ };
1770
+ await next(message);
1896
1771
  }
1897
- const content = textParts.join("");
1898
- const stopReason = event.data.stopReason;
1899
- if (!content || content.trim().length === 0) {
1900
- const shouldPreserveToolCalls2 = stopReason === "tool_use";
1901
- return [
1902
- {
1903
- ...createInitialMessageAssemblerState(),
1904
- pendingToolCalls: shouldPreserveToolCalls2 ? state.pendingToolCalls : {}
1905
- },
1906
- []
1907
- ];
1772
+ /**
1773
+ * Clear all middlewares
1774
+ */
1775
+ clear() {
1776
+ this.middlewares.length = 0;
1908
1777
  }
1909
- const assistantMessage = {
1910
- id: state.currentMessageId,
1911
- role: "assistant",
1912
- subtype: "assistant",
1913
- content,
1914
- timestamp: state.messageStartTime || Date.now(),
1915
- // Usage data is not available in message_stop event
1916
- // It would need to be tracked separately if needed
1917
- usage: void 0
1918
- };
1919
- const assistantEvent = {
1920
- type: "assistant_message",
1921
- uuid: generateId(),
1922
- agentId: event.agentId,
1923
- timestamp: Date.now(),
1924
- data: assistantMessage
1925
- };
1926
- const shouldPreserveToolCalls = stopReason === "tool_use";
1927
- return [
1928
- {
1929
- ...createInitialMessageAssemblerState(),
1930
- pendingToolCalls: shouldPreserveToolCalls ? state.pendingToolCalls : {}
1931
- },
1932
- [assistantEvent]
1933
- ];
1934
- }
1935
- var logger2$1 = createLogger("engine/stateEventProcessor");
1936
- function createInitialStateEventProcessorContext() {
1937
- return {};
1938
- }
1939
- function generateId2() {
1940
- return `state_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1941
- }
1942
- var stateEventProcessor = (context, input) => {
1943
- logger2$1.debug(`[Stream Event] ${input.type}`, {
1944
- context,
1945
- eventData: "data" in input ? input.data : void 0
1946
- });
1947
- switch (input.type) {
1948
- case "message_start":
1949
- return handleMessageStart2(context, input);
1950
- case "message_delta":
1951
- return handleMessageDelta(context);
1952
- case "message_stop":
1953
- return handleMessageStop2(context, input);
1954
- case "text_content_block_start":
1955
- return handleTextContentBlockStart(context, input);
1956
- case "tool_use_content_block_start":
1957
- return handleToolUseContentBlockStart2(context, input);
1958
- case "tool_use_content_block_stop":
1959
- return handleToolUseContentBlockStop2(context);
1960
- case "tool_call":
1961
- return handleToolCall(context);
1962
- case "interrupted":
1963
- return handleInterrupted(context, input);
1964
- default:
1965
- logger2$1.debug(`[Stream Event] ${input.type} (unhandled)`);
1966
- return [context, []];
1778
+ /**
1779
+ * Get the number of middlewares
1780
+ */
1781
+ get size() {
1782
+ return this.middlewares.length;
1967
1783
  }
1968
1784
  };
1969
- function handleMessageStart2(context, event) {
1970
- const conversationStartEvent = {
1971
- type: "conversation_start",
1972
- uuid: generateId2(),
1973
- agentId: event.agentId,
1974
- timestamp: event.timestamp,
1975
- transition: {
1976
- reason: "conversation_started",
1977
- trigger: "message_start"
1978
- },
1979
- data: {
1980
- userMessage: {}
1981
- // Will be populated by higher-level component
1982
- }
1983
- };
1984
- return [context, [conversationStartEvent]];
1985
- }
1986
- function handleMessageDelta(context, _event) {
1987
- return [context, []];
1988
- }
1989
- function handleMessageStop2(context, event) {
1990
- const stopReason = event.data.stopReason;
1991
- logger2$1.debug("message_stop received", { stopReason });
1992
- if (stopReason === "tool_use") {
1993
- logger2$1.debug("Skipping conversation_end (tool_use in progress)");
1994
- return [context, []];
1785
+ var logger32 = createLogger("core/InterceptorChain");
1786
+ var InterceptorChain = class {
1787
+ constructor(agentId) {
1788
+ __publicField(this, "interceptors", []);
1789
+ __publicField(this, "agentId");
1790
+ this.agentId = agentId;
1995
1791
  }
1996
- const conversationEndEvent = {
1997
- type: "conversation_end",
1998
- uuid: generateId2(),
1999
- agentId: event.agentId,
2000
- timestamp: event.timestamp,
2001
- transition: {
2002
- reason: "conversation_completed",
2003
- trigger: "message_stop"
2004
- },
2005
- data: {
2006
- assistantMessage: {},
2007
- // Will be populated by higher-level component
2008
- durationMs: 0,
2009
- // Will be calculated by StateMachine or TurnTracker
2010
- durationApiMs: 0,
2011
- numTurns: 0,
2012
- result: "completed",
2013
- totalCostUsd: 0,
2014
- usage: {
2015
- input: 0,
2016
- output: 0
1792
+ /**
1793
+ * Add interceptor to the chain
1794
+ *
1795
+ * @param interceptor - Interceptor function
1796
+ * @returns Unsubscribe function to remove the interceptor
1797
+ */
1798
+ intercept(interceptor) {
1799
+ this.interceptors.push(interceptor);
1800
+ return () => {
1801
+ const index = this.interceptors.indexOf(interceptor);
1802
+ if (index !== -1) {
1803
+ this.interceptors.splice(index, 1);
1804
+ }
1805
+ };
1806
+ }
1807
+ /**
1808
+ * Execute the interceptor chain
1809
+ *
1810
+ * @param event - Event to process
1811
+ * @param finalHandler - Handler called at the end of the chain
1812
+ */
1813
+ execute(event, finalHandler) {
1814
+ let index = 0;
1815
+ const next = (e) => {
1816
+ if (index < this.interceptors.length) {
1817
+ const interceptor = this.interceptors[index++];
1818
+ try {
1819
+ interceptor(e, next);
1820
+ } catch (error) {
1821
+ logger32.error("Interceptor error", {
1822
+ agentId: this.agentId,
1823
+ eventType: e.type,
1824
+ interceptorIndex: index - 1,
1825
+ error
1826
+ });
1827
+ next(e);
1828
+ }
1829
+ } else {
1830
+ finalHandler(e);
2017
1831
  }
1832
+ };
1833
+ next(event);
1834
+ }
1835
+ /**
1836
+ * Clear all interceptors
1837
+ */
1838
+ clear() {
1839
+ this.interceptors.length = 0;
1840
+ }
1841
+ /**
1842
+ * Get the number of interceptors
1843
+ */
1844
+ get size() {
1845
+ return this.interceptors.length;
1846
+ }
1847
+ };
1848
+ var REACT_TO_EVENT_MAP = {
1849
+ // Stream Layer Events
1850
+ onMessageStart: "message_start",
1851
+ onMessageDelta: "message_delta",
1852
+ onMessageStop: "message_stop",
1853
+ onTextContentBlockStart: "text_content_block_start",
1854
+ onTextDelta: "text_delta",
1855
+ onTextContentBlockStop: "text_content_block_stop",
1856
+ onToolUseContentBlockStart: "tool_use_content_block_start",
1857
+ onInputJsonDelta: "input_json_delta",
1858
+ onToolUseContentBlockStop: "tool_use_content_block_stop",
1859
+ onToolCall: "tool_call",
1860
+ onToolResult: "tool_result",
1861
+ // Message Layer Events
1862
+ onUserMessage: "user_message",
1863
+ onAssistantMessage: "assistant_message",
1864
+ onToolCallMessage: "tool_call_message",
1865
+ onToolResultMessage: "tool_result_message",
1866
+ // Error Layer Events (independent, transportable via SSE)
1867
+ onError: "error",
1868
+ // Turn Layer Events
1869
+ onTurnRequest: "turn_request",
1870
+ onTurnResponse: "turn_response"
1871
+ };
1872
+ function mapReactHandlers(reactHandlers) {
1873
+ const eventHandlerMap = {};
1874
+ for (const [reactKey, eventKey] of Object.entries(REACT_TO_EVENT_MAP)) {
1875
+ const handler = reactHandlers[reactKey];
1876
+ if (handler) {
1877
+ eventHandlerMap[eventKey] = handler;
2018
1878
  }
2019
- };
2020
- return [context, [conversationEndEvent]];
2021
- }
2022
- function handleTextContentBlockStart(context, event) {
2023
- const respondingEvent = {
2024
- type: "conversation_responding",
2025
- uuid: generateId2(),
2026
- agentId: event.agentId,
2027
- timestamp: Date.now(),
2028
- transition: {
2029
- reason: "assistant_responding",
2030
- trigger: "text_content_block_start"
2031
- },
2032
- data: {}
2033
- };
2034
- return [context, [respondingEvent]];
1879
+ }
1880
+ return eventHandlerMap;
2035
1881
  }
2036
- function handleToolUseContentBlockStart2(context, event) {
2037
- const outputs = [];
2038
- const toolPlannedEvent = {
2039
- type: "tool_planned",
2040
- uuid: generateId2(),
2041
- agentId: event.agentId,
2042
- timestamp: event.timestamp,
2043
- data: {
2044
- id: event.data.id,
2045
- name: event.data.name,
2046
- input: {}
1882
+ var logger42 = createLogger("core/AgentInstance");
1883
+ var AgentInstance = class {
1884
+ constructor(definition, context, engine, driver, sandbox) {
1885
+ __publicField(this, "agentId");
1886
+ __publicField(this, "definition");
1887
+ __publicField(this, "context");
1888
+ __publicField(this, "createdAt");
1889
+ __publicField(this, "sandbox");
1890
+ __publicField(this, "_lifecycle", "running");
1891
+ __publicField(this, "engine");
1892
+ __publicField(this, "driver");
1893
+ __publicField(this, "stateMachine", new AgentStateMachine());
1894
+ __publicField(this, "eventBus", new AgentEventBus());
1895
+ __publicField(this, "errorClassifier");
1896
+ __publicField(this, "middlewareChain", new MiddlewareChain());
1897
+ __publicField(this, "interceptorChain");
1898
+ __publicField(this, "readyHandlers", /* @__PURE__ */ new Set());
1899
+ __publicField(this, "destroyHandlers", /* @__PURE__ */ new Set());
1900
+ this.agentId = context.agentId;
1901
+ this.definition = definition;
1902
+ this.context = context;
1903
+ this.engine = engine;
1904
+ this.createdAt = context.createdAt;
1905
+ this.sandbox = sandbox;
1906
+ this.driver = driver;
1907
+ this.errorClassifier = new AgentErrorClassifier(this.agentId);
1908
+ this.interceptorChain = new InterceptorChain(this.agentId);
1909
+ logger42.debug("AgentInstance created", {
1910
+ agentId: this.agentId,
1911
+ definitionName: definition.name,
1912
+ driverName: this.driver.name
1913
+ });
1914
+ }
1915
+ /**
1916
+ * Current lifecycle state
1917
+ */
1918
+ get lifecycle() {
1919
+ return this._lifecycle;
1920
+ }
1921
+ /**
1922
+ * Current conversation state (delegated to StateMachine)
1923
+ */
1924
+ get state() {
1925
+ return this.stateMachine.state;
1926
+ }
1927
+ /**
1928
+ * Receive a message from user
1929
+ *
1930
+ * Runs through middleware chain before actual processing.
1931
+ *
1932
+ * Error Handling:
1933
+ * - Errors are caught and converted to ErrorMessageEvent
1934
+ * - Handlers receive the error event before re-throwing
1935
+ * - This ensures UI can display errors
1936
+ */
1937
+ async receive(message) {
1938
+ if (this._lifecycle === "destroyed") {
1939
+ logger42.warn("Receive called on destroyed agent", { agentId: this.agentId });
1940
+ const error = this.errorClassifier.create(
1941
+ "system",
1942
+ "AGENT_DESTROYED",
1943
+ "Agent has been destroyed",
1944
+ false
1945
+ );
1946
+ const errorEvent = this.errorClassifier.createEvent(error);
1947
+ this.notifyHandlers(errorEvent);
1948
+ throw new Error("[Agent] Agent has been destroyed");
2047
1949
  }
2048
- };
2049
- outputs.push(toolPlannedEvent);
2050
- const toolExecutingEvent = {
2051
- type: "tool_executing",
2052
- uuid: generateId2(),
2053
- agentId: event.agentId,
2054
- timestamp: event.timestamp,
2055
- transition: {
2056
- reason: "tool_planning_started",
2057
- trigger: "tool_use_content_block_start"
2058
- },
2059
- data: {}
2060
- };
2061
- outputs.push(toolExecutingEvent);
2062
- return [context, outputs];
2063
- }
2064
- function handleToolUseContentBlockStop2(context, _event) {
2065
- return [context, []];
2066
- }
2067
- function handleToolCall(context, _event) {
2068
- return [context, []];
2069
- }
2070
- function handleInterrupted(context, event) {
2071
- logger2$1.debug("interrupted event received", { reason: event.data.reason });
2072
- const conversationInterruptedEvent = {
2073
- type: "conversation_interrupted",
2074
- uuid: generateId2(),
2075
- agentId: event.agentId,
2076
- timestamp: event.timestamp,
2077
- transition: {
2078
- reason: event.data.reason,
2079
- trigger: "interrupted"
2080
- },
2081
- data: {
2082
- reason: event.data.reason
1950
+ if (this.state !== "idle") {
1951
+ logger42.warn("Receive called while agent is busy", {
1952
+ agentId: this.agentId,
1953
+ currentState: this.state
1954
+ });
1955
+ const error = this.errorClassifier.create(
1956
+ "system",
1957
+ "AGENT_BUSY",
1958
+ `Agent is busy (state: ${this.state}), please wait for current operation to complete`,
1959
+ false
1960
+ );
1961
+ const errorEvent = this.errorClassifier.createEvent(error);
1962
+ this.notifyHandlers(errorEvent);
1963
+ throw new Error(`[Agent] Agent is busy (state: ${this.state})`);
2083
1964
  }
2084
- };
2085
- return [context, [conversationInterruptedEvent]];
2086
- }
2087
- function createInitialTurnTrackerState() {
2088
- return {
2089
- pendingTurn: null,
2090
- costPerInputToken: 3e-6,
2091
- // $3 per 1M tokens
2092
- costPerOutputToken: 15e-6
2093
- // $15 per 1M tokens
2094
- };
2095
- }
2096
- function generateId3() {
2097
- return `turn_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
2098
- }
2099
- function calculateCost(usage, costPerInputToken, costPerOutputToken) {
2100
- const inputCost = usage.input * costPerInputToken;
2101
- const outputCost = usage.output * costPerOutputToken;
2102
- return inputCost + outputCost;
2103
- }
2104
- var turnTrackerProcessor = (state, input) => {
2105
- switch (input.type) {
2106
- case "user_message":
2107
- return handleUserMessage(state, input);
2108
- case "message_stop":
2109
- return handleMessageStop3(state, input);
2110
- case "assistant_message":
2111
- return [state, []];
2112
- default:
2113
- return [state, []];
1965
+ const userMessage = typeof message === "string" ? {
1966
+ id: `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1967
+ role: "user",
1968
+ subtype: "user",
1969
+ content: message,
1970
+ timestamp: Date.now()
1971
+ } : message;
1972
+ logger42.debug("Receiving message", {
1973
+ agentId: this.agentId,
1974
+ messageId: userMessage.id
1975
+ });
1976
+ const userMessageEvent = {
1977
+ uuid: `evt_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1978
+ type: "user_message",
1979
+ agentId: this.agentId,
1980
+ timestamp: Date.now(),
1981
+ data: userMessage
1982
+ };
1983
+ this.presentOutput(userMessageEvent);
1984
+ this.notifyHandlers(userMessageEvent);
1985
+ await this.executeMiddlewareChain(userMessage);
2114
1986
  }
2115
- };
2116
- function handleUserMessage(state, event) {
2117
- const turnId = generateId3();
2118
- const pendingTurn = {
2119
- turnId,
2120
- userMessage: event.data,
2121
- requestedAt: event.timestamp
2122
- };
2123
- const turnRequestEvent = {
2124
- type: "turn_request",
2125
- uuid: generateId3(),
2126
- agentId: event.agentId,
2127
- timestamp: Date.now(),
2128
- turnId,
2129
- data: {
2130
- userMessage: event.data,
2131
- requestedAt: event.timestamp
1987
+ /**
1988
+ * Execute middleware chain and then process the message
1989
+ */
1990
+ async executeMiddlewareChain(message) {
1991
+ await this.middlewareChain.execute(message, (msg) => this.doReceive(msg));
1992
+ }
1993
+ /**
1994
+ * Process a single stream event through the engine
1995
+ *
1996
+ * Used by:
1997
+ * - doReceive() - normal message flow
1998
+ * - AgentInterrupter - interrupt event injection
1999
+ *
2000
+ * @param streamEvent - Stream event to process
2001
+ */
2002
+ processStreamEvent(streamEvent) {
2003
+ const outputs = this.engine.process(this.agentId, streamEvent);
2004
+ for (const output of outputs) {
2005
+ this.presentOutput(output);
2006
+ }
2007
+ for (const output of outputs) {
2008
+ this.notifyHandlers(output);
2009
+ }
2010
+ }
2011
+ /**
2012
+ * Actual message processing logic
2013
+ *
2014
+ * Coordinates the flow:
2015
+ * 1. Driver receives message → produces StreamEvents
2016
+ * 2. Engine processes events → produces outputs
2017
+ * 3. Presenters handle outputs
2018
+ * 4. Handlers receive outputs
2019
+ */
2020
+ async doReceive(userMessage) {
2021
+ try {
2022
+ logger42.debug("Processing message through driver", {
2023
+ agentId: this.agentId,
2024
+ messageId: userMessage.id
2025
+ });
2026
+ const queuedEvent = {
2027
+ type: "conversation_queued",
2028
+ uuid: `${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
2029
+ agentId: this.agentId,
2030
+ timestamp: Date.now(),
2031
+ data: {
2032
+ userMessage
2033
+ }
2034
+ };
2035
+ this.notifyHandlers(queuedEvent);
2036
+ const streamEvents = this.driver.receive(userMessage);
2037
+ for await (const streamEvent of streamEvents) {
2038
+ this.processStreamEvent(streamEvent);
2039
+ }
2040
+ logger42.debug("Message processing completed", {
2041
+ agentId: this.agentId,
2042
+ messageId: userMessage.id
2043
+ });
2044
+ } catch (error) {
2045
+ const agentError = this.errorClassifier.classify(error);
2046
+ const errorEvent = this.errorClassifier.createEvent(agentError);
2047
+ logger42.error("Message processing failed", {
2048
+ agentId: this.agentId,
2049
+ messageId: userMessage.id,
2050
+ errorCategory: agentError.category,
2051
+ errorCode: agentError.code,
2052
+ error
2053
+ });
2054
+ this.notifyHandlers(errorEvent);
2055
+ throw error;
2132
2056
  }
2133
- };
2134
- return [
2135
- {
2136
- ...state,
2137
- pendingTurn
2138
- },
2139
- [turnRequestEvent]
2140
- ];
2141
- }
2142
- function handleMessageStop3(state, event) {
2143
- if (!state.pendingTurn) {
2144
- return [state, []];
2145
2057
  }
2146
- const stopReason = event.data.stopReason;
2147
- if (stopReason === "end_turn" || stopReason === "max_tokens" || stopReason === "stop_sequence") {
2148
- return completeTurn(state, event.agentId, event.timestamp);
2058
+ /**
2059
+ * Send output to all presenters
2060
+ *
2061
+ * Note: Presenters are no longer part of AgentDefinition.
2062
+ * This is a placeholder for future presenter injection via Runtime or middleware.
2063
+ */
2064
+ presentOutput(_output) {
2149
2065
  }
2150
- return [state, []];
2151
- }
2152
- function completeTurn(state, agentId, completedAt) {
2153
- if (!state.pendingTurn) {
2154
- return [state, []];
2066
+ on(typeOrHandlerOrMap, handler) {
2067
+ if (typeof typeOrHandlerOrMap === "function") {
2068
+ return this.eventBus.onAny(typeOrHandlerOrMap);
2069
+ }
2070
+ if (this.isEventHandlerMap(typeOrHandlerOrMap)) {
2071
+ const unsubscribes = [];
2072
+ for (const [eventType, eventHandler] of Object.entries(typeOrHandlerOrMap)) {
2073
+ if (eventHandler) {
2074
+ unsubscribes.push(this.eventBus.on(eventType, eventHandler));
2075
+ }
2076
+ }
2077
+ return () => {
2078
+ for (const unsub of unsubscribes) {
2079
+ unsub();
2080
+ }
2081
+ };
2082
+ }
2083
+ const types = Array.isArray(typeOrHandlerOrMap) ? typeOrHandlerOrMap : [typeOrHandlerOrMap];
2084
+ const h = handler;
2085
+ return this.eventBus.on(types, h);
2155
2086
  }
2156
- const { turnId, requestedAt } = state.pendingTurn;
2157
- const duration = completedAt - requestedAt;
2158
- const usage = { input: 0, output: 0 };
2159
- const cost = calculateCost(usage, state.costPerInputToken, state.costPerOutputToken);
2160
- const turnResponseEvent = {
2161
- type: "turn_response",
2162
- uuid: generateId3(),
2163
- agentId,
2164
- timestamp: Date.now(),
2165
- turnId,
2166
- data: {
2167
- assistantMessage: {
2168
- id: generateId3(),
2169
- role: "assistant",
2170
- subtype: "assistant",
2171
- content: "",
2172
- timestamp: completedAt
2173
- },
2174
- respondedAt: completedAt,
2175
- durationMs: duration,
2176
- usage,
2177
- costUsd: cost
2087
+ /**
2088
+ * Check if the argument is an EventHandlerMap (object with event type keys)
2089
+ */
2090
+ isEventHandlerMap(arg) {
2091
+ if (typeof arg !== "object" || arg === null || Array.isArray(arg)) {
2092
+ return false;
2178
2093
  }
2179
- };
2180
- return [
2181
- {
2182
- ...state,
2183
- pendingTurn: null
2184
- },
2185
- [turnResponseEvent]
2186
- ];
2187
- }
2188
- var agentProcessor = combineProcessors({
2189
- messageAssembler: messageAssemblerProcessor,
2190
- stateEventProcessor,
2191
- turnTracker: turnTrackerProcessor
2192
- });
2193
- var createInitialAgentEngineState = combineInitialStates({
2194
- messageAssembler: createInitialMessageAssemblerState,
2195
- stateEventProcessor: createInitialStateEventProcessorContext,
2196
- turnTracker: createInitialTurnTrackerState
2197
- });
2198
- var logger3$1 = createLogger("engine/AgentEngine");
2199
- var AgentEngine = class {
2200
- constructor() {
2201
- __publicField(this, "store");
2202
- this.store = new MemoryStore();
2203
- logger3$1.debug("AgentEngine initialized");
2094
+ const keys = Object.keys(arg);
2095
+ if (keys.length === 0) {
2096
+ return false;
2097
+ }
2098
+ return keys.every((key) => {
2099
+ const value = arg[key];
2100
+ return value === void 0 || typeof value === "function";
2101
+ });
2204
2102
  }
2205
2103
  /**
2206
- * Process a single stream event and return output events
2104
+ * Subscribe to state changes (delegated to StateMachine)
2207
2105
  *
2208
- * This is the core Mealy Machine operation:
2209
- * process(agentId, event) → outputs[]
2106
+ * @param handler - Callback receiving { prev, current } state change
2107
+ * @returns Unsubscribe function
2108
+ */
2109
+ onStateChange(handler) {
2110
+ return this.stateMachine.onStateChange(handler);
2111
+ }
2112
+ /**
2113
+ * React-style fluent event subscription
2210
2114
  *
2211
- * @param agentId - The agent identifier (for state isolation)
2212
- * @param event - Stream event to process
2213
- * @returns Array of output events (state, message, turn events)
2115
+ * Converts onXxx handlers to event type keys and delegates to on(handlers)
2214
2116
  */
2215
- process(agentId, event) {
2216
- const eventType = event.type || "unknown";
2217
- logger3$1.debug("Processing event", { agentId, eventType });
2218
- const isNewState = !this.store.has(agentId);
2219
- let state = this.store.get(agentId) ?? createInitialAgentEngineState();
2220
- if (isNewState) {
2221
- logger3$1.debug("Created initial state for agent", { agentId });
2117
+ react(handlers) {
2118
+ const eventHandlerMap = mapReactHandlers(handlers);
2119
+ return this.on(eventHandlerMap);
2120
+ }
2121
+ /**
2122
+ * Subscribe to agent ready event
2123
+ *
2124
+ * If already running, handler is called immediately.
2125
+ */
2126
+ onReady(handler) {
2127
+ if (this._lifecycle === "running") {
2128
+ try {
2129
+ handler();
2130
+ } catch (error) {
2131
+ logger42.error("onReady handler error", {
2132
+ agentId: this.agentId,
2133
+ error
2134
+ });
2135
+ }
2222
2136
  }
2223
- const allOutputs = [];
2224
- allOutputs.push(event);
2225
- const [newState, outputs] = agentProcessor(state, event);
2226
- state = newState;
2227
- for (const output of outputs) {
2228
- allOutputs.push(output);
2229
- const [chainedState, chainedOutputs] = this.processChained(state, output);
2230
- state = chainedState;
2231
- allOutputs.push(...chainedOutputs);
2137
+ this.readyHandlers.add(handler);
2138
+ return () => {
2139
+ this.readyHandlers.delete(handler);
2140
+ };
2141
+ }
2142
+ /**
2143
+ * Subscribe to agent destroy event
2144
+ */
2145
+ onDestroy(handler) {
2146
+ this.destroyHandlers.add(handler);
2147
+ return () => {
2148
+ this.destroyHandlers.delete(handler);
2149
+ };
2150
+ }
2151
+ /**
2152
+ * Add middleware to intercept incoming messages
2153
+ */
2154
+ use(middleware) {
2155
+ return this.middlewareChain.use(middleware);
2156
+ }
2157
+ /**
2158
+ * Add interceptor to intercept outgoing events
2159
+ */
2160
+ intercept(interceptor) {
2161
+ return this.interceptorChain.intercept(interceptor);
2162
+ }
2163
+ /**
2164
+ * Interrupt - User-initiated stop
2165
+ *
2166
+ * Stops the current operation gracefully.
2167
+ * Flow:
2168
+ * 1. Call driver.interrupt() to abort active requests
2169
+ * 2. Driver yields InterruptedStreamEvent
2170
+ * 3. Event flows through engine pipeline
2171
+ * 4. StateEventProcessor generates conversation_interrupted
2172
+ * 5. StateMachine transitions to idle state
2173
+ * 6. UI receives state change notification
2174
+ */
2175
+ interrupt() {
2176
+ logger42.debug("User interrupt requested", { agentId: this.agentId, currentState: this.state });
2177
+ this.driver.interrupt();
2178
+ }
2179
+ /**
2180
+ * Destroy - Clean up resources
2181
+ */
2182
+ async destroy() {
2183
+ logger42.debug("Destroying agent", { agentId: this.agentId });
2184
+ for (const handler of this.destroyHandlers) {
2185
+ try {
2186
+ handler();
2187
+ } catch (error) {
2188
+ logger42.error("onDestroy handler error", {
2189
+ agentId: this.agentId,
2190
+ error
2191
+ });
2192
+ }
2232
2193
  }
2233
- this.store.set(agentId, state);
2234
- if (outputs.length > 0) {
2235
- logger3$1.debug("Produced outputs", {
2236
- agentId,
2237
- inputEvent: eventType,
2238
- outputCount: allOutputs.length,
2239
- processorOutputs: outputs.length
2240
- });
2194
+ this._lifecycle = "destroyed";
2195
+ this.stateMachine.reset();
2196
+ this.eventBus.destroy();
2197
+ this.readyHandlers.clear();
2198
+ this.destroyHandlers.clear();
2199
+ this.middlewareChain.clear();
2200
+ this.interceptorChain.clear();
2201
+ this.engine.clearState(this.agentId);
2202
+ logger42.info("Agent destroyed", { agentId: this.agentId });
2203
+ }
2204
+ /**
2205
+ * Notify all registered handlers
2206
+ *
2207
+ * Flow:
2208
+ * 1. StateMachine processes StateEvents (for state transitions)
2209
+ * 2. Interceptor chain can modify/filter events
2210
+ * 3. EventBus emits to all subscribers
2211
+ */
2212
+ notifyHandlers(event) {
2213
+ if (isStateEvent(event)) {
2214
+ this.stateMachine.process(event);
2241
2215
  }
2242
- return allOutputs;
2216
+ this.executeInterceptorChain(event);
2217
+ }
2218
+ /**
2219
+ * Execute interceptor chain and then emit to EventBus
2220
+ */
2221
+ executeInterceptorChain(event) {
2222
+ this.interceptorChain.execute(event, (e) => this.eventBus.emit(e));
2223
+ }
2224
+ /**
2225
+ * Get the event consumer for external subscriptions
2226
+ *
2227
+ * Use this to expose event subscription without emit capability.
2228
+ */
2229
+ getEventConsumer() {
2230
+ return this.eventBus.asConsumer();
2231
+ }
2232
+ };
2233
+ var MemoryStore = class {
2234
+ constructor() {
2235
+ __publicField(this, "states", /* @__PURE__ */ new Map());
2236
+ }
2237
+ get(id) {
2238
+ return this.states.get(id);
2239
+ }
2240
+ set(id, state) {
2241
+ this.states.set(id, state);
2242
+ }
2243
+ delete(id) {
2244
+ this.states.delete(id);
2245
+ }
2246
+ has(id) {
2247
+ return this.states.has(id);
2243
2248
  }
2244
2249
  /**
2245
- * Process chained events recursively
2246
- *
2247
- * Some processors produce events that trigger other processors:
2248
- * - MessageAssembler produces MessageEvents
2249
- * - TurnTracker consumes MessageEvents to produce TurnEvents
2250
+ * Clear all stored states
2250
2251
  */
2251
- processChained(state, event) {
2252
- const [newState, outputs] = agentProcessor(state, event);
2253
- if (outputs.length === 0) {
2254
- return [newState, []];
2255
- }
2256
- const allOutputs = [...outputs];
2257
- let currentState = newState;
2258
- for (const output of outputs) {
2259
- const [chainedState, chainedOutputs] = this.processChained(currentState, output);
2260
- currentState = chainedState;
2261
- allOutputs.push(...chainedOutputs);
2262
- }
2263
- return [currentState, allOutputs];
2252
+ clear() {
2253
+ this.states.clear();
2264
2254
  }
2265
2255
  /**
2266
- * Clear state for an agent
2267
- *
2268
- * Call this when an agent is destroyed to free memory.
2256
+ * Get the number of stored states
2269
2257
  */
2270
- clearState(agentId) {
2271
- logger3$1.debug("Clearing state", { agentId });
2272
- this.store.delete(agentId);
2258
+ get size() {
2259
+ return this.states.size;
2273
2260
  }
2274
2261
  /**
2275
- * Check if state exists for an agent
2262
+ * Get all stored IDs
2276
2263
  */
2277
- hasState(agentId) {
2278
- return this.store.has(agentId);
2264
+ keys() {
2265
+ return this.states.keys();
2279
2266
  }
2280
2267
  };
2281
- var __defProp2 = Object.defineProperty;
2282
- var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
2283
- var __publicField2 = (obj, key, value) => __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
2284
- var logger = createLogger("agentx/DefinitionManager");
2285
- function generateMetaImageId(definitionName) {
2286
- return `meta_${definitionName}`;
2268
+ createLogger("engine/Mealy");
2269
+ function combineProcessors(processors) {
2270
+ return (state, event) => {
2271
+ const newState = {};
2272
+ const allOutputs = [];
2273
+ for (const key in processors) {
2274
+ const processor = processors[key];
2275
+ const subState = state[key];
2276
+ const [newSubState, outputs] = processor(subState, event);
2277
+ newState[key] = newSubState;
2278
+ allOutputs.push(...outputs);
2279
+ }
2280
+ return [newState, allOutputs];
2281
+ };
2287
2282
  }
2288
- function toDefinitionRecord(definition) {
2289
- const now = /* @__PURE__ */ new Date();
2283
+ function combineInitialStates(initialStates) {
2284
+ return () => {
2285
+ const state = {};
2286
+ for (const key in initialStates) {
2287
+ state[key] = initialStates[key]();
2288
+ }
2289
+ return state;
2290
+ };
2291
+ }
2292
+ function createInitialMessageAssemblerState() {
2290
2293
  return {
2291
- name: definition.name,
2292
- description: definition.description,
2293
- systemPrompt: definition.systemPrompt,
2294
- definition,
2295
- source: "code",
2296
- createdAt: now,
2297
- updatedAt: now
2294
+ currentMessageId: null,
2295
+ messageStartTime: null,
2296
+ pendingContents: {},
2297
+ pendingToolCalls: {}
2298
2298
  };
2299
2299
  }
2300
- var DefinitionManagerImpl = class {
2301
- constructor(repository) {
2302
- this.repository = repository;
2303
- __publicField2(this, "cache", /* @__PURE__ */ new Map());
2304
- }
2305
- register(definition) {
2306
- if (this.cache.has(definition.name)) {
2307
- throw new Error(`Definition already exists: ${definition.name}`);
2308
- }
2309
- this.cache.set(definition.name, definition);
2310
- const definitionRecord = toDefinitionRecord(definition);
2311
- this.repository.saveDefinition(definitionRecord).catch((err) => {
2312
- logger.error("Failed to save definition", { name: definition.name, error: err });
2313
- });
2314
- const metaImageId = generateMetaImageId(definition.name);
2315
- const imageRecord = {
2316
- imageId: metaImageId,
2317
- type: "meta",
2318
- definitionName: definition.name,
2319
- parentImageId: null,
2320
- definition,
2321
- config: {},
2322
- messages: [],
2323
- createdAt: /* @__PURE__ */ new Date()
2324
- };
2325
- this.repository.saveImage(imageRecord).catch((err) => {
2326
- logger.error("Failed to save MetaImage", { definitionName: definition.name, error: err });
2327
- });
2328
- logger.info("Definition registered", {
2329
- name: definition.name,
2330
- metaImageId
2331
- });
2332
- }
2333
- get(name) {
2334
- return this.cache.get(name);
2335
- }
2336
- list() {
2337
- return Array.from(this.cache.values());
2338
- }
2339
- has(name) {
2340
- return this.cache.has(name);
2341
- }
2342
- unregister(name) {
2343
- const definition = this.cache.get(name);
2344
- if (!definition) {
2345
- return false;
2346
- }
2347
- this.cache.delete(name);
2348
- this.repository.deleteDefinition(name).catch((err) => {
2349
- logger.error("Failed to delete definition", { name, error: err });
2350
- });
2351
- const metaImageId = generateMetaImageId(name);
2352
- this.repository.deleteImage(metaImageId).catch((err) => {
2353
- logger.error("Failed to delete MetaImage", { definitionName: name, error: err });
2354
- });
2355
- logger.info("Definition unregistered", { name });
2356
- return true;
2300
+ function generateId() {
2301
+ return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
2302
+ }
2303
+ var messageAssemblerProcessor = (state, input) => {
2304
+ switch (input.type) {
2305
+ case "message_start":
2306
+ return handleMessageStart(state, input);
2307
+ case "text_delta":
2308
+ return handleTextDelta(state, input);
2309
+ case "tool_use_content_block_start":
2310
+ return handleToolUseContentBlockStart(state, input);
2311
+ case "input_json_delta":
2312
+ return handleInputJsonDelta(state, input);
2313
+ case "tool_use_content_block_stop":
2314
+ return handleToolUseContentBlockStop(state, input);
2315
+ case "tool_result":
2316
+ return handleToolResult(state, input);
2317
+ case "message_stop":
2318
+ return handleMessageStop(state, input);
2319
+ default:
2320
+ return [state, []];
2357
2321
  }
2358
2322
  };
2359
- var logger2 = createLogger("agentx/ImageManager");
2360
- function generateMetaImageId2(definitionName) {
2361
- return `meta_${definitionName}`;
2323
+ function handleMessageStart(state, event) {
2324
+ return [
2325
+ {
2326
+ ...state,
2327
+ currentMessageId: generateId(),
2328
+ messageStartTime: event.timestamp,
2329
+ pendingContents: {}
2330
+ },
2331
+ []
2332
+ ];
2362
2333
  }
2363
- function toAgentImage(record) {
2364
- const definition = record.definition;
2365
- if (record.type === "meta") {
2366
- const metaImage = {
2367
- type: "meta",
2368
- imageId: record.imageId,
2369
- definitionName: record.definitionName,
2370
- definition,
2371
- config: record.config,
2372
- messages: [],
2373
- createdAt: record.createdAt
2374
- };
2375
- return metaImage;
2376
- } else {
2377
- return {
2378
- type: "derived",
2379
- imageId: record.imageId,
2380
- parentImageId: record.parentImageId,
2381
- definitionName: record.definitionName,
2382
- definition,
2383
- config: record.config,
2384
- messages: record.messages,
2385
- createdAt: record.createdAt
2386
- };
2387
- }
2334
+ function handleTextDelta(state, event) {
2335
+ const index = 0;
2336
+ const existingContent = state.pendingContents[index];
2337
+ const pendingContent = (existingContent == null ? void 0 : existingContent.type) === "text" ? {
2338
+ ...existingContent,
2339
+ textDeltas: [...existingContent.textDeltas || [], event.data.text]
2340
+ } : {
2341
+ type: "text",
2342
+ index,
2343
+ textDeltas: [event.data.text]
2344
+ };
2345
+ return [
2346
+ {
2347
+ ...state,
2348
+ pendingContents: {
2349
+ ...state.pendingContents,
2350
+ [index]: pendingContent
2351
+ }
2352
+ },
2353
+ []
2354
+ ];
2388
2355
  }
2389
- var ImageManagerImpl = class {
2390
- constructor(repository, containerManager, defaultContainerId) {
2391
- __publicField2(this, "repository");
2392
- __publicField2(this, "containerManager");
2393
- __publicField2(this, "defaultContainerId");
2394
- this.repository = repository;
2395
- this.containerManager = containerManager;
2396
- this.defaultContainerId = defaultContainerId;
2397
- }
2398
- async get(imageId) {
2399
- const record = await this.repository.findImageById(imageId);
2400
- if (!record) {
2401
- return void 0;
2402
- }
2403
- return toAgentImage(record);
2404
- }
2405
- async getMetaImage(definitionName) {
2406
- const metaImageId = generateMetaImageId2(definitionName);
2407
- const record = await this.repository.findImageById(metaImageId);
2408
- if (!record || record.type !== "meta") {
2409
- return void 0;
2410
- }
2411
- return toAgentImage(record);
2412
- }
2413
- async list() {
2414
- const records = await this.repository.findAllImages();
2415
- return records.map(toAgentImage);
2356
+ function handleToolUseContentBlockStart(state, event) {
2357
+ const index = 1;
2358
+ const pendingContent = {
2359
+ type: "tool_use",
2360
+ index,
2361
+ toolId: event.data.id,
2362
+ toolName: event.data.name,
2363
+ toolInputJson: ""
2364
+ };
2365
+ return [
2366
+ {
2367
+ ...state,
2368
+ pendingContents: {
2369
+ ...state.pendingContents,
2370
+ [index]: pendingContent
2371
+ }
2372
+ },
2373
+ []
2374
+ ];
2375
+ }
2376
+ function handleInputJsonDelta(state, event) {
2377
+ const index = 1;
2378
+ const existingContent = state.pendingContents[index];
2379
+ if (!existingContent || existingContent.type !== "tool_use") {
2380
+ return [state, []];
2416
2381
  }
2417
- async listByDefinition(definitionName) {
2418
- const allRecords = await this.repository.findAllImages();
2419
- const filtered = allRecords.filter((r) => r.definitionName === definitionName);
2420
- return filtered.map(toAgentImage);
2382
+ const pendingContent = {
2383
+ ...existingContent,
2384
+ toolInputJson: (existingContent.toolInputJson || "") + event.data.partialJson
2385
+ };
2386
+ return [
2387
+ {
2388
+ ...state,
2389
+ pendingContents: {
2390
+ ...state.pendingContents,
2391
+ [index]: pendingContent
2392
+ }
2393
+ },
2394
+ []
2395
+ ];
2396
+ }
2397
+ function handleToolUseContentBlockStop(state, event) {
2398
+ const index = 1;
2399
+ const pendingContent = state.pendingContents[index];
2400
+ if (!pendingContent || pendingContent.type !== "tool_use") {
2401
+ return [state, []];
2421
2402
  }
2422
- async exists(imageId) {
2423
- return this.repository.imageExists(imageId);
2403
+ let toolInput = {};
2404
+ try {
2405
+ toolInput = pendingContent.toolInputJson ? JSON.parse(pendingContent.toolInputJson) : {};
2406
+ } catch {
2407
+ toolInput = {};
2424
2408
  }
2425
- async delete(imageId) {
2426
- const record = await this.repository.findImageById(imageId);
2427
- if (!record) {
2428
- return false;
2409
+ const outputs = [];
2410
+ const toolId = pendingContent.toolId;
2411
+ const toolName = pendingContent.toolName;
2412
+ const toolCallEvent = {
2413
+ type: "tool_call",
2414
+ uuid: generateId(),
2415
+ agentId: event.agentId,
2416
+ timestamp: Date.now(),
2417
+ data: {
2418
+ id: toolId,
2419
+ name: toolName,
2420
+ input: toolInput
2429
2421
  }
2430
- if (record.type === "meta") {
2431
- logger2.warn("Cannot delete MetaImage directly", { imageId });
2432
- return false;
2422
+ };
2423
+ outputs.push(toolCallEvent);
2424
+ const toolCall = {
2425
+ type: "tool-call",
2426
+ id: toolId,
2427
+ name: toolName,
2428
+ input: toolInput
2429
+ };
2430
+ const toolCallMessage = {
2431
+ id: generateId(),
2432
+ role: "assistant",
2433
+ subtype: "tool-call",
2434
+ toolCall,
2435
+ timestamp: Date.now()
2436
+ };
2437
+ const toolCallMessageEvent = {
2438
+ type: "tool_call_message",
2439
+ uuid: generateId(),
2440
+ agentId: event.agentId,
2441
+ timestamp: Date.now(),
2442
+ data: toolCallMessage
2443
+ };
2444
+ outputs.push(toolCallMessageEvent);
2445
+ const { [index]: _, ...remainingContents } = state.pendingContents;
2446
+ return [
2447
+ {
2448
+ ...state,
2449
+ pendingContents: remainingContents,
2450
+ pendingToolCalls: {
2451
+ ...state.pendingToolCalls,
2452
+ [toolId]: { id: toolId, name: toolName }
2453
+ }
2454
+ },
2455
+ outputs
2456
+ ];
2457
+ }
2458
+ function handleToolResult(state, event) {
2459
+ const { toolId, content, isError } = event.data;
2460
+ const pendingToolCall = state.pendingToolCalls[toolId];
2461
+ const toolName = (pendingToolCall == null ? void 0 : pendingToolCall.name) || "unknown";
2462
+ const toolResult = {
2463
+ type: "tool-result",
2464
+ id: toolId,
2465
+ name: toolName,
2466
+ output: {
2467
+ type: isError ? "error-text" : "text",
2468
+ value: typeof content === "string" ? content : JSON.stringify(content)
2433
2469
  }
2434
- await this.repository.deleteImage(imageId);
2435
- logger2.info("Image deleted", { imageId });
2436
- return true;
2470
+ };
2471
+ const toolResultMessage = {
2472
+ id: generateId(),
2473
+ role: "tool",
2474
+ subtype: "tool-result",
2475
+ toolResult,
2476
+ toolCallId: toolId,
2477
+ timestamp: Date.now()
2478
+ };
2479
+ const toolResultMessageEvent = {
2480
+ type: "tool_result_message",
2481
+ uuid: generateId(),
2482
+ agentId: event.agentId,
2483
+ timestamp: Date.now(),
2484
+ data: toolResultMessage
2485
+ };
2486
+ const { [toolId]: _, ...remainingToolCalls } = state.pendingToolCalls;
2487
+ return [
2488
+ {
2489
+ ...state,
2490
+ pendingToolCalls: remainingToolCalls
2491
+ },
2492
+ [toolResultMessageEvent]
2493
+ ];
2494
+ }
2495
+ function handleMessageStop(state, event) {
2496
+ if (!state.currentMessageId) {
2497
+ return [state, []];
2437
2498
  }
2438
- async run(imageId, options) {
2439
- logger2.info("Running agent from image", { imageId, containerId: options == null ? void 0 : options.containerId });
2440
- const image = await this.get(imageId);
2441
- if (!image) {
2442
- throw new Error(`Image not found: ${imageId}`);
2443
- }
2444
- let containerId = (options == null ? void 0 : options.containerId) || this.defaultContainerId;
2445
- if (!containerId) {
2446
- const container = await this.containerManager.create();
2447
- containerId = container.containerId;
2448
- this.defaultContainerId = containerId;
2449
- logger2.debug("Auto-created default container", { containerId });
2499
+ const textParts = [];
2500
+ const sortedContents = Object.values(state.pendingContents).sort((a, b) => a.index - b.index);
2501
+ for (const pending of sortedContents) {
2502
+ if (pending.type === "text" && pending.textDeltas) {
2503
+ textParts.push(pending.textDeltas.join(""));
2450
2504
  }
2451
- return this.containerManager.run(image, containerId);
2452
- }
2453
- };
2454
- var logger3 = createLogger("agentx/AgentManager");
2455
- var AgentManager = class {
2456
- constructor(containerManager) {
2457
- this.containerManager = containerManager;
2458
- }
2459
- /**
2460
- * Get an existing agent by ID
2461
- */
2462
- get(agentId) {
2463
- return this.containerManager.getAgent(agentId);
2464
- }
2465
- /**
2466
- * Check if an agent exists
2467
- */
2468
- has(agentId) {
2469
- return this.containerManager.hasAgent(agentId);
2470
- }
2471
- /**
2472
- * List all agents
2473
- */
2474
- list() {
2475
- return this.containerManager.listAgents();
2476
2505
  }
2477
- /**
2478
- * Destroy an agent by ID
2479
- */
2480
- async destroy(agentId) {
2481
- logger3.debug("Destroying agent", { agentId });
2482
- await this.containerManager.destroyAgent(agentId);
2483
- logger3.info("Agent destroyed", { agentId });
2506
+ const content = textParts.join("");
2507
+ const stopReason = event.data.stopReason;
2508
+ if (!content || content.trim().length === 0) {
2509
+ const shouldPreserveToolCalls2 = stopReason === "tool_use";
2510
+ return [
2511
+ {
2512
+ ...createInitialMessageAssemblerState(),
2513
+ pendingToolCalls: shouldPreserveToolCalls2 ? state.pendingToolCalls : {}
2514
+ },
2515
+ []
2516
+ ];
2484
2517
  }
2485
- /**
2486
- * Destroy all agents
2487
- */
2488
- async destroyAll() {
2489
- const agents = this.containerManager.listAgents();
2490
- logger3.debug("Destroying all agents", { count: agents.length });
2491
- await this.containerManager.destroyAllAgents();
2492
- logger3.info("All agents destroyed", { count: agents.length });
2518
+ const assistantMessage = {
2519
+ id: state.currentMessageId,
2520
+ role: "assistant",
2521
+ subtype: "assistant",
2522
+ content,
2523
+ timestamp: state.messageStartTime || Date.now(),
2524
+ // Usage data is not available in message_stop event
2525
+ // It would need to be tracked separately if needed
2526
+ usage: void 0
2527
+ };
2528
+ const assistantEvent = {
2529
+ type: "assistant_message",
2530
+ uuid: generateId(),
2531
+ agentId: event.agentId,
2532
+ timestamp: Date.now(),
2533
+ data: assistantMessage
2534
+ };
2535
+ const shouldPreserveToolCalls = stopReason === "tool_use";
2536
+ return [
2537
+ {
2538
+ ...createInitialMessageAssemblerState(),
2539
+ pendingToolCalls: shouldPreserveToolCalls ? state.pendingToolCalls : {}
2540
+ },
2541
+ [assistantEvent]
2542
+ ];
2543
+ }
2544
+ var logger23 = createLogger("engine/stateEventProcessor");
2545
+ function createInitialStateEventProcessorContext() {
2546
+ return {};
2547
+ }
2548
+ function generateId2() {
2549
+ return `state_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
2550
+ }
2551
+ var stateEventProcessor = (context, input) => {
2552
+ logger23.debug(`[Stream Event] ${input.type}`, {
2553
+ context,
2554
+ eventData: "data" in input ? input.data : void 0
2555
+ });
2556
+ switch (input.type) {
2557
+ case "message_start":
2558
+ return handleMessageStart2(context, input);
2559
+ case "message_delta":
2560
+ return handleMessageDelta(context);
2561
+ case "message_stop":
2562
+ return handleMessageStop2(context, input);
2563
+ case "text_content_block_start":
2564
+ return handleTextContentBlockStart(context, input);
2565
+ case "tool_use_content_block_start":
2566
+ return handleToolUseContentBlockStart2(context, input);
2567
+ case "tool_use_content_block_stop":
2568
+ return handleToolUseContentBlockStop2(context);
2569
+ case "tool_call":
2570
+ return handleToolCall(context);
2571
+ case "interrupted":
2572
+ return handleInterrupted(context, input);
2573
+ default:
2574
+ logger23.debug(`[Stream Event] ${input.type} (unhandled)`);
2575
+ return [context, []];
2493
2576
  }
2494
2577
  };
2495
- var logger4 = createLogger("agentx/SessionManager");
2496
- function generateSessionId() {
2497
- const timestamp = Date.now().toString(36);
2498
- const random = Math.random().toString(36).substring(2, 8);
2499
- return `session_${timestamp}_${random}`;
2578
+ function handleMessageStart2(context, event) {
2579
+ const conversationStartEvent = {
2580
+ type: "conversation_start",
2581
+ uuid: generateId2(),
2582
+ agentId: event.agentId,
2583
+ timestamp: event.timestamp,
2584
+ transition: {
2585
+ reason: "conversation_started",
2586
+ trigger: "message_start"
2587
+ },
2588
+ data: {
2589
+ userMessage: {}
2590
+ // Will be populated by higher-level component
2591
+ }
2592
+ };
2593
+ return [context, [conversationStartEvent]];
2500
2594
  }
2501
- function generateImageId() {
2502
- const timestamp = Date.now().toString(36);
2503
- const random = Math.random().toString(36).substring(2, 8);
2504
- return `image_${timestamp}_${random}`;
2595
+ function handleMessageDelta(context, _event) {
2596
+ return [context, []];
2505
2597
  }
2506
- var SessionImpl = class _SessionImpl {
2507
- constructor(record, repository, containerManager, defaultContainerId) {
2508
- __publicField2(this, "sessionId");
2509
- __publicField2(this, "userId");
2510
- __publicField2(this, "imageId");
2511
- __publicField2(this, "createdAt");
2512
- __publicField2(this, "_title");
2513
- __publicField2(this, "_updatedAt");
2514
- __publicField2(this, "repository");
2515
- __publicField2(this, "containerManager");
2516
- __publicField2(this, "defaultContainerId");
2517
- this.sessionId = record.sessionId;
2518
- this.userId = record.userId;
2519
- this.imageId = record.imageId;
2520
- this._title = record.title;
2521
- this.createdAt = record.createdAt.getTime();
2522
- this._updatedAt = record.updatedAt.getTime();
2523
- this.repository = repository;
2524
- this.containerManager = containerManager;
2525
- this.defaultContainerId = defaultContainerId;
2526
- }
2527
- get title() {
2528
- return this._title;
2529
- }
2530
- get updatedAt() {
2531
- return this._updatedAt;
2598
+ function handleMessageStop2(context, event) {
2599
+ const stopReason = event.data.stopReason;
2600
+ logger23.debug("message_stop received", { stopReason });
2601
+ if (stopReason === "tool_use") {
2602
+ logger23.debug("Skipping conversation_end (tool_use in progress)");
2603
+ return [context, []];
2532
2604
  }
2533
- async resume(options) {
2534
- logger4.info("Resuming agent from session", {
2535
- sessionId: this.sessionId,
2536
- imageId: this.imageId,
2537
- containerId: options == null ? void 0 : options.containerId
2538
- });
2539
- let containerId = (options == null ? void 0 : options.containerId) || this.defaultContainerId;
2540
- if (!containerId) {
2541
- const container = await this.containerManager.create();
2542
- containerId = container.containerId;
2543
- logger4.debug("Auto-created default container for session", {
2544
- containerId,
2545
- sessionId: this.sessionId
2546
- });
2605
+ const conversationEndEvent = {
2606
+ type: "conversation_end",
2607
+ uuid: generateId2(),
2608
+ agentId: event.agentId,
2609
+ timestamp: event.timestamp,
2610
+ transition: {
2611
+ reason: "conversation_completed",
2612
+ trigger: "message_stop"
2613
+ },
2614
+ data: {
2615
+ assistantMessage: {},
2616
+ // Will be populated by higher-level component
2617
+ durationMs: 0,
2618
+ // Will be calculated by StateMachine or TurnTracker
2619
+ durationApiMs: 0,
2620
+ numTurns: 0,
2621
+ result: "completed",
2622
+ totalCostUsd: 0,
2623
+ usage: {
2624
+ input: 0,
2625
+ output: 0
2626
+ }
2547
2627
  }
2548
- const agent = await this.containerManager.resume(this, containerId);
2549
- this.collect(agent);
2550
- return agent;
2551
- }
2552
- collect(agent) {
2553
- logger4.debug("Collecting messages from agent", {
2554
- sessionId: this.sessionId,
2555
- agentId: agent.agentId
2556
- });
2557
- const sessionId = this.sessionId;
2558
- const repository = this.repository;
2559
- const saveMessage = (data, role) => {
2560
- const record = {
2561
- messageId: data.id,
2562
- sessionId,
2563
- role,
2564
- content: data,
2565
- createdAt: new Date(data.timestamp ?? Date.now())
2566
- };
2567
- repository.saveMessage(record).catch((error) => {
2568
- logger4.error("Failed to persist message", {
2569
- sessionId,
2570
- messageId: record.messageId,
2571
- error
2572
- });
2573
- });
2574
- };
2575
- agent.on("user_message", (event) => saveMessage(event.data, "user"));
2576
- agent.on("assistant_message", (event) => saveMessage(event.data, "assistant"));
2577
- agent.on("tool_call_message", (event) => saveMessage(event.data, "tool"));
2578
- agent.on("tool_result_message", (event) => saveMessage(event.data, "tool"));
2579
- }
2580
- async getMessages() {
2581
- logger4.debug("Getting messages for session", { sessionId: this.sessionId });
2582
- const records = await this.repository.findMessagesBySessionId(this.sessionId);
2583
- return records.map((record) => record.content);
2584
- }
2585
- async fork() {
2586
- logger4.info("Forking session", { sessionId: this.sessionId });
2587
- const imageRecord = await this.repository.findImageById(this.imageId);
2588
- if (!imageRecord) {
2589
- throw new Error(`Image not found: ${this.imageId}`);
2628
+ };
2629
+ return [context, [conversationEndEvent]];
2630
+ }
2631
+ function handleTextContentBlockStart(context, event) {
2632
+ const respondingEvent = {
2633
+ type: "conversation_responding",
2634
+ uuid: generateId2(),
2635
+ agentId: event.agentId,
2636
+ timestamp: Date.now(),
2637
+ transition: {
2638
+ reason: "assistant_responding",
2639
+ trigger: "text_content_block_start"
2640
+ },
2641
+ data: {}
2642
+ };
2643
+ return [context, [respondingEvent]];
2644
+ }
2645
+ function handleToolUseContentBlockStart2(context, event) {
2646
+ const outputs = [];
2647
+ const toolPlannedEvent = {
2648
+ type: "tool_planned",
2649
+ uuid: generateId2(),
2650
+ agentId: event.agentId,
2651
+ timestamp: event.timestamp,
2652
+ data: {
2653
+ id: event.data.id,
2654
+ name: event.data.name,
2655
+ input: {}
2590
2656
  }
2591
- const newImageId = generateImageId();
2592
- const newImageRecord = {
2593
- imageId: newImageId,
2594
- type: "derived",
2595
- definitionName: imageRecord.definitionName,
2596
- parentImageId: imageRecord.imageId,
2597
- definition: imageRecord.definition,
2598
- config: imageRecord.config,
2599
- messages: [...imageRecord.messages],
2600
- // Copy messages
2601
- createdAt: /* @__PURE__ */ new Date()
2602
- };
2603
- await this.repository.saveImage(newImageRecord);
2604
- const newSessionId = generateSessionId();
2605
- const now = /* @__PURE__ */ new Date();
2606
- const newSessionRecord = {
2607
- sessionId: newSessionId,
2608
- userId: this.userId,
2609
- imageId: newImageId,
2610
- title: this._title ? `Fork of ${this._title}` : null,
2611
- createdAt: now,
2612
- updatedAt: now
2613
- };
2614
- await this.repository.saveSession(newSessionRecord);
2615
- logger4.info("Session forked", {
2616
- originalSessionId: this.sessionId,
2617
- newSessionId,
2618
- newImageId
2619
- });
2620
- return new _SessionImpl(
2621
- newSessionRecord,
2622
- this.repository,
2623
- this.containerManager,
2624
- this.defaultContainerId
2625
- );
2626
- }
2627
- async setTitle(title) {
2628
- logger4.debug("Setting session title", { sessionId: this.sessionId, title });
2629
- const now = /* @__PURE__ */ new Date();
2630
- await this.repository.saveSession({
2631
- sessionId: this.sessionId,
2632
- userId: this.userId,
2633
- imageId: this.imageId,
2634
- title,
2635
- createdAt: new Date(this.createdAt),
2636
- updatedAt: now
2637
- });
2638
- this._title = title;
2639
- this._updatedAt = now.getTime();
2640
- logger4.info("Session title updated", { sessionId: this.sessionId, title });
2657
+ };
2658
+ outputs.push(toolPlannedEvent);
2659
+ const toolExecutingEvent = {
2660
+ type: "tool_executing",
2661
+ uuid: generateId2(),
2662
+ agentId: event.agentId,
2663
+ timestamp: event.timestamp,
2664
+ transition: {
2665
+ reason: "tool_planning_started",
2666
+ trigger: "tool_use_content_block_start"
2667
+ },
2668
+ data: {}
2669
+ };
2670
+ outputs.push(toolExecutingEvent);
2671
+ return [context, outputs];
2672
+ }
2673
+ function handleToolUseContentBlockStop2(context, _event) {
2674
+ return [context, []];
2675
+ }
2676
+ function handleToolCall(context, _event) {
2677
+ return [context, []];
2678
+ }
2679
+ function handleInterrupted(context, event) {
2680
+ logger23.debug("interrupted event received", { reason: event.data.reason });
2681
+ const conversationInterruptedEvent = {
2682
+ type: "conversation_interrupted",
2683
+ uuid: generateId2(),
2684
+ agentId: event.agentId,
2685
+ timestamp: event.timestamp,
2686
+ transition: {
2687
+ reason: event.data.reason,
2688
+ trigger: "interrupted"
2689
+ },
2690
+ data: {
2691
+ reason: event.data.reason
2692
+ }
2693
+ };
2694
+ return [context, [conversationInterruptedEvent]];
2695
+ }
2696
+ function createInitialTurnTrackerState() {
2697
+ return {
2698
+ pendingTurn: null,
2699
+ costPerInputToken: 3e-6,
2700
+ // $3 per 1M tokens
2701
+ costPerOutputToken: 15e-6
2702
+ // $15 per 1M tokens
2703
+ };
2704
+ }
2705
+ function generateId3() {
2706
+ return `turn_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
2707
+ }
2708
+ function calculateCost(usage, costPerInputToken, costPerOutputToken) {
2709
+ const inputCost = usage.input * costPerInputToken;
2710
+ const outputCost = usage.output * costPerOutputToken;
2711
+ return inputCost + outputCost;
2712
+ }
2713
+ var turnTrackerProcessor = (state, input) => {
2714
+ switch (input.type) {
2715
+ case "user_message":
2716
+ return handleUserMessage(state, input);
2717
+ case "message_stop":
2718
+ return handleMessageStop3(state, input);
2719
+ case "assistant_message":
2720
+ return [state, []];
2721
+ default:
2722
+ return [state, []];
2641
2723
  }
2642
2724
  };
2643
- var SessionManagerImpl = class {
2644
- constructor(repository, containerManager, defaultContainerId) {
2645
- __publicField2(this, "repository");
2646
- __publicField2(this, "containerManager");
2647
- __publicField2(this, "defaultContainerId");
2648
- this.repository = repository;
2649
- this.containerManager = containerManager;
2650
- this.defaultContainerId = defaultContainerId;
2651
- }
2652
- async create(imageId, userId) {
2653
- const sessionId = generateSessionId();
2654
- const now = /* @__PURE__ */ new Date();
2655
- const record = {
2656
- sessionId,
2657
- userId,
2658
- imageId,
2659
- title: null,
2660
- createdAt: now,
2661
- updatedAt: now
2662
- };
2663
- await this.repository.saveSession(record);
2664
- logger4.info("Session created", { sessionId, imageId, userId });
2665
- return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
2666
- }
2667
- async get(sessionId) {
2668
- const record = await this.repository.findSessionById(sessionId);
2669
- if (!record) return void 0;
2670
- return new SessionImpl(record, this.repository, this.containerManager, this.defaultContainerId);
2671
- }
2672
- async has(sessionId) {
2673
- return this.repository.sessionExists(sessionId);
2674
- }
2675
- async list() {
2676
- const records = await this.repository.findAllSessions();
2677
- return records.map(
2678
- (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
2679
- );
2680
- }
2681
- async listByImage(imageId) {
2682
- const records = await this.repository.findSessionsByImageId(imageId);
2683
- return records.map(
2684
- (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
2685
- );
2686
- }
2687
- async listByUser(userId) {
2688
- const records = await this.repository.findSessionsByUserId(userId);
2689
- return records.map(
2690
- (r) => new SessionImpl(r, this.repository, this.containerManager, this.defaultContainerId)
2691
- );
2725
+ function handleUserMessage(state, event) {
2726
+ const turnId = generateId3();
2727
+ const pendingTurn = {
2728
+ turnId,
2729
+ userMessage: event.data,
2730
+ requestedAt: event.timestamp
2731
+ };
2732
+ const turnRequestEvent = {
2733
+ type: "turn_request",
2734
+ uuid: generateId3(),
2735
+ agentId: event.agentId,
2736
+ timestamp: Date.now(),
2737
+ turnId,
2738
+ data: {
2739
+ userMessage: event.data,
2740
+ requestedAt: event.timestamp
2741
+ }
2742
+ };
2743
+ return [
2744
+ {
2745
+ ...state,
2746
+ pendingTurn
2747
+ },
2748
+ [turnRequestEvent]
2749
+ ];
2750
+ }
2751
+ function handleMessageStop3(state, event) {
2752
+ if (!state.pendingTurn) {
2753
+ return [state, []];
2692
2754
  }
2693
- async destroy(sessionId) {
2694
- await this.repository.deleteSession(sessionId);
2695
- logger4.info("Session destroyed", { sessionId });
2755
+ const stopReason = event.data.stopReason;
2756
+ if (stopReason === "end_turn" || stopReason === "max_tokens" || stopReason === "stop_sequence") {
2757
+ return completeTurn(state, event.agentId, event.timestamp);
2696
2758
  }
2697
- async destroyByImage(imageId) {
2698
- await this.repository.deleteSessionsByImageId(imageId);
2699
- logger4.info("Sessions destroyed by image", { imageId });
2759
+ return [state, []];
2760
+ }
2761
+ function completeTurn(state, agentId, completedAt) {
2762
+ if (!state.pendingTurn) {
2763
+ return [state, []];
2700
2764
  }
2701
- async destroyAll() {
2702
- const sessions = await this.repository.findAllSessions();
2703
- for (const session of sessions) {
2704
- await this.repository.deleteSession(session.sessionId);
2765
+ const { turnId, requestedAt } = state.pendingTurn;
2766
+ const duration = completedAt - requestedAt;
2767
+ const usage = { input: 0, output: 0 };
2768
+ const cost = calculateCost(usage, state.costPerInputToken, state.costPerOutputToken);
2769
+ const turnResponseEvent = {
2770
+ type: "turn_response",
2771
+ uuid: generateId3(),
2772
+ agentId,
2773
+ timestamp: Date.now(),
2774
+ turnId,
2775
+ data: {
2776
+ assistantMessage: {
2777
+ id: generateId3(),
2778
+ role: "assistant",
2779
+ subtype: "assistant",
2780
+ content: "",
2781
+ timestamp: completedAt
2782
+ },
2783
+ respondedAt: completedAt,
2784
+ durationMs: duration,
2785
+ usage,
2786
+ costUsd: cost
2705
2787
  }
2706
- logger4.info("All sessions destroyed");
2707
- }
2708
- };
2709
- var logger5 = createLogger("agentx/ErrorManager");
2710
- var ErrorManager = class {
2788
+ };
2789
+ return [
2790
+ {
2791
+ ...state,
2792
+ pendingTurn: null
2793
+ },
2794
+ [turnResponseEvent]
2795
+ ];
2796
+ }
2797
+ var agentProcessor = combineProcessors({
2798
+ messageAssembler: messageAssemblerProcessor,
2799
+ stateEventProcessor,
2800
+ turnTracker: turnTrackerProcessor
2801
+ });
2802
+ var createInitialAgentEngineState = combineInitialStates({
2803
+ messageAssembler: createInitialMessageAssemblerState,
2804
+ stateEventProcessor: createInitialStateEventProcessorContext,
2805
+ turnTracker: createInitialTurnTrackerState
2806
+ });
2807
+ var logger33 = createLogger("engine/AgentEngine");
2808
+ var AgentEngine = class {
2711
2809
  constructor() {
2712
- __publicField2(this, "handlers", /* @__PURE__ */ new Set());
2810
+ __publicField(this, "store");
2811
+ this.store = new MemoryStore();
2812
+ logger33.debug("AgentEngine initialized");
2713
2813
  }
2714
2814
  /**
2715
- * Handle an error from any agent
2815
+ * Process a single stream event and return output events
2716
2816
  *
2717
- * Called internally when an agent emits an error event.
2718
- * 1. Default logging (always)
2719
- * 2. Custom handlers (user-registered)
2817
+ * This is the core Mealy Machine operation:
2818
+ * process(agentId, event) outputs[]
2819
+ *
2820
+ * @param agentId - The agent identifier (for state isolation)
2821
+ * @param event - Stream event to process
2822
+ * @returns Array of output events (state, message, turn events)
2720
2823
  */
2721
- handle(agentId, error, event) {
2722
- this.logError(agentId, error);
2723
- for (const handler of this.handlers) {
2724
- try {
2725
- handler.handle(agentId, error, event);
2726
- } catch (e) {
2727
- logger5.error("ErrorHandler failed", { error: e });
2728
- }
2824
+ process(agentId, event) {
2825
+ const eventType = event.type || "unknown";
2826
+ logger33.debug("Processing event", { agentId, eventType });
2827
+ const isNewState = !this.store.has(agentId);
2828
+ let state = this.store.get(agentId) ?? createInitialAgentEngineState();
2829
+ if (isNewState) {
2830
+ logger33.debug("Created initial state for agent", { agentId });
2831
+ }
2832
+ const allOutputs = [];
2833
+ allOutputs.push(event);
2834
+ const [newState, outputs] = agentProcessor(state, event);
2835
+ state = newState;
2836
+ for (const output of outputs) {
2837
+ allOutputs.push(output);
2838
+ const [chainedState, chainedOutputs] = this.processChained(state, output);
2839
+ state = chainedState;
2840
+ allOutputs.push(...chainedOutputs);
2841
+ }
2842
+ this.store.set(agentId, state);
2843
+ if (outputs.length > 0) {
2844
+ logger33.debug("Produced outputs", {
2845
+ agentId,
2846
+ inputEvent: eventType,
2847
+ outputCount: allOutputs.length,
2848
+ processorOutputs: outputs.length
2849
+ });
2729
2850
  }
2851
+ return allOutputs;
2730
2852
  }
2731
2853
  /**
2732
- * Add a custom error handler
2854
+ * Process chained events recursively
2855
+ *
2856
+ * Some processors produce events that trigger other processors:
2857
+ * - MessageAssembler produces MessageEvents
2858
+ * - TurnTracker consumes MessageEvents to produce TurnEvents
2733
2859
  */
2734
- addHandler(handler) {
2735
- this.handlers.add(handler);
2736
- return () => {
2737
- this.handlers.delete(handler);
2738
- };
2860
+ processChained(state, event) {
2861
+ const [newState, outputs] = agentProcessor(state, event);
2862
+ if (outputs.length === 0) {
2863
+ return [newState, []];
2864
+ }
2865
+ const allOutputs = [...outputs];
2866
+ let currentState = newState;
2867
+ for (const output of outputs) {
2868
+ const [chainedState, chainedOutputs] = this.processChained(currentState, output);
2869
+ currentState = chainedState;
2870
+ allOutputs.push(...chainedOutputs);
2871
+ }
2872
+ return [currentState, allOutputs];
2739
2873
  }
2740
2874
  /**
2741
- * Remove an error handler
2875
+ * Clear state for an agent
2876
+ *
2877
+ * Call this when an agent is destroyed to free memory.
2742
2878
  */
2743
- removeHandler(handler) {
2744
- this.handlers.delete(handler);
2879
+ clearState(agentId) {
2880
+ logger33.debug("Clearing state", { agentId });
2881
+ this.store.delete(agentId);
2745
2882
  }
2746
2883
  /**
2747
- * Default error logging
2884
+ * Check if state exists for an agent
2748
2885
  */
2749
- logError(agentId, error) {
2750
- const prefix = `[${agentId}] ${error.category}/${error.code}`;
2751
- if (error.severity === "fatal") {
2752
- logger5.error(`${prefix}: ${error.message}`, { error });
2753
- } else if (error.severity === "error") {
2754
- logger5.error(`${prefix}: ${error.message}`);
2755
- } else {
2756
- logger5.warn(`${prefix}: ${error.message}`);
2757
- }
2886
+ hasState(agentId) {
2887
+ return this.store.has(agentId);
2758
2888
  }
2759
2889
  };
2760
- var logger6 = createLogger("agentx/ContainerManager");
2890
+ var logger7 = createLogger("agentx/ContainerManager");
2761
2891
  function generateContainerId() {
2762
2892
  const timestamp = Date.now().toString(36);
2763
2893
  const random = Math.random().toString(36).substring(2, 8);
@@ -2770,10 +2900,10 @@ function generateAgentId() {
2770
2900
  }
2771
2901
  var ContainerManagerImpl = class {
2772
2902
  constructor(runtime, repository) {
2773
- __publicField2(this, "agents", /* @__PURE__ */ new Map());
2774
- __publicField2(this, "engine");
2775
- __publicField2(this, "runtime");
2776
- __publicField2(this, "repository");
2903
+ __publicField(this, "agents", /* @__PURE__ */ new Map());
2904
+ __publicField(this, "engine");
2905
+ __publicField(this, "runtime");
2906
+ __publicField(this, "repository");
2777
2907
  this.runtime = runtime;
2778
2908
  this.repository = repository;
2779
2909
  this.engine = new AgentEngine();
@@ -2789,7 +2919,7 @@ var ContainerManagerImpl = class {
2789
2919
  config: config2
2790
2920
  };
2791
2921
  await this.repository.saveContainer(record);
2792
- logger6.info("Container created", { containerId });
2922
+ logger7.info("Container created", { containerId });
2793
2923
  return record;
2794
2924
  }
2795
2925
  async get(containerId) {
@@ -2804,7 +2934,7 @@ var ContainerManagerImpl = class {
2804
2934
  return false;
2805
2935
  }
2806
2936
  await this.repository.deleteContainer(containerId);
2807
- logger6.info("Container deleted", { containerId });
2937
+ logger7.info("Container deleted", { containerId });
2808
2938
  return true;
2809
2939
  }
2810
2940
  async exists(containerId) {
@@ -2812,7 +2942,7 @@ var ContainerManagerImpl = class {
2812
2942
  }
2813
2943
  // ==================== Agent Runtime ====================
2814
2944
  async run(image, containerId) {
2815
- logger6.info("Running agent from image", {
2945
+ logger7.info("Running agent from image", {
2816
2946
  imageId: image.imageId,
2817
2947
  containerId
2818
2948
  });
@@ -2834,7 +2964,7 @@ var ContainerManagerImpl = class {
2834
2964
  const driver = this.runtime.createDriver(image.definition, context, sandbox);
2835
2965
  const agent = new AgentInstance(image.definition, context, this.engine, driver, sandbox);
2836
2966
  this.agents.set(agentId, agent);
2837
- logger6.info("Agent started", {
2967
+ logger7.info("Agent started", {
2838
2968
  agentId,
2839
2969
  imageId: image.imageId,
2840
2970
  containerId,
@@ -2843,7 +2973,7 @@ var ContainerManagerImpl = class {
2843
2973
  return agent;
2844
2974
  }
2845
2975
  async resume(session, containerId) {
2846
- logger6.info("Resuming agent from session", {
2976
+ logger7.info("Resuming agent from session", {
2847
2977
  sessionId: session.sessionId,
2848
2978
  imageId: session.imageId,
2849
2979
  containerId
@@ -2871,7 +3001,7 @@ var ContainerManagerImpl = class {
2871
3001
  const driver = this.runtime.createDriver(definition, context, sandbox);
2872
3002
  const agent = new AgentInstance(definition, context, this.engine, driver, sandbox);
2873
3003
  this.agents.set(agentId, agent);
2874
- logger6.info("Agent resumed", {
3004
+ logger7.info("Agent resumed", {
2875
3005
  agentId,
2876
3006
  sessionId: session.sessionId,
2877
3007
  imageId: session.imageId,
@@ -2882,13 +3012,13 @@ var ContainerManagerImpl = class {
2882
3012
  async destroyAgent(agentId) {
2883
3013
  const agent = this.agents.get(agentId);
2884
3014
  if (!agent) {
2885
- logger6.warn("Agent not found for destroy", { agentId });
3015
+ logger7.warn("Agent not found for destroy", { agentId });
2886
3016
  return;
2887
3017
  }
2888
- logger6.debug("Destroying agent", { agentId });
3018
+ logger7.debug("Destroying agent", { agentId });
2889
3019
  await agent.destroy();
2890
3020
  this.agents.delete(agentId);
2891
- logger6.info("Agent destroyed", { agentId });
3021
+ logger7.info("Agent destroyed", { agentId });
2892
3022
  }
2893
3023
  getAgent(agentId) {
2894
3024
  return this.agents.get(agentId);
@@ -2901,14 +3031,14 @@ var ContainerManagerImpl = class {
2901
3031
  }
2902
3032
  async destroyAllAgents() {
2903
3033
  const agentIds = Array.from(this.agents.keys());
2904
- logger6.debug("Destroying all agents", { count: agentIds.length });
3034
+ logger7.debug("Destroying all agents", { count: agentIds.length });
2905
3035
  await Promise.all(agentIds.map((id) => this.destroyAgent(id)));
2906
- logger6.info("All agents destroyed", { count: agentIds.length });
3036
+ logger7.info("All agents destroyed", { count: agentIds.length });
2907
3037
  }
2908
3038
  };
2909
- var logger7 = createLogger("agentx/AgentX");
3039
+ var logger8 = createLogger("agentx/AgentX");
2910
3040
  function createAgentX(runtime, options) {
2911
- logger7.info("Creating AgentX instance", { runtime: runtime.name });
3041
+ logger8.info("Creating AgentX instance", { runtime: runtime.name });
2912
3042
  if (!runtime.repository) {
2913
3043
  throw new Error("Runtime must have a repository for persistence");
2914
3044
  }
@@ -2919,7 +3049,7 @@ function createAgentX(runtime, options) {
2919
3049
  const agentManager = new AgentManager(containerManager);
2920
3050
  const imageManager = new ImageManagerImpl(repository, containerManager, options == null ? void 0 : options.containerId);
2921
3051
  const sessionManager = new SessionManagerImpl(repository, containerManager, options == null ? void 0 : options.containerId);
2922
- logger7.debug("AgentX instance created", { runtime: runtime.name });
3052
+ logger8.debug("AgentX instance created", { runtime: runtime.name });
2923
3053
  return {
2924
3054
  mode: "local",
2925
3055
  containers: containerManager,
@@ -2933,9 +3063,9 @@ function createAgentX(runtime, options) {
2933
3063
  createLogger("agentx/RemoteRepository");
2934
3064
  var _BrowserLogger = class _BrowserLogger2 {
2935
3065
  constructor(name, options = {}) {
2936
- __publicField2(this, "name");
2937
- __publicField2(this, "level");
2938
- __publicField2(this, "collapsed");
3066
+ __publicField(this, "name");
3067
+ __publicField(this, "level");
3068
+ __publicField(this, "collapsed");
2939
3069
  this.name = name;
2940
3070
  this.level = options.level ?? LogLevel.INFO;
2941
3071
  this.collapsed = options.collapsed ?? true;
@@ -3013,7 +3143,7 @@ var _BrowserLogger = class _BrowserLogger2 {
3013
3143
  }
3014
3144
  }
3015
3145
  };
3016
- __publicField2(_BrowserLogger, "STYLES", {
3146
+ __publicField(_BrowserLogger, "STYLES", {
3017
3147
  DEBUG: "color: #6B7280; font-weight: normal;",
3018
3148
  // gray
3019
3149
  INFO: "color: #10B981; font-weight: normal;",
@@ -3028,7 +3158,7 @@ __publicField2(_BrowserLogger, "STYLES", {
3028
3158
  // purple
3029
3159
  MESSAGE: "color: inherit; font-weight: normal;"
3030
3160
  });
3031
- __publicField2(_BrowserLogger, "BADGE_STYLES", {
3161
+ __publicField(_BrowserLogger, "BADGE_STYLES", {
3032
3162
  DEBUG: "background: #E5E7EB; color: #374151; padding: 2px 6px; border-radius: 3px; font-size: 11px;",
3033
3163
  INFO: "background: #D1FAE5; color: #065F46; padding: 2px 6px; border-radius: 3px; font-size: 11px;",
3034
3164
  WARN: "background: #FEF3C7; color: #92400E; padding: 2px 6px; border-radius: 3px; font-size: 11px;",
@@ -3038,4 +3168,4 @@ createLogger("agentx/RemoteAgentIdResolver");
3038
3168
  export {
3039
3169
  createAgentX
3040
3170
  };
3041
- //# sourceMappingURL=index-CB5mSMCj.js.map
3171
+ //# sourceMappingURL=index-CRELszoW.js.map