@elizaos/core 1.0.8 → 1.0.10

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.
@@ -106,7 +106,7 @@ __export(v2_exports, {
106
106
  isMessageMetadata: () => isMessageMetadata,
107
107
  logger: () => logger2,
108
108
  messageHandlerTemplate: () => messageHandlerTemplate2,
109
- parseBooleanFromText: () => parseBooleanFromText2,
109
+ parseBooleanFromText: () => parseBooleanFromText3,
110
110
  parseJSONObjectFromText: () => parseJSONObjectFromText2,
111
111
  parseKeyValueXml: () => parseKeyValueXml2,
112
112
  postCreationTemplate: () => postCreationTemplate2,
@@ -513,7 +513,10 @@ var ServiceType3 = {
513
513
  WALLET: "wallet",
514
514
  LP_POOL: "lp_pool",
515
515
  TOKEN_DATA: "token_data",
516
- DATABASE_MIGRATION: "database_migration"
516
+ DATABASE_MIGRATION: "database_migration",
517
+ PLUGIN_MANAGER: "PLUGIN_MANAGER",
518
+ PLUGIN_CONFIGURATION: "PLUGIN_CONFIGURATION",
519
+ PLUGIN_USER_INTERACTION: "PLUGIN_USER_INTERACTION"
517
520
  };
518
521
  var Service3 = class {
519
522
  constructor(runtime) {
@@ -679,71 +682,12 @@ var ILpService = class extends Service3 {
679
682
  }
680
683
  };
681
684
 
682
- // src/actions.ts
685
+ // src/utils.ts
686
+ import handlebars from "handlebars";
687
+ import { sha1 } from "js-sha1";
688
+ import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
683
689
  import { names, uniqueNamesGenerator } from "unique-names-generator";
684
- var composeActionExamples2 = (actionsData, count) => {
685
- if (!actionsData.length || count <= 0) {
686
- return "";
687
- }
688
- const actionsWithExamples = actionsData.filter(
689
- (action) => action.examples && Array.isArray(action.examples) && action.examples.length > 0
690
- );
691
- if (!actionsWithExamples.length) {
692
- return "";
693
- }
694
- const examplesCopy = actionsWithExamples.map((action) => [
695
- ...action.examples
696
- ]);
697
- const selectedExamples = [];
698
- let availableActionIndices = examplesCopy.map((examples, index) => examples.length > 0 ? index : -1).filter((index) => index !== -1);
699
- while (selectedExamples.length < count && availableActionIndices.length > 0) {
700
- const randomIndex = Math.floor(Math.random() * availableActionIndices.length);
701
- const actionIndex = availableActionIndices[randomIndex];
702
- const examples = examplesCopy[actionIndex];
703
- const exampleIndex = Math.floor(Math.random() * examples.length);
704
- selectedExamples.push(examples.splice(exampleIndex, 1)[0]);
705
- if (examples.length === 0) {
706
- availableActionIndices.splice(randomIndex, 1);
707
- }
708
- }
709
- return formatSelectedExamples(selectedExamples);
710
- };
711
- var formatSelectedExamples = (examples) => {
712
- const MAX_NAME_PLACEHOLDERS = 5;
713
- return examples.map((example) => {
714
- const randomNames = Array.from(
715
- { length: MAX_NAME_PLACEHOLDERS },
716
- () => uniqueNamesGenerator({ dictionaries: [names] })
717
- );
718
- const conversation = example.map((message) => {
719
- let messageText = `${message.name}: ${message.content.text}`;
720
- if (message.content.action) {
721
- messageText += ` (action: ${message.content.action})`;
722
- }
723
- if (message.content.actions?.length) {
724
- messageText += ` (actions: ${message.content.actions.join(", ")})`;
725
- }
726
- for (let i = 0; i < randomNames.length; i++) {
727
- messageText = messageText.replaceAll(`{{name${i + 1}}}`, randomNames[i]);
728
- }
729
- return messageText;
730
- }).join("\n");
731
- return `
732
- ${conversation}`;
733
- }).join("\n");
734
- };
735
- function formatActionNames2(actions) {
736
- if (!actions?.length) return "";
737
- return [...actions].sort(() => Math.random() - 0.5).map((action) => action.name).join(", ");
738
- }
739
- function formatActions2(actions) {
740
- if (!actions?.length) return "";
741
- return [...actions].sort(() => Math.random() - 0.5).map((action) => `${action.name}: ${action.description}`).join(",\n");
742
- }
743
-
744
- // src/database.ts
745
- var DatabaseAdapter2 = class {
746
- };
690
+ import { z } from "zod";
747
691
 
748
692
  // src/logger.ts
749
693
  import pino from "pino";
@@ -762,391 +706,71 @@ if (process.env.SENTRY_LOGGING !== "false") {
762
706
  });
763
707
  }
764
708
 
765
- // src/utils.ts
766
- import handlebars from "handlebars";
767
- import { sha1 } from "js-sha1";
768
- import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
769
- import { names as names2, uniqueNamesGenerator as uniqueNamesGenerator2 } from "unique-names-generator";
770
- import { z } from "zod";
771
- function upgradeDoubleToTriple(tpl) {
772
- return tpl.replace(
773
- // ────────╮ negative-LB: not already "{{{"
774
- // │ {{ ─ opening braces
775
- // │ ╰──── negative-LA: not {, #, /, !, >
776
- // ▼
777
- /(?<!{){{(?![{#\/!>])([\s\S]*?)}}/g,
778
- (_match, inner) => {
779
- if (inner.trim() === "else") return `{{${inner}}}`;
780
- return `{{{${inner}}}}`;
781
- }
782
- );
709
+ // src/logger.ts
710
+ function parseBooleanFromText(value) {
711
+ if (!value) return false;
712
+ const normalized = value.toLowerCase().trim();
713
+ return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on";
783
714
  }
784
- var composePrompt = ({
785
- state,
786
- template
787
- }) => {
788
- const templateStr = typeof template === "function" ? template({ state }) : template;
789
- const templateFunction = handlebars.compile(upgradeDoubleToTriple(templateStr));
790
- const output = composeRandomUser(templateFunction(state), 10);
791
- return output;
792
- };
793
- var composePromptFromState = ({
794
- state,
795
- template
796
- }) => {
797
- const templateStr = typeof template === "function" ? template({ state }) : template;
798
- const templateFunction = handlebars.compile(upgradeDoubleToTriple(templateStr));
799
- const stateKeys = Object.keys(state);
800
- const filteredKeys = stateKeys.filter((key) => !["text", "values", "data"].includes(key));
801
- const filteredState = filteredKeys.reduce((acc, key) => {
802
- acc[key] = state[key];
803
- return acc;
804
- }, {});
805
- const output = composeRandomUser(templateFunction({ ...filteredState, ...state.values }), 10);
806
- return output;
807
- };
808
- var addHeader = (header, body) => {
809
- return body.length > 0 ? `${header ? `${header}
810
- ` : header}${body}
811
- ` : "";
812
- };
813
- var composeRandomUser = (template, length) => {
814
- const exampleNames = Array.from(
815
- { length },
816
- () => uniqueNamesGenerator2({ dictionaries: [names2] })
817
- );
818
- let result = template;
819
- for (let i = 0; i < exampleNames.length; i++) {
820
- result = result.replaceAll(`{{name${i + 1}}}`, exampleNames[i]);
715
+ var InMemoryDestination = class {
716
+ /**
717
+ * Constructor for creating a new instance of the class.
718
+ * @param {DestinationStream|null} stream - The stream to assign to the instance. Can be null.
719
+ */
720
+ constructor(stream) {
721
+ this.logs = [];
722
+ this.maxLogs = 1e3;
723
+ this.stream = stream;
821
724
  }
822
- return result;
823
- };
824
- var formatPosts = ({
825
- messages,
826
- entities,
827
- conversationHeader = true
828
- }) => {
829
- const groupedMessages = {};
830
- messages.forEach((message) => {
831
- if (message.roomId) {
832
- if (!groupedMessages[message.roomId]) {
833
- groupedMessages[message.roomId] = [];
725
+ /**
726
+ * Writes a log entry to the memory buffer and forwards it to the pretty print stream if available.
727
+ *
728
+ * @param {string | LogEntry} data - The data to be written, which can be either a string or a LogEntry object.
729
+ * @returns {void}
730
+ */
731
+ write(data) {
732
+ let logEntry;
733
+ let stringData;
734
+ if (typeof data === "string") {
735
+ stringData = data;
736
+ try {
737
+ logEntry = JSON.parse(data);
738
+ } catch (e) {
739
+ if (this.stream) {
740
+ this.stream.write(data);
741
+ }
742
+ return;
834
743
  }
835
- groupedMessages[message.roomId].push(message);
744
+ } else {
745
+ logEntry = data;
746
+ stringData = JSON.stringify(data);
836
747
  }
837
- });
838
- Object.values(groupedMessages).forEach((roomMessages) => {
839
- roomMessages.sort((a, b) => a.createdAt - b.createdAt);
840
- });
841
- const sortedRooms = Object.entries(groupedMessages).sort(
842
- ([, messagesA], [, messagesB]) => messagesB[messagesB.length - 1].createdAt - messagesA[messagesA.length - 1].createdAt
843
- );
844
- const formattedPosts = sortedRooms.map(([roomId, roomMessages]) => {
845
- const messageStrings = roomMessages.filter((message) => message.entityId).map((message) => {
846
- const entity = entities.find((entity2) => entity2.id === message.entityId);
847
- if (!entity) {
848
- logger_default.warn("core::prompts:formatPosts - no entity for", message.entityId);
748
+ if (!logEntry.time) {
749
+ logEntry.time = Date.now();
750
+ }
751
+ const isDebugMode2 = (process?.env?.LOG_LEVEL || "").toLowerCase() === "debug";
752
+ const isLoggingDiagnostic = Boolean(process?.env?.LOG_DIAGNOSTIC);
753
+ if (isLoggingDiagnostic) {
754
+ logEntry.diagnostic = true;
755
+ }
756
+ if (!isDebugMode2) {
757
+ if (logEntry.agentName && logEntry.agentId) {
758
+ const msg = logEntry.msg || "";
759
+ if (typeof msg === "string" && (msg.includes("registered successfully") || msg.includes("Registering") || msg.includes("Success:") || msg.includes("linked to") || msg.includes("Started"))) {
760
+ if (isLoggingDiagnostic) {
761
+ console.error("Filtered log:", stringData);
762
+ }
763
+ return;
764
+ }
849
765
  }
850
- const userName = entity?.names[0] || "Unknown User";
851
- const displayName = entity?.names[0] || "unknown";
852
- return `Name: ${userName} (@${displayName} EntityID:${message.entityId})
853
- MessageID: ${message.id}${message.content.inReplyTo ? `
854
- In reply to: ${message.content.inReplyTo}` : ""}
855
- Source: ${message.content.source}
856
- Date: ${formatTimestamp(message.createdAt)}
857
- Text:
858
- ${message.content.text}`;
859
- });
860
- const header = conversationHeader ? `Conversation: ${roomId.slice(-5)}
861
- ` : "";
862
- return `${header}${messageStrings.join("\n\n")}`;
863
- });
864
- return formattedPosts.join("\n\n");
865
- };
866
- var formatMessages = ({
867
- messages,
868
- entities
869
- }) => {
870
- const messageStrings = messages.reverse().filter((message) => message.entityId).map((message) => {
871
- const messageText = message.content.text;
872
- const messageActions = message.content.actions;
873
- const messageThought = message.content.thought;
874
- const formattedName = entities.find((entity) => entity.id === message.entityId)?.names[0] || "Unknown User";
875
- const attachments = message.content.attachments;
876
- const attachmentString = attachments && attachments.length > 0 ? ` (Attachments: ${attachments.map((media) => `[${media.id} - ${media.title} (${media.url})]`).join(", ")})` : null;
877
- const messageTime = new Date(message.createdAt);
878
- const hours = messageTime.getHours().toString().padStart(2, "0");
879
- const minutes = messageTime.getMinutes().toString().padStart(2, "0");
880
- const timeString = `${hours}:${minutes}`;
881
- const timestamp = formatTimestamp(message.createdAt);
882
- const thoughtString = messageThought ? `(${formattedName}'s internal thought: ${messageThought})` : null;
883
- const timestampString = `${timeString} (${timestamp}) [${message.entityId}]`;
884
- const textString = messageText ? `${timestampString} ${formattedName}: ${messageText}` : null;
885
- const actionString = messageActions && messageActions.length > 0 ? `${textString ? "" : timestampString} (${formattedName}'s actions: ${messageActions.join(", ")})` : null;
886
- const messageString = [textString, thoughtString, actionString, attachmentString].filter(Boolean).join("\n");
887
- return messageString;
888
- }).join("\n");
889
- return messageStrings;
890
- };
891
- var formatTimestamp = (messageDate) => {
892
- const now = /* @__PURE__ */ new Date();
893
- const diff = now.getTime() - messageDate;
894
- const absDiff = Math.abs(diff);
895
- const seconds = Math.floor(absDiff / 1e3);
896
- const minutes = Math.floor(seconds / 60);
897
- const hours = Math.floor(minutes / 60);
898
- const days = Math.floor(hours / 24);
899
- if (absDiff < 6e4) {
900
- return "just now";
901
- }
902
- if (minutes < 60) {
903
- return `${minutes} minute${minutes !== 1 ? "s" : ""} ago`;
904
- }
905
- if (hours < 24) {
906
- return `${hours} hour${hours !== 1 ? "s" : ""} ago`;
907
- }
908
- return `${days} day${days !== 1 ? "s" : ""} ago`;
909
- };
910
- var jsonBlockPattern = /```json\n([\s\S]*?)\n```/;
911
- function parseKeyValueXml(text) {
912
- if (!text) return null;
913
- let xmlBlockMatch = text.match(/<response>([\s\S]*?)<\/response>/);
914
- let xmlContent;
915
- if (xmlBlockMatch) {
916
- xmlContent = xmlBlockMatch[1];
917
- logger_default.debug("Found response XML block");
918
- } else {
919
- const fallbackMatch = text.match(/<(\w+)>([\s\S]*?)<\/\1>/);
920
- if (!fallbackMatch) {
921
- logger_default.warn("Could not find XML block in text");
922
- logger_default.debug("Text content:", text.substring(0, 200) + "...");
923
- return null;
924
- }
925
- xmlContent = fallbackMatch[2];
926
- logger_default.debug(`Found XML block with tag: ${fallbackMatch[1]}`);
927
- }
928
- const result = {};
929
- const tagPattern = /<([\w-]+)>([\s\S]*?)<\/([\w-]+)>/g;
930
- let match;
931
- while ((match = tagPattern.exec(xmlContent)) !== null) {
932
- if (match[1] === match[3]) {
933
- const key = match[1];
934
- const value = match[2].replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&").replace(/&quot;/g, '"').replace(/&apos;/g, "'").trim();
935
- if (key === "actions" || key === "providers" || key === "evaluators") {
936
- result[key] = value ? value.split(",").map((s) => s.trim()) : [];
937
- } else if (key === "simple") {
938
- result[key] = value.toLowerCase() === "true";
939
- } else {
940
- result[key] = value;
941
- }
942
- } else {
943
- logger_default.warn(`Mismatched XML tags found: <${match[1]}> and </${match[3]}>`);
944
- }
945
- }
946
- if (Object.keys(result).length === 0) {
947
- logger_default.warn("No key-value pairs extracted from XML content");
948
- logger_default.debug("XML content was:", xmlContent.substring(0, 200) + "...");
949
- return null;
950
- }
951
- return result;
952
- }
953
- function parseJSONObjectFromText(text) {
954
- let jsonData = null;
955
- const jsonBlockMatch = text.match(jsonBlockPattern);
956
- try {
957
- if (jsonBlockMatch) {
958
- jsonData = JSON.parse(normalizeJsonString(jsonBlockMatch[1].trim()));
959
- } else {
960
- jsonData = JSON.parse(normalizeJsonString(text.trim()));
961
- }
962
- } catch (_e) {
963
- return null;
964
- }
965
- if (jsonData && typeof jsonData === "object" && !Array.isArray(jsonData)) {
966
- return jsonData;
967
- }
968
- return null;
969
- }
970
- var normalizeJsonString = (str) => {
971
- str = str.replace(/\{\s+/, "{").replace(/\s+\}/, "}").trim();
972
- str = str.replace(/("[\w\d_-]+")\s*: \s*(?!"|\[)([\s\S]+?)(?=(,\s*"|\}$))/g, '$1: "$2"');
973
- str = str.replace(/"([^"]+)"\s*:\s*'([^']*)'/g, (_, key, value) => `"${key}": "${value}"`);
974
- str = str.replace(/("[\w\d_-]+")\s*:\s*([A-Za-z_]+)(?!["\w])/g, '$1: "$2"');
975
- return str;
976
- };
977
- function truncateToCompleteSentence(text, maxLength) {
978
- if (text.length <= maxLength) {
979
- return text;
980
- }
981
- const lastPeriodIndex = text.lastIndexOf(".", maxLength - 1);
982
- if (lastPeriodIndex !== -1) {
983
- const truncatedAtPeriod = text.slice(0, lastPeriodIndex + 1).trim();
984
- if (truncatedAtPeriod.length > 0) {
985
- return truncatedAtPeriod;
986
- }
987
- }
988
- const lastSpaceIndex = text.lastIndexOf(" ", maxLength - 1);
989
- if (lastSpaceIndex !== -1) {
990
- const truncatedAtSpace = text.slice(0, lastSpaceIndex).trim();
991
- if (truncatedAtSpace.length > 0) {
992
- return `${truncatedAtSpace}...`;
993
- }
994
- }
995
- const hardTruncated = text.slice(0, maxLength - 3).trim();
996
- return `${hardTruncated}...`;
997
- }
998
- async function splitChunks(content, chunkSize = 512, bleed = 20) {
999
- logger_default.debug("[splitChunks] Starting text split");
1000
- const characterstoTokens = 3.5;
1001
- const textSplitter = new RecursiveCharacterTextSplitter({
1002
- chunkSize: Number(Math.floor(chunkSize * characterstoTokens)),
1003
- chunkOverlap: Number(Math.floor(bleed * characterstoTokens))
1004
- });
1005
- const chunks = await textSplitter.splitText(content);
1006
- logger_default.debug("[splitChunks] Split complete:", {
1007
- numberOfChunks: chunks.length,
1008
- averageChunkSize: chunks.reduce((acc, chunk) => acc + chunk.length, 0) / chunks.length
1009
- });
1010
- return chunks;
1011
- }
1012
- async function trimTokens(prompt, maxTokens, runtime) {
1013
- if (!prompt) throw new Error("Trim tokens received a null prompt");
1014
- if (prompt.length < maxTokens / 5) return prompt;
1015
- if (maxTokens <= 0) throw new Error("maxTokens must be positive");
1016
- const tokens = await runtime.useModel(ModelType2.TEXT_TOKENIZER_ENCODE, {
1017
- prompt
1018
- });
1019
- if (tokens.length <= maxTokens) {
1020
- return prompt;
1021
- }
1022
- const truncatedTokens = tokens.slice(-maxTokens);
1023
- return await runtime.useModel(ModelType2.TEXT_TOKENIZER_DECODE, {
1024
- tokens: truncatedTokens
1025
- });
1026
- }
1027
- function safeReplacer() {
1028
- const seen = /* @__PURE__ */ new WeakSet();
1029
- return function(key, value) {
1030
- if (typeof value === "object" && value !== null) {
1031
- if (seen.has(value)) {
1032
- return "[Circular]";
1033
- }
1034
- seen.add(value);
1035
- }
1036
- return value;
1037
- };
1038
- }
1039
- function parseBooleanFromText(value) {
1040
- if (!value) return false;
1041
- const affirmative = ["YES", "Y", "TRUE", "T", "1", "ON", "ENABLE"];
1042
- const negative = ["NO", "N", "FALSE", "F", "0", "OFF", "DISABLE"];
1043
- const normalizedText = value.trim().toUpperCase();
1044
- if (affirmative.includes(normalizedText)) {
1045
- return true;
1046
- }
1047
- if (negative.includes(normalizedText)) {
1048
- return false;
1049
- }
1050
- return false;
1051
- }
1052
- var uuidSchema = z.string().uuid();
1053
- function validateUuid(value) {
1054
- const result = uuidSchema.safeParse(value);
1055
- return result.success ? result.data : null;
1056
- }
1057
- function stringToUuid(target) {
1058
- if (typeof target === "number") {
1059
- target = target.toString();
1060
- }
1061
- if (typeof target !== "string") {
1062
- throw TypeError("Value must be string");
1063
- }
1064
- const _uint8ToHex = (ubyte) => {
1065
- const first = ubyte >> 4;
1066
- const second = ubyte - (first << 4);
1067
- const HEX_DIGITS = "0123456789abcdef".split("");
1068
- return HEX_DIGITS[first] + HEX_DIGITS[second];
1069
- };
1070
- const _uint8ArrayToHex = (buf) => {
1071
- let out = "";
1072
- for (let i = 0; i < buf.length; i++) {
1073
- out += _uint8ToHex(buf[i]);
1074
- }
1075
- return out;
1076
- };
1077
- const escapedStr = encodeURIComponent(target);
1078
- const buffer = new Uint8Array(escapedStr.length);
1079
- for (let i = 0; i < escapedStr.length; i++) {
1080
- buffer[i] = escapedStr[i].charCodeAt(0);
1081
- }
1082
- const hash = sha1(buffer);
1083
- const hashBuffer = new Uint8Array(hash.length / 2);
1084
- for (let i = 0; i < hash.length; i += 2) {
1085
- hashBuffer[i / 2] = Number.parseInt(hash.slice(i, i + 2), 16);
1086
- }
1087
- return `${_uint8ArrayToHex(hashBuffer.slice(0, 4))}-${_uint8ArrayToHex(hashBuffer.slice(4, 6))}-${_uint8ToHex(hashBuffer[6] & 15)}${_uint8ToHex(hashBuffer[7])}-${_uint8ToHex(hashBuffer[8] & 63 | 128)}${_uint8ToHex(hashBuffer[9])}-${_uint8ArrayToHex(hashBuffer.slice(10, 16))}`;
1088
- }
1089
-
1090
- // src/logger.ts
1091
- var InMemoryDestination = class {
1092
- /**
1093
- * Constructor for creating a new instance of the class.
1094
- * @param {DestinationStream|null} stream - The stream to assign to the instance. Can be null.
1095
- */
1096
- constructor(stream) {
1097
- this.logs = [];
1098
- this.maxLogs = 1e3;
1099
- this.stream = stream;
1100
- }
1101
- /**
1102
- * Writes a log entry to the memory buffer and forwards it to the pretty print stream if available.
1103
- *
1104
- * @param {string | LogEntry} data - The data to be written, which can be either a string or a LogEntry object.
1105
- * @returns {void}
1106
- */
1107
- write(data) {
1108
- let logEntry;
1109
- let stringData;
1110
- if (typeof data === "string") {
1111
- stringData = data;
1112
- try {
1113
- logEntry = JSON.parse(data);
1114
- } catch (e) {
1115
- if (this.stream) {
1116
- this.stream.write(data);
1117
- }
1118
- return;
1119
- }
1120
- } else {
1121
- logEntry = data;
1122
- stringData = JSON.stringify(data);
1123
- }
1124
- if (!logEntry.time) {
1125
- logEntry.time = Date.now();
1126
- }
1127
- const isDebugMode2 = (process?.env?.LOG_LEVEL || "").toLowerCase() === "debug";
1128
- const isLoggingDiagnostic = Boolean(process?.env?.LOG_DIAGNOSTIC);
1129
- if (isLoggingDiagnostic) {
1130
- logEntry.diagnostic = true;
1131
- }
1132
- if (!isDebugMode2) {
1133
- if (logEntry.agentName && logEntry.agentId) {
1134
- const msg = logEntry.msg || "";
1135
- if (typeof msg === "string" && (msg.includes("registered successfully") || msg.includes("Registering") || msg.includes("Success:") || msg.includes("linked to") || msg.includes("Started"))) {
1136
- if (isLoggingDiagnostic) {
1137
- console.error("Filtered log:", stringData);
1138
- }
1139
- return;
1140
- }
1141
- }
1142
- }
1143
- this.logs.push(logEntry);
1144
- if (this.logs.length > this.maxLogs) {
1145
- this.logs.shift();
1146
- }
1147
- if (this.stream) {
1148
- this.stream.write(stringData);
1149
- }
766
+ }
767
+ this.logs.push(logEntry);
768
+ if (this.logs.length > this.maxLogs) {
769
+ this.logs.shift();
770
+ }
771
+ if (this.stream) {
772
+ this.stream.write(stringData);
773
+ }
1150
774
  }
1151
775
  /**
1152
776
  * Retrieves the recent logs from the system.
@@ -1298,58 +922,540 @@ var options = {
1298
922
  }
1299
923
  }
1300
924
  };
1301
- var createLogger = (bindings = false) => {
1302
- const opts = { ...options };
1303
- if (bindings) {
1304
- opts.base = bindings;
1305
- opts.transport = {
1306
- target: "pino-pretty",
1307
- // this is just a string, not a dynamic import
1308
- options: {
1309
- colorize: true,
1310
- translateTime: "SYS:standard",
1311
- ignore: "pid,hostname"
1312
- }
925
+ var createLogger = (bindings = false) => {
926
+ const opts = { ...options };
927
+ if (bindings) {
928
+ opts.base = bindings;
929
+ opts.transport = {
930
+ target: "pino-pretty",
931
+ // this is just a string, not a dynamic import
932
+ options: {
933
+ colorize: true,
934
+ translateTime: "SYS:standard",
935
+ ignore: "pid,hostname"
936
+ }
937
+ };
938
+ }
939
+ const logger3 = pino(opts);
940
+ return logger3;
941
+ };
942
+ var logger = pino(options);
943
+ if (typeof process !== "undefined") {
944
+ let stream = null;
945
+ if (!raw) {
946
+ try {
947
+ const pretty = __require("pino-pretty");
948
+ stream = pretty.default ? pretty.default(createPrettyConfig()) : null;
949
+ } catch (e) {
950
+ createStream().then((prettyStream) => {
951
+ const destination = new InMemoryDestination(prettyStream);
952
+ logger = pino(options, destination);
953
+ logger[Symbol.for("pino-destination")] = destination;
954
+ logger.clear = () => {
955
+ const destination2 = logger[Symbol.for("pino-destination")];
956
+ if (destination2 instanceof InMemoryDestination) {
957
+ destination2.clear();
958
+ }
959
+ };
960
+ });
961
+ }
962
+ }
963
+ if (stream !== null || raw) {
964
+ const destination = new InMemoryDestination(stream);
965
+ logger = pino(options, destination);
966
+ logger[Symbol.for("pino-destination")] = destination;
967
+ logger.clear = () => {
968
+ const destination2 = logger[Symbol.for("pino-destination")];
969
+ if (destination2 instanceof InMemoryDestination) {
970
+ destination2.clear();
971
+ }
972
+ };
973
+ }
974
+ }
975
+ var elizaLogger = logger;
976
+ var logger_default = logger;
977
+
978
+ // src/utils.ts
979
+ function upgradeDoubleToTriple(tpl) {
980
+ return tpl.replace(
981
+ // ────────╮ negative-LB: not already "{{{"
982
+ // │ {{ ─ opening braces
983
+ // │ ╰──── negative-LA: not {, #, /, !, >
984
+ // ▼
985
+ /(?<!{){{(?![{#\/!>])([\s\S]*?)}}/g,
986
+ (_match, inner) => {
987
+ if (inner.trim() === "else") return `{{${inner}}}`;
988
+ return `{{{${inner}}}}`;
989
+ }
990
+ );
991
+ }
992
+ var composePrompt = ({
993
+ state,
994
+ template
995
+ }) => {
996
+ const templateStr = typeof template === "function" ? template({ state }) : template;
997
+ const templateFunction = handlebars.compile(upgradeDoubleToTriple(templateStr));
998
+ const output = composeRandomUser(templateFunction(state), 10);
999
+ return output;
1000
+ };
1001
+ var composePromptFromState = ({
1002
+ state,
1003
+ template
1004
+ }) => {
1005
+ const templateStr = typeof template === "function" ? template({ state }) : template;
1006
+ const templateFunction = handlebars.compile(upgradeDoubleToTriple(templateStr));
1007
+ const stateKeys = Object.keys(state);
1008
+ const filteredKeys = stateKeys.filter((key) => !["text", "values", "data"].includes(key));
1009
+ const filteredState = filteredKeys.reduce((acc, key) => {
1010
+ acc[key] = state[key];
1011
+ return acc;
1012
+ }, {});
1013
+ const output = composeRandomUser(templateFunction({ ...filteredState, ...state.values }), 10);
1014
+ return output;
1015
+ };
1016
+ var addHeader = (header, body) => {
1017
+ return body.length > 0 ? `${header ? `${header}
1018
+ ` : header}${body}
1019
+ ` : "";
1020
+ };
1021
+ var composeRandomUser = (template, length) => {
1022
+ const exampleNames = Array.from(
1023
+ { length },
1024
+ () => uniqueNamesGenerator({ dictionaries: [names] })
1025
+ );
1026
+ let result = template;
1027
+ for (let i = 0; i < exampleNames.length; i++) {
1028
+ result = result.replaceAll(`{{name${i + 1}}}`, exampleNames[i]);
1029
+ }
1030
+ return result;
1031
+ };
1032
+ var formatPosts = ({
1033
+ messages,
1034
+ entities,
1035
+ conversationHeader = true
1036
+ }) => {
1037
+ const groupedMessages = {};
1038
+ messages.forEach((message) => {
1039
+ if (message.roomId) {
1040
+ if (!groupedMessages[message.roomId]) {
1041
+ groupedMessages[message.roomId] = [];
1042
+ }
1043
+ groupedMessages[message.roomId].push(message);
1044
+ }
1045
+ });
1046
+ Object.values(groupedMessages).forEach((roomMessages) => {
1047
+ roomMessages.sort((a, b) => a.createdAt - b.createdAt);
1048
+ });
1049
+ const sortedRooms = Object.entries(groupedMessages).sort(
1050
+ ([, messagesA], [, messagesB]) => messagesB[messagesB.length - 1].createdAt - messagesA[messagesA.length - 1].createdAt
1051
+ );
1052
+ const formattedPosts = sortedRooms.map(([roomId, roomMessages]) => {
1053
+ const messageStrings = roomMessages.filter((message) => message.entityId).map((message) => {
1054
+ const entity = entities.find((entity2) => entity2.id === message.entityId);
1055
+ if (!entity) {
1056
+ logger_default.warn("core::prompts:formatPosts - no entity for", message.entityId);
1057
+ }
1058
+ const userName = entity?.names[0] || "Unknown User";
1059
+ const displayName = entity?.names[0] || "unknown";
1060
+ return `Name: ${userName} (@${displayName} EntityID:${message.entityId})
1061
+ MessageID: ${message.id}${message.content.inReplyTo ? `
1062
+ In reply to: ${message.content.inReplyTo}` : ""}
1063
+ Source: ${message.content.source}
1064
+ Date: ${formatTimestamp(message.createdAt)}
1065
+ Text:
1066
+ ${message.content.text}`;
1067
+ });
1068
+ const header = conversationHeader ? `Conversation: ${roomId.slice(-5)}
1069
+ ` : "";
1070
+ return `${header}${messageStrings.join("\n\n")}`;
1071
+ });
1072
+ return formattedPosts.join("\n\n");
1073
+ };
1074
+ var formatMessages = ({
1075
+ messages,
1076
+ entities
1077
+ }) => {
1078
+ const messageStrings = messages.reverse().filter((message) => message.entityId).map((message) => {
1079
+ const messageText = message.content.text;
1080
+ const messageActions = message.content.actions;
1081
+ const messageThought = message.content.thought;
1082
+ const formattedName = entities.find((entity) => entity.id === message.entityId)?.names[0] || "Unknown User";
1083
+ const attachments = message.content.attachments;
1084
+ const attachmentString = attachments && attachments.length > 0 ? ` (Attachments: ${attachments.map((media) => `[${media.id} - ${media.title} (${media.url})]`).join(", ")})` : null;
1085
+ const messageTime = new Date(message.createdAt);
1086
+ const hours = messageTime.getHours().toString().padStart(2, "0");
1087
+ const minutes = messageTime.getMinutes().toString().padStart(2, "0");
1088
+ const timeString = `${hours}:${minutes}`;
1089
+ const timestamp = formatTimestamp(message.createdAt);
1090
+ const thoughtString = messageThought ? `(${formattedName}'s internal thought: ${messageThought})` : null;
1091
+ const timestampString = `${timeString} (${timestamp}) [${message.entityId}]`;
1092
+ const textString = messageText ? `${timestampString} ${formattedName}: ${messageText}` : null;
1093
+ const actionString = messageActions && messageActions.length > 0 ? `${textString ? "" : timestampString} (${formattedName}'s actions: ${messageActions.join(", ")})` : null;
1094
+ const messageString = [textString, thoughtString, actionString, attachmentString].filter(Boolean).join("\n");
1095
+ return messageString;
1096
+ }).join("\n");
1097
+ return messageStrings;
1098
+ };
1099
+ var formatTimestamp = (messageDate) => {
1100
+ const now = /* @__PURE__ */ new Date();
1101
+ const diff = now.getTime() - messageDate;
1102
+ const absDiff = Math.abs(diff);
1103
+ const seconds = Math.floor(absDiff / 1e3);
1104
+ const minutes = Math.floor(seconds / 60);
1105
+ const hours = Math.floor(minutes / 60);
1106
+ const days = Math.floor(hours / 24);
1107
+ if (absDiff < 6e4) {
1108
+ return "just now";
1109
+ }
1110
+ if (minutes < 60) {
1111
+ return `${minutes} minute${minutes !== 1 ? "s" : ""} ago`;
1112
+ }
1113
+ if (hours < 24) {
1114
+ return `${hours} hour${hours !== 1 ? "s" : ""} ago`;
1115
+ }
1116
+ return `${days} day${days !== 1 ? "s" : ""} ago`;
1117
+ };
1118
+ var jsonBlockPattern = /```json\n([\s\S]*?)\n```/;
1119
+ function parseKeyValueXml(text) {
1120
+ if (!text) return null;
1121
+ let xmlBlockMatch = text.match(/<response>([\s\S]*?)<\/response>/);
1122
+ let xmlContent;
1123
+ if (xmlBlockMatch) {
1124
+ xmlContent = xmlBlockMatch[1];
1125
+ logger_default.debug("Found response XML block");
1126
+ } else {
1127
+ const fallbackMatch = text.match(/<(\w+)>([\s\S]*?)<\/\1>/);
1128
+ if (!fallbackMatch) {
1129
+ logger_default.warn("Could not find XML block in text");
1130
+ logger_default.debug("Text content:", text.substring(0, 200) + "...");
1131
+ return null;
1132
+ }
1133
+ xmlContent = fallbackMatch[2];
1134
+ logger_default.debug(`Found XML block with tag: ${fallbackMatch[1]}`);
1135
+ }
1136
+ const result = {};
1137
+ const tagPattern = /<([\w-]+)>([\s\S]*?)<\/([\w-]+)>/g;
1138
+ let match;
1139
+ while ((match = tagPattern.exec(xmlContent)) !== null) {
1140
+ if (match[1] === match[3]) {
1141
+ const key = match[1];
1142
+ const value = match[2].replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&").replace(/&quot;/g, '"').replace(/&apos;/g, "'").trim();
1143
+ if (key === "actions" || key === "providers" || key === "evaluators") {
1144
+ result[key] = value ? value.split(",").map((s) => s.trim()) : [];
1145
+ } else if (key === "simple") {
1146
+ result[key] = value.toLowerCase() === "true";
1147
+ } else {
1148
+ result[key] = value;
1149
+ }
1150
+ } else {
1151
+ logger_default.warn(`Mismatched XML tags found: <${match[1]}> and </${match[3]}>`);
1152
+ }
1153
+ }
1154
+ if (Object.keys(result).length === 0) {
1155
+ logger_default.warn("No key-value pairs extracted from XML content");
1156
+ logger_default.debug("XML content was:", xmlContent.substring(0, 200) + "...");
1157
+ return null;
1158
+ }
1159
+ return result;
1160
+ }
1161
+ function parseJSONObjectFromText(text) {
1162
+ let jsonData = null;
1163
+ const jsonBlockMatch = text.match(jsonBlockPattern);
1164
+ try {
1165
+ if (jsonBlockMatch) {
1166
+ jsonData = JSON.parse(normalizeJsonString(jsonBlockMatch[1].trim()));
1167
+ } else {
1168
+ jsonData = JSON.parse(normalizeJsonString(text.trim()));
1169
+ }
1170
+ } catch (_e) {
1171
+ return null;
1172
+ }
1173
+ if (jsonData && typeof jsonData === "object" && !Array.isArray(jsonData)) {
1174
+ return jsonData;
1175
+ }
1176
+ return null;
1177
+ }
1178
+ var normalizeJsonString = (str) => {
1179
+ str = str.replace(/\{\s+/, "{").replace(/\s+\}/, "}").trim();
1180
+ str = str.replace(/("[\w\d_-]+")\s*: \s*(?!"|\[)([\s\S]+?)(?=(,\s*"|\}$))/g, '$1: "$2"');
1181
+ str = str.replace(/"([^"]+)"\s*:\s*'([^']*)'/g, (_, key, value) => `"${key}": "${value}"`);
1182
+ str = str.replace(/("[\w\d_-]+")\s*:\s*([A-Za-z_]+)(?!["\w])/g, '$1: "$2"');
1183
+ return str;
1184
+ };
1185
+ function truncateToCompleteSentence(text, maxLength) {
1186
+ if (text.length <= maxLength) {
1187
+ return text;
1188
+ }
1189
+ const lastPeriodIndex = text.lastIndexOf(".", maxLength - 1);
1190
+ if (lastPeriodIndex !== -1) {
1191
+ const truncatedAtPeriod = text.slice(0, lastPeriodIndex + 1).trim();
1192
+ if (truncatedAtPeriod.length > 0) {
1193
+ return truncatedAtPeriod;
1194
+ }
1195
+ }
1196
+ const lastSpaceIndex = text.lastIndexOf(" ", maxLength - 1);
1197
+ if (lastSpaceIndex !== -1) {
1198
+ const truncatedAtSpace = text.slice(0, lastSpaceIndex).trim();
1199
+ if (truncatedAtSpace.length > 0) {
1200
+ return `${truncatedAtSpace}...`;
1201
+ }
1202
+ }
1203
+ const hardTruncated = text.slice(0, maxLength - 3).trim();
1204
+ return `${hardTruncated}...`;
1205
+ }
1206
+ async function splitChunks(content, chunkSize = 512, bleed = 20) {
1207
+ logger_default.debug("[splitChunks] Starting text split");
1208
+ const characterstoTokens = 3.5;
1209
+ const textSplitter = new RecursiveCharacterTextSplitter({
1210
+ chunkSize: Number(Math.floor(chunkSize * characterstoTokens)),
1211
+ chunkOverlap: Number(Math.floor(bleed * characterstoTokens))
1212
+ });
1213
+ const chunks = await textSplitter.splitText(content);
1214
+ logger_default.debug("[splitChunks] Split complete:", {
1215
+ numberOfChunks: chunks.length,
1216
+ averageChunkSize: chunks.reduce((acc, chunk) => acc + chunk.length, 0) / chunks.length
1217
+ });
1218
+ return chunks;
1219
+ }
1220
+ async function trimTokens(prompt, maxTokens, runtime) {
1221
+ if (!prompt) throw new Error("Trim tokens received a null prompt");
1222
+ if (prompt.length < maxTokens / 5) return prompt;
1223
+ if (maxTokens <= 0) throw new Error("maxTokens must be positive");
1224
+ const tokens = await runtime.useModel(ModelType2.TEXT_TOKENIZER_ENCODE, {
1225
+ prompt
1226
+ });
1227
+ if (tokens.length <= maxTokens) {
1228
+ return prompt;
1229
+ }
1230
+ const truncatedTokens = tokens.slice(-maxTokens);
1231
+ return await runtime.useModel(ModelType2.TEXT_TOKENIZER_DECODE, {
1232
+ tokens: truncatedTokens
1233
+ });
1234
+ }
1235
+ function safeReplacer() {
1236
+ const seen = /* @__PURE__ */ new WeakSet();
1237
+ return function(key, value) {
1238
+ if (typeof value === "object" && value !== null) {
1239
+ if (seen.has(value)) {
1240
+ return "[Circular]";
1241
+ }
1242
+ seen.add(value);
1243
+ }
1244
+ return value;
1245
+ };
1246
+ }
1247
+ function parseBooleanFromText2(value) {
1248
+ if (!value) return false;
1249
+ const affirmative = ["YES", "Y", "TRUE", "T", "1", "ON", "ENABLE"];
1250
+ const negative = ["NO", "N", "FALSE", "F", "0", "OFF", "DISABLE"];
1251
+ const normalizedText = value.trim().toUpperCase();
1252
+ if (affirmative.includes(normalizedText)) {
1253
+ return true;
1254
+ }
1255
+ if (negative.includes(normalizedText)) {
1256
+ return false;
1257
+ }
1258
+ return false;
1259
+ }
1260
+ var uuidSchema = z.string().uuid();
1261
+ function validateUuid(value) {
1262
+ const result = uuidSchema.safeParse(value);
1263
+ return result.success ? result.data : null;
1264
+ }
1265
+ function stringToUuid(target) {
1266
+ if (typeof target === "number") {
1267
+ target = target.toString();
1268
+ }
1269
+ if (typeof target !== "string") {
1270
+ throw TypeError("Value must be string");
1271
+ }
1272
+ const _uint8ToHex = (ubyte) => {
1273
+ const first = ubyte >> 4;
1274
+ const second = ubyte - (first << 4);
1275
+ const HEX_DIGITS = "0123456789abcdef".split("");
1276
+ return HEX_DIGITS[first] + HEX_DIGITS[second];
1277
+ };
1278
+ const _uint8ArrayToHex = (buf) => {
1279
+ let out = "";
1280
+ for (let i = 0; i < buf.length; i++) {
1281
+ out += _uint8ToHex(buf[i]);
1282
+ }
1283
+ return out;
1284
+ };
1285
+ const escapedStr = encodeURIComponent(target);
1286
+ const buffer = new Uint8Array(escapedStr.length);
1287
+ for (let i = 0; i < escapedStr.length; i++) {
1288
+ buffer[i] = escapedStr[i].charCodeAt(0);
1289
+ }
1290
+ const hash = sha1(buffer);
1291
+ const hashBuffer = new Uint8Array(hash.length / 2);
1292
+ for (let i = 0; i < hash.length; i += 2) {
1293
+ hashBuffer[i / 2] = Number.parseInt(hash.slice(i, i + 2), 16);
1294
+ }
1295
+ return `${_uint8ArrayToHex(hashBuffer.slice(0, 4))}-${_uint8ArrayToHex(hashBuffer.slice(4, 6))}-${_uint8ToHex(hashBuffer[6] & 15)}${_uint8ToHex(hashBuffer[7])}-${_uint8ToHex(hashBuffer[8] & 63 | 128)}${_uint8ToHex(hashBuffer[9])}-${_uint8ArrayToHex(hashBuffer.slice(10, 16))}`;
1296
+ }
1297
+ var getContentTypeFromMimeType = (mimeType) => {
1298
+ if (mimeType.startsWith("image/")) return "image" /* IMAGE */;
1299
+ if (mimeType.startsWith("video/")) return "video" /* VIDEO */;
1300
+ if (mimeType.startsWith("audio/")) return "audio" /* AUDIO */;
1301
+ if (mimeType.includes("pdf") || mimeType.includes("document") || mimeType.startsWith("text/")) {
1302
+ return "document" /* DOCUMENT */;
1303
+ }
1304
+ return void 0;
1305
+ };
1306
+
1307
+ // src/schemas/character.ts
1308
+ import { z as z2 } from "zod";
1309
+ var uuidSchema2 = z2.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "Invalid UUID format");
1310
+ var contentSchema = z2.object({
1311
+ text: z2.string().optional(),
1312
+ thought: z2.string().optional(),
1313
+ actions: z2.array(z2.string()).optional(),
1314
+ providers: z2.array(z2.string()).optional(),
1315
+ source: z2.string().optional(),
1316
+ target: z2.string().optional(),
1317
+ url: z2.string().optional(),
1318
+ inReplyTo: uuidSchema2.optional(),
1319
+ attachments: z2.array(z2.any()).optional(),
1320
+ channelType: z2.string().optional()
1321
+ }).passthrough();
1322
+ var messageExampleSchema = z2.object({
1323
+ name: z2.string(),
1324
+ content: contentSchema
1325
+ });
1326
+ var directoryItemSchema = z2.object({
1327
+ directory: z2.string(),
1328
+ shared: z2.boolean().optional()
1329
+ });
1330
+ var knowledgeItemSchema = z2.union([
1331
+ z2.string(),
1332
+ z2.object({
1333
+ path: z2.string(),
1334
+ shared: z2.boolean().optional()
1335
+ }),
1336
+ directoryItemSchema
1337
+ ]);
1338
+ var templateTypeSchema = z2.union([
1339
+ z2.string(),
1340
+ z2.function().optional()
1341
+ // Functions won't be in JSON but allowed in runtime
1342
+ ]);
1343
+ var styleSchema = z2.object({
1344
+ all: z2.array(z2.string()).optional(),
1345
+ chat: z2.array(z2.string()).optional(),
1346
+ post: z2.array(z2.string()).optional()
1347
+ }).optional();
1348
+ var settingsSchema = z2.record(z2.union([z2.string(), z2.boolean(), z2.number(), z2.any()])).optional();
1349
+ var secretsSchema = z2.record(z2.union([z2.string(), z2.boolean(), z2.number()])).optional();
1350
+ var characterSchema = z2.object({
1351
+ id: uuidSchema2.optional(),
1352
+ name: z2.string().min(1, "Character name is required"),
1353
+ username: z2.string().optional(),
1354
+ system: z2.string().optional(),
1355
+ templates: z2.record(templateTypeSchema).optional(),
1356
+ bio: z2.union([z2.string(), z2.array(z2.string())]),
1357
+ messageExamples: z2.array(z2.array(messageExampleSchema)).optional(),
1358
+ postExamples: z2.array(z2.string()).optional(),
1359
+ topics: z2.array(z2.string()).optional(),
1360
+ adjectives: z2.array(z2.string()).optional(),
1361
+ knowledge: z2.array(knowledgeItemSchema).optional(),
1362
+ plugins: z2.array(z2.string()).optional(),
1363
+ settings: settingsSchema,
1364
+ secrets: secretsSchema,
1365
+ style: styleSchema
1366
+ }).strict();
1367
+ function validateCharacter(data) {
1368
+ const result = characterSchema.safeParse(data);
1369
+ if (result.success) {
1370
+ return {
1371
+ success: true,
1372
+ data: result.data
1313
1373
  };
1314
1374
  }
1315
- const logger3 = pino(opts);
1316
- return logger3;
1317
- };
1318
- var logger = pino(options);
1319
- if (typeof process !== "undefined") {
1320
- let stream = null;
1321
- if (!raw) {
1322
- try {
1323
- const pretty = __require("pino-pretty");
1324
- stream = pretty.default ? pretty.default(createPrettyConfig()) : null;
1325
- } catch (e) {
1326
- createStream().then((prettyStream) => {
1327
- const destination = new InMemoryDestination(prettyStream);
1328
- logger = pino(options, destination);
1329
- logger[Symbol.for("pino-destination")] = destination;
1330
- logger.clear = () => {
1331
- const destination2 = logger[Symbol.for("pino-destination")];
1332
- if (destination2 instanceof InMemoryDestination) {
1333
- destination2.clear();
1334
- }
1335
- };
1336
- });
1375
+ return {
1376
+ success: false,
1377
+ error: {
1378
+ message: `Character validation failed: ${result.error.message}`,
1379
+ issues: result.error.issues
1337
1380
  }
1338
- }
1339
- if (stream !== null || raw) {
1340
- const destination = new InMemoryDestination(stream);
1341
- logger = pino(options, destination);
1342
- logger[Symbol.for("pino-destination")] = destination;
1343
- logger.clear = () => {
1344
- const destination2 = logger[Symbol.for("pino-destination")];
1345
- if (destination2 instanceof InMemoryDestination) {
1346
- destination2.clear();
1381
+ };
1382
+ }
1383
+ function parseAndValidateCharacter(jsonString) {
1384
+ try {
1385
+ const parsed = JSON.parse(jsonString);
1386
+ return validateCharacter(parsed);
1387
+ } catch (error) {
1388
+ return {
1389
+ success: false,
1390
+ error: {
1391
+ message: `Invalid JSON: ${error instanceof Error ? error.message : "Unknown JSON parsing error"}`
1347
1392
  }
1348
1393
  };
1349
1394
  }
1350
1395
  }
1351
- var elizaLogger = logger;
1352
- var logger_default = logger;
1396
+ function isValidCharacter(data) {
1397
+ return validateCharacter(data).success;
1398
+ }
1399
+
1400
+ // src/actions.ts
1401
+ import { names as names2, uniqueNamesGenerator as uniqueNamesGenerator2 } from "unique-names-generator";
1402
+ var composeActionExamples2 = (actionsData, count) => {
1403
+ if (!actionsData.length || count <= 0) {
1404
+ return "";
1405
+ }
1406
+ const actionsWithExamples = actionsData.filter(
1407
+ (action) => action.examples && Array.isArray(action.examples) && action.examples.length > 0
1408
+ );
1409
+ if (!actionsWithExamples.length) {
1410
+ return "";
1411
+ }
1412
+ const examplesCopy = actionsWithExamples.map((action) => [
1413
+ ...action.examples
1414
+ ]);
1415
+ const selectedExamples = [];
1416
+ let availableActionIndices = examplesCopy.map((examples, index) => examples.length > 0 ? index : -1).filter((index) => index !== -1);
1417
+ while (selectedExamples.length < count && availableActionIndices.length > 0) {
1418
+ const randomIndex = Math.floor(Math.random() * availableActionIndices.length);
1419
+ const actionIndex = availableActionIndices[randomIndex];
1420
+ const examples = examplesCopy[actionIndex];
1421
+ const exampleIndex = Math.floor(Math.random() * examples.length);
1422
+ selectedExamples.push(examples.splice(exampleIndex, 1)[0]);
1423
+ if (examples.length === 0) {
1424
+ availableActionIndices.splice(randomIndex, 1);
1425
+ }
1426
+ }
1427
+ return formatSelectedExamples(selectedExamples);
1428
+ };
1429
+ var formatSelectedExamples = (examples) => {
1430
+ const MAX_NAME_PLACEHOLDERS = 5;
1431
+ return examples.map((example) => {
1432
+ const randomNames = Array.from(
1433
+ { length: MAX_NAME_PLACEHOLDERS },
1434
+ () => uniqueNamesGenerator2({ dictionaries: [names2] })
1435
+ );
1436
+ const conversation = example.map((message) => {
1437
+ let messageText = `${message.name}: ${message.content.text}`;
1438
+ for (let i = 0; i < randomNames.length; i++) {
1439
+ messageText = messageText.replaceAll(`{{name${i + 1}}}`, randomNames[i]);
1440
+ }
1441
+ return messageText;
1442
+ }).join("\n");
1443
+ return `
1444
+ ${conversation}`;
1445
+ }).join("\n");
1446
+ };
1447
+ function formatActionNames2(actions) {
1448
+ if (!actions?.length) return "";
1449
+ return [...actions].sort(() => Math.random() - 0.5).map((action) => action.name).join(", ");
1450
+ }
1451
+ function formatActions2(actions) {
1452
+ if (!actions?.length) return "";
1453
+ return [...actions].sort(() => Math.random() - 0.5).map((action) => `${action.name}: ${action.description}`).join(",\n");
1454
+ }
1455
+
1456
+ // src/database.ts
1457
+ var DatabaseAdapter2 = class {
1458
+ };
1353
1459
 
1354
1460
  // src/prompts.ts
1355
1461
  var shouldRespondTemplate = `<task>Decide on behalf of {{agentName}} whether they should respond to the message, ignore it or stop the conversation.</task>
@@ -1388,78 +1494,35 @@ These are the available valid actions:
1388
1494
  </actionNames>
1389
1495
 
1390
1496
  <instructions>
1391
- Analyze the message and create a response plan for {{agentName}}.
1497
+ Write a thought and plan for {{agentName}} and decide what actions to take. Also include the providers that {{agentName}} will use to have the right context for responding and acting, if any.
1392
1498
 
1393
- STEP 1 - DETERMINE RESPONSE TYPE:
1394
- - SIMPLE RESPONSE: If you only need to send a text reply without any tools, data lookups, or complex operations
1395
- \u2192 Use only REPLY action with no providers
1396
- \u2192 This is the preferred path for basic conversations
1397
- \u2192 Do NOT use this for questions that require checking stored knowledge!
1398
-
1399
- - COMPLEX RESPONSE: If you need to:
1400
- \u2192 Use external tools or services (CALL_TOOL, etc.)
1401
- \u2192 Look up specific information (needs providers like KNOWLEDGE, ATTACHMENTS, etc.)
1402
- \u2192 Answer questions about what you know or might know (ALWAYS check KNOWLEDGE first!)
1403
- \u2192 Perform multiple operations
1404
- \u2192 Update data or settings
1499
+ IMPORTANT ACTION ORDERING RULES:
1500
+ - Actions are executed in the ORDER you list them - the order MATTERS!
1501
+ - REPLY should come FIRST to acknowledge the user's request before executing other actions
1502
+ - Common patterns:
1503
+ - For requests requiring tool use: REPLY,CALL_MCP_TOOL (acknowledge first, then gather info)
1504
+ - For task execution: REPLY,SEND_MESSAGE or REPLY,EVM_SWAP_TOKENS (acknowledge first, then do the task)
1505
+ - For multi-step operations: REPLY,ACTION1,ACTION2 (acknowledge first, then complete all steps)
1506
+ - REPLY is used to acknowledge and inform the user about what you're going to do
1507
+ - Follow-up actions execute the actual tasks after acknowledgment
1508
+ - Use IGNORE only when you should not respond at all
1405
1509
 
1406
- STEP 2 - PROVIDER SELECTION (for complex responses):
1407
1510
  IMPORTANT PROVIDER SELECTION RULES:
1408
1511
  - If the message mentions images, photos, pictures, attachments, or visual content, OR if you see "(Attachments:" in the conversation, you MUST include "ATTACHMENTS" in your providers list
1409
1512
  - If the message asks about or references specific people, include "ENTITIES" in your providers list
1410
1513
  - If the message asks about relationships or connections between people, include "RELATIONSHIPS" in your providers list
1411
1514
  - If the message asks about facts or specific information, include "FACTS" in your providers list
1412
1515
  - If the message asks about the environment or world context, include "WORLD" in your providers list
1413
- - **CRITICAL: If the message asks "do you know", "who created", "what is", "tell me about", or ANY question that might be answered by stored knowledge, you MUST include "KNOWLEDGE" in your providers list. Always check KNOWLEDGE before saying you don't know something!**
1414
- - Some actions may require specific providers (this will be clear from the action's purpose)
1415
-
1416
- REMEMBER: It's better to check providers and find nothing than to assume you don't have information without checking!
1516
+ - If you need external knowledge, information, or context beyond the current conversation to provide a helpful response, include "KNOWLEDGE" in your providers list
1417
1517
 
1418
- STEP 3 - ACTION PLANNING:
1419
- For complex responses, consider the order of actions:
1420
- - If using tools (CALL_TOOL, etc.): First REPLY to acknowledge the request (e.g., "Let me check that for you"), then execute the tool action
1421
- - Tool actions often handle their own responses, so you may not need a final REPLY after them
1422
- - Actions should flow logically: acknowledge \u2192 gather data \u2192 process \u2192 respond
1423
-
1424
- Think about your response as a plan:
1425
- 1. What is the user asking for?
1426
- 2. Do I need any additional context or data? (providers)
1427
- 3. What actions do I need to take and in what order?
1428
- 4. How will I communicate the results?
1518
+ First, think about what you want to do next and plan your actions. Then, write the next message and include the actions you plan to take.
1429
1519
  </instructions>
1430
1520
 
1431
- <output_format>
1432
- First, think about what you want to do and create your plan.
1433
-
1434
- For SIMPLE responses (text-only reply):
1435
- - Set thought to explain your reasoning
1436
- - Set actions to ["REPLY"]
1437
- - Leave providers empty or set to []
1438
- - Set text to your response message
1439
-
1440
- For COMPLEX responses (using tools/providers):
1441
- - Set thought to explain your plan and reasoning
1442
- - Set actions in the order they should execute (e.g., ["REPLY", "CALL_TOOL"])
1443
- - Set providers to gather needed context
1444
- - Set text for your initial response (if using REPLY first)
1445
-
1446
- Remember: Some actions like CALL_TOOL will send their own responses, so plan accordingly.
1447
- </output_format>
1448
-
1449
- <response>
1450
- <thought>User asking if I know something - must check KNOWLEDGE provider first before saying I don't know</thought>
1451
- <actions>REPLY</actions>
1452
- <providers>KNOWLEDGE</providers>
1453
- <text>Let me check if I have any information about Roxane's creator...</text>
1454
- </response>
1455
- </examples>
1456
-
1457
1521
  <keys>
1458
- "thought" should be a short description of what the agent is thinking about and their plan
1459
- "actions" should be a comma-separated list of the actions {{agentName}} plans to take in order (if none, use IGNORE, if simply responding with text, use REPLY)
1460
- "providers" should be a comma-separated list of the providers that {{agentName}} will use to have the right context for responding and acting (leave empty for simple responses)
1461
- "evaluators" should be an optional comma-separated list of the evaluators that {{agentName}} will use to evaluate the conversation after responding
1462
- "text" should be the text of the next message for {{agentName}} (used with REPLY action)
1522
+ "thought" should be a short description of what the agent is thinking about and planning.
1523
+ "actions" should be a comma-separated list of the actions {{agentName}} plans to take based on the thought, IN THE ORDER THEY SHOULD BE EXECUTED (if none, use IGNORE, if simply responding with text, use REPLY)
1524
+ "providers" should be a comma-separated list of the providers that {{agentName}} will use to have the right context for responding and acting (NEVER use "IGNORE" as a provider - use specific provider names like ATTACHMENTS, ENTITIES, FACTS, KNOWLEDGE, etc.)
1525
+ "text" should be the text of the next message for {{agentName}} which they will send to the conversation.
1463
1526
  </keys>
1464
1527
 
1465
1528
  <output>
@@ -2639,9 +2702,9 @@ var AgentRuntime = class {
2639
2702
  this.character = opts.character;
2640
2703
  const logLevel = process.env.LOG_LEVEL || "info";
2641
2704
  this.logger = createLogger({
2642
- agentName: this.character?.name
2705
+ agentName: this.character?.name,
2706
+ logLevel
2643
2707
  });
2644
- this.logger.debug(`[AgentRuntime] Process working directory: ${process.cwd()}`);
2645
2708
  this.#conversationLength = opts.conversationLength ?? this.#conversationLength;
2646
2709
  if (opts.adapter) {
2647
2710
  this.registerDatabaseAdapter(opts.adapter);
@@ -2658,8 +2721,37 @@ var AgentRuntime = class {
2658
2721
  }
2659
2722
  }
2660
2723
  this.logger.debug(`Success: Agent ID: ${this.agentId}`);
2724
+ this.currentRunId = void 0;
2661
2725
  }
2662
2726
  #conversationLength;
2727
+ /**
2728
+ * Create a new run ID for tracking a sequence of model calls
2729
+ */
2730
+ createRunId() {
2731
+ return uuidv4();
2732
+ }
2733
+ /**
2734
+ * Start a new run for tracking prompts
2735
+ */
2736
+ startRun() {
2737
+ this.currentRunId = this.createRunId();
2738
+ return this.currentRunId;
2739
+ }
2740
+ /**
2741
+ * End the current run
2742
+ */
2743
+ endRun() {
2744
+ this.currentRunId = void 0;
2745
+ }
2746
+ /**
2747
+ * Get the current run ID (creates one if it doesn't exist)
2748
+ */
2749
+ getCurrentRunId() {
2750
+ if (!this.currentRunId) {
2751
+ this.currentRunId = this.createRunId();
2752
+ }
2753
+ return this.currentRunId;
2754
+ }
2663
2755
  async registerPlugin(plugin) {
2664
2756
  if (!plugin?.name) {
2665
2757
  const errorMsg = "Plugin or plugin name is undefined";
@@ -3045,6 +3137,12 @@ var AgentRuntime = class {
3045
3137
  }
3046
3138
  try {
3047
3139
  this.logger.debug(`Executing handler for action: ${action.name}`);
3140
+ const actionId = uuidv4();
3141
+ this.currentActionContext = {
3142
+ actionName: action.name,
3143
+ actionId,
3144
+ prompts: []
3145
+ };
3048
3146
  const result = await action.handler(this, message, state, {}, callback, responses);
3049
3147
  this.logger.debug(`Success: Action ${action.name} executed successfully.`);
3050
3148
  this.adapter.log({
@@ -3053,15 +3151,20 @@ var AgentRuntime = class {
3053
3151
  type: "action",
3054
3152
  body: {
3055
3153
  action: action.name,
3154
+ actionId,
3056
3155
  message: message.content.text,
3057
3156
  messageId: message.id,
3058
3157
  state,
3059
- responses
3158
+ responses,
3159
+ prompts: this.currentActionContext?.prompts || [],
3160
+ promptCount: this.currentActionContext?.prompts.length || 0
3060
3161
  }
3061
3162
  });
3163
+ this.currentActionContext = void 0;
3062
3164
  } catch (error) {
3063
3165
  const errorMessage = error instanceof Error ? error.message : String(error);
3064
3166
  this.logger.error(error);
3167
+ this.currentActionContext = void 0;
3065
3168
  const actionMemory = {
3066
3169
  id: uuidv4(),
3067
3170
  content: {
@@ -3609,13 +3712,43 @@ var AgentRuntime = class {
3609
3712
  `[useModel] ${modelKey} output (took ${Number(elapsedTime.toFixed(2)).toLocaleString()}ms):`,
3610
3713
  Array.isArray(response) ? `${JSON.stringify(response.slice(0, 5))}...${JSON.stringify(response.slice(-5))} (${response.length} items)` : JSON.stringify(response, safeReplacer(), 2).replace(/\\n/g, "\n")
3611
3714
  );
3715
+ if (modelKey !== ModelType2.TEXT_EMBEDDING && promptContent) {
3716
+ if (this.currentActionContext) {
3717
+ this.currentActionContext.prompts.push({
3718
+ modelType: modelKey,
3719
+ prompt: promptContent,
3720
+ timestamp: Date.now()
3721
+ });
3722
+ }
3723
+ await this.adapter.log({
3724
+ entityId: this.agentId,
3725
+ roomId: this.agentId,
3726
+ body: {
3727
+ modelType,
3728
+ modelKey,
3729
+ prompt: promptContent,
3730
+ runId: this.getCurrentRunId(),
3731
+ timestamp: Date.now(),
3732
+ executionTime: elapsedTime,
3733
+ provider: provider || this.models.get(modelKey)?.[0]?.provider || "unknown",
3734
+ actionContext: this.currentActionContext ? {
3735
+ actionName: this.currentActionContext.actionName,
3736
+ actionId: this.currentActionContext.actionId
3737
+ } : void 0
3738
+ },
3739
+ type: `prompt:${modelKey}`
3740
+ });
3741
+ }
3612
3742
  this.adapter.log({
3613
3743
  entityId: this.agentId,
3614
3744
  roomId: this.agentId,
3615
3745
  body: {
3616
3746
  modelType,
3617
3747
  modelKey,
3618
- params: params ? typeof params === "object" ? Object.keys(params) : typeof params : null,
3748
+ params: {
3749
+ ...typeof params === "object" && !Array.isArray(params) && params ? params : {},
3750
+ prompt: promptContent
3751
+ },
3619
3752
  response: Array.isArray(response) && response.every((x) => typeof x === "number") ? "[array]" : response
3620
3753
  },
3621
3754
  type: `useModel:${modelKey}`
@@ -3812,6 +3945,24 @@ var AgentRuntime = class {
3812
3945
  async getMemories(params) {
3813
3946
  return await this.adapter.getMemories(params);
3814
3947
  }
3948
+ async getAllMemories() {
3949
+ const tables = ["memories", "messages", "facts", "documents"];
3950
+ const allMemories = [];
3951
+ for (const tableName of tables) {
3952
+ try {
3953
+ const memories = await this.adapter.getMemories({
3954
+ agentId: this.agentId,
3955
+ tableName,
3956
+ count: 1e4
3957
+ // Get a large number to fetch all
3958
+ });
3959
+ allMemories.push(...memories);
3960
+ } catch (error) {
3961
+ this.logger.debug(`Failed to get memories from table ${tableName}:`, error);
3962
+ }
3963
+ }
3964
+ return allMemories;
3965
+ }
3815
3966
  async getMemoryById(id) {
3816
3967
  return await this.adapter.getMemoryById(id);
3817
3968
  }
@@ -3856,6 +4007,18 @@ var AgentRuntime = class {
3856
4007
  async deleteManyMemories(memoryIds) {
3857
4008
  await this.adapter.deleteManyMemories(memoryIds);
3858
4009
  }
4010
+ async clearAllAgentMemories() {
4011
+ this.logger.info(`Clearing all memories for agent ${this.character.name} (${this.agentId})`);
4012
+ const allMemories = await this.getAllMemories();
4013
+ const memoryIds = allMemories.map((memory) => memory.id);
4014
+ if (memoryIds.length === 0) {
4015
+ this.logger.info("No memories found to delete");
4016
+ return;
4017
+ }
4018
+ this.logger.info(`Found ${memoryIds.length} memories to delete`);
4019
+ await this.adapter.deleteManyMemories(memoryIds);
4020
+ this.logger.info(`Successfully cleared all ${memoryIds.length} memories for agent`);
4021
+ }
3859
4022
  async deleteAllMemories(roomId, tableName) {
3860
4023
  await this.adapter.deleteAllMemories(roomId, tableName);
3861
4024
  }
@@ -5351,6 +5514,12 @@ var AgentRuntime2 = class {
5351
5514
  async addEmbeddingToMemory(memory) {
5352
5515
  return this._runtime.addEmbeddingToMemory(memory);
5353
5516
  }
5517
+ async getAllMemories() {
5518
+ return this._runtime.getAllMemories();
5519
+ }
5520
+ async clearAllAgentMemories() {
5521
+ return this._runtime.clearAllAgentMemories();
5522
+ }
5354
5523
  async getMemories(params) {
5355
5524
  return this._runtime.getMemories(params);
5356
5525
  }
@@ -5510,15 +5679,38 @@ var AgentRuntime2 = class {
5510
5679
  async sendControlMessage(params) {
5511
5680
  return this._runtime.sendControlMessage(params);
5512
5681
  }
5682
+ /**
5683
+ * Register a message send handler for a specific source
5684
+ * @param source - The source identifier (e.g., 'discord', 'telegram')
5685
+ * @param handler - The handler function to send messages
5686
+ */
5513
5687
  registerSendHandler(source, handler) {
5514
- return this._runtime.registerSendHandler(source, handler);
5688
+ this._runtime.registerSendHandler(source, handler);
5515
5689
  }
5690
+ /**
5691
+ * Send a message to a specific target
5692
+ * @param target - The target information including source and channel/user ID
5693
+ * @param content - The message content to send
5694
+ */
5516
5695
  async sendMessageToTarget(target, content) {
5517
5696
  return this._runtime.sendMessageToTarget(target, content);
5518
5697
  }
5519
5698
  async getMemoriesByWorldId(params) {
5520
5699
  return this._runtime.getMemoriesByWorldId(params);
5521
5700
  }
5701
+ // Run tracking methods
5702
+ createRunId() {
5703
+ return this._runtime.createRunId();
5704
+ }
5705
+ startRun() {
5706
+ return this._runtime.startRun();
5707
+ }
5708
+ endRun() {
5709
+ return this._runtime.endRun();
5710
+ }
5711
+ getCurrentRunId() {
5712
+ return this._runtime.getCurrentRunId();
5713
+ }
5522
5714
  };
5523
5715
 
5524
5716
  // src/specs/v2/settings.ts
@@ -5615,8 +5807,8 @@ function parseKeyValueXml2(text) {
5615
5807
  function parseJSONObjectFromText2(text) {
5616
5808
  return parseJSONObjectFromText(text);
5617
5809
  }
5618
- function parseBooleanFromText2(text) {
5619
- return parseBooleanFromText(text);
5810
+ function parseBooleanFromText3(text) {
5811
+ return parseBooleanFromText2(text);
5620
5812
  }
5621
5813
  function safeReplacer2() {
5622
5814
  return safeReplacer();
@@ -5671,10 +5863,6 @@ export {
5671
5863
  SOCKET_MESSAGE_TYPE2 as SOCKET_MESSAGE_TYPE,
5672
5864
  IWalletService,
5673
5865
  ILpService,
5674
- composeActionExamples2 as composeActionExamples,
5675
- formatActionNames2 as formatActionNames,
5676
- formatActions2 as formatActions,
5677
- DatabaseAdapter2 as DatabaseAdapter,
5678
5866
  Sentry,
5679
5867
  createLogger,
5680
5868
  logger,
@@ -5692,9 +5880,18 @@ export {
5692
5880
  splitChunks,
5693
5881
  trimTokens,
5694
5882
  safeReplacer,
5695
- parseBooleanFromText,
5883
+ parseBooleanFromText2 as parseBooleanFromText,
5696
5884
  validateUuid,
5697
5885
  stringToUuid,
5886
+ getContentTypeFromMimeType,
5887
+ characterSchema,
5888
+ validateCharacter,
5889
+ parseAndValidateCharacter,
5890
+ isValidCharacter,
5891
+ composeActionExamples2 as composeActionExamples,
5892
+ formatActionNames2 as formatActionNames,
5893
+ formatActions2 as formatActions,
5894
+ DatabaseAdapter2 as DatabaseAdapter,
5698
5895
  findEntityByName,
5699
5896
  createUniqueUuid,
5700
5897
  getEntityDetails,
@@ -5799,7 +5996,7 @@ export {
5799
5996
  truncateToCompleteSentence2,
5800
5997
  parseKeyValueXml2,
5801
5998
  parseJSONObjectFromText2,
5802
- parseBooleanFromText2,
5999
+ parseBooleanFromText3 as parseBooleanFromText2,
5803
6000
  safeReplacer2,
5804
6001
  trimTokens2,
5805
6002
  ServiceBuilder2,