@agentxjs/ui 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-CB5mSMCj.js → index-CRELszoW.js} +1956 -1826
- package/dist/index-CRELszoW.js.map +1 -0
- package/dist/{index-CyXGvO5F.js → index-O2e5VGwL.js} +45 -46
- package/dist/{index-CyXGvO5F.js.map → index-O2e5VGwL.js.map} +1 -1
- package/dist/index.js +44 -44
- package/package.json +5 -5
- package/dist/index-CB5mSMCj.js.map +0 -1
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
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
|
|
749
|
-
var
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
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
|
-
|
|
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
|
-
|
|
780
|
-
|
|
781
|
-
|
|
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
|
-
|
|
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
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
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
|
-
|
|
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
|
-
|
|
876
|
-
|
|
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
|
-
|
|
884
|
-
|
|
885
|
-
this.emit(event);
|
|
886
|
-
}
|
|
792
|
+
isWarnEnabled() {
|
|
793
|
+
return this.level <= LogLevel.WARN;
|
|
887
794
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
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
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
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
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
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
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
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
|
-
|
|
925
|
-
|
|
926
|
-
|
|
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
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
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
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
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
|
-
|
|
951
|
-
|
|
952
|
-
|
|
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 (
|
|
959
|
-
|
|
890
|
+
if (this.config.defaultImplementation) {
|
|
891
|
+
return this.config.defaultImplementation(name);
|
|
960
892
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
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
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
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
|
-
|
|
994
|
-
|
|
995
|
-
|
|
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
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
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
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
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
|
|
1037
|
-
|
|
1038
|
-
|
|
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
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
if (
|
|
1053
|
-
return
|
|
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
|
-
|
|
1056
|
-
|
|
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
|
-
|
|
1059
|
-
|
|
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 (
|
|
1062
|
-
|
|
1052
|
+
if (record.type === "meta") {
|
|
1053
|
+
logger2.warn("Cannot delete MetaImage directly", { imageId });
|
|
1054
|
+
return false;
|
|
1063
1055
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
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
|
-
|
|
1068
|
-
|
|
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.
|
|
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
|
-
*
|
|
1082
|
+
* Get an existing agent by ID
|
|
1074
1083
|
*/
|
|
1075
|
-
|
|
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
|
-
*
|
|
1087
|
-
*
|
|
1088
|
-
* ErrorEvent is independent from Message layer and transportable via SSE.
|
|
1088
|
+
* Check if an agent exists
|
|
1089
1089
|
*/
|
|
1090
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
1128
|
-
|
|
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
|
-
*
|
|
1100
|
+
* Destroy an agent by ID
|
|
1141
1101
|
*/
|
|
1142
|
-
|
|
1143
|
-
|
|
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
|
-
*
|
|
1108
|
+
* Destroy all agents
|
|
1147
1109
|
*/
|
|
1148
|
-
|
|
1149
|
-
|
|
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
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
this
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
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
|
-
|
|
1204
|
-
*/
|
|
1205
|
-
clear() {
|
|
1206
|
-
this.interceptors.length = 0;
|
|
1149
|
+
get title() {
|
|
1150
|
+
return this._title;
|
|
1207
1151
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
*/
|
|
1211
|
-
get size() {
|
|
1212
|
-
return this.interceptors.length;
|
|
1152
|
+
get updatedAt() {
|
|
1153
|
+
return this._updatedAt;
|
|
1213
1154
|
}
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
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
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
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
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
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
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
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
|
-
*
|
|
1320
|
-
*
|
|
1321
|
-
* Runs through middleware chain before actual processing.
|
|
1337
|
+
* Handle an error from any agent
|
|
1322
1338
|
*
|
|
1323
|
-
*
|
|
1324
|
-
*
|
|
1325
|
-
*
|
|
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
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
"
|
|
1335
|
-
|
|
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
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
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
|
-
*
|
|
1363
|
+
* Remove an error handler
|
|
1380
1364
|
*/
|
|
1381
|
-
|
|
1382
|
-
|
|
1365
|
+
removeHandler(handler) {
|
|
1366
|
+
this.handlers.delete(handler);
|
|
1383
1367
|
}
|
|
1384
1368
|
/**
|
|
1385
|
-
*
|
|
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
|
-
|
|
1394
|
-
const
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
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.
|
|
1421
|
+
this.handlers.delete(handler);
|
|
1540
1422
|
};
|
|
1541
1423
|
}
|
|
1542
1424
|
/**
|
|
1543
|
-
*
|
|
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
|
-
|
|
1552
|
-
|
|
1427
|
+
reset() {
|
|
1428
|
+
this._state;
|
|
1429
|
+
this._state = "idle";
|
|
1430
|
+
this.handlers.clear();
|
|
1553
1431
|
}
|
|
1554
1432
|
/**
|
|
1555
|
-
*
|
|
1433
|
+
* Map StateEvent type to AgentState
|
|
1556
1434
|
*
|
|
1557
|
-
*
|
|
1558
|
-
*
|
|
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
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
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
|
-
*
|
|
1481
|
+
* Notify all registered handlers of state change
|
|
1572
1482
|
*/
|
|
1573
|
-
|
|
1574
|
-
|
|
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
|
-
|
|
1580
|
-
|
|
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
|
|
1497
|
+
var logger22 = createLogger("core/AgentEventBus");
|
|
1498
|
+
var AgentEventBus = class {
|
|
1625
1499
|
constructor() {
|
|
1626
|
-
__publicField(this, "
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
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
|
-
|
|
1632
|
-
|
|
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
|
-
|
|
1635
|
-
|
|
1516
|
+
emitBatch(events) {
|
|
1517
|
+
for (const event of events) {
|
|
1518
|
+
this.emit(event);
|
|
1519
|
+
}
|
|
1636
1520
|
}
|
|
1637
|
-
|
|
1638
|
-
|
|
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
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
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
|
-
*
|
|
1642
|
+
* Execute handler respecting priority order for typed subscriptions
|
|
1648
1643
|
*/
|
|
1649
|
-
|
|
1650
|
-
|
|
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
|
-
*
|
|
1656
|
+
* Execute handler respecting priority order for global subscriptions
|
|
1654
1657
|
*/
|
|
1655
|
-
|
|
1656
|
-
|
|
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
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1681
|
-
|
|
1682
|
-
}
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
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
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
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
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
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
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
toolInput = {};
|
|
1734
|
+
};
|
|
1735
|
+
var MiddlewareChain = class {
|
|
1736
|
+
constructor() {
|
|
1737
|
+
__publicField(this, "middlewares", []);
|
|
1799
1738
|
}
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
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
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
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
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
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
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
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
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
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
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
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
|
|
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
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
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
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
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
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
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
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
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
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
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
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
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
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
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
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
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
|
-
*
|
|
2104
|
+
* Subscribe to state changes (delegated to StateMachine)
|
|
2207
2105
|
*
|
|
2208
|
-
*
|
|
2209
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
2216
|
-
const
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
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
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
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.
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
2252
|
-
|
|
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
|
-
*
|
|
2267
|
-
*
|
|
2268
|
-
* Call this when an agent is destroyed to free memory.
|
|
2256
|
+
* Get the number of stored states
|
|
2269
2257
|
*/
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
this.store.delete(agentId);
|
|
2258
|
+
get size() {
|
|
2259
|
+
return this.states.size;
|
|
2273
2260
|
}
|
|
2274
2261
|
/**
|
|
2275
|
-
*
|
|
2262
|
+
* Get all stored IDs
|
|
2276
2263
|
*/
|
|
2277
|
-
|
|
2278
|
-
return this.
|
|
2264
|
+
keys() {
|
|
2265
|
+
return this.states.keys();
|
|
2279
2266
|
}
|
|
2280
2267
|
};
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
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
|
|
2289
|
-
|
|
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
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
source: "code",
|
|
2296
|
-
createdAt: now,
|
|
2297
|
-
updatedAt: now
|
|
2294
|
+
currentMessageId: null,
|
|
2295
|
+
messageStartTime: null,
|
|
2296
|
+
pendingContents: {},
|
|
2297
|
+
pendingToolCalls: {}
|
|
2298
2298
|
};
|
|
2299
2299
|
}
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
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
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
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
|
|
2364
|
-
const
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
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
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
}
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
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
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
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
|
-
|
|
2423
|
-
|
|
2403
|
+
let toolInput = {};
|
|
2404
|
+
try {
|
|
2405
|
+
toolInput = pendingContent.toolInputJson ? JSON.parse(pendingContent.toolInputJson) : {};
|
|
2406
|
+
} catch {
|
|
2407
|
+
toolInput = {};
|
|
2424
2408
|
}
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
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
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
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
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
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
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
if (
|
|
2442
|
-
|
|
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
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
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
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
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
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
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
|
|
2502
|
-
|
|
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
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
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
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
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
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
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
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
}
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
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
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
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
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
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
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2759
|
+
return [state, []];
|
|
2760
|
+
}
|
|
2761
|
+
function completeTurn(state, agentId, completedAt) {
|
|
2762
|
+
if (!state.pendingTurn) {
|
|
2763
|
+
return [state, []];
|
|
2700
2764
|
}
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
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
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
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
|
-
|
|
2810
|
+
__publicField(this, "store");
|
|
2811
|
+
this.store = new MemoryStore();
|
|
2812
|
+
logger33.debug("AgentEngine initialized");
|
|
2713
2813
|
}
|
|
2714
2814
|
/**
|
|
2715
|
-
*
|
|
2815
|
+
* Process a single stream event and return output events
|
|
2716
2816
|
*
|
|
2717
|
-
*
|
|
2718
|
-
*
|
|
2719
|
-
*
|
|
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
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
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
|
-
*
|
|
2875
|
+
* Clear state for an agent
|
|
2876
|
+
*
|
|
2877
|
+
* Call this when an agent is destroyed to free memory.
|
|
2742
2878
|
*/
|
|
2743
|
-
|
|
2744
|
-
|
|
2879
|
+
clearState(agentId) {
|
|
2880
|
+
logger33.debug("Clearing state", { agentId });
|
|
2881
|
+
this.store.delete(agentId);
|
|
2745
2882
|
}
|
|
2746
2883
|
/**
|
|
2747
|
-
*
|
|
2884
|
+
* Check if state exists for an agent
|
|
2748
2885
|
*/
|
|
2749
|
-
|
|
2750
|
-
|
|
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
|
|
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
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3015
|
+
logger7.warn("Agent not found for destroy", { agentId });
|
|
2886
3016
|
return;
|
|
2887
3017
|
}
|
|
2888
|
-
|
|
3018
|
+
logger7.debug("Destroying agent", { agentId });
|
|
2889
3019
|
await agent.destroy();
|
|
2890
3020
|
this.agents.delete(agentId);
|
|
2891
|
-
|
|
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
|
-
|
|
3034
|
+
logger7.debug("Destroying all agents", { count: agentIds.length });
|
|
2905
3035
|
await Promise.all(agentIds.map((id) => this.destroyAgent(id)));
|
|
2906
|
-
|
|
3036
|
+
logger7.info("All agents destroyed", { count: agentIds.length });
|
|
2907
3037
|
}
|
|
2908
3038
|
};
|
|
2909
|
-
var
|
|
3039
|
+
var logger8 = createLogger("agentx/AgentX");
|
|
2910
3040
|
function createAgentX(runtime, options) {
|
|
2911
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
3171
|
+
//# sourceMappingURL=index-CRELszoW.js.map
|