@elizaos/server 1.6.4-alpha.15 → 1.6.4-alpha.17
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.d.ts +2 -0
- package/dist/index.js +2607 -1863
- package/dist/services/message.d.ts +7 -0
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -18,358 +18,6 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
18
18
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
19
19
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
20
20
|
|
|
21
|
-
// ../../node_modules/path-to-regexp/dist/index.js
|
|
22
|
-
var require_dist = __commonJS((exports) => {
|
|
23
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.PathError = exports.TokenData = undefined;
|
|
25
|
-
exports.parse = parse;
|
|
26
|
-
exports.compile = compile;
|
|
27
|
-
exports.match = match;
|
|
28
|
-
exports.pathToRegexp = pathToRegexp;
|
|
29
|
-
exports.stringify = stringify;
|
|
30
|
-
var DEFAULT_DELIMITER = "/";
|
|
31
|
-
var NOOP_VALUE = (value) => value;
|
|
32
|
-
var ID_START = /^[$_\p{ID_Start}]$/u;
|
|
33
|
-
var ID_CONTINUE = /^[$\u200c\u200d\p{ID_Continue}]$/u;
|
|
34
|
-
var SIMPLE_TOKENS = {
|
|
35
|
-
"{": "{",
|
|
36
|
-
"}": "}",
|
|
37
|
-
"(": "(",
|
|
38
|
-
")": ")",
|
|
39
|
-
"[": "[",
|
|
40
|
-
"]": "]",
|
|
41
|
-
"+": "+",
|
|
42
|
-
"?": "?",
|
|
43
|
-
"!": "!"
|
|
44
|
-
};
|
|
45
|
-
function escapeText(str) {
|
|
46
|
-
return str.replace(/[{}()\[\]+?!:*\\]/g, "\\$&");
|
|
47
|
-
}
|
|
48
|
-
function escape(str) {
|
|
49
|
-
return str.replace(/[.+*?^${}()[\]|/\\]/g, "\\$&");
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
class TokenData {
|
|
53
|
-
constructor(tokens, originalPath) {
|
|
54
|
-
this.tokens = tokens;
|
|
55
|
-
this.originalPath = originalPath;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
exports.TokenData = TokenData;
|
|
59
|
-
|
|
60
|
-
class PathError extends TypeError {
|
|
61
|
-
constructor(message, originalPath) {
|
|
62
|
-
let text = message;
|
|
63
|
-
if (originalPath)
|
|
64
|
-
text += `: ${originalPath}`;
|
|
65
|
-
text += `; visit https://git.new/pathToRegexpError for info`;
|
|
66
|
-
super(text);
|
|
67
|
-
this.originalPath = originalPath;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
exports.PathError = PathError;
|
|
71
|
-
function parse(str, options = {}) {
|
|
72
|
-
const { encodePath = NOOP_VALUE } = options;
|
|
73
|
-
const chars = [...str];
|
|
74
|
-
const tokens = [];
|
|
75
|
-
let index = 0;
|
|
76
|
-
let pos = 0;
|
|
77
|
-
function name() {
|
|
78
|
-
let value = "";
|
|
79
|
-
if (ID_START.test(chars[index])) {
|
|
80
|
-
do {
|
|
81
|
-
value += chars[index++];
|
|
82
|
-
} while (ID_CONTINUE.test(chars[index]));
|
|
83
|
-
} else if (chars[index] === '"') {
|
|
84
|
-
let quoteStart = index;
|
|
85
|
-
while (index++ < chars.length) {
|
|
86
|
-
if (chars[index] === '"') {
|
|
87
|
-
index++;
|
|
88
|
-
quoteStart = 0;
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
if (chars[index] === "\\")
|
|
92
|
-
index++;
|
|
93
|
-
value += chars[index];
|
|
94
|
-
}
|
|
95
|
-
if (quoteStart) {
|
|
96
|
-
throw new PathError(`Unterminated quote at index ${quoteStart}`, str);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
if (!value) {
|
|
100
|
-
throw new PathError(`Missing parameter name at index ${index}`, str);
|
|
101
|
-
}
|
|
102
|
-
return value;
|
|
103
|
-
}
|
|
104
|
-
while (index < chars.length) {
|
|
105
|
-
const value = chars[index];
|
|
106
|
-
const type = SIMPLE_TOKENS[value];
|
|
107
|
-
if (type) {
|
|
108
|
-
tokens.push({ type, index: index++, value });
|
|
109
|
-
} else if (value === "\\") {
|
|
110
|
-
tokens.push({ type: "escape", index: index++, value: chars[index++] });
|
|
111
|
-
} else if (value === ":") {
|
|
112
|
-
tokens.push({ type: "param", index: index++, value: name() });
|
|
113
|
-
} else if (value === "*") {
|
|
114
|
-
tokens.push({ type: "wildcard", index: index++, value: name() });
|
|
115
|
-
} else {
|
|
116
|
-
tokens.push({ type: "char", index: index++, value });
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
tokens.push({ type: "end", index, value: "" });
|
|
120
|
-
function consumeUntil(endType) {
|
|
121
|
-
const output = [];
|
|
122
|
-
while (true) {
|
|
123
|
-
const token = tokens[pos++];
|
|
124
|
-
if (token.type === endType)
|
|
125
|
-
break;
|
|
126
|
-
if (token.type === "char" || token.type === "escape") {
|
|
127
|
-
let path = token.value;
|
|
128
|
-
let cur = tokens[pos];
|
|
129
|
-
while (cur.type === "char" || cur.type === "escape") {
|
|
130
|
-
path += cur.value;
|
|
131
|
-
cur = tokens[++pos];
|
|
132
|
-
}
|
|
133
|
-
output.push({
|
|
134
|
-
type: "text",
|
|
135
|
-
value: encodePath(path)
|
|
136
|
-
});
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
if (token.type === "param" || token.type === "wildcard") {
|
|
140
|
-
output.push({
|
|
141
|
-
type: token.type,
|
|
142
|
-
name: token.value
|
|
143
|
-
});
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
if (token.type === "{") {
|
|
147
|
-
output.push({
|
|
148
|
-
type: "group",
|
|
149
|
-
tokens: consumeUntil("}")
|
|
150
|
-
});
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
throw new PathError(`Unexpected ${token.type} at index ${token.index}, expected ${endType}`, str);
|
|
154
|
-
}
|
|
155
|
-
return output;
|
|
156
|
-
}
|
|
157
|
-
return new TokenData(consumeUntil("end"), str);
|
|
158
|
-
}
|
|
159
|
-
function compile(path, options = {}) {
|
|
160
|
-
const { encode = encodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
|
|
161
|
-
const data = typeof path === "object" ? path : parse(path, options);
|
|
162
|
-
const fn = tokensToFunction(data.tokens, delimiter, encode);
|
|
163
|
-
return function path(params = {}) {
|
|
164
|
-
const [path2, ...missing] = fn(params);
|
|
165
|
-
if (missing.length) {
|
|
166
|
-
throw new TypeError(`Missing parameters: ${missing.join(", ")}`);
|
|
167
|
-
}
|
|
168
|
-
return path2;
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
function tokensToFunction(tokens, delimiter, encode) {
|
|
172
|
-
const encoders = tokens.map((token) => tokenToFunction(token, delimiter, encode));
|
|
173
|
-
return (data) => {
|
|
174
|
-
const result = [""];
|
|
175
|
-
for (const encoder of encoders) {
|
|
176
|
-
const [value, ...extras] = encoder(data);
|
|
177
|
-
result[0] += value;
|
|
178
|
-
result.push(...extras);
|
|
179
|
-
}
|
|
180
|
-
return result;
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
function tokenToFunction(token, delimiter, encode) {
|
|
184
|
-
if (token.type === "text")
|
|
185
|
-
return () => [token.value];
|
|
186
|
-
if (token.type === "group") {
|
|
187
|
-
const fn = tokensToFunction(token.tokens, delimiter, encode);
|
|
188
|
-
return (data) => {
|
|
189
|
-
const [value, ...missing] = fn(data);
|
|
190
|
-
if (!missing.length)
|
|
191
|
-
return [value];
|
|
192
|
-
return [""];
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
const encodeValue = encode || NOOP_VALUE;
|
|
196
|
-
if (token.type === "wildcard" && encode !== false) {
|
|
197
|
-
return (data) => {
|
|
198
|
-
const value = data[token.name];
|
|
199
|
-
if (value == null)
|
|
200
|
-
return ["", token.name];
|
|
201
|
-
if (!Array.isArray(value) || value.length === 0) {
|
|
202
|
-
throw new TypeError(`Expected "${token.name}" to be a non-empty array`);
|
|
203
|
-
}
|
|
204
|
-
return [
|
|
205
|
-
value.map((value2, index) => {
|
|
206
|
-
if (typeof value2 !== "string") {
|
|
207
|
-
throw new TypeError(`Expected "${token.name}/${index}" to be a string`);
|
|
208
|
-
}
|
|
209
|
-
return encodeValue(value2);
|
|
210
|
-
}).join(delimiter)
|
|
211
|
-
];
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
return (data) => {
|
|
215
|
-
const value = data[token.name];
|
|
216
|
-
if (value == null)
|
|
217
|
-
return ["", token.name];
|
|
218
|
-
if (typeof value !== "string") {
|
|
219
|
-
throw new TypeError(`Expected "${token.name}" to be a string`);
|
|
220
|
-
}
|
|
221
|
-
return [encodeValue(value)];
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
function match(path, options = {}) {
|
|
225
|
-
const { decode = decodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
|
|
226
|
-
const { regexp, keys } = pathToRegexp(path, options);
|
|
227
|
-
const decoders = keys.map((key) => {
|
|
228
|
-
if (decode === false)
|
|
229
|
-
return NOOP_VALUE;
|
|
230
|
-
if (key.type === "param")
|
|
231
|
-
return decode;
|
|
232
|
-
return (value) => value.split(delimiter).map(decode);
|
|
233
|
-
});
|
|
234
|
-
return function match(input) {
|
|
235
|
-
const m = regexp.exec(input);
|
|
236
|
-
if (!m)
|
|
237
|
-
return false;
|
|
238
|
-
const path2 = m[0];
|
|
239
|
-
const params = Object.create(null);
|
|
240
|
-
for (let i = 1;i < m.length; i++) {
|
|
241
|
-
if (m[i] === undefined)
|
|
242
|
-
continue;
|
|
243
|
-
const key = keys[i - 1];
|
|
244
|
-
const decoder = decoders[i - 1];
|
|
245
|
-
params[key.name] = decoder(m[i]);
|
|
246
|
-
}
|
|
247
|
-
return { path: path2, params };
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
function pathToRegexp(path, options = {}) {
|
|
251
|
-
const { delimiter = DEFAULT_DELIMITER, end = true, sensitive = false, trailing = true } = options;
|
|
252
|
-
const keys = [];
|
|
253
|
-
const flags = sensitive ? "" : "i";
|
|
254
|
-
const sources = [];
|
|
255
|
-
for (const input of pathsToArray(path, [])) {
|
|
256
|
-
const data = typeof input === "object" ? input : parse(input, options);
|
|
257
|
-
for (const tokens of flatten(data.tokens, 0, [])) {
|
|
258
|
-
sources.push(toRegExpSource(tokens, delimiter, keys, data.originalPath));
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
let pattern = `^(?:${sources.join("|")})`;
|
|
262
|
-
if (trailing)
|
|
263
|
-
pattern += `(?:${escape(delimiter)}$)?`;
|
|
264
|
-
pattern += end ? "$" : `(?=${escape(delimiter)}|$)`;
|
|
265
|
-
const regexp = new RegExp(pattern, flags);
|
|
266
|
-
return { regexp, keys };
|
|
267
|
-
}
|
|
268
|
-
function pathsToArray(paths, init) {
|
|
269
|
-
if (Array.isArray(paths)) {
|
|
270
|
-
for (const p of paths)
|
|
271
|
-
pathsToArray(p, init);
|
|
272
|
-
} else {
|
|
273
|
-
init.push(paths);
|
|
274
|
-
}
|
|
275
|
-
return init;
|
|
276
|
-
}
|
|
277
|
-
function* flatten(tokens, index, init) {
|
|
278
|
-
if (index === tokens.length) {
|
|
279
|
-
return yield init;
|
|
280
|
-
}
|
|
281
|
-
const token = tokens[index];
|
|
282
|
-
if (token.type === "group") {
|
|
283
|
-
for (const seq of flatten(token.tokens, 0, init.slice())) {
|
|
284
|
-
yield* flatten(tokens, index + 1, seq);
|
|
285
|
-
}
|
|
286
|
-
} else {
|
|
287
|
-
init.push(token);
|
|
288
|
-
}
|
|
289
|
-
yield* flatten(tokens, index + 1, init);
|
|
290
|
-
}
|
|
291
|
-
function toRegExpSource(tokens, delimiter, keys, originalPath) {
|
|
292
|
-
let result = "";
|
|
293
|
-
let backtrack = "";
|
|
294
|
-
let isSafeSegmentParam = true;
|
|
295
|
-
for (const token of tokens) {
|
|
296
|
-
if (token.type === "text") {
|
|
297
|
-
result += escape(token.value);
|
|
298
|
-
backtrack += token.value;
|
|
299
|
-
isSafeSegmentParam || (isSafeSegmentParam = token.value.includes(delimiter));
|
|
300
|
-
continue;
|
|
301
|
-
}
|
|
302
|
-
if (token.type === "param" || token.type === "wildcard") {
|
|
303
|
-
if (!isSafeSegmentParam && !backtrack) {
|
|
304
|
-
throw new PathError(`Missing text before "${token.name}" ${token.type}`, originalPath);
|
|
305
|
-
}
|
|
306
|
-
if (token.type === "param") {
|
|
307
|
-
result += `(${negate(delimiter, isSafeSegmentParam ? "" : backtrack)}+)`;
|
|
308
|
-
} else {
|
|
309
|
-
result += `([\\s\\S]+)`;
|
|
310
|
-
}
|
|
311
|
-
keys.push(token);
|
|
312
|
-
backtrack = "";
|
|
313
|
-
isSafeSegmentParam = false;
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
return result;
|
|
318
|
-
}
|
|
319
|
-
function negate(delimiter, backtrack) {
|
|
320
|
-
if (backtrack.length < 2) {
|
|
321
|
-
if (delimiter.length < 2)
|
|
322
|
-
return `[^${escape(delimiter + backtrack)}]`;
|
|
323
|
-
return `(?:(?!${escape(delimiter)})[^${escape(backtrack)}])`;
|
|
324
|
-
}
|
|
325
|
-
if (delimiter.length < 2) {
|
|
326
|
-
return `(?:(?!${escape(backtrack)})[^${escape(delimiter)}])`;
|
|
327
|
-
}
|
|
328
|
-
return `(?:(?!${escape(backtrack)}|${escape(delimiter)})[\\s\\S])`;
|
|
329
|
-
}
|
|
330
|
-
function stringifyTokens(tokens) {
|
|
331
|
-
let value = "";
|
|
332
|
-
let i = 0;
|
|
333
|
-
function name(value2) {
|
|
334
|
-
const isSafe = isNameSafe(value2) && isNextNameSafe(tokens[i]);
|
|
335
|
-
return isSafe ? value2 : JSON.stringify(value2);
|
|
336
|
-
}
|
|
337
|
-
while (i < tokens.length) {
|
|
338
|
-
const token = tokens[i++];
|
|
339
|
-
if (token.type === "text") {
|
|
340
|
-
value += escapeText(token.value);
|
|
341
|
-
continue;
|
|
342
|
-
}
|
|
343
|
-
if (token.type === "group") {
|
|
344
|
-
value += `{${stringifyTokens(token.tokens)}}`;
|
|
345
|
-
continue;
|
|
346
|
-
}
|
|
347
|
-
if (token.type === "param") {
|
|
348
|
-
value += `:${name(token.name)}`;
|
|
349
|
-
continue;
|
|
350
|
-
}
|
|
351
|
-
if (token.type === "wildcard") {
|
|
352
|
-
value += `*${name(token.name)}`;
|
|
353
|
-
continue;
|
|
354
|
-
}
|
|
355
|
-
throw new TypeError(`Unknown token type: ${token.type}`);
|
|
356
|
-
}
|
|
357
|
-
return value;
|
|
358
|
-
}
|
|
359
|
-
function stringify(data) {
|
|
360
|
-
return stringifyTokens(data.tokens);
|
|
361
|
-
}
|
|
362
|
-
function isNameSafe(name) {
|
|
363
|
-
const [first, ...rest] = name;
|
|
364
|
-
return ID_START.test(first) && rest.every((char) => ID_CONTINUE.test(char));
|
|
365
|
-
}
|
|
366
|
-
function isNextNameSafe(token) {
|
|
367
|
-
if (token && token.type === "text")
|
|
368
|
-
return !ID_CONTINUE.test(token.value[0]);
|
|
369
|
-
return true;
|
|
370
|
-
}
|
|
371
|
-
});
|
|
372
|
-
|
|
373
21
|
// ../../node_modules/ip-address/dist/common.js
|
|
374
22
|
var require_common = __commonJS((exports) => {
|
|
375
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -1442,6 +1090,358 @@ var require_ip_address = __commonJS((exports) => {
|
|
|
1442
1090
|
exports.v6 = { helpers };
|
|
1443
1091
|
});
|
|
1444
1092
|
|
|
1093
|
+
// ../../node_modules/path-to-regexp/dist/index.js
|
|
1094
|
+
var require_dist = __commonJS((exports) => {
|
|
1095
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1096
|
+
exports.PathError = exports.TokenData = undefined;
|
|
1097
|
+
exports.parse = parse;
|
|
1098
|
+
exports.compile = compile;
|
|
1099
|
+
exports.match = match;
|
|
1100
|
+
exports.pathToRegexp = pathToRegexp;
|
|
1101
|
+
exports.stringify = stringify;
|
|
1102
|
+
var DEFAULT_DELIMITER = "/";
|
|
1103
|
+
var NOOP_VALUE = (value) => value;
|
|
1104
|
+
var ID_START = /^[$_\p{ID_Start}]$/u;
|
|
1105
|
+
var ID_CONTINUE = /^[$\u200c\u200d\p{ID_Continue}]$/u;
|
|
1106
|
+
var SIMPLE_TOKENS = {
|
|
1107
|
+
"{": "{",
|
|
1108
|
+
"}": "}",
|
|
1109
|
+
"(": "(",
|
|
1110
|
+
")": ")",
|
|
1111
|
+
"[": "[",
|
|
1112
|
+
"]": "]",
|
|
1113
|
+
"+": "+",
|
|
1114
|
+
"?": "?",
|
|
1115
|
+
"!": "!"
|
|
1116
|
+
};
|
|
1117
|
+
function escapeText(str) {
|
|
1118
|
+
return str.replace(/[{}()\[\]+?!:*\\]/g, "\\$&");
|
|
1119
|
+
}
|
|
1120
|
+
function escape(str) {
|
|
1121
|
+
return str.replace(/[.+*?^${}()[\]|/\\]/g, "\\$&");
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
class TokenData {
|
|
1125
|
+
constructor(tokens, originalPath) {
|
|
1126
|
+
this.tokens = tokens;
|
|
1127
|
+
this.originalPath = originalPath;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
exports.TokenData = TokenData;
|
|
1131
|
+
|
|
1132
|
+
class PathError extends TypeError {
|
|
1133
|
+
constructor(message, originalPath) {
|
|
1134
|
+
let text = message;
|
|
1135
|
+
if (originalPath)
|
|
1136
|
+
text += `: ${originalPath}`;
|
|
1137
|
+
text += `; visit https://git.new/pathToRegexpError for info`;
|
|
1138
|
+
super(text);
|
|
1139
|
+
this.originalPath = originalPath;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
exports.PathError = PathError;
|
|
1143
|
+
function parse(str, options = {}) {
|
|
1144
|
+
const { encodePath = NOOP_VALUE } = options;
|
|
1145
|
+
const chars = [...str];
|
|
1146
|
+
const tokens = [];
|
|
1147
|
+
let index = 0;
|
|
1148
|
+
let pos = 0;
|
|
1149
|
+
function name() {
|
|
1150
|
+
let value = "";
|
|
1151
|
+
if (ID_START.test(chars[index])) {
|
|
1152
|
+
do {
|
|
1153
|
+
value += chars[index++];
|
|
1154
|
+
} while (ID_CONTINUE.test(chars[index]));
|
|
1155
|
+
} else if (chars[index] === '"') {
|
|
1156
|
+
let quoteStart = index;
|
|
1157
|
+
while (index++ < chars.length) {
|
|
1158
|
+
if (chars[index] === '"') {
|
|
1159
|
+
index++;
|
|
1160
|
+
quoteStart = 0;
|
|
1161
|
+
break;
|
|
1162
|
+
}
|
|
1163
|
+
if (chars[index] === "\\")
|
|
1164
|
+
index++;
|
|
1165
|
+
value += chars[index];
|
|
1166
|
+
}
|
|
1167
|
+
if (quoteStart) {
|
|
1168
|
+
throw new PathError(`Unterminated quote at index ${quoteStart}`, str);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
if (!value) {
|
|
1172
|
+
throw new PathError(`Missing parameter name at index ${index}`, str);
|
|
1173
|
+
}
|
|
1174
|
+
return value;
|
|
1175
|
+
}
|
|
1176
|
+
while (index < chars.length) {
|
|
1177
|
+
const value = chars[index];
|
|
1178
|
+
const type = SIMPLE_TOKENS[value];
|
|
1179
|
+
if (type) {
|
|
1180
|
+
tokens.push({ type, index: index++, value });
|
|
1181
|
+
} else if (value === "\\") {
|
|
1182
|
+
tokens.push({ type: "escape", index: index++, value: chars[index++] });
|
|
1183
|
+
} else if (value === ":") {
|
|
1184
|
+
tokens.push({ type: "param", index: index++, value: name() });
|
|
1185
|
+
} else if (value === "*") {
|
|
1186
|
+
tokens.push({ type: "wildcard", index: index++, value: name() });
|
|
1187
|
+
} else {
|
|
1188
|
+
tokens.push({ type: "char", index: index++, value });
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
tokens.push({ type: "end", index, value: "" });
|
|
1192
|
+
function consumeUntil(endType) {
|
|
1193
|
+
const output = [];
|
|
1194
|
+
while (true) {
|
|
1195
|
+
const token = tokens[pos++];
|
|
1196
|
+
if (token.type === endType)
|
|
1197
|
+
break;
|
|
1198
|
+
if (token.type === "char" || token.type === "escape") {
|
|
1199
|
+
let path = token.value;
|
|
1200
|
+
let cur = tokens[pos];
|
|
1201
|
+
while (cur.type === "char" || cur.type === "escape") {
|
|
1202
|
+
path += cur.value;
|
|
1203
|
+
cur = tokens[++pos];
|
|
1204
|
+
}
|
|
1205
|
+
output.push({
|
|
1206
|
+
type: "text",
|
|
1207
|
+
value: encodePath(path)
|
|
1208
|
+
});
|
|
1209
|
+
continue;
|
|
1210
|
+
}
|
|
1211
|
+
if (token.type === "param" || token.type === "wildcard") {
|
|
1212
|
+
output.push({
|
|
1213
|
+
type: token.type,
|
|
1214
|
+
name: token.value
|
|
1215
|
+
});
|
|
1216
|
+
continue;
|
|
1217
|
+
}
|
|
1218
|
+
if (token.type === "{") {
|
|
1219
|
+
output.push({
|
|
1220
|
+
type: "group",
|
|
1221
|
+
tokens: consumeUntil("}")
|
|
1222
|
+
});
|
|
1223
|
+
continue;
|
|
1224
|
+
}
|
|
1225
|
+
throw new PathError(`Unexpected ${token.type} at index ${token.index}, expected ${endType}`, str);
|
|
1226
|
+
}
|
|
1227
|
+
return output;
|
|
1228
|
+
}
|
|
1229
|
+
return new TokenData(consumeUntil("end"), str);
|
|
1230
|
+
}
|
|
1231
|
+
function compile(path, options = {}) {
|
|
1232
|
+
const { encode = encodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
|
|
1233
|
+
const data = typeof path === "object" ? path : parse(path, options);
|
|
1234
|
+
const fn = tokensToFunction(data.tokens, delimiter, encode);
|
|
1235
|
+
return function path(params = {}) {
|
|
1236
|
+
const [path2, ...missing] = fn(params);
|
|
1237
|
+
if (missing.length) {
|
|
1238
|
+
throw new TypeError(`Missing parameters: ${missing.join(", ")}`);
|
|
1239
|
+
}
|
|
1240
|
+
return path2;
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
function tokensToFunction(tokens, delimiter, encode) {
|
|
1244
|
+
const encoders = tokens.map((token) => tokenToFunction(token, delimiter, encode));
|
|
1245
|
+
return (data) => {
|
|
1246
|
+
const result = [""];
|
|
1247
|
+
for (const encoder of encoders) {
|
|
1248
|
+
const [value, ...extras] = encoder(data);
|
|
1249
|
+
result[0] += value;
|
|
1250
|
+
result.push(...extras);
|
|
1251
|
+
}
|
|
1252
|
+
return result;
|
|
1253
|
+
};
|
|
1254
|
+
}
|
|
1255
|
+
function tokenToFunction(token, delimiter, encode) {
|
|
1256
|
+
if (token.type === "text")
|
|
1257
|
+
return () => [token.value];
|
|
1258
|
+
if (token.type === "group") {
|
|
1259
|
+
const fn = tokensToFunction(token.tokens, delimiter, encode);
|
|
1260
|
+
return (data) => {
|
|
1261
|
+
const [value, ...missing] = fn(data);
|
|
1262
|
+
if (!missing.length)
|
|
1263
|
+
return [value];
|
|
1264
|
+
return [""];
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
const encodeValue = encode || NOOP_VALUE;
|
|
1268
|
+
if (token.type === "wildcard" && encode !== false) {
|
|
1269
|
+
return (data) => {
|
|
1270
|
+
const value = data[token.name];
|
|
1271
|
+
if (value == null)
|
|
1272
|
+
return ["", token.name];
|
|
1273
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
1274
|
+
throw new TypeError(`Expected "${token.name}" to be a non-empty array`);
|
|
1275
|
+
}
|
|
1276
|
+
return [
|
|
1277
|
+
value.map((value2, index) => {
|
|
1278
|
+
if (typeof value2 !== "string") {
|
|
1279
|
+
throw new TypeError(`Expected "${token.name}/${index}" to be a string`);
|
|
1280
|
+
}
|
|
1281
|
+
return encodeValue(value2);
|
|
1282
|
+
}).join(delimiter)
|
|
1283
|
+
];
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
return (data) => {
|
|
1287
|
+
const value = data[token.name];
|
|
1288
|
+
if (value == null)
|
|
1289
|
+
return ["", token.name];
|
|
1290
|
+
if (typeof value !== "string") {
|
|
1291
|
+
throw new TypeError(`Expected "${token.name}" to be a string`);
|
|
1292
|
+
}
|
|
1293
|
+
return [encodeValue(value)];
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
function match(path, options = {}) {
|
|
1297
|
+
const { decode = decodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
|
|
1298
|
+
const { regexp, keys } = pathToRegexp(path, options);
|
|
1299
|
+
const decoders = keys.map((key) => {
|
|
1300
|
+
if (decode === false)
|
|
1301
|
+
return NOOP_VALUE;
|
|
1302
|
+
if (key.type === "param")
|
|
1303
|
+
return decode;
|
|
1304
|
+
return (value) => value.split(delimiter).map(decode);
|
|
1305
|
+
});
|
|
1306
|
+
return function match(input) {
|
|
1307
|
+
const m = regexp.exec(input);
|
|
1308
|
+
if (!m)
|
|
1309
|
+
return false;
|
|
1310
|
+
const path2 = m[0];
|
|
1311
|
+
const params = Object.create(null);
|
|
1312
|
+
for (let i = 1;i < m.length; i++) {
|
|
1313
|
+
if (m[i] === undefined)
|
|
1314
|
+
continue;
|
|
1315
|
+
const key = keys[i - 1];
|
|
1316
|
+
const decoder = decoders[i - 1];
|
|
1317
|
+
params[key.name] = decoder(m[i]);
|
|
1318
|
+
}
|
|
1319
|
+
return { path: path2, params };
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
function pathToRegexp(path, options = {}) {
|
|
1323
|
+
const { delimiter = DEFAULT_DELIMITER, end = true, sensitive = false, trailing = true } = options;
|
|
1324
|
+
const keys = [];
|
|
1325
|
+
const flags = sensitive ? "" : "i";
|
|
1326
|
+
const sources = [];
|
|
1327
|
+
for (const input of pathsToArray(path, [])) {
|
|
1328
|
+
const data = typeof input === "object" ? input : parse(input, options);
|
|
1329
|
+
for (const tokens of flatten(data.tokens, 0, [])) {
|
|
1330
|
+
sources.push(toRegExpSource(tokens, delimiter, keys, data.originalPath));
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
let pattern = `^(?:${sources.join("|")})`;
|
|
1334
|
+
if (trailing)
|
|
1335
|
+
pattern += `(?:${escape(delimiter)}$)?`;
|
|
1336
|
+
pattern += end ? "$" : `(?=${escape(delimiter)}|$)`;
|
|
1337
|
+
const regexp = new RegExp(pattern, flags);
|
|
1338
|
+
return { regexp, keys };
|
|
1339
|
+
}
|
|
1340
|
+
function pathsToArray(paths, init) {
|
|
1341
|
+
if (Array.isArray(paths)) {
|
|
1342
|
+
for (const p of paths)
|
|
1343
|
+
pathsToArray(p, init);
|
|
1344
|
+
} else {
|
|
1345
|
+
init.push(paths);
|
|
1346
|
+
}
|
|
1347
|
+
return init;
|
|
1348
|
+
}
|
|
1349
|
+
function* flatten(tokens, index, init) {
|
|
1350
|
+
if (index === tokens.length) {
|
|
1351
|
+
return yield init;
|
|
1352
|
+
}
|
|
1353
|
+
const token = tokens[index];
|
|
1354
|
+
if (token.type === "group") {
|
|
1355
|
+
for (const seq of flatten(token.tokens, 0, init.slice())) {
|
|
1356
|
+
yield* flatten(tokens, index + 1, seq);
|
|
1357
|
+
}
|
|
1358
|
+
} else {
|
|
1359
|
+
init.push(token);
|
|
1360
|
+
}
|
|
1361
|
+
yield* flatten(tokens, index + 1, init);
|
|
1362
|
+
}
|
|
1363
|
+
function toRegExpSource(tokens, delimiter, keys, originalPath) {
|
|
1364
|
+
let result = "";
|
|
1365
|
+
let backtrack = "";
|
|
1366
|
+
let isSafeSegmentParam = true;
|
|
1367
|
+
for (const token of tokens) {
|
|
1368
|
+
if (token.type === "text") {
|
|
1369
|
+
result += escape(token.value);
|
|
1370
|
+
backtrack += token.value;
|
|
1371
|
+
isSafeSegmentParam || (isSafeSegmentParam = token.value.includes(delimiter));
|
|
1372
|
+
continue;
|
|
1373
|
+
}
|
|
1374
|
+
if (token.type === "param" || token.type === "wildcard") {
|
|
1375
|
+
if (!isSafeSegmentParam && !backtrack) {
|
|
1376
|
+
throw new PathError(`Missing text before "${token.name}" ${token.type}`, originalPath);
|
|
1377
|
+
}
|
|
1378
|
+
if (token.type === "param") {
|
|
1379
|
+
result += `(${negate(delimiter, isSafeSegmentParam ? "" : backtrack)}+)`;
|
|
1380
|
+
} else {
|
|
1381
|
+
result += `([\\s\\S]+)`;
|
|
1382
|
+
}
|
|
1383
|
+
keys.push(token);
|
|
1384
|
+
backtrack = "";
|
|
1385
|
+
isSafeSegmentParam = false;
|
|
1386
|
+
continue;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
return result;
|
|
1390
|
+
}
|
|
1391
|
+
function negate(delimiter, backtrack) {
|
|
1392
|
+
if (backtrack.length < 2) {
|
|
1393
|
+
if (delimiter.length < 2)
|
|
1394
|
+
return `[^${escape(delimiter + backtrack)}]`;
|
|
1395
|
+
return `(?:(?!${escape(delimiter)})[^${escape(backtrack)}])`;
|
|
1396
|
+
}
|
|
1397
|
+
if (delimiter.length < 2) {
|
|
1398
|
+
return `(?:(?!${escape(backtrack)})[^${escape(delimiter)}])`;
|
|
1399
|
+
}
|
|
1400
|
+
return `(?:(?!${escape(backtrack)}|${escape(delimiter)})[\\s\\S])`;
|
|
1401
|
+
}
|
|
1402
|
+
function stringifyTokens(tokens) {
|
|
1403
|
+
let value = "";
|
|
1404
|
+
let i = 0;
|
|
1405
|
+
function name(value2) {
|
|
1406
|
+
const isSafe = isNameSafe(value2) && isNextNameSafe(tokens[i]);
|
|
1407
|
+
return isSafe ? value2 : JSON.stringify(value2);
|
|
1408
|
+
}
|
|
1409
|
+
while (i < tokens.length) {
|
|
1410
|
+
const token = tokens[i++];
|
|
1411
|
+
if (token.type === "text") {
|
|
1412
|
+
value += escapeText(token.value);
|
|
1413
|
+
continue;
|
|
1414
|
+
}
|
|
1415
|
+
if (token.type === "group") {
|
|
1416
|
+
value += `{${stringifyTokens(token.tokens)}}`;
|
|
1417
|
+
continue;
|
|
1418
|
+
}
|
|
1419
|
+
if (token.type === "param") {
|
|
1420
|
+
value += `:${name(token.name)}`;
|
|
1421
|
+
continue;
|
|
1422
|
+
}
|
|
1423
|
+
if (token.type === "wildcard") {
|
|
1424
|
+
value += `*${name(token.name)}`;
|
|
1425
|
+
continue;
|
|
1426
|
+
}
|
|
1427
|
+
throw new TypeError(`Unknown token type: ${token.type}`);
|
|
1428
|
+
}
|
|
1429
|
+
return value;
|
|
1430
|
+
}
|
|
1431
|
+
function stringify(data) {
|
|
1432
|
+
return stringifyTokens(data.tokens);
|
|
1433
|
+
}
|
|
1434
|
+
function isNameSafe(name) {
|
|
1435
|
+
const [first, ...rest] = name;
|
|
1436
|
+
return ID_START.test(first) && rest.every((char) => ID_CONTINUE.test(char));
|
|
1437
|
+
}
|
|
1438
|
+
function isNextNameSafe(token) {
|
|
1439
|
+
if (token && token.type === "text")
|
|
1440
|
+
return !ID_CONTINUE.test(token.value[0]);
|
|
1441
|
+
return true;
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
|
|
1445
1445
|
// ../../node_modules/dotenv/package.json
|
|
1446
1446
|
var require_package = __commonJS((exports, module) => {
|
|
1447
1447
|
module.exports = {
|
|
@@ -24384,6 +24384,584 @@ import {
|
|
|
24384
24384
|
import cors2 from "cors";
|
|
24385
24385
|
import express34 from "express";
|
|
24386
24386
|
|
|
24387
|
+
// ../../node_modules/express-rate-limit/dist/index.mjs
|
|
24388
|
+
var import_ip_address = __toESM(require_ip_address(), 1);
|
|
24389
|
+
import { isIPv6 } from "node:net";
|
|
24390
|
+
import { isIPv6 as isIPv62 } from "node:net";
|
|
24391
|
+
import { Buffer as Buffer2 } from "node:buffer";
|
|
24392
|
+
import { createHash } from "node:crypto";
|
|
24393
|
+
import { isIP } from "node:net";
|
|
24394
|
+
function ipKeyGenerator(ip, ipv6Subnet = 56) {
|
|
24395
|
+
if (ipv6Subnet && isIPv6(ip)) {
|
|
24396
|
+
return `${new import_ip_address.Address6(`${ip}/${ipv6Subnet}`).startAddress().correctForm()}/${ipv6Subnet}`;
|
|
24397
|
+
}
|
|
24398
|
+
return ip;
|
|
24399
|
+
}
|
|
24400
|
+
var MemoryStore = class {
|
|
24401
|
+
constructor(validations2) {
|
|
24402
|
+
this.validations = validations2;
|
|
24403
|
+
this.previous = /* @__PURE__ */ new Map;
|
|
24404
|
+
this.current = /* @__PURE__ */ new Map;
|
|
24405
|
+
this.localKeys = true;
|
|
24406
|
+
}
|
|
24407
|
+
init(options) {
|
|
24408
|
+
this.windowMs = options.windowMs;
|
|
24409
|
+
this.validations?.windowMs(this.windowMs);
|
|
24410
|
+
if (this.interval)
|
|
24411
|
+
clearInterval(this.interval);
|
|
24412
|
+
this.interval = setInterval(() => {
|
|
24413
|
+
this.clearExpired();
|
|
24414
|
+
}, this.windowMs);
|
|
24415
|
+
this.interval.unref?.();
|
|
24416
|
+
}
|
|
24417
|
+
async get(key) {
|
|
24418
|
+
return this.current.get(key) ?? this.previous.get(key);
|
|
24419
|
+
}
|
|
24420
|
+
async increment(key) {
|
|
24421
|
+
const client = this.getClient(key);
|
|
24422
|
+
const now = Date.now();
|
|
24423
|
+
if (client.resetTime.getTime() <= now) {
|
|
24424
|
+
this.resetClient(client, now);
|
|
24425
|
+
}
|
|
24426
|
+
client.totalHits++;
|
|
24427
|
+
return client;
|
|
24428
|
+
}
|
|
24429
|
+
async decrement(key) {
|
|
24430
|
+
const client = this.getClient(key);
|
|
24431
|
+
if (client.totalHits > 0)
|
|
24432
|
+
client.totalHits--;
|
|
24433
|
+
}
|
|
24434
|
+
async resetKey(key) {
|
|
24435
|
+
this.current.delete(key);
|
|
24436
|
+
this.previous.delete(key);
|
|
24437
|
+
}
|
|
24438
|
+
async resetAll() {
|
|
24439
|
+
this.current.clear();
|
|
24440
|
+
this.previous.clear();
|
|
24441
|
+
}
|
|
24442
|
+
shutdown() {
|
|
24443
|
+
clearInterval(this.interval);
|
|
24444
|
+
this.resetAll();
|
|
24445
|
+
}
|
|
24446
|
+
resetClient(client, now = Date.now()) {
|
|
24447
|
+
client.totalHits = 0;
|
|
24448
|
+
client.resetTime.setTime(now + this.windowMs);
|
|
24449
|
+
return client;
|
|
24450
|
+
}
|
|
24451
|
+
getClient(key) {
|
|
24452
|
+
if (this.current.has(key))
|
|
24453
|
+
return this.current.get(key);
|
|
24454
|
+
let client;
|
|
24455
|
+
if (this.previous.has(key)) {
|
|
24456
|
+
client = this.previous.get(key);
|
|
24457
|
+
this.previous.delete(key);
|
|
24458
|
+
} else {
|
|
24459
|
+
client = { totalHits: 0, resetTime: /* @__PURE__ */ new Date };
|
|
24460
|
+
this.resetClient(client);
|
|
24461
|
+
}
|
|
24462
|
+
this.current.set(key, client);
|
|
24463
|
+
return client;
|
|
24464
|
+
}
|
|
24465
|
+
clearExpired() {
|
|
24466
|
+
this.previous = this.current;
|
|
24467
|
+
this.current = /* @__PURE__ */ new Map;
|
|
24468
|
+
}
|
|
24469
|
+
};
|
|
24470
|
+
var SUPPORTED_DRAFT_VERSIONS = [
|
|
24471
|
+
"draft-6",
|
|
24472
|
+
"draft-7",
|
|
24473
|
+
"draft-8"
|
|
24474
|
+
];
|
|
24475
|
+
var getResetSeconds = (windowMs, resetTime) => {
|
|
24476
|
+
let resetSeconds;
|
|
24477
|
+
if (resetTime) {
|
|
24478
|
+
const deltaSeconds = Math.ceil((resetTime.getTime() - Date.now()) / 1000);
|
|
24479
|
+
resetSeconds = Math.max(0, deltaSeconds);
|
|
24480
|
+
} else {
|
|
24481
|
+
resetSeconds = Math.ceil(windowMs / 1000);
|
|
24482
|
+
}
|
|
24483
|
+
return resetSeconds;
|
|
24484
|
+
};
|
|
24485
|
+
var getPartitionKey = (key) => {
|
|
24486
|
+
const hash = createHash("sha256");
|
|
24487
|
+
hash.update(key);
|
|
24488
|
+
const partitionKey = hash.digest("hex").slice(0, 12);
|
|
24489
|
+
return Buffer2.from(partitionKey).toString("base64");
|
|
24490
|
+
};
|
|
24491
|
+
var setLegacyHeaders = (response, info) => {
|
|
24492
|
+
if (response.headersSent)
|
|
24493
|
+
return;
|
|
24494
|
+
response.setHeader("X-RateLimit-Limit", info.limit.toString());
|
|
24495
|
+
response.setHeader("X-RateLimit-Remaining", info.remaining.toString());
|
|
24496
|
+
if (info.resetTime instanceof Date) {
|
|
24497
|
+
response.setHeader("Date", (/* @__PURE__ */ new Date()).toUTCString());
|
|
24498
|
+
response.setHeader("X-RateLimit-Reset", Math.ceil(info.resetTime.getTime() / 1000).toString());
|
|
24499
|
+
}
|
|
24500
|
+
};
|
|
24501
|
+
var setDraft6Headers = (response, info, windowMs) => {
|
|
24502
|
+
if (response.headersSent)
|
|
24503
|
+
return;
|
|
24504
|
+
const windowSeconds = Math.ceil(windowMs / 1000);
|
|
24505
|
+
const resetSeconds = getResetSeconds(windowMs, info.resetTime);
|
|
24506
|
+
response.setHeader("RateLimit-Policy", `${info.limit};w=${windowSeconds}`);
|
|
24507
|
+
response.setHeader("RateLimit-Limit", info.limit.toString());
|
|
24508
|
+
response.setHeader("RateLimit-Remaining", info.remaining.toString());
|
|
24509
|
+
if (typeof resetSeconds === "number")
|
|
24510
|
+
response.setHeader("RateLimit-Reset", resetSeconds.toString());
|
|
24511
|
+
};
|
|
24512
|
+
var setDraft7Headers = (response, info, windowMs) => {
|
|
24513
|
+
if (response.headersSent)
|
|
24514
|
+
return;
|
|
24515
|
+
const windowSeconds = Math.ceil(windowMs / 1000);
|
|
24516
|
+
const resetSeconds = getResetSeconds(windowMs, info.resetTime);
|
|
24517
|
+
response.setHeader("RateLimit-Policy", `${info.limit};w=${windowSeconds}`);
|
|
24518
|
+
response.setHeader("RateLimit", `limit=${info.limit}, remaining=${info.remaining}, reset=${resetSeconds}`);
|
|
24519
|
+
};
|
|
24520
|
+
var setDraft8Headers = (response, info, windowMs, name, key) => {
|
|
24521
|
+
if (response.headersSent)
|
|
24522
|
+
return;
|
|
24523
|
+
const windowSeconds = Math.ceil(windowMs / 1000);
|
|
24524
|
+
const resetSeconds = getResetSeconds(windowMs, info.resetTime);
|
|
24525
|
+
const partitionKey = getPartitionKey(key);
|
|
24526
|
+
const header = `r=${info.remaining}; t=${resetSeconds}`;
|
|
24527
|
+
const policy = `q=${info.limit}; w=${windowSeconds}; pk=:${partitionKey}:`;
|
|
24528
|
+
response.append("RateLimit", `"${name}"; ${header}`);
|
|
24529
|
+
response.append("RateLimit-Policy", `"${name}"; ${policy}`);
|
|
24530
|
+
};
|
|
24531
|
+
var setRetryAfterHeader = (response, info, windowMs) => {
|
|
24532
|
+
if (response.headersSent)
|
|
24533
|
+
return;
|
|
24534
|
+
const resetSeconds = getResetSeconds(windowMs, info.resetTime);
|
|
24535
|
+
response.setHeader("Retry-After", resetSeconds.toString());
|
|
24536
|
+
};
|
|
24537
|
+
var omitUndefinedProperties = (passedOptions) => {
|
|
24538
|
+
const omittedOptions = {};
|
|
24539
|
+
for (const k of Object.keys(passedOptions)) {
|
|
24540
|
+
const key = k;
|
|
24541
|
+
if (passedOptions[key] !== undefined) {
|
|
24542
|
+
omittedOptions[key] = passedOptions[key];
|
|
24543
|
+
}
|
|
24544
|
+
}
|
|
24545
|
+
return omittedOptions;
|
|
24546
|
+
};
|
|
24547
|
+
var ValidationError = class extends Error {
|
|
24548
|
+
constructor(code, message) {
|
|
24549
|
+
const url = `https://express-rate-limit.github.io/${code}/`;
|
|
24550
|
+
super(`${message} See ${url} for more information.`);
|
|
24551
|
+
this.name = this.constructor.name;
|
|
24552
|
+
this.code = code;
|
|
24553
|
+
this.help = url;
|
|
24554
|
+
}
|
|
24555
|
+
};
|
|
24556
|
+
var ChangeWarning = class extends ValidationError {
|
|
24557
|
+
};
|
|
24558
|
+
var usedStores = /* @__PURE__ */ new Set;
|
|
24559
|
+
var singleCountKeys = /* @__PURE__ */ new WeakMap;
|
|
24560
|
+
var validations = {
|
|
24561
|
+
enabled: {
|
|
24562
|
+
default: true
|
|
24563
|
+
},
|
|
24564
|
+
disable() {
|
|
24565
|
+
for (const k of Object.keys(this.enabled))
|
|
24566
|
+
this.enabled[k] = false;
|
|
24567
|
+
},
|
|
24568
|
+
ip(ip) {
|
|
24569
|
+
if (ip === undefined) {
|
|
24570
|
+
throw new ValidationError("ERR_ERL_UNDEFINED_IP_ADDRESS", `An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.`);
|
|
24571
|
+
}
|
|
24572
|
+
if (!isIP(ip)) {
|
|
24573
|
+
throw new ValidationError("ERR_ERL_INVALID_IP_ADDRESS", `An invalid 'request.ip' (${ip}) was detected. Consider passing a custom 'keyGenerator' function to the rate limiter.`);
|
|
24574
|
+
}
|
|
24575
|
+
},
|
|
24576
|
+
trustProxy(request) {
|
|
24577
|
+
if (request.app.get("trust proxy") === true) {
|
|
24578
|
+
throw new ValidationError("ERR_ERL_PERMISSIVE_TRUST_PROXY", `The Express 'trust proxy' setting is true, which allows anyone to trivially bypass IP-based rate limiting.`);
|
|
24579
|
+
}
|
|
24580
|
+
},
|
|
24581
|
+
xForwardedForHeader(request) {
|
|
24582
|
+
if (request.headers["x-forwarded-for"] && request.app.get("trust proxy") === false) {
|
|
24583
|
+
throw new ValidationError("ERR_ERL_UNEXPECTED_X_FORWARDED_FOR", `The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.`);
|
|
24584
|
+
}
|
|
24585
|
+
},
|
|
24586
|
+
forwardedHeader(request) {
|
|
24587
|
+
if (request.headers.forwarded && request.ip === request.socket?.remoteAddress) {
|
|
24588
|
+
throw new ValidationError("ERR_ERL_FORWARDED_HEADER", `The 'Forwarded' header (standardized X-Forwarded-For) is set but currently being ignored. Add a custom keyGenerator to use a value from this header.`);
|
|
24589
|
+
}
|
|
24590
|
+
},
|
|
24591
|
+
positiveHits(hits) {
|
|
24592
|
+
if (typeof hits !== "number" || hits < 1 || hits !== Math.round(hits)) {
|
|
24593
|
+
throw new ValidationError("ERR_ERL_INVALID_HITS", `The totalHits value returned from the store must be a positive integer, got ${hits}`);
|
|
24594
|
+
}
|
|
24595
|
+
},
|
|
24596
|
+
unsharedStore(store) {
|
|
24597
|
+
if (usedStores.has(store)) {
|
|
24598
|
+
const maybeUniquePrefix = store?.localKeys ? "" : " (with a unique prefix)";
|
|
24599
|
+
throw new ValidationError("ERR_ERL_STORE_REUSE", `A Store instance must not be shared across multiple rate limiters. Create a new instance of ${store.constructor.name}${maybeUniquePrefix} for each limiter instead.`);
|
|
24600
|
+
}
|
|
24601
|
+
usedStores.add(store);
|
|
24602
|
+
},
|
|
24603
|
+
singleCount(request, store, key) {
|
|
24604
|
+
let storeKeys = singleCountKeys.get(request);
|
|
24605
|
+
if (!storeKeys) {
|
|
24606
|
+
storeKeys = /* @__PURE__ */ new Map;
|
|
24607
|
+
singleCountKeys.set(request, storeKeys);
|
|
24608
|
+
}
|
|
24609
|
+
const storeKey = store.localKeys ? store : store.constructor.name;
|
|
24610
|
+
let keys = storeKeys.get(storeKey);
|
|
24611
|
+
if (!keys) {
|
|
24612
|
+
keys = [];
|
|
24613
|
+
storeKeys.set(storeKey, keys);
|
|
24614
|
+
}
|
|
24615
|
+
const prefixedKey = `${store.prefix ?? ""}${key}`;
|
|
24616
|
+
if (keys.includes(prefixedKey)) {
|
|
24617
|
+
throw new ValidationError("ERR_ERL_DOUBLE_COUNT", `The hit count for ${key} was incremented more than once for a single request.`);
|
|
24618
|
+
}
|
|
24619
|
+
keys.push(prefixedKey);
|
|
24620
|
+
},
|
|
24621
|
+
limit(limit) {
|
|
24622
|
+
if (limit === 0) {
|
|
24623
|
+
throw new ChangeWarning("WRN_ERL_MAX_ZERO", "Setting limit or max to 0 disables rate limiting in express-rate-limit v6 and older, but will cause all requests to be blocked in v7");
|
|
24624
|
+
}
|
|
24625
|
+
},
|
|
24626
|
+
draftPolliHeaders(draft_polli_ratelimit_headers) {
|
|
24627
|
+
if (draft_polli_ratelimit_headers) {
|
|
24628
|
+
throw new ChangeWarning("WRN_ERL_DEPRECATED_DRAFT_POLLI_HEADERS", `The draft_polli_ratelimit_headers configuration option is deprecated and has been removed in express-rate-limit v7, please set standardHeaders: 'draft-6' instead.`);
|
|
24629
|
+
}
|
|
24630
|
+
},
|
|
24631
|
+
onLimitReached(onLimitReached) {
|
|
24632
|
+
if (onLimitReached) {
|
|
24633
|
+
throw new ChangeWarning("WRN_ERL_DEPRECATED_ON_LIMIT_REACHED", "The onLimitReached configuration option is deprecated and has been removed in express-rate-limit v7.");
|
|
24634
|
+
}
|
|
24635
|
+
},
|
|
24636
|
+
headersDraftVersion(version) {
|
|
24637
|
+
if (typeof version !== "string" || !SUPPORTED_DRAFT_VERSIONS.includes(version)) {
|
|
24638
|
+
const versionString = SUPPORTED_DRAFT_VERSIONS.join(", ");
|
|
24639
|
+
throw new ValidationError("ERR_ERL_HEADERS_UNSUPPORTED_DRAFT_VERSION", `standardHeaders: only the following versions of the IETF draft specification are supported: ${versionString}.`);
|
|
24640
|
+
}
|
|
24641
|
+
},
|
|
24642
|
+
headersResetTime(resetTime) {
|
|
24643
|
+
if (!resetTime) {
|
|
24644
|
+
throw new ValidationError("ERR_ERL_HEADERS_NO_RESET", `standardHeaders: 'draft-7' requires a 'resetTime', but the store did not provide one. The 'windowMs' value will be used instead, which may cause clients to wait longer than necessary.`);
|
|
24645
|
+
}
|
|
24646
|
+
},
|
|
24647
|
+
validationsConfig() {
|
|
24648
|
+
const supportedValidations = Object.keys(this).filter((k) => !["enabled", "disable"].includes(k));
|
|
24649
|
+
supportedValidations.push("default");
|
|
24650
|
+
for (const key of Object.keys(this.enabled)) {
|
|
24651
|
+
if (!supportedValidations.includes(key)) {
|
|
24652
|
+
throw new ValidationError("ERR_ERL_UNKNOWN_VALIDATION", `options.validate.${key} is not recognized. Supported validate options are: ${supportedValidations.join(", ")}.`);
|
|
24653
|
+
}
|
|
24654
|
+
}
|
|
24655
|
+
},
|
|
24656
|
+
creationStack(store) {
|
|
24657
|
+
const { stack } = new Error("express-rate-limit validation check (set options.validate.creationStack=false to disable)");
|
|
24658
|
+
if (stack?.includes("Layer.handle [as handle_request]") || stack?.includes("Layer.handleRequest")) {
|
|
24659
|
+
if (!store.localKeys) {
|
|
24660
|
+
throw new ValidationError("ERR_ERL_CREATED_IN_REQUEST_HANDLER", "express-rate-limit instance should *usually* be created at app initialization, not when responding to a request.");
|
|
24661
|
+
}
|
|
24662
|
+
throw new ValidationError("ERR_ERL_CREATED_IN_REQUEST_HANDLER", "express-rate-limit instance should be created at app initialization, not when responding to a request.");
|
|
24663
|
+
}
|
|
24664
|
+
},
|
|
24665
|
+
ipv6Subnet(ipv6Subnet) {
|
|
24666
|
+
if (ipv6Subnet === false) {
|
|
24667
|
+
return;
|
|
24668
|
+
}
|
|
24669
|
+
if (!Number.isInteger(ipv6Subnet) || ipv6Subnet < 32 || ipv6Subnet > 64) {
|
|
24670
|
+
throw new ValidationError("ERR_ERL_IPV6_SUBNET", `Unexpected ipv6Subnet value: ${ipv6Subnet}. Expected an integer between 32 and 64 (usually 48-64).`);
|
|
24671
|
+
}
|
|
24672
|
+
},
|
|
24673
|
+
ipv6SubnetOrKeyGenerator(options) {
|
|
24674
|
+
if (options.ipv6Subnet !== undefined && options.keyGenerator) {
|
|
24675
|
+
throw new ValidationError("ERR_ERL_IPV6SUBNET_OR_KEYGENERATOR", `Incompatible options: the 'ipv6Subnet' option is ignored when a custom 'keyGenerator' function is also set.`);
|
|
24676
|
+
}
|
|
24677
|
+
},
|
|
24678
|
+
keyGeneratorIpFallback(keyGenerator) {
|
|
24679
|
+
if (!keyGenerator) {
|
|
24680
|
+
return;
|
|
24681
|
+
}
|
|
24682
|
+
const src = keyGenerator.toString();
|
|
24683
|
+
if ((src.includes("req.ip") || src.includes("request.ip")) && !src.includes("ipKeyGenerator")) {
|
|
24684
|
+
throw new ValidationError("ERR_ERL_KEY_GEN_IPV6", "Custom keyGenerator appears to use request IP without calling the ipKeyGenerator helper function for IPv6 addresses. This could allow IPv6 users to bypass limits.");
|
|
24685
|
+
}
|
|
24686
|
+
},
|
|
24687
|
+
windowMs(windowMs) {
|
|
24688
|
+
const SET_TIMEOUT_MAX = 2 ** 31 - 1;
|
|
24689
|
+
if (typeof windowMs !== "number" || Number.isNaN(windowMs) || windowMs < 1 || windowMs > SET_TIMEOUT_MAX) {
|
|
24690
|
+
throw new ValidationError("ERR_ERL_WINDOW_MS", `Invalid windowMs value: ${windowMs}${typeof windowMs !== "number" ? ` (${typeof windowMs})` : ""}, must be a number between 1 and ${SET_TIMEOUT_MAX} when using the default MemoryStore`);
|
|
24691
|
+
}
|
|
24692
|
+
}
|
|
24693
|
+
};
|
|
24694
|
+
var getValidations = (_enabled) => {
|
|
24695
|
+
let enabled;
|
|
24696
|
+
if (typeof _enabled === "boolean") {
|
|
24697
|
+
enabled = {
|
|
24698
|
+
default: _enabled
|
|
24699
|
+
};
|
|
24700
|
+
} else {
|
|
24701
|
+
enabled = {
|
|
24702
|
+
default: true,
|
|
24703
|
+
..._enabled
|
|
24704
|
+
};
|
|
24705
|
+
}
|
|
24706
|
+
const wrappedValidations = { enabled };
|
|
24707
|
+
for (const [name, validation] of Object.entries(validations)) {
|
|
24708
|
+
if (typeof validation === "function")
|
|
24709
|
+
wrappedValidations[name] = (...args) => {
|
|
24710
|
+
if (!(enabled[name] ?? enabled.default)) {
|
|
24711
|
+
return;
|
|
24712
|
+
}
|
|
24713
|
+
try {
|
|
24714
|
+
validation.apply(wrappedValidations, args);
|
|
24715
|
+
} catch (error) {
|
|
24716
|
+
if (error instanceof ChangeWarning)
|
|
24717
|
+
console.warn(error);
|
|
24718
|
+
else
|
|
24719
|
+
console.error(error);
|
|
24720
|
+
}
|
|
24721
|
+
};
|
|
24722
|
+
}
|
|
24723
|
+
return wrappedValidations;
|
|
24724
|
+
};
|
|
24725
|
+
var isLegacyStore = (store) => typeof store.incr === "function" && typeof store.increment !== "function";
|
|
24726
|
+
var promisifyStore = (passedStore) => {
|
|
24727
|
+
if (!isLegacyStore(passedStore)) {
|
|
24728
|
+
return passedStore;
|
|
24729
|
+
}
|
|
24730
|
+
const legacyStore = passedStore;
|
|
24731
|
+
|
|
24732
|
+
class PromisifiedStore {
|
|
24733
|
+
async increment(key) {
|
|
24734
|
+
return new Promise((resolve, reject) => {
|
|
24735
|
+
legacyStore.incr(key, (error, totalHits, resetTime) => {
|
|
24736
|
+
if (error)
|
|
24737
|
+
reject(error);
|
|
24738
|
+
resolve({ totalHits, resetTime });
|
|
24739
|
+
});
|
|
24740
|
+
});
|
|
24741
|
+
}
|
|
24742
|
+
async decrement(key) {
|
|
24743
|
+
return legacyStore.decrement(key);
|
|
24744
|
+
}
|
|
24745
|
+
async resetKey(key) {
|
|
24746
|
+
return legacyStore.resetKey(key);
|
|
24747
|
+
}
|
|
24748
|
+
async resetAll() {
|
|
24749
|
+
if (typeof legacyStore.resetAll === "function")
|
|
24750
|
+
return legacyStore.resetAll();
|
|
24751
|
+
}
|
|
24752
|
+
}
|
|
24753
|
+
return new PromisifiedStore;
|
|
24754
|
+
};
|
|
24755
|
+
var getOptionsFromConfig = (config) => {
|
|
24756
|
+
const { validations: validations2, ...directlyPassableEntries } = config;
|
|
24757
|
+
return {
|
|
24758
|
+
...directlyPassableEntries,
|
|
24759
|
+
validate: validations2.enabled
|
|
24760
|
+
};
|
|
24761
|
+
};
|
|
24762
|
+
var parseOptions = (passedOptions) => {
|
|
24763
|
+
const notUndefinedOptions = omitUndefinedProperties(passedOptions);
|
|
24764
|
+
const validations2 = getValidations(notUndefinedOptions?.validate ?? true);
|
|
24765
|
+
validations2.validationsConfig();
|
|
24766
|
+
validations2.draftPolliHeaders(notUndefinedOptions.draft_polli_ratelimit_headers);
|
|
24767
|
+
validations2.onLimitReached(notUndefinedOptions.onLimitReached);
|
|
24768
|
+
if (notUndefinedOptions.ipv6Subnet !== undefined && typeof notUndefinedOptions.ipv6Subnet !== "function") {
|
|
24769
|
+
validations2.ipv6Subnet(notUndefinedOptions.ipv6Subnet);
|
|
24770
|
+
}
|
|
24771
|
+
validations2.keyGeneratorIpFallback(notUndefinedOptions.keyGenerator);
|
|
24772
|
+
validations2.ipv6SubnetOrKeyGenerator(notUndefinedOptions);
|
|
24773
|
+
let standardHeaders = notUndefinedOptions.standardHeaders ?? false;
|
|
24774
|
+
if (standardHeaders === true)
|
|
24775
|
+
standardHeaders = "draft-6";
|
|
24776
|
+
const config = {
|
|
24777
|
+
windowMs: 60 * 1000,
|
|
24778
|
+
limit: passedOptions.max ?? 5,
|
|
24779
|
+
message: "Too many requests, please try again later.",
|
|
24780
|
+
statusCode: 429,
|
|
24781
|
+
legacyHeaders: passedOptions.headers ?? true,
|
|
24782
|
+
identifier(request, _response) {
|
|
24783
|
+
let duration = "";
|
|
24784
|
+
const property = config.requestPropertyName;
|
|
24785
|
+
const { limit } = request[property];
|
|
24786
|
+
const seconds = config.windowMs / 1000;
|
|
24787
|
+
const minutes = config.windowMs / (1000 * 60);
|
|
24788
|
+
const hours = config.windowMs / (1000 * 60 * 60);
|
|
24789
|
+
const days = config.windowMs / (1000 * 60 * 60 * 24);
|
|
24790
|
+
if (seconds < 60)
|
|
24791
|
+
duration = `${seconds}sec`;
|
|
24792
|
+
else if (minutes < 60)
|
|
24793
|
+
duration = `${minutes}min`;
|
|
24794
|
+
else if (hours < 24)
|
|
24795
|
+
duration = `${hours}hr${hours > 1 ? "s" : ""}`;
|
|
24796
|
+
else
|
|
24797
|
+
duration = `${days}day${days > 1 ? "s" : ""}`;
|
|
24798
|
+
return `${limit}-in-${duration}`;
|
|
24799
|
+
},
|
|
24800
|
+
requestPropertyName: "rateLimit",
|
|
24801
|
+
skipFailedRequests: false,
|
|
24802
|
+
skipSuccessfulRequests: false,
|
|
24803
|
+
requestWasSuccessful: (_request, response) => response.statusCode < 400,
|
|
24804
|
+
skip: (_request, _response) => false,
|
|
24805
|
+
async keyGenerator(request, response) {
|
|
24806
|
+
validations2.ip(request.ip);
|
|
24807
|
+
validations2.trustProxy(request);
|
|
24808
|
+
validations2.xForwardedForHeader(request);
|
|
24809
|
+
validations2.forwardedHeader(request);
|
|
24810
|
+
const ip = request.ip;
|
|
24811
|
+
let subnet = 56;
|
|
24812
|
+
if (isIPv62(ip)) {
|
|
24813
|
+
subnet = typeof config.ipv6Subnet === "function" ? await config.ipv6Subnet(request, response) : config.ipv6Subnet;
|
|
24814
|
+
if (typeof config.ipv6Subnet === "function")
|
|
24815
|
+
validations2.ipv6Subnet(subnet);
|
|
24816
|
+
}
|
|
24817
|
+
return ipKeyGenerator(ip, subnet);
|
|
24818
|
+
},
|
|
24819
|
+
ipv6Subnet: 56,
|
|
24820
|
+
async handler(request, response, _next, _optionsUsed) {
|
|
24821
|
+
response.status(config.statusCode);
|
|
24822
|
+
const message = typeof config.message === "function" ? await config.message(request, response) : config.message;
|
|
24823
|
+
if (!response.writableEnded)
|
|
24824
|
+
response.send(message);
|
|
24825
|
+
},
|
|
24826
|
+
passOnStoreError: false,
|
|
24827
|
+
...notUndefinedOptions,
|
|
24828
|
+
standardHeaders,
|
|
24829
|
+
store: promisifyStore(notUndefinedOptions.store ?? new MemoryStore(validations2)),
|
|
24830
|
+
validations: validations2
|
|
24831
|
+
};
|
|
24832
|
+
if (typeof config.store.increment !== "function" || typeof config.store.decrement !== "function" || typeof config.store.resetKey !== "function" || config.store.resetAll !== undefined && typeof config.store.resetAll !== "function" || config.store.init !== undefined && typeof config.store.init !== "function") {
|
|
24833
|
+
throw new TypeError("An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface.");
|
|
24834
|
+
}
|
|
24835
|
+
return config;
|
|
24836
|
+
};
|
|
24837
|
+
var handleAsyncErrors = (fn) => async (request, response, next) => {
|
|
24838
|
+
try {
|
|
24839
|
+
await Promise.resolve(fn(request, response, next)).catch(next);
|
|
24840
|
+
} catch (error) {
|
|
24841
|
+
next(error);
|
|
24842
|
+
}
|
|
24843
|
+
};
|
|
24844
|
+
var rateLimit = (passedOptions) => {
|
|
24845
|
+
const config = parseOptions(passedOptions ?? {});
|
|
24846
|
+
const options = getOptionsFromConfig(config);
|
|
24847
|
+
config.validations.creationStack(config.store);
|
|
24848
|
+
config.validations.unsharedStore(config.store);
|
|
24849
|
+
if (typeof config.store.init === "function")
|
|
24850
|
+
config.store.init(options);
|
|
24851
|
+
const middleware = handleAsyncErrors(async (request, response, next) => {
|
|
24852
|
+
const skip = await config.skip(request, response);
|
|
24853
|
+
if (skip) {
|
|
24854
|
+
next();
|
|
24855
|
+
return;
|
|
24856
|
+
}
|
|
24857
|
+
const augmentedRequest = request;
|
|
24858
|
+
const key = await config.keyGenerator(request, response);
|
|
24859
|
+
let totalHits = 0;
|
|
24860
|
+
let resetTime;
|
|
24861
|
+
try {
|
|
24862
|
+
const incrementResult = await config.store.increment(key);
|
|
24863
|
+
totalHits = incrementResult.totalHits;
|
|
24864
|
+
resetTime = incrementResult.resetTime;
|
|
24865
|
+
} catch (error) {
|
|
24866
|
+
if (config.passOnStoreError) {
|
|
24867
|
+
console.error("express-rate-limit: error from store, allowing request without rate-limiting.", error);
|
|
24868
|
+
next();
|
|
24869
|
+
return;
|
|
24870
|
+
}
|
|
24871
|
+
throw error;
|
|
24872
|
+
}
|
|
24873
|
+
config.validations.positiveHits(totalHits);
|
|
24874
|
+
config.validations.singleCount(request, config.store, key);
|
|
24875
|
+
const retrieveLimit = typeof config.limit === "function" ? config.limit(request, response) : config.limit;
|
|
24876
|
+
const limit = await retrieveLimit;
|
|
24877
|
+
config.validations.limit(limit);
|
|
24878
|
+
const info = {
|
|
24879
|
+
limit,
|
|
24880
|
+
used: totalHits,
|
|
24881
|
+
remaining: Math.max(limit - totalHits, 0),
|
|
24882
|
+
resetTime,
|
|
24883
|
+
key
|
|
24884
|
+
};
|
|
24885
|
+
Object.defineProperty(info, "current", {
|
|
24886
|
+
configurable: false,
|
|
24887
|
+
enumerable: false,
|
|
24888
|
+
value: totalHits
|
|
24889
|
+
});
|
|
24890
|
+
augmentedRequest[config.requestPropertyName] = info;
|
|
24891
|
+
if (config.legacyHeaders && !response.headersSent) {
|
|
24892
|
+
setLegacyHeaders(response, info);
|
|
24893
|
+
}
|
|
24894
|
+
if (config.standardHeaders && !response.headersSent) {
|
|
24895
|
+
switch (config.standardHeaders) {
|
|
24896
|
+
case "draft-6": {
|
|
24897
|
+
setDraft6Headers(response, info, config.windowMs);
|
|
24898
|
+
break;
|
|
24899
|
+
}
|
|
24900
|
+
case "draft-7": {
|
|
24901
|
+
config.validations.headersResetTime(info.resetTime);
|
|
24902
|
+
setDraft7Headers(response, info, config.windowMs);
|
|
24903
|
+
break;
|
|
24904
|
+
}
|
|
24905
|
+
case "draft-8": {
|
|
24906
|
+
const retrieveName = typeof config.identifier === "function" ? config.identifier(request, response) : config.identifier;
|
|
24907
|
+
const name = await retrieveName;
|
|
24908
|
+
config.validations.headersResetTime(info.resetTime);
|
|
24909
|
+
setDraft8Headers(response, info, config.windowMs, name, key);
|
|
24910
|
+
break;
|
|
24911
|
+
}
|
|
24912
|
+
default: {
|
|
24913
|
+
config.validations.headersDraftVersion(config.standardHeaders);
|
|
24914
|
+
break;
|
|
24915
|
+
}
|
|
24916
|
+
}
|
|
24917
|
+
}
|
|
24918
|
+
if (config.skipFailedRequests || config.skipSuccessfulRequests) {
|
|
24919
|
+
let decremented = false;
|
|
24920
|
+
const decrementKey = async () => {
|
|
24921
|
+
if (!decremented) {
|
|
24922
|
+
await config.store.decrement(key);
|
|
24923
|
+
decremented = true;
|
|
24924
|
+
}
|
|
24925
|
+
};
|
|
24926
|
+
if (config.skipFailedRequests) {
|
|
24927
|
+
response.on("finish", async () => {
|
|
24928
|
+
if (!await config.requestWasSuccessful(request, response))
|
|
24929
|
+
await decrementKey();
|
|
24930
|
+
});
|
|
24931
|
+
response.on("close", async () => {
|
|
24932
|
+
if (!response.writableEnded)
|
|
24933
|
+
await decrementKey();
|
|
24934
|
+
});
|
|
24935
|
+
response.on("error", async () => {
|
|
24936
|
+
await decrementKey();
|
|
24937
|
+
});
|
|
24938
|
+
}
|
|
24939
|
+
if (config.skipSuccessfulRequests) {
|
|
24940
|
+
response.on("finish", async () => {
|
|
24941
|
+
if (await config.requestWasSuccessful(request, response))
|
|
24942
|
+
await decrementKey();
|
|
24943
|
+
});
|
|
24944
|
+
}
|
|
24945
|
+
}
|
|
24946
|
+
config.validations.disable();
|
|
24947
|
+
if (totalHits > limit) {
|
|
24948
|
+
if (config.legacyHeaders || config.standardHeaders) {
|
|
24949
|
+
setRetryAfterHeader(response, info, config.windowMs);
|
|
24950
|
+
}
|
|
24951
|
+
config.handler(request, response, next, options);
|
|
24952
|
+
return;
|
|
24953
|
+
}
|
|
24954
|
+
next();
|
|
24955
|
+
});
|
|
24956
|
+
const getThrowFn = () => {
|
|
24957
|
+
throw new Error("The current store does not support the get/getKey method");
|
|
24958
|
+
};
|
|
24959
|
+
middleware.resetKey = config.store.resetKey.bind(config.store);
|
|
24960
|
+
middleware.getKey = typeof config.store.get === "function" ? config.store.get.bind(config.store) : getThrowFn;
|
|
24961
|
+
return middleware;
|
|
24962
|
+
};
|
|
24963
|
+
var rate_limit_default = rateLimit;
|
|
24964
|
+
|
|
24387
24965
|
// ../../node_modules/helmet/index.mjs
|
|
24388
24966
|
var dangerouslyDisableDefaultSrc = Symbol("dangerouslyDisableDefaultSrc");
|
|
24389
24967
|
var SHOULD_BE_QUOTED = new Set(["none", "self", "strict-dynamic", "report-sample", "inline-speculation-rules", "unsafe-inline", "unsafe-eval", "unsafe-hashes", "wasm-unsafe-eval"]);
|
|
@@ -25883,1581 +26461,1019 @@ function createAgentRunsRouter(elizaOS) {
|
|
|
25883
26461
|
promptCount: body.promptCount,
|
|
25884
26462
|
prompts: body.prompts,
|
|
25885
26463
|
params: body.params,
|
|
25886
|
-
response: body.response
|
|
25887
|
-
}
|
|
25888
|
-
});
|
|
25889
|
-
}
|
|
25890
|
-
for (const e of modelLogs) {
|
|
25891
|
-
const body = e.body;
|
|
25892
|
-
events.push({
|
|
25893
|
-
type: "MODEL_USED",
|
|
25894
|
-
timestamp: new Date(e.createdAt).getTime(),
|
|
25895
|
-
data: {
|
|
25896
|
-
modelType: body.modelType || (typeof e.type === "string" ? e.type.replace("useModel:", "") : undefined),
|
|
25897
|
-
provider: body.provider,
|
|
25898
|
-
executionTime: body.executionTime,
|
|
25899
|
-
actionContext: body.actionContext,
|
|
25900
|
-
params: body.params,
|
|
25901
|
-
response: body.response,
|
|
25902
|
-
usage: body.usage,
|
|
25903
|
-
prompts: body.prompts,
|
|
25904
|
-
prompt: body.prompt,
|
|
25905
|
-
inputTokens: body.inputTokens,
|
|
25906
|
-
outputTokens: body.outputTokens,
|
|
25907
|
-
cost: body.cost
|
|
25908
|
-
}
|
|
25909
|
-
});
|
|
25910
|
-
}
|
|
25911
|
-
for (const e of evaluatorLogs) {
|
|
25912
|
-
const body = e.body;
|
|
25913
|
-
events.push({
|
|
25914
|
-
type: "EVALUATOR_COMPLETED",
|
|
25915
|
-
timestamp: new Date(e.createdAt).getTime(),
|
|
25916
|
-
data: {
|
|
25917
|
-
evaluatorName: body.evaluator,
|
|
25918
|
-
success: true
|
|
25919
|
-
}
|
|
25920
|
-
});
|
|
25921
|
-
}
|
|
25922
|
-
for (const e of embeddingLogs) {
|
|
25923
|
-
const body = e.body;
|
|
25924
|
-
events.push({
|
|
25925
|
-
type: "EMBEDDING_EVENT",
|
|
25926
|
-
timestamp: new Date(e.createdAt).getTime(),
|
|
25927
|
-
data: {
|
|
25928
|
-
status: body.status,
|
|
25929
|
-
memoryId: body.memoryId,
|
|
25930
|
-
durationMs: body.duration
|
|
25931
|
-
}
|
|
25932
|
-
});
|
|
25933
|
-
}
|
|
25934
|
-
events.sort((a, b) => a.timestamp - b.timestamp);
|
|
25935
|
-
const firstRunEvent = started || runEvents[0] || related[0];
|
|
25936
|
-
const summary = {
|
|
25937
|
-
runId,
|
|
25938
|
-
status,
|
|
25939
|
-
startedAt: startedAt || (firstRunEvent ? new Date(firstRunEvent.createdAt).getTime() : undefined),
|
|
25940
|
-
endedAt,
|
|
25941
|
-
durationMs,
|
|
25942
|
-
messageId: firstRunEvent?.body?.messageId,
|
|
25943
|
-
roomId: firstRunEvent?.body?.roomId || roomId,
|
|
25944
|
-
entityId: firstRunEvent?.body?.entityId || agentId,
|
|
25945
|
-
counts
|
|
25946
|
-
};
|
|
25947
|
-
sendSuccess(res, { summary, events });
|
|
25948
|
-
} catch (error) {
|
|
25949
|
-
sendError(res, 500, "RUN_DETAIL_ERROR", "Error retrieving run details", error instanceof Error ? error.message : String(error));
|
|
25950
|
-
}
|
|
25951
|
-
});
|
|
25952
|
-
return router;
|
|
25953
|
-
}
|
|
25954
|
-
|
|
25955
|
-
// src/api/memory/agents.ts
|
|
25956
|
-
import { MemoryType, createUniqueUuid as createUniqueUuid2 } from "@elizaos/core";
|
|
25957
|
-
import { validateUuid as validateUuid7, logger as logger6 } from "@elizaos/core";
|
|
25958
|
-
import express7 from "express";
|
|
25959
|
-
function createAgentMemoryRouter(elizaOS) {
|
|
25960
|
-
const router = express7.Router();
|
|
25961
|
-
router.get("/:agentId/rooms/:roomId/memories", async (req, res) => {
|
|
25962
|
-
const agentId = validateUuid7(req.params.agentId);
|
|
25963
|
-
const channelId = validateUuid7(req.params.roomId);
|
|
25964
|
-
if (!agentId || !channelId) {
|
|
25965
|
-
return sendError(res, 400, "INVALID_ID", "Invalid agent ID or channel ID format");
|
|
25966
|
-
}
|
|
25967
|
-
const runtime = elizaOS.getAgent(agentId);
|
|
25968
|
-
if (!runtime) {
|
|
25969
|
-
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
25970
|
-
}
|
|
25971
|
-
try {
|
|
25972
|
-
const limit = req.query.limit ? Number.parseInt(req.query.limit, 10) : 20;
|
|
25973
|
-
const before = req.query.before ? Number.parseInt(req.query.before, 10) : Date.now();
|
|
25974
|
-
const includeEmbedding = req.query.includeEmbedding === "true";
|
|
25975
|
-
const tableName = req.query.tableName || "messages";
|
|
25976
|
-
const roomId = createUniqueUuid2(runtime, channelId);
|
|
25977
|
-
logger6.info(`[ROOM MEMORIES] Converting channelId ${channelId} to roomId ${roomId} for agent ${agentId}`);
|
|
25978
|
-
const memories = await runtime.getMemories({
|
|
25979
|
-
tableName,
|
|
25980
|
-
roomId,
|
|
25981
|
-
count: limit,
|
|
25982
|
-
end: before
|
|
25983
|
-
});
|
|
25984
|
-
const cleanMemories = includeEmbedding ? memories : memories.map((memory) => ({
|
|
25985
|
-
...memory,
|
|
25986
|
-
embedding: undefined
|
|
25987
|
-
}));
|
|
25988
|
-
sendSuccess(res, { memories: cleanMemories });
|
|
25989
|
-
} catch (error) {
|
|
25990
|
-
logger6.error("[MEMORIES GET] Error retrieving memories for room:", error instanceof Error ? error.message : String(error));
|
|
25991
|
-
sendError(res, 500, "500", "Failed to retrieve memories", error instanceof Error ? error.message : String(error));
|
|
25992
|
-
}
|
|
25993
|
-
});
|
|
25994
|
-
router.get("/:agentId/memories", async (req, res) => {
|
|
25995
|
-
const agentId = validateUuid7(req.params.agentId);
|
|
25996
|
-
if (!agentId) {
|
|
25997
|
-
return sendError(res, 400, "INVALID_ID", "Invalid agent ID");
|
|
25998
|
-
}
|
|
25999
|
-
const runtime = elizaOS.getAgent(agentId);
|
|
26000
|
-
if (!runtime) {
|
|
26001
|
-
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26002
|
-
}
|
|
26003
|
-
try {
|
|
26004
|
-
const tableName = req.query.tableName || "messages";
|
|
26005
|
-
const includeEmbedding = req.query.includeEmbedding === "true";
|
|
26006
|
-
let roomIdToUse;
|
|
26007
|
-
if (req.query.channelId) {
|
|
26008
|
-
const channelId = validateUuid7(req.query.channelId);
|
|
26009
|
-
if (!channelId) {
|
|
26010
|
-
return sendError(res, 400, "INVALID_ID", "Invalid channel ID format");
|
|
26011
|
-
}
|
|
26012
|
-
roomIdToUse = createUniqueUuid2(runtime, channelId);
|
|
26013
|
-
logger6.info(`[AGENT MEMORIES] Converting channelId ${channelId} to roomId ${roomIdToUse} for agent ${agentId}`);
|
|
26014
|
-
} else if (req.query.roomId) {
|
|
26015
|
-
const roomId = validateUuid7(req.query.roomId);
|
|
26016
|
-
if (!roomId) {
|
|
26017
|
-
return sendError(res, 400, "INVALID_ID", "Invalid room ID format");
|
|
26018
|
-
}
|
|
26019
|
-
roomIdToUse = roomId;
|
|
26020
|
-
}
|
|
26021
|
-
const memories = await runtime.getMemories({
|
|
26022
|
-
agentId,
|
|
26023
|
-
tableName,
|
|
26024
|
-
roomId: roomIdToUse
|
|
26025
|
-
});
|
|
26026
|
-
const cleanMemories = includeEmbedding ? memories : memories.map((memory) => ({
|
|
26027
|
-
...memory,
|
|
26028
|
-
embedding: undefined
|
|
26029
|
-
}));
|
|
26030
|
-
sendSuccess(res, { memories: cleanMemories });
|
|
26031
|
-
} catch (error) {
|
|
26032
|
-
logger6.error(`[AGENT MEMORIES] Error retrieving memories for agent ${agentId}:`, error instanceof Error ? error.message : String(error));
|
|
26033
|
-
sendError(res, 500, "MEMORY_ERROR", "Error retrieving agent memories", error instanceof Error ? error.message : String(error));
|
|
26034
|
-
}
|
|
26035
|
-
});
|
|
26036
|
-
router.patch("/:agentId/memories/:memoryId", async (req, res) => {
|
|
26037
|
-
const agentId = validateUuid7(req.params.agentId);
|
|
26038
|
-
const memoryId = validateUuid7(req.params.memoryId);
|
|
26039
|
-
const { id: _idFromData, ...restOfMemoryData } = req.body;
|
|
26040
|
-
if (!agentId || !memoryId) {
|
|
26041
|
-
return sendError(res, 400, "INVALID_ID", "Invalid agent ID or memory ID format");
|
|
26042
|
-
}
|
|
26043
|
-
const runtime = elizaOS.getAgent(agentId);
|
|
26044
|
-
if (!runtime) {
|
|
26045
|
-
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26046
|
-
}
|
|
26047
|
-
try {
|
|
26048
|
-
const memoryToUpdate = {
|
|
26049
|
-
id: memoryId,
|
|
26050
|
-
...restOfMemoryData,
|
|
26051
|
-
agentId: restOfMemoryData.agentId ? validateUuid7(restOfMemoryData.agentId) || undefined : agentId,
|
|
26052
|
-
roomId: restOfMemoryData.roomId ? validateUuid7(restOfMemoryData.roomId) || undefined : undefined,
|
|
26053
|
-
entityId: restOfMemoryData.entityId ? validateUuid7(restOfMemoryData.entityId) || undefined : undefined,
|
|
26054
|
-
worldId: restOfMemoryData.worldId ? validateUuid7(restOfMemoryData.worldId) || undefined : undefined,
|
|
26055
|
-
metadata: restOfMemoryData.metadata
|
|
26056
|
-
};
|
|
26057
|
-
Object.keys(memoryToUpdate).forEach((key) => {
|
|
26058
|
-
if (memoryToUpdate[key] === undefined) {
|
|
26059
|
-
delete memoryToUpdate[key];
|
|
26060
|
-
}
|
|
26061
|
-
});
|
|
26062
|
-
await runtime.updateMemory(memoryToUpdate);
|
|
26063
|
-
logger6.success(`[MEMORY UPDATE] Successfully updated memory ${memoryId}`);
|
|
26064
|
-
sendSuccess(res, { id: memoryId, message: "Memory updated successfully" });
|
|
26065
|
-
} catch (error) {
|
|
26066
|
-
logger6.error(`[MEMORY UPDATE] Error updating memory ${memoryId}:`, error instanceof Error ? error.message : String(error));
|
|
26067
|
-
sendError(res, 500, "UPDATE_ERROR", "Failed to update memory", error instanceof Error ? error.message : String(error));
|
|
26068
|
-
}
|
|
26069
|
-
});
|
|
26070
|
-
router.delete("/:agentId/memories", async (req, res) => {
|
|
26071
|
-
try {
|
|
26072
|
-
const agentId = validateUuid7(req.params.agentId);
|
|
26073
|
-
if (!agentId) {
|
|
26074
|
-
return sendError(res, 400, "INVALID_ID", "Invalid agent ID");
|
|
26075
|
-
}
|
|
26076
|
-
const runtime = elizaOS.getAgent(agentId);
|
|
26077
|
-
if (!runtime) {
|
|
26078
|
-
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26079
|
-
}
|
|
26080
|
-
const deleted = (await runtime.getAllMemories()).length;
|
|
26081
|
-
await runtime.clearAllAgentMemories();
|
|
26082
|
-
sendSuccess(res, { deleted, message: "All agent memories cleared successfully" });
|
|
26083
|
-
} catch (error) {
|
|
26084
|
-
logger6.error("[DELETE ALL AGENT MEMORIES] Error deleting all agent memories:", error instanceof Error ? error.message : String(error));
|
|
26085
|
-
sendError(res, 500, "DELETE_ERROR", "Error deleting all agent memories", error instanceof Error ? error.message : String(error));
|
|
26086
|
-
}
|
|
26087
|
-
});
|
|
26088
|
-
router.delete("/:agentId/memories/all/:roomId", async (req, res) => {
|
|
26089
|
-
try {
|
|
26090
|
-
const agentId = validateUuid7(req.params.agentId);
|
|
26091
|
-
const roomId = validateUuid7(req.params.roomId);
|
|
26092
|
-
if (!agentId) {
|
|
26093
|
-
return sendError(res, 400, "INVALID_ID", "Invalid agent ID");
|
|
26094
|
-
}
|
|
26095
|
-
if (!roomId) {
|
|
26096
|
-
return sendError(res, 400, "INVALID_ID", "Invalid room ID");
|
|
26097
|
-
}
|
|
26098
|
-
const runtime = elizaOS.getAgent(agentId);
|
|
26099
|
-
if (!runtime) {
|
|
26100
|
-
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26101
|
-
}
|
|
26102
|
-
await runtime.deleteAllMemories(roomId, MemoryType.MESSAGE);
|
|
26103
|
-
await runtime.deleteAllMemories(roomId, MemoryType.DOCUMENT);
|
|
26104
|
-
res.status(204).send();
|
|
26105
|
-
} catch (error) {
|
|
26106
|
-
logger6.error("[DELETE ALL MEMORIES] Error deleting all memories:", error instanceof Error ? error.message : String(error));
|
|
26107
|
-
sendError(res, 500, "DELETE_ERROR", "Error deleting all memories", error instanceof Error ? error.message : String(error));
|
|
26108
|
-
}
|
|
26109
|
-
});
|
|
26110
|
-
router.delete("/:agentId/memories/:memoryId", async (req, res) => {
|
|
26111
|
-
try {
|
|
26112
|
-
const agentId = validateUuid7(req.params.agentId);
|
|
26113
|
-
const memoryId = validateUuid7(req.params.memoryId);
|
|
26114
|
-
if (!agentId || !memoryId) {
|
|
26115
|
-
return sendError(res, 400, "INVALID_ID", "Invalid agent ID or memory ID format");
|
|
26116
|
-
}
|
|
26117
|
-
const runtime = elizaOS.getAgent(agentId);
|
|
26118
|
-
if (!runtime) {
|
|
26119
|
-
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26120
|
-
}
|
|
26121
|
-
await runtime.deleteMemory(memoryId);
|
|
26122
|
-
sendSuccess(res, { message: "Memory deleted successfully" });
|
|
26123
|
-
} catch (error) {
|
|
26124
|
-
logger6.error(`[DELETE MEMORY] Error deleting memory ${req.params.memoryId}:`, error instanceof Error ? error.message : String(error));
|
|
26125
|
-
sendError(res, 500, "DELETE_ERROR", "Error deleting memory", error instanceof Error ? error.message : String(error));
|
|
26126
|
-
}
|
|
26127
|
-
});
|
|
26128
|
-
return router;
|
|
26129
|
-
}
|
|
26130
|
-
|
|
26131
|
-
// src/api/memory/rooms.ts
|
|
26132
|
-
import { validateUuid as validateUuid8, logger as logger7, createUniqueUuid as createUniqueUuid3, ChannelType } from "@elizaos/core";
|
|
26133
|
-
import express8 from "express";
|
|
26134
|
-
function createRoomManagementRouter(elizaOS) {
|
|
26135
|
-
const router = express8.Router();
|
|
26136
|
-
router.post("/:agentId/rooms", async (req, res) => {
|
|
26137
|
-
const agentId = validateUuid8(req.params.agentId);
|
|
26138
|
-
if (!agentId) {
|
|
26139
|
-
return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
|
|
26140
|
-
}
|
|
26141
|
-
const runtime = elizaOS.getAgent(agentId);
|
|
26142
|
-
if (!runtime) {
|
|
26143
|
-
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26144
|
-
}
|
|
26145
|
-
try {
|
|
26146
|
-
const { name, type = ChannelType.DM, source = "client", worldId, metadata } = req.body;
|
|
26147
|
-
if (!name) {
|
|
26148
|
-
return sendError(res, 400, "MISSING_PARAM", "Room name is required");
|
|
26149
|
-
}
|
|
26150
|
-
const roomId = createUniqueUuid3(runtime, `room-${Date.now()}`);
|
|
26151
|
-
const serverId = req.body.serverId || `server-${Date.now()}`;
|
|
26152
|
-
let resolvedWorldId = worldId;
|
|
26153
|
-
if (!resolvedWorldId) {
|
|
26154
|
-
const worldName = `World for ${name}`;
|
|
26155
|
-
resolvedWorldId = createUniqueUuid3(runtime, `world-${Date.now()}`);
|
|
26156
|
-
await runtime.ensureWorldExists({
|
|
26157
|
-
id: resolvedWorldId,
|
|
26158
|
-
name: worldName,
|
|
26159
|
-
agentId: runtime.agentId,
|
|
26160
|
-
serverId,
|
|
26161
|
-
metadata
|
|
26162
|
-
});
|
|
26163
|
-
}
|
|
26164
|
-
await runtime.ensureRoomExists({
|
|
26165
|
-
id: roomId,
|
|
26166
|
-
name,
|
|
26167
|
-
source,
|
|
26168
|
-
type,
|
|
26169
|
-
channelId: roomId,
|
|
26170
|
-
serverId,
|
|
26171
|
-
worldId: resolvedWorldId,
|
|
26172
|
-
metadata
|
|
26173
|
-
});
|
|
26174
|
-
await runtime.addParticipant(runtime.agentId, roomId);
|
|
26175
|
-
await runtime.ensureParticipantInRoom(runtime.agentId, roomId);
|
|
26176
|
-
await runtime.setParticipantUserState(roomId, runtime.agentId, "FOLLOWED");
|
|
26177
|
-
sendSuccess(res, {
|
|
26178
|
-
id: roomId,
|
|
26179
|
-
name,
|
|
26180
|
-
agentId,
|
|
26181
|
-
createdAt: Date.now(),
|
|
26182
|
-
source,
|
|
26183
|
-
type,
|
|
26184
|
-
worldId: resolvedWorldId,
|
|
26185
|
-
serverId,
|
|
26186
|
-
metadata
|
|
26187
|
-
}, 201);
|
|
26188
|
-
} catch (error) {
|
|
26189
|
-
logger7.error(`[ROOM CREATE] Error creating room for agent ${agentId}:`, error instanceof Error ? error.message : String(error));
|
|
26190
|
-
sendError(res, 500, "CREATE_ERROR", "Failed to create room", error instanceof Error ? error.message : String(error));
|
|
26191
|
-
}
|
|
26192
|
-
});
|
|
26193
|
-
router.get("/:agentId/rooms", async (req, res) => {
|
|
26194
|
-
const agentId = validateUuid8(req.params.agentId);
|
|
26195
|
-
if (!agentId) {
|
|
26196
|
-
return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
|
|
26197
|
-
}
|
|
26198
|
-
const runtime = elizaOS.getAgent(agentId);
|
|
26199
|
-
if (!runtime) {
|
|
26200
|
-
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26201
|
-
}
|
|
26202
|
-
try {
|
|
26203
|
-
const worlds = await runtime.getAllWorlds();
|
|
26204
|
-
const participantRoomIds = await runtime.getRoomsForParticipant(agentId);
|
|
26205
|
-
const agentRooms = [];
|
|
26206
|
-
for (const world of worlds) {
|
|
26207
|
-
const worldRooms = await runtime.getRooms(world.id);
|
|
26208
|
-
for (const room of worldRooms) {
|
|
26209
|
-
if (participantRoomIds.includes(room.id)) {
|
|
26210
|
-
agentRooms.push({
|
|
26211
|
-
...room
|
|
26212
|
-
});
|
|
26213
|
-
}
|
|
26214
|
-
}
|
|
26215
|
-
}
|
|
26216
|
-
sendSuccess(res, { rooms: agentRooms });
|
|
26217
|
-
} catch (error) {
|
|
26218
|
-
logger7.error(`[ROOMS LIST] Error retrieving rooms for agent ${agentId}:`, error instanceof Error ? error.message : String(error));
|
|
26219
|
-
sendError(res, 500, "RETRIEVAL_ERROR", "Failed to retrieve agent rooms", error instanceof Error ? error.message : String(error));
|
|
26220
|
-
}
|
|
26221
|
-
});
|
|
26222
|
-
router.get("/:agentId/rooms/:roomId", async (req, res) => {
|
|
26223
|
-
const agentId = validateUuid8(req.params.agentId);
|
|
26224
|
-
const roomId = validateUuid8(req.params.roomId);
|
|
26225
|
-
if (!agentId || !roomId) {
|
|
26226
|
-
return sendError(res, 400, "INVALID_ID", "Invalid agent ID or room ID format");
|
|
26227
|
-
}
|
|
26228
|
-
const runtime = elizaOS.getAgent(agentId);
|
|
26229
|
-
if (!runtime) {
|
|
26230
|
-
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26231
|
-
}
|
|
26232
|
-
try {
|
|
26233
|
-
const room = await runtime.getRoom(roomId);
|
|
26234
|
-
if (!room) {
|
|
26235
|
-
return sendError(res, 404, "NOT_FOUND", "Room not found");
|
|
26236
|
-
}
|
|
26237
|
-
let worldName;
|
|
26238
|
-
if (room.worldId) {
|
|
26239
|
-
const world = await runtime.getWorld(room.worldId);
|
|
26240
|
-
worldName = world?.name;
|
|
26241
|
-
}
|
|
26242
|
-
sendSuccess(res, {
|
|
26243
|
-
...room,
|
|
26244
|
-
...worldName && { worldName }
|
|
26245
|
-
});
|
|
26246
|
-
} catch (error) {
|
|
26247
|
-
logger7.error(`[ROOM DETAILS] Error retrieving room ${roomId} for agent ${agentId}:`, error instanceof Error ? error.message : String(error));
|
|
26248
|
-
sendError(res, 500, "RETRIEVAL_ERROR", "Failed to retrieve room details", error instanceof Error ? error.message : String(error));
|
|
26249
|
-
}
|
|
26250
|
-
});
|
|
26251
|
-
return router;
|
|
26252
|
-
}
|
|
26253
|
-
|
|
26254
|
-
// src/api/agents/index.ts
|
|
26255
|
-
function agentsRouter(elizaOS, serverInstance) {
|
|
26256
|
-
const router = express9.Router();
|
|
26257
|
-
router.use("/", createAgentCrudRouter(elizaOS, serverInstance));
|
|
26258
|
-
router.use("/", createAgentLifecycleRouter(elizaOS, serverInstance));
|
|
26259
|
-
router.use("/", createAgentWorldsRouter(elizaOS));
|
|
26260
|
-
router.use("/", createAgentPanelsRouter(elizaOS));
|
|
26261
|
-
router.use("/", createAgentLogsRouter(elizaOS));
|
|
26262
|
-
router.use("/", createAgentRunsRouter(elizaOS));
|
|
26263
|
-
router.use("/", createAgentMemoryRouter(elizaOS));
|
|
26264
|
-
router.use("/", createRoomManagementRouter(elizaOS));
|
|
26265
|
-
return router;
|
|
26266
|
-
}
|
|
26267
|
-
|
|
26268
|
-
// src/api/messaging/index.ts
|
|
26269
|
-
import express15 from "express";
|
|
26270
|
-
|
|
26271
|
-
// src/api/messaging/core.ts
|
|
26272
|
-
import { logger as logger8, validateUuid as validateUuid9 } from "@elizaos/core";
|
|
26273
|
-
import express10 from "express";
|
|
26274
|
-
|
|
26275
|
-
// src/bus.ts
|
|
26276
|
-
class InternalMessageBus extends EventTarget {
|
|
26277
|
-
_maxListeners = 50;
|
|
26278
|
-
handlers = new Map;
|
|
26279
|
-
emit(event, data) {
|
|
26280
|
-
return this.dispatchEvent(new CustomEvent(event, { detail: data }));
|
|
26281
|
-
}
|
|
26282
|
-
on(event, handler) {
|
|
26283
|
-
if (!this.handlers.has(event)) {
|
|
26284
|
-
this.handlers.set(event, new Map);
|
|
26285
|
-
}
|
|
26286
|
-
const eventHandlers = this.handlers.get(event);
|
|
26287
|
-
if (eventHandlers.has(handler)) {
|
|
26288
|
-
return this;
|
|
26289
|
-
}
|
|
26290
|
-
const wrappedHandler = (e) => {
|
|
26291
|
-
if (e instanceof CustomEvent) {
|
|
26292
|
-
handler(e.detail);
|
|
26293
|
-
} else {
|
|
26294
|
-
handler(undefined);
|
|
26295
|
-
}
|
|
26296
|
-
};
|
|
26297
|
-
eventHandlers.set(handler, wrappedHandler);
|
|
26298
|
-
this.addEventListener(event, wrappedHandler);
|
|
26299
|
-
return this;
|
|
26300
|
-
}
|
|
26301
|
-
off(event, handler) {
|
|
26302
|
-
const eventHandlers = this.handlers.get(event);
|
|
26303
|
-
const wrappedHandler = eventHandlers?.get(handler);
|
|
26304
|
-
if (wrappedHandler) {
|
|
26305
|
-
this.removeEventListener(event, wrappedHandler);
|
|
26306
|
-
eventHandlers?.delete(handler);
|
|
26307
|
-
if (eventHandlers && eventHandlers.size === 0) {
|
|
26308
|
-
this.handlers.delete(event);
|
|
26309
|
-
}
|
|
26310
|
-
}
|
|
26311
|
-
}
|
|
26312
|
-
getMaxListeners() {
|
|
26313
|
-
return this._maxListeners;
|
|
26314
|
-
}
|
|
26315
|
-
setMaxListeners(n) {
|
|
26316
|
-
this._maxListeners = n;
|
|
26317
|
-
}
|
|
26318
|
-
removeAllListeners(event) {
|
|
26319
|
-
if (event) {
|
|
26320
|
-
const eventHandlers = this.handlers.get(event);
|
|
26321
|
-
if (eventHandlers) {
|
|
26322
|
-
for (const [_handler, wrappedHandler] of eventHandlers) {
|
|
26323
|
-
this.removeEventListener(event, wrappedHandler);
|
|
26324
|
-
}
|
|
26325
|
-
this.handlers.delete(event);
|
|
26326
|
-
}
|
|
26327
|
-
} else {
|
|
26328
|
-
for (const [eventName, eventHandlers] of this.handlers) {
|
|
26329
|
-
for (const [_handler, wrappedHandler] of eventHandlers) {
|
|
26330
|
-
this.removeEventListener(eventName, wrappedHandler);
|
|
26331
|
-
}
|
|
26332
|
-
}
|
|
26333
|
-
this.handlers.clear();
|
|
26334
|
-
}
|
|
26335
|
-
}
|
|
26336
|
-
}
|
|
26337
|
-
var internalMessageBus = new InternalMessageBus;
|
|
26338
|
-
internalMessageBus.setMaxListeners(50);
|
|
26339
|
-
var bus_default = internalMessageBus;
|
|
26340
|
-
|
|
26341
|
-
// src/utils/media-transformer.ts
|
|
26342
|
-
import path from "node:path";
|
|
26343
|
-
import { getGeneratedDir, getUploadsAgentsDir, getUploadsChannelsDir } from "@elizaos/core";
|
|
26344
|
-
var ID_PATTERN = /^([^/\\]+)[/\\]([^/\\]+)$/;
|
|
26345
|
-
var PATH_CONFIGS = [
|
|
26346
|
-
{
|
|
26347
|
-
getPath: getGeneratedDir,
|
|
26348
|
-
apiPrefix: "/media/generated/",
|
|
26349
|
-
pattern: ID_PATTERN
|
|
26350
|
-
},
|
|
26351
|
-
{
|
|
26352
|
-
getPath: getUploadsAgentsDir,
|
|
26353
|
-
apiPrefix: "/media/uploads/agents/",
|
|
26354
|
-
pattern: ID_PATTERN
|
|
26355
|
-
},
|
|
26356
|
-
{
|
|
26357
|
-
getPath: getUploadsChannelsDir,
|
|
26358
|
-
apiPrefix: "/media/uploads/channels/",
|
|
26359
|
-
pattern: ID_PATTERN
|
|
26360
|
-
}
|
|
26361
|
-
];
|
|
26362
|
-
var isExternalUrl = (p) => /^(?:https?:|blob:|data:|file:|ipfs:|s3:|gs:)/i.test(p);
|
|
26363
|
-
function transformPathToApiUrl(filePath) {
|
|
26364
|
-
if (!filePath || isExternalUrl(filePath) || filePath.startsWith("/media/") || !path.isAbsolute(filePath)) {
|
|
26365
|
-
return filePath;
|
|
26366
|
-
}
|
|
26367
|
-
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
26368
|
-
for (const config of PATH_CONFIGS) {
|
|
26369
|
-
const configPathRaw = config.getPath().replace(/\\/g, "/");
|
|
26370
|
-
const configPath = configPathRaw.endsWith("/") ? configPathRaw : `${configPathRaw}/`;
|
|
26371
|
-
if (normalizedPath === configPathRaw || normalizedPath.startsWith(configPath)) {
|
|
26372
|
-
const relative = normalizedPath === configPathRaw ? "" : normalizedPath.slice(configPath.length);
|
|
26373
|
-
if (relative) {
|
|
26374
|
-
const match = relative.match(config.pattern);
|
|
26375
|
-
if (match) {
|
|
26376
|
-
const [, id, filename] = match;
|
|
26377
|
-
return `${config.apiPrefix}${encodeURIComponent(id)}${"/"}${encodeURIComponent(filename)}`;
|
|
26378
|
-
}
|
|
26464
|
+
response: body.response
|
|
26465
|
+
}
|
|
26466
|
+
});
|
|
26379
26467
|
}
|
|
26380
|
-
|
|
26381
|
-
|
|
26382
|
-
|
|
26383
|
-
|
|
26384
|
-
|
|
26385
|
-
|
|
26386
|
-
|
|
26387
|
-
|
|
26388
|
-
|
|
26389
|
-
|
|
26390
|
-
|
|
26468
|
+
for (const e of modelLogs) {
|
|
26469
|
+
const body = e.body;
|
|
26470
|
+
events.push({
|
|
26471
|
+
type: "MODEL_USED",
|
|
26472
|
+
timestamp: new Date(e.createdAt).getTime(),
|
|
26473
|
+
data: {
|
|
26474
|
+
modelType: body.modelType || (typeof e.type === "string" ? e.type.replace("useModel:", "") : undefined),
|
|
26475
|
+
provider: body.provider,
|
|
26476
|
+
executionTime: body.executionTime,
|
|
26477
|
+
actionContext: body.actionContext,
|
|
26478
|
+
params: body.params,
|
|
26479
|
+
response: body.response,
|
|
26480
|
+
usage: body.usage,
|
|
26481
|
+
prompts: body.prompts,
|
|
26482
|
+
prompt: body.prompt,
|
|
26483
|
+
inputTokens: body.inputTokens,
|
|
26484
|
+
outputTokens: body.outputTokens,
|
|
26485
|
+
cost: body.cost
|
|
26486
|
+
}
|
|
26487
|
+
});
|
|
26391
26488
|
}
|
|
26392
|
-
|
|
26393
|
-
|
|
26489
|
+
for (const e of evaluatorLogs) {
|
|
26490
|
+
const body = e.body;
|
|
26491
|
+
events.push({
|
|
26492
|
+
type: "EVALUATOR_COMPLETED",
|
|
26493
|
+
timestamp: new Date(e.createdAt).getTime(),
|
|
26494
|
+
data: {
|
|
26495
|
+
evaluatorName: body.evaluator,
|
|
26496
|
+
success: true
|
|
26497
|
+
}
|
|
26498
|
+
});
|
|
26394
26499
|
}
|
|
26395
|
-
|
|
26396
|
-
|
|
26397
|
-
|
|
26398
|
-
|
|
26399
|
-
|
|
26400
|
-
|
|
26401
|
-
|
|
26402
|
-
|
|
26403
|
-
|
|
26404
|
-
|
|
26405
|
-
}
|
|
26406
|
-
|
|
26407
|
-
|
|
26408
|
-
|
|
26409
|
-
|
|
26410
|
-
|
|
26411
|
-
|
|
26412
|
-
|
|
26413
|
-
|
|
26500
|
+
for (const e of embeddingLogs) {
|
|
26501
|
+
const body = e.body;
|
|
26502
|
+
events.push({
|
|
26503
|
+
type: "EMBEDDING_EVENT",
|
|
26504
|
+
timestamp: new Date(e.createdAt).getTime(),
|
|
26505
|
+
data: {
|
|
26506
|
+
status: body.status,
|
|
26507
|
+
memoryId: body.memoryId,
|
|
26508
|
+
durationMs: body.duration
|
|
26509
|
+
}
|
|
26510
|
+
});
|
|
26511
|
+
}
|
|
26512
|
+
events.sort((a, b) => a.timestamp - b.timestamp);
|
|
26513
|
+
const firstRunEvent = started || runEvents[0] || related[0];
|
|
26514
|
+
const summary = {
|
|
26515
|
+
runId,
|
|
26516
|
+
status,
|
|
26517
|
+
startedAt: startedAt || (firstRunEvent ? new Date(firstRunEvent.createdAt).getTime() : undefined),
|
|
26518
|
+
endedAt,
|
|
26519
|
+
durationMs,
|
|
26520
|
+
messageId: firstRunEvent?.body?.messageId,
|
|
26521
|
+
roomId: firstRunEvent?.body?.roomId || roomId,
|
|
26522
|
+
entityId: firstRunEvent?.body?.entityId || agentId,
|
|
26523
|
+
counts
|
|
26524
|
+
};
|
|
26525
|
+
sendSuccess(res, { summary, events });
|
|
26526
|
+
} catch (error) {
|
|
26527
|
+
sendError(res, 500, "RUN_DETAIL_ERROR", "Error retrieving run details", error instanceof Error ? error.message : String(error));
|
|
26414
26528
|
}
|
|
26415
|
-
}
|
|
26416
|
-
|
|
26417
|
-
message.metadata.attachments = attachmentsToApiUrls(message.metadata.attachments);
|
|
26418
|
-
}
|
|
26419
|
-
return message;
|
|
26529
|
+
});
|
|
26530
|
+
return router;
|
|
26420
26531
|
}
|
|
26421
26532
|
|
|
26422
|
-
// src/api/
|
|
26423
|
-
|
|
26424
|
-
|
|
26425
|
-
|
|
26426
|
-
|
|
26427
|
-
|
|
26428
|
-
|
|
26429
|
-
|
|
26430
|
-
|
|
26431
|
-
|
|
26432
|
-
|
|
26433
|
-
source_type,
|
|
26434
|
-
raw_message,
|
|
26435
|
-
metadata
|
|
26436
|
-
} = req.body;
|
|
26437
|
-
const isValidServerId = server_id === DEFAULT_SERVER_ID || validateUuid9(server_id);
|
|
26438
|
-
if (!validateUuid9(channel_id) || !validateUuid9(author_id) || !content || !isValidServerId || !source_type || !raw_message) {
|
|
26439
|
-
return res.status(400).json({
|
|
26440
|
-
success: false,
|
|
26441
|
-
error: "Missing required fields: channel_id, server_id, author_id, content, source_type, raw_message"
|
|
26442
|
-
});
|
|
26533
|
+
// src/api/memory/agents.ts
|
|
26534
|
+
import { MemoryType, createUniqueUuid as createUniqueUuid2 } from "@elizaos/core";
|
|
26535
|
+
import { validateUuid as validateUuid7, logger as logger6 } from "@elizaos/core";
|
|
26536
|
+
import express7 from "express";
|
|
26537
|
+
function createAgentMemoryRouter(elizaOS) {
|
|
26538
|
+
const router = express7.Router();
|
|
26539
|
+
router.get("/:agentId/rooms/:roomId/memories", async (req, res) => {
|
|
26540
|
+
const agentId = validateUuid7(req.params.agentId);
|
|
26541
|
+
const channelId = validateUuid7(req.params.roomId);
|
|
26542
|
+
if (!agentId || !channelId) {
|
|
26543
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID or channel ID format");
|
|
26443
26544
|
}
|
|
26444
|
-
|
|
26445
|
-
|
|
26446
|
-
|
|
26447
|
-
error: "Invalid in_reply_to_message_id format"
|
|
26448
|
-
});
|
|
26545
|
+
const runtime = elizaOS.getAgent(agentId);
|
|
26546
|
+
if (!runtime) {
|
|
26547
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26449
26548
|
}
|
|
26450
26549
|
try {
|
|
26451
|
-
const
|
|
26452
|
-
|
|
26453
|
-
|
|
26454
|
-
|
|
26455
|
-
|
|
26456
|
-
|
|
26457
|
-
|
|
26458
|
-
|
|
26459
|
-
|
|
26460
|
-
|
|
26461
|
-
|
|
26462
|
-
|
|
26463
|
-
|
|
26464
|
-
|
|
26465
|
-
|
|
26466
|
-
|
|
26467
|
-
|
|
26468
|
-
serverId: server_id,
|
|
26469
|
-
createdAt: new Date(createdMessage.createdAt).getTime(),
|
|
26470
|
-
source: createdMessage.sourceType,
|
|
26471
|
-
id: createdMessage.id,
|
|
26472
|
-
thought: raw_message?.thought,
|
|
26473
|
-
actions: raw_message?.actions,
|
|
26474
|
-
attachments: transformedAttachments
|
|
26475
|
-
});
|
|
26476
|
-
}
|
|
26477
|
-
res.status(201).json({ success: true, data: createdMessage });
|
|
26550
|
+
const limit = req.query.limit ? Number.parseInt(req.query.limit, 10) : 20;
|
|
26551
|
+
const before = req.query.before ? Number.parseInt(req.query.before, 10) : Date.now();
|
|
26552
|
+
const includeEmbedding = req.query.includeEmbedding === "true";
|
|
26553
|
+
const tableName = req.query.tableName || "messages";
|
|
26554
|
+
const roomId = createUniqueUuid2(runtime, channelId);
|
|
26555
|
+
logger6.info(`[ROOM MEMORIES] Converting channelId ${channelId} to roomId ${roomId} for agent ${agentId}`);
|
|
26556
|
+
const memories = await runtime.getMemories({
|
|
26557
|
+
tableName,
|
|
26558
|
+
roomId,
|
|
26559
|
+
count: limit,
|
|
26560
|
+
end: before
|
|
26561
|
+
});
|
|
26562
|
+
const cleanMemories = includeEmbedding ? memories : memories.map((memory) => ({
|
|
26563
|
+
...memory,
|
|
26564
|
+
embedding: undefined
|
|
26565
|
+
}));
|
|
26566
|
+
sendSuccess(res, { memories: cleanMemories });
|
|
26478
26567
|
} catch (error) {
|
|
26479
|
-
|
|
26480
|
-
res
|
|
26568
|
+
logger6.error("[MEMORIES GET] Error retrieving memories for room:", error instanceof Error ? error.message : String(error));
|
|
26569
|
+
sendError(res, 500, "500", "Failed to retrieve memories", error instanceof Error ? error.message : String(error));
|
|
26481
26570
|
}
|
|
26482
26571
|
});
|
|
26483
|
-
router.
|
|
26484
|
-
const
|
|
26485
|
-
|
|
26486
|
-
|
|
26487
|
-
server_id,
|
|
26488
|
-
author_id,
|
|
26489
|
-
content,
|
|
26490
|
-
in_reply_to_message_id,
|
|
26491
|
-
source_type,
|
|
26492
|
-
raw_message,
|
|
26493
|
-
metadata
|
|
26494
|
-
} = req.body;
|
|
26495
|
-
const isValidServerId = server_id === DEFAULT_SERVER_ID || validateUuid9(server_id);
|
|
26496
|
-
if (!validateUuid9(channel_id) || !validateUuid9(author_id) || !content || !isValidServerId || !source_type || !raw_message) {
|
|
26497
|
-
return res.status(400).json({
|
|
26498
|
-
success: false,
|
|
26499
|
-
error: "Missing required fields: channel_id, server_id, author_id, content, source_type, raw_message"
|
|
26500
|
-
});
|
|
26501
|
-
}
|
|
26502
|
-
if (in_reply_to_message_id && !validateUuid9(in_reply_to_message_id)) {
|
|
26503
|
-
return res.status(400).json({ success: false, error: "Invalid in_reply_to_message_id format" });
|
|
26572
|
+
router.get("/:agentId/memories", async (req, res) => {
|
|
26573
|
+
const agentId = validateUuid7(req.params.agentId);
|
|
26574
|
+
if (!agentId) {
|
|
26575
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID");
|
|
26504
26576
|
}
|
|
26505
|
-
|
|
26506
|
-
|
|
26577
|
+
const runtime = elizaOS.getAgent(agentId);
|
|
26578
|
+
if (!runtime) {
|
|
26579
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26507
26580
|
}
|
|
26508
26581
|
try {
|
|
26509
|
-
const
|
|
26510
|
-
|
|
26511
|
-
|
|
26512
|
-
|
|
26513
|
-
|
|
26514
|
-
|
|
26515
|
-
|
|
26516
|
-
|
|
26517
|
-
|
|
26518
|
-
|
|
26519
|
-
|
|
26520
|
-
|
|
26521
|
-
|
|
26522
|
-
|
|
26523
|
-
|
|
26524
|
-
|
|
26525
|
-
text: savedMessage.content,
|
|
26526
|
-
roomId: channel_id,
|
|
26527
|
-
serverId: server_id,
|
|
26528
|
-
createdAt: new Date(savedMessage.createdAt).getTime(),
|
|
26529
|
-
source: savedMessage.sourceType,
|
|
26530
|
-
id: savedMessage.id,
|
|
26531
|
-
thought: raw_message?.thought,
|
|
26532
|
-
actions: raw_message?.actions,
|
|
26533
|
-
attachments: transformedAttachments,
|
|
26534
|
-
updatedAt: new Date(savedMessage.updatedAt).getTime(),
|
|
26535
|
-
rawMessage: raw_message
|
|
26536
|
-
});
|
|
26582
|
+
const tableName = req.query.tableName || "messages";
|
|
26583
|
+
const includeEmbedding = req.query.includeEmbedding === "true";
|
|
26584
|
+
let roomIdToUse;
|
|
26585
|
+
if (req.query.channelId) {
|
|
26586
|
+
const channelId = validateUuid7(req.query.channelId);
|
|
26587
|
+
if (!channelId) {
|
|
26588
|
+
return sendError(res, 400, "INVALID_ID", "Invalid channel ID format");
|
|
26589
|
+
}
|
|
26590
|
+
roomIdToUse = createUniqueUuid2(runtime, channelId);
|
|
26591
|
+
logger6.info(`[AGENT MEMORIES] Converting channelId ${channelId} to roomId ${roomIdToUse} for agent ${agentId}`);
|
|
26592
|
+
} else if (req.query.roomId) {
|
|
26593
|
+
const roomId = validateUuid7(req.query.roomId);
|
|
26594
|
+
if (!roomId) {
|
|
26595
|
+
return sendError(res, 400, "INVALID_ID", "Invalid room ID format");
|
|
26596
|
+
}
|
|
26597
|
+
roomIdToUse = roomId;
|
|
26537
26598
|
}
|
|
26538
|
-
|
|
26599
|
+
const memories = await runtime.getMemories({
|
|
26600
|
+
agentId,
|
|
26601
|
+
tableName,
|
|
26602
|
+
roomId: roomIdToUse
|
|
26603
|
+
});
|
|
26604
|
+
const cleanMemories = includeEmbedding ? memories : memories.map((memory) => ({
|
|
26605
|
+
...memory,
|
|
26606
|
+
embedding: undefined
|
|
26607
|
+
}));
|
|
26608
|
+
sendSuccess(res, { memories: cleanMemories });
|
|
26539
26609
|
} catch (error) {
|
|
26540
|
-
|
|
26541
|
-
|
|
26610
|
+
logger6.error(`[AGENT MEMORIES] Error retrieving memories for agent ${agentId}:`, error instanceof Error ? error.message : String(error));
|
|
26611
|
+
sendError(res, 500, "MEMORY_ERROR", "Error retrieving agent memories", error instanceof Error ? error.message : String(error));
|
|
26542
26612
|
}
|
|
26543
26613
|
});
|
|
26544
|
-
router.patch("/
|
|
26545
|
-
const
|
|
26546
|
-
|
|
26547
|
-
|
|
26548
|
-
|
|
26549
|
-
|
|
26550
|
-
content,
|
|
26551
|
-
raw_message,
|
|
26552
|
-
source_type,
|
|
26553
|
-
in_reply_to_message_id,
|
|
26554
|
-
metadata,
|
|
26555
|
-
author_id,
|
|
26556
|
-
server_id
|
|
26557
|
-
} = req.body ?? {};
|
|
26558
|
-
if (in_reply_to_message_id && !validateUuid9(in_reply_to_message_id)) {
|
|
26559
|
-
return res.status(400).json({ success: false, error: "Invalid in_reply_to_message_id format" });
|
|
26560
|
-
}
|
|
26561
|
-
if (author_id && !validateUuid9(author_id)) {
|
|
26562
|
-
return res.status(400).json({ success: false, error: "Invalid author_id format" });
|
|
26614
|
+
router.patch("/:agentId/memories/:memoryId", async (req, res) => {
|
|
26615
|
+
const agentId = validateUuid7(req.params.agentId);
|
|
26616
|
+
const memoryId = validateUuid7(req.params.memoryId);
|
|
26617
|
+
const { id: _idFromData, ...restOfMemoryData } = req.body;
|
|
26618
|
+
if (!agentId || !memoryId) {
|
|
26619
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID or memory ID format");
|
|
26563
26620
|
}
|
|
26564
|
-
|
|
26565
|
-
|
|
26621
|
+
const runtime = elizaOS.getAgent(agentId);
|
|
26622
|
+
if (!runtime) {
|
|
26623
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26566
26624
|
}
|
|
26567
26625
|
try {
|
|
26568
|
-
const
|
|
26569
|
-
|
|
26570
|
-
|
|
26571
|
-
|
|
26572
|
-
|
|
26573
|
-
|
|
26626
|
+
const memoryToUpdate = {
|
|
26627
|
+
id: memoryId,
|
|
26628
|
+
...restOfMemoryData,
|
|
26629
|
+
agentId: restOfMemoryData.agentId ? validateUuid7(restOfMemoryData.agentId) || undefined : agentId,
|
|
26630
|
+
roomId: restOfMemoryData.roomId ? validateUuid7(restOfMemoryData.roomId) || undefined : undefined,
|
|
26631
|
+
entityId: restOfMemoryData.entityId ? validateUuid7(restOfMemoryData.entityId) || undefined : undefined,
|
|
26632
|
+
worldId: restOfMemoryData.worldId ? validateUuid7(restOfMemoryData.worldId) || undefined : undefined,
|
|
26633
|
+
metadata: restOfMemoryData.metadata
|
|
26634
|
+
};
|
|
26635
|
+
Object.keys(memoryToUpdate).forEach((key) => {
|
|
26636
|
+
if (memoryToUpdate[key] === undefined) {
|
|
26637
|
+
delete memoryToUpdate[key];
|
|
26638
|
+
}
|
|
26574
26639
|
});
|
|
26575
|
-
|
|
26576
|
-
|
|
26577
|
-
}
|
|
26578
|
-
const transformedAttachments = attachmentsToApiUrls(metadata?.attachments ?? raw_message?.attachments);
|
|
26579
|
-
if (serverInstance.socketIO) {
|
|
26580
|
-
serverInstance.socketIO.to(updated.channelId).emit("messageBroadcast", {
|
|
26581
|
-
senderId: author_id || updated.authorId,
|
|
26582
|
-
senderName: metadata?.agentName || "Agent",
|
|
26583
|
-
text: updated.content,
|
|
26584
|
-
roomId: updated.channelId,
|
|
26585
|
-
serverId: server_id,
|
|
26586
|
-
createdAt: new Date(updated.createdAt).getTime(),
|
|
26587
|
-
source: updated.sourceType,
|
|
26588
|
-
id: updated.id,
|
|
26589
|
-
thought: raw_message?.thought,
|
|
26590
|
-
actions: raw_message?.actions,
|
|
26591
|
-
attachments: transformedAttachments,
|
|
26592
|
-
updatedAt: new Date(updated.updatedAt).getTime(),
|
|
26593
|
-
rawMessage: raw_message
|
|
26594
|
-
});
|
|
26595
|
-
}
|
|
26596
|
-
return res.status(200).json({ success: true, data: updated });
|
|
26640
|
+
await runtime.updateMemory(memoryToUpdate);
|
|
26641
|
+
logger6.success(`[MEMORY UPDATE] Successfully updated memory ${memoryId}`);
|
|
26642
|
+
sendSuccess(res, { id: memoryId, message: "Memory updated successfully" });
|
|
26597
26643
|
} catch (error) {
|
|
26598
|
-
|
|
26599
|
-
|
|
26644
|
+
logger6.error(`[MEMORY UPDATE] Error updating memory ${memoryId}:`, error instanceof Error ? error.message : String(error));
|
|
26645
|
+
sendError(res, 500, "UPDATE_ERROR", "Failed to update memory", error instanceof Error ? error.message : String(error));
|
|
26600
26646
|
}
|
|
26601
26647
|
});
|
|
26602
|
-
router.
|
|
26603
|
-
const messagePayload = req.body;
|
|
26604
|
-
if (!messagePayload.channel_id || !messagePayload.server_id || !messagePayload.author_id || !messagePayload.content) {
|
|
26605
|
-
return res.status(400).json({ success: false, error: "Invalid external message payload" });
|
|
26606
|
-
}
|
|
26648
|
+
router.delete("/:agentId/memories", async (req, res) => {
|
|
26607
26649
|
try {
|
|
26608
|
-
const
|
|
26609
|
-
|
|
26610
|
-
|
|
26611
|
-
content: messagePayload.content,
|
|
26612
|
-
rawMessage: messagePayload.raw_message,
|
|
26613
|
-
sourceId: messagePayload.source_id,
|
|
26614
|
-
sourceType: messagePayload.source_type,
|
|
26615
|
-
inReplyToRootMessageId: messagePayload.in_reply_to_message_id ? validateUuid9(messagePayload.in_reply_to_message_id) || undefined : undefined,
|
|
26616
|
-
metadata: messagePayload.metadata
|
|
26617
|
-
};
|
|
26618
|
-
const createdRootMessage = await serverInstance.createMessage(messageToCreate);
|
|
26619
|
-
const messageForBus = {
|
|
26620
|
-
id: createdRootMessage.id,
|
|
26621
|
-
channel_id: createdRootMessage.channelId,
|
|
26622
|
-
server_id: messagePayload.server_id,
|
|
26623
|
-
author_id: createdRootMessage.authorId,
|
|
26624
|
-
author_display_name: messagePayload.author_display_name,
|
|
26625
|
-
content: createdRootMessage.content,
|
|
26626
|
-
raw_message: createdRootMessage.rawMessage,
|
|
26627
|
-
source_id: createdRootMessage.sourceId,
|
|
26628
|
-
source_type: createdRootMessage.sourceType,
|
|
26629
|
-
in_reply_to_message_id: createdRootMessage.inReplyToRootMessageId,
|
|
26630
|
-
created_at: new Date(createdRootMessage.createdAt).getTime(),
|
|
26631
|
-
metadata: createdRootMessage.metadata
|
|
26632
|
-
};
|
|
26633
|
-
bus_default.emit("new_message", messageForBus);
|
|
26634
|
-
logger8.info("[Messages Router /ingest-external] Published to internal message bus:", createdRootMessage.id);
|
|
26635
|
-
if (serverInstance.socketIO) {
|
|
26636
|
-
serverInstance.socketIO.to(messageForBus.channel_id).emit("messageBroadcast", {
|
|
26637
|
-
senderId: messageForBus.author_id,
|
|
26638
|
-
senderName: messageForBus.author_display_name || "User",
|
|
26639
|
-
text: messageForBus.content,
|
|
26640
|
-
roomId: messageForBus.channel_id,
|
|
26641
|
-
serverId: messageForBus.server_id,
|
|
26642
|
-
createdAt: messageForBus.created_at,
|
|
26643
|
-
source: messageForBus.source_type,
|
|
26644
|
-
id: messageForBus.id
|
|
26645
|
-
});
|
|
26650
|
+
const agentId = validateUuid7(req.params.agentId);
|
|
26651
|
+
if (!agentId) {
|
|
26652
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID");
|
|
26646
26653
|
}
|
|
26647
|
-
|
|
26648
|
-
|
|
26649
|
-
|
|
26650
|
-
|
|
26651
|
-
|
|
26654
|
+
const runtime = elizaOS.getAgent(agentId);
|
|
26655
|
+
if (!runtime) {
|
|
26656
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26657
|
+
}
|
|
26658
|
+
const deleted = (await runtime.getAllMemories()).length;
|
|
26659
|
+
await runtime.clearAllAgentMemories();
|
|
26660
|
+
sendSuccess(res, { deleted, message: "All agent memories cleared successfully" });
|
|
26652
26661
|
} catch (error) {
|
|
26653
|
-
|
|
26654
|
-
res
|
|
26662
|
+
logger6.error("[DELETE ALL AGENT MEMORIES] Error deleting all agent memories:", error instanceof Error ? error.message : String(error));
|
|
26663
|
+
sendError(res, 500, "DELETE_ERROR", "Error deleting all agent memories", error instanceof Error ? error.message : String(error));
|
|
26655
26664
|
}
|
|
26656
26665
|
});
|
|
26657
|
-
|
|
26658
|
-
}
|
|
26659
|
-
|
|
26660
|
-
// src/api/messaging/servers.ts
|
|
26661
|
-
import { logger as logger9, validateUuid as validateUuid10 } from "@elizaos/core";
|
|
26662
|
-
import express11 from "express";
|
|
26663
|
-
var DEFAULT_SERVER_ID2 = "00000000-0000-0000-0000-000000000000";
|
|
26664
|
-
function createServersRouter(serverInstance) {
|
|
26665
|
-
const router = express11.Router();
|
|
26666
|
-
router.get("/central-servers", async (_req, res) => {
|
|
26666
|
+
router.delete("/:agentId/memories/all/:roomId", async (req, res) => {
|
|
26667
26667
|
try {
|
|
26668
|
-
const
|
|
26669
|
-
|
|
26668
|
+
const agentId = validateUuid7(req.params.agentId);
|
|
26669
|
+
const roomId = validateUuid7(req.params.roomId);
|
|
26670
|
+
if (!agentId) {
|
|
26671
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID");
|
|
26672
|
+
}
|
|
26673
|
+
if (!roomId) {
|
|
26674
|
+
return sendError(res, 400, "INVALID_ID", "Invalid room ID");
|
|
26675
|
+
}
|
|
26676
|
+
const runtime = elizaOS.getAgent(agentId);
|
|
26677
|
+
if (!runtime) {
|
|
26678
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26679
|
+
}
|
|
26680
|
+
await runtime.deleteAllMemories(roomId, MemoryType.MESSAGE);
|
|
26681
|
+
await runtime.deleteAllMemories(roomId, MemoryType.DOCUMENT);
|
|
26682
|
+
res.status(204).send();
|
|
26670
26683
|
} catch (error) {
|
|
26671
|
-
|
|
26672
|
-
res
|
|
26684
|
+
logger6.error("[DELETE ALL MEMORIES] Error deleting all memories:", error instanceof Error ? error.message : String(error));
|
|
26685
|
+
sendError(res, 500, "DELETE_ERROR", "Error deleting all memories", error instanceof Error ? error.message : String(error));
|
|
26673
26686
|
}
|
|
26674
26687
|
});
|
|
26675
|
-
router.
|
|
26676
|
-
const { name, sourceType, sourceId, metadata } = req.body;
|
|
26677
|
-
if (!name || !sourceType) {
|
|
26678
|
-
return res.status(400).json({
|
|
26679
|
-
success: false,
|
|
26680
|
-
error: "Missing required fields: name, sourceType"
|
|
26681
|
-
});
|
|
26682
|
-
}
|
|
26688
|
+
router.delete("/:agentId/memories/:memoryId", async (req, res) => {
|
|
26683
26689
|
try {
|
|
26684
|
-
const
|
|
26685
|
-
|
|
26686
|
-
|
|
26687
|
-
|
|
26688
|
-
|
|
26689
|
-
|
|
26690
|
-
|
|
26690
|
+
const agentId = validateUuid7(req.params.agentId);
|
|
26691
|
+
const memoryId = validateUuid7(req.params.memoryId);
|
|
26692
|
+
if (!agentId || !memoryId) {
|
|
26693
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID or memory ID format");
|
|
26694
|
+
}
|
|
26695
|
+
const runtime = elizaOS.getAgent(agentId);
|
|
26696
|
+
if (!runtime) {
|
|
26697
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26698
|
+
}
|
|
26699
|
+
await runtime.deleteMemory(memoryId);
|
|
26700
|
+
sendSuccess(res, { message: "Memory deleted successfully" });
|
|
26691
26701
|
} catch (error) {
|
|
26692
|
-
|
|
26693
|
-
res
|
|
26702
|
+
logger6.error(`[DELETE MEMORY] Error deleting memory ${req.params.memoryId}:`, error instanceof Error ? error.message : String(error));
|
|
26703
|
+
sendError(res, 500, "DELETE_ERROR", "Error deleting memory", error instanceof Error ? error.message : String(error));
|
|
26694
26704
|
}
|
|
26695
26705
|
});
|
|
26696
|
-
router
|
|
26697
|
-
|
|
26698
|
-
|
|
26699
|
-
|
|
26700
|
-
|
|
26701
|
-
|
|
26702
|
-
|
|
26703
|
-
|
|
26704
|
-
|
|
26705
|
-
|
|
26706
|
-
|
|
26707
|
-
|
|
26708
|
-
type: "agent_added_to_server",
|
|
26709
|
-
serverId,
|
|
26710
|
-
agentId
|
|
26711
|
-
};
|
|
26712
|
-
bus_default.emit("server_agent_update", messageForBus);
|
|
26713
|
-
res.status(201).json({
|
|
26714
|
-
success: true,
|
|
26715
|
-
data: {
|
|
26716
|
-
serverId,
|
|
26717
|
-
agentId,
|
|
26718
|
-
message: "Agent added to server successfully"
|
|
26719
|
-
}
|
|
26720
|
-
});
|
|
26721
|
-
} catch (error) {
|
|
26722
|
-
logger9.error(`[MessagesRouter] Error adding agent ${agentId} to server ${serverId}:`, error instanceof Error ? error.message : String(error));
|
|
26723
|
-
res.status(500).json({ success: false, error: "Failed to add agent to server" });
|
|
26706
|
+
return router;
|
|
26707
|
+
}
|
|
26708
|
+
|
|
26709
|
+
// src/api/memory/rooms.ts
|
|
26710
|
+
import { validateUuid as validateUuid8, logger as logger7, createUniqueUuid as createUniqueUuid3, ChannelType } from "@elizaos/core";
|
|
26711
|
+
import express8 from "express";
|
|
26712
|
+
function createRoomManagementRouter(elizaOS) {
|
|
26713
|
+
const router = express8.Router();
|
|
26714
|
+
router.post("/:agentId/rooms", async (req, res) => {
|
|
26715
|
+
const agentId = validateUuid8(req.params.agentId);
|
|
26716
|
+
if (!agentId) {
|
|
26717
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
|
|
26724
26718
|
}
|
|
26725
|
-
|
|
26726
|
-
|
|
26727
|
-
|
|
26728
|
-
const agentId = validateUuid10(req.params.agentId);
|
|
26729
|
-
if (!serverId || !agentId) {
|
|
26730
|
-
return res.status(400).json({
|
|
26731
|
-
success: false,
|
|
26732
|
-
error: "Invalid serverId or agentId format"
|
|
26733
|
-
});
|
|
26719
|
+
const runtime = elizaOS.getAgent(agentId);
|
|
26720
|
+
if (!runtime) {
|
|
26721
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26734
26722
|
}
|
|
26735
26723
|
try {
|
|
26736
|
-
|
|
26737
|
-
|
|
26738
|
-
|
|
26739
|
-
|
|
26740
|
-
|
|
26741
|
-
}
|
|
26742
|
-
|
|
26743
|
-
|
|
26744
|
-
|
|
26745
|
-
|
|
26724
|
+
const { name, type = ChannelType.DM, source = "client", worldId, metadata } = req.body;
|
|
26725
|
+
if (!name) {
|
|
26726
|
+
return sendError(res, 400, "MISSING_PARAM", "Room name is required");
|
|
26727
|
+
}
|
|
26728
|
+
const roomId = createUniqueUuid3(runtime, `room-${Date.now()}`);
|
|
26729
|
+
const serverId = req.body.serverId || `server-${Date.now()}`;
|
|
26730
|
+
let resolvedWorldId = worldId;
|
|
26731
|
+
if (!resolvedWorldId) {
|
|
26732
|
+
const worldName = `World for ${name}`;
|
|
26733
|
+
resolvedWorldId = createUniqueUuid3(runtime, `world-${Date.now()}`);
|
|
26734
|
+
await runtime.ensureWorldExists({
|
|
26735
|
+
id: resolvedWorldId,
|
|
26736
|
+
name: worldName,
|
|
26737
|
+
agentId: runtime.agentId,
|
|
26746
26738
|
serverId,
|
|
26747
|
-
|
|
26748
|
-
|
|
26749
|
-
|
|
26739
|
+
metadata
|
|
26740
|
+
});
|
|
26741
|
+
}
|
|
26742
|
+
await runtime.ensureRoomExists({
|
|
26743
|
+
id: roomId,
|
|
26744
|
+
name,
|
|
26745
|
+
source,
|
|
26746
|
+
type,
|
|
26747
|
+
channelId: roomId,
|
|
26748
|
+
serverId,
|
|
26749
|
+
worldId: resolvedWorldId,
|
|
26750
|
+
metadata
|
|
26750
26751
|
});
|
|
26752
|
+
await runtime.addParticipant(runtime.agentId, roomId);
|
|
26753
|
+
await runtime.ensureParticipantInRoom(runtime.agentId, roomId);
|
|
26754
|
+
await runtime.setParticipantUserState(roomId, runtime.agentId, "FOLLOWED");
|
|
26755
|
+
sendSuccess(res, {
|
|
26756
|
+
id: roomId,
|
|
26757
|
+
name,
|
|
26758
|
+
agentId,
|
|
26759
|
+
createdAt: Date.now(),
|
|
26760
|
+
source,
|
|
26761
|
+
type,
|
|
26762
|
+
worldId: resolvedWorldId,
|
|
26763
|
+
serverId,
|
|
26764
|
+
metadata
|
|
26765
|
+
}, 201);
|
|
26751
26766
|
} catch (error) {
|
|
26752
|
-
|
|
26753
|
-
res
|
|
26767
|
+
logger7.error(`[ROOM CREATE] Error creating room for agent ${agentId}:`, error instanceof Error ? error.message : String(error));
|
|
26768
|
+
sendError(res, 500, "CREATE_ERROR", "Failed to create room", error instanceof Error ? error.message : String(error));
|
|
26754
26769
|
}
|
|
26755
26770
|
});
|
|
26756
|
-
router.get("
|
|
26757
|
-
const
|
|
26758
|
-
if (!
|
|
26759
|
-
return res
|
|
26760
|
-
|
|
26761
|
-
|
|
26762
|
-
|
|
26771
|
+
router.get("/:agentId/rooms", async (req, res) => {
|
|
26772
|
+
const agentId = validateUuid8(req.params.agentId);
|
|
26773
|
+
if (!agentId) {
|
|
26774
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
|
|
26775
|
+
}
|
|
26776
|
+
const runtime = elizaOS.getAgent(agentId);
|
|
26777
|
+
if (!runtime) {
|
|
26778
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26763
26779
|
}
|
|
26764
26780
|
try {
|
|
26765
|
-
const
|
|
26766
|
-
|
|
26767
|
-
|
|
26768
|
-
|
|
26769
|
-
|
|
26770
|
-
|
|
26781
|
+
const worlds = await runtime.getAllWorlds();
|
|
26782
|
+
const participantRoomIds = await runtime.getRoomsForParticipant(agentId);
|
|
26783
|
+
const agentRooms = [];
|
|
26784
|
+
for (const world of worlds) {
|
|
26785
|
+
const worldRooms = await runtime.getRooms(world.id);
|
|
26786
|
+
for (const room of worldRooms) {
|
|
26787
|
+
if (participantRoomIds.includes(room.id)) {
|
|
26788
|
+
agentRooms.push({
|
|
26789
|
+
...room
|
|
26790
|
+
});
|
|
26791
|
+
}
|
|
26771
26792
|
}
|
|
26772
|
-
}
|
|
26793
|
+
}
|
|
26794
|
+
sendSuccess(res, { rooms: agentRooms });
|
|
26773
26795
|
} catch (error) {
|
|
26774
|
-
|
|
26775
|
-
res
|
|
26796
|
+
logger7.error(`[ROOMS LIST] Error retrieving rooms for agent ${agentId}:`, error instanceof Error ? error.message : String(error));
|
|
26797
|
+
sendError(res, 500, "RETRIEVAL_ERROR", "Failed to retrieve agent rooms", error instanceof Error ? error.message : String(error));
|
|
26776
26798
|
}
|
|
26777
26799
|
});
|
|
26778
|
-
router.get("
|
|
26779
|
-
const agentId =
|
|
26780
|
-
|
|
26781
|
-
|
|
26782
|
-
|
|
26783
|
-
|
|
26784
|
-
|
|
26800
|
+
router.get("/:agentId/rooms/:roomId", async (req, res) => {
|
|
26801
|
+
const agentId = validateUuid8(req.params.agentId);
|
|
26802
|
+
const roomId = validateUuid8(req.params.roomId);
|
|
26803
|
+
if (!agentId || !roomId) {
|
|
26804
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID or room ID format");
|
|
26805
|
+
}
|
|
26806
|
+
const runtime = elizaOS.getAgent(agentId);
|
|
26807
|
+
if (!runtime) {
|
|
26808
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
26785
26809
|
}
|
|
26786
26810
|
try {
|
|
26787
|
-
const
|
|
26788
|
-
|
|
26789
|
-
|
|
26790
|
-
|
|
26791
|
-
|
|
26792
|
-
|
|
26793
|
-
|
|
26811
|
+
const room = await runtime.getRoom(roomId);
|
|
26812
|
+
if (!room) {
|
|
26813
|
+
return sendError(res, 404, "NOT_FOUND", "Room not found");
|
|
26814
|
+
}
|
|
26815
|
+
let worldName;
|
|
26816
|
+
if (room.worldId) {
|
|
26817
|
+
const world = await runtime.getWorld(room.worldId);
|
|
26818
|
+
worldName = world?.name;
|
|
26819
|
+
}
|
|
26820
|
+
sendSuccess(res, {
|
|
26821
|
+
...room,
|
|
26822
|
+
...worldName && { worldName }
|
|
26794
26823
|
});
|
|
26795
26824
|
} catch (error) {
|
|
26796
|
-
|
|
26797
|
-
res
|
|
26825
|
+
logger7.error(`[ROOM DETAILS] Error retrieving room ${roomId} for agent ${agentId}:`, error instanceof Error ? error.message : String(error));
|
|
26826
|
+
sendError(res, 500, "RETRIEVAL_ERROR", "Failed to retrieve room details", error instanceof Error ? error.message : String(error));
|
|
26798
26827
|
}
|
|
26799
26828
|
});
|
|
26800
26829
|
return router;
|
|
26801
26830
|
}
|
|
26802
26831
|
|
|
26803
|
-
// src/api/
|
|
26804
|
-
|
|
26805
|
-
|
|
26806
|
-
|
|
26807
|
-
|
|
26808
|
-
|
|
26809
|
-
|
|
26810
|
-
|
|
26811
|
-
|
|
26812
|
-
|
|
26832
|
+
// src/api/agents/index.ts
|
|
26833
|
+
function agentsRouter(elizaOS, serverInstance) {
|
|
26834
|
+
const router = express9.Router();
|
|
26835
|
+
router.use("/", createAgentCrudRouter(elizaOS, serverInstance));
|
|
26836
|
+
router.use("/", createAgentLifecycleRouter(elizaOS, serverInstance));
|
|
26837
|
+
router.use("/", createAgentWorldsRouter(elizaOS));
|
|
26838
|
+
router.use("/", createAgentPanelsRouter(elizaOS));
|
|
26839
|
+
router.use("/", createAgentLogsRouter(elizaOS));
|
|
26840
|
+
router.use("/", createAgentRunsRouter(elizaOS));
|
|
26841
|
+
router.use("/", createAgentMemoryRouter(elizaOS));
|
|
26842
|
+
router.use("/", createRoomManagementRouter(elizaOS));
|
|
26843
|
+
return router;
|
|
26844
|
+
}
|
|
26813
26845
|
|
|
26814
|
-
// src/
|
|
26815
|
-
import
|
|
26816
|
-
|
|
26817
|
-
|
|
26818
|
-
|
|
26819
|
-
|
|
26820
|
-
|
|
26821
|
-
|
|
26822
|
-
|
|
26823
|
-
|
|
26824
|
-
|
|
26825
|
-
|
|
26826
|
-
|
|
26827
|
-
return res.status(401).send("Unauthorized: Invalid or missing X-API-KEY");
|
|
26846
|
+
// src/api/messaging/index.ts
|
|
26847
|
+
import express15 from "express";
|
|
26848
|
+
|
|
26849
|
+
// src/api/messaging/core.ts
|
|
26850
|
+
import { logger as logger8, validateUuid as validateUuid9 } from "@elizaos/core";
|
|
26851
|
+
import express10 from "express";
|
|
26852
|
+
|
|
26853
|
+
// src/bus.ts
|
|
26854
|
+
class InternalMessageBus extends EventTarget {
|
|
26855
|
+
_maxListeners = 50;
|
|
26856
|
+
handlers = new Map;
|
|
26857
|
+
emit(event, data) {
|
|
26858
|
+
return this.dispatchEvent(new CustomEvent(event, { detail: data }));
|
|
26828
26859
|
}
|
|
26829
|
-
|
|
26830
|
-
|
|
26831
|
-
|
|
26832
|
-
import { logger as logger11 } from "@elizaos/core";
|
|
26833
|
-
var securityMiddleware = () => {
|
|
26834
|
-
return (req, res, next) => {
|
|
26835
|
-
res.setHeader("X-Content-Type-Options", "nosniff");
|
|
26836
|
-
res.setHeader("X-Frame-Options", "SAMEORIGIN");
|
|
26837
|
-
res.setHeader("X-XSS-Protection", "1; mode=block");
|
|
26838
|
-
res.setHeader("Referrer-Policy", "no-referrer");
|
|
26839
|
-
res.removeHeader("X-Powered-By");
|
|
26840
|
-
res.removeHeader("Server");
|
|
26841
|
-
const userAgent = req.get("User-Agent");
|
|
26842
|
-
const forwarded = req.get("X-Forwarded-For");
|
|
26843
|
-
const realIp = req.get("X-Real-IP");
|
|
26844
|
-
const clientIp = forwarded || realIp || req.ip;
|
|
26845
|
-
if (userAgent && (userAgent.includes("..") || userAgent.includes("<script"))) {
|
|
26846
|
-
logger11.warn(`[SECURITY] Suspicious User-Agent from ${clientIp}: ${userAgent}`);
|
|
26860
|
+
on(event, handler) {
|
|
26861
|
+
if (!this.handlers.has(event)) {
|
|
26862
|
+
this.handlers.set(event, new Map);
|
|
26847
26863
|
}
|
|
26848
|
-
const
|
|
26849
|
-
|
|
26850
|
-
|
|
26851
|
-
{ pattern: "..", name: "Path traversal" },
|
|
26852
|
-
{ pattern: "<script", name: "XSS attempt" },
|
|
26853
|
-
{ pattern: "javascript:", name: "JavaScript injection" }
|
|
26854
|
-
];
|
|
26855
|
-
const sqlKeywords = ["union", "select", "drop", "delete", "insert", "update"];
|
|
26856
|
-
let hasSqlPattern = false;
|
|
26857
|
-
const lowerUrl = url.toLowerCase();
|
|
26858
|
-
const lowerQuery = queryString.toLowerCase();
|
|
26859
|
-
for (let i = 0;i < sqlKeywords.length - 1; i++) {
|
|
26860
|
-
const keyword1 = sqlKeywords[i];
|
|
26861
|
-
for (let j = i + 1;j < sqlKeywords.length; j++) {
|
|
26862
|
-
const keyword2 = sqlKeywords[j];
|
|
26863
|
-
if (lowerUrl.includes(keyword1) && lowerUrl.includes(keyword2) || lowerQuery.includes(keyword1) && lowerQuery.includes(keyword2)) {
|
|
26864
|
-
hasSqlPattern = true;
|
|
26865
|
-
break;
|
|
26866
|
-
}
|
|
26867
|
-
}
|
|
26868
|
-
if (hasSqlPattern)
|
|
26869
|
-
break;
|
|
26864
|
+
const eventHandlers = this.handlers.get(event);
|
|
26865
|
+
if (eventHandlers.has(handler)) {
|
|
26866
|
+
return this;
|
|
26870
26867
|
}
|
|
26871
|
-
|
|
26872
|
-
if (
|
|
26873
|
-
|
|
26874
|
-
|
|
26868
|
+
const wrappedHandler = (e) => {
|
|
26869
|
+
if (e instanceof CustomEvent) {
|
|
26870
|
+
handler(e.detail);
|
|
26871
|
+
} else {
|
|
26872
|
+
handler(undefined);
|
|
26875
26873
|
}
|
|
26876
|
-
}
|
|
26877
|
-
|
|
26878
|
-
|
|
26879
|
-
|
|
26880
|
-
next();
|
|
26881
|
-
};
|
|
26882
|
-
};
|
|
26883
|
-
// ../../node_modules/express-rate-limit/dist/index.mjs
|
|
26884
|
-
var import_ip_address = __toESM(require_ip_address(), 1);
|
|
26885
|
-
import { isIPv6 } from "node:net";
|
|
26886
|
-
import { isIPv6 as isIPv62 } from "node:net";
|
|
26887
|
-
import { Buffer as Buffer2 } from "node:buffer";
|
|
26888
|
-
import { createHash } from "node:crypto";
|
|
26889
|
-
import { isIP } from "node:net";
|
|
26890
|
-
function ipKeyGenerator(ip, ipv6Subnet = 56) {
|
|
26891
|
-
if (ipv6Subnet && isIPv6(ip)) {
|
|
26892
|
-
return `${new import_ip_address.Address6(`${ip}/${ipv6Subnet}`).startAddress().correctForm()}/${ipv6Subnet}`;
|
|
26893
|
-
}
|
|
26894
|
-
return ip;
|
|
26895
|
-
}
|
|
26896
|
-
var MemoryStore = class {
|
|
26897
|
-
constructor(validations2) {
|
|
26898
|
-
this.validations = validations2;
|
|
26899
|
-
this.previous = /* @__PURE__ */ new Map;
|
|
26900
|
-
this.current = /* @__PURE__ */ new Map;
|
|
26901
|
-
this.localKeys = true;
|
|
26902
|
-
}
|
|
26903
|
-
init(options) {
|
|
26904
|
-
this.windowMs = options.windowMs;
|
|
26905
|
-
this.validations?.windowMs(this.windowMs);
|
|
26906
|
-
if (this.interval)
|
|
26907
|
-
clearInterval(this.interval);
|
|
26908
|
-
this.interval = setInterval(() => {
|
|
26909
|
-
this.clearExpired();
|
|
26910
|
-
}, this.windowMs);
|
|
26911
|
-
this.interval.unref?.();
|
|
26912
|
-
}
|
|
26913
|
-
async get(key) {
|
|
26914
|
-
return this.current.get(key) ?? this.previous.get(key);
|
|
26874
|
+
};
|
|
26875
|
+
eventHandlers.set(handler, wrappedHandler);
|
|
26876
|
+
this.addEventListener(event, wrappedHandler);
|
|
26877
|
+
return this;
|
|
26915
26878
|
}
|
|
26916
|
-
|
|
26917
|
-
const
|
|
26918
|
-
const
|
|
26919
|
-
if (
|
|
26920
|
-
this.
|
|
26879
|
+
off(event, handler) {
|
|
26880
|
+
const eventHandlers = this.handlers.get(event);
|
|
26881
|
+
const wrappedHandler = eventHandlers?.get(handler);
|
|
26882
|
+
if (wrappedHandler) {
|
|
26883
|
+
this.removeEventListener(event, wrappedHandler);
|
|
26884
|
+
eventHandlers?.delete(handler);
|
|
26885
|
+
if (eventHandlers && eventHandlers.size === 0) {
|
|
26886
|
+
this.handlers.delete(event);
|
|
26887
|
+
}
|
|
26921
26888
|
}
|
|
26922
|
-
client.totalHits++;
|
|
26923
|
-
return client;
|
|
26924
|
-
}
|
|
26925
|
-
async decrement(key) {
|
|
26926
|
-
const client = this.getClient(key);
|
|
26927
|
-
if (client.totalHits > 0)
|
|
26928
|
-
client.totalHits--;
|
|
26929
|
-
}
|
|
26930
|
-
async resetKey(key) {
|
|
26931
|
-
this.current.delete(key);
|
|
26932
|
-
this.previous.delete(key);
|
|
26933
|
-
}
|
|
26934
|
-
async resetAll() {
|
|
26935
|
-
this.current.clear();
|
|
26936
|
-
this.previous.clear();
|
|
26937
26889
|
}
|
|
26938
|
-
|
|
26939
|
-
|
|
26940
|
-
this.resetAll();
|
|
26890
|
+
getMaxListeners() {
|
|
26891
|
+
return this._maxListeners;
|
|
26941
26892
|
}
|
|
26942
|
-
|
|
26943
|
-
|
|
26944
|
-
client.resetTime.setTime(now + this.windowMs);
|
|
26945
|
-
return client;
|
|
26893
|
+
setMaxListeners(n) {
|
|
26894
|
+
this._maxListeners = n;
|
|
26946
26895
|
}
|
|
26947
|
-
|
|
26948
|
-
if (
|
|
26949
|
-
|
|
26950
|
-
|
|
26951
|
-
|
|
26952
|
-
|
|
26953
|
-
|
|
26896
|
+
removeAllListeners(event) {
|
|
26897
|
+
if (event) {
|
|
26898
|
+
const eventHandlers = this.handlers.get(event);
|
|
26899
|
+
if (eventHandlers) {
|
|
26900
|
+
for (const [_handler, wrappedHandler] of eventHandlers) {
|
|
26901
|
+
this.removeEventListener(event, wrappedHandler);
|
|
26902
|
+
}
|
|
26903
|
+
this.handlers.delete(event);
|
|
26904
|
+
}
|
|
26954
26905
|
} else {
|
|
26955
|
-
|
|
26956
|
-
|
|
26906
|
+
for (const [eventName, eventHandlers] of this.handlers) {
|
|
26907
|
+
for (const [_handler, wrappedHandler] of eventHandlers) {
|
|
26908
|
+
this.removeEventListener(eventName, wrappedHandler);
|
|
26909
|
+
}
|
|
26910
|
+
}
|
|
26911
|
+
this.handlers.clear();
|
|
26957
26912
|
}
|
|
26958
|
-
this.current.set(key, client);
|
|
26959
|
-
return client;
|
|
26960
26913
|
}
|
|
26961
|
-
|
|
26962
|
-
|
|
26963
|
-
|
|
26914
|
+
}
|
|
26915
|
+
var internalMessageBus = new InternalMessageBus;
|
|
26916
|
+
internalMessageBus.setMaxListeners(50);
|
|
26917
|
+
var bus_default = internalMessageBus;
|
|
26918
|
+
|
|
26919
|
+
// src/utils/media-transformer.ts
|
|
26920
|
+
import path from "node:path";
|
|
26921
|
+
import { getGeneratedDir, getUploadsAgentsDir, getUploadsChannelsDir } from "@elizaos/core";
|
|
26922
|
+
var ID_PATTERN = /^([^/\\]+)[/\\]([^/\\]+)$/;
|
|
26923
|
+
var PATH_CONFIGS = [
|
|
26924
|
+
{
|
|
26925
|
+
getPath: getGeneratedDir,
|
|
26926
|
+
apiPrefix: "/media/generated/",
|
|
26927
|
+
pattern: ID_PATTERN
|
|
26928
|
+
},
|
|
26929
|
+
{
|
|
26930
|
+
getPath: getUploadsAgentsDir,
|
|
26931
|
+
apiPrefix: "/media/uploads/agents/",
|
|
26932
|
+
pattern: ID_PATTERN
|
|
26933
|
+
},
|
|
26934
|
+
{
|
|
26935
|
+
getPath: getUploadsChannelsDir,
|
|
26936
|
+
apiPrefix: "/media/uploads/channels/",
|
|
26937
|
+
pattern: ID_PATTERN
|
|
26964
26938
|
}
|
|
26965
|
-
};
|
|
26966
|
-
var SUPPORTED_DRAFT_VERSIONS = [
|
|
26967
|
-
"draft-6",
|
|
26968
|
-
"draft-7",
|
|
26969
|
-
"draft-8"
|
|
26970
26939
|
];
|
|
26971
|
-
var
|
|
26972
|
-
|
|
26973
|
-
if (
|
|
26974
|
-
|
|
26975
|
-
resetSeconds = Math.max(0, deltaSeconds);
|
|
26976
|
-
} else {
|
|
26977
|
-
resetSeconds = Math.ceil(windowMs / 1000);
|
|
26978
|
-
}
|
|
26979
|
-
return resetSeconds;
|
|
26980
|
-
};
|
|
26981
|
-
var getPartitionKey = (key) => {
|
|
26982
|
-
const hash = createHash("sha256");
|
|
26983
|
-
hash.update(key);
|
|
26984
|
-
const partitionKey = hash.digest("hex").slice(0, 12);
|
|
26985
|
-
return Buffer2.from(partitionKey).toString("base64");
|
|
26986
|
-
};
|
|
26987
|
-
var setLegacyHeaders = (response, info) => {
|
|
26988
|
-
if (response.headersSent)
|
|
26989
|
-
return;
|
|
26990
|
-
response.setHeader("X-RateLimit-Limit", info.limit.toString());
|
|
26991
|
-
response.setHeader("X-RateLimit-Remaining", info.remaining.toString());
|
|
26992
|
-
if (info.resetTime instanceof Date) {
|
|
26993
|
-
response.setHeader("Date", (/* @__PURE__ */ new Date()).toUTCString());
|
|
26994
|
-
response.setHeader("X-RateLimit-Reset", Math.ceil(info.resetTime.getTime() / 1000).toString());
|
|
26940
|
+
var isExternalUrl = (p) => /^(?:https?:|blob:|data:|file:|ipfs:|s3:|gs:)/i.test(p);
|
|
26941
|
+
function transformPathToApiUrl(filePath) {
|
|
26942
|
+
if (!filePath || isExternalUrl(filePath) || filePath.startsWith("/media/") || !path.isAbsolute(filePath)) {
|
|
26943
|
+
return filePath;
|
|
26995
26944
|
}
|
|
26996
|
-
|
|
26997
|
-
|
|
26998
|
-
|
|
26999
|
-
|
|
27000
|
-
|
|
27001
|
-
|
|
27002
|
-
|
|
27003
|
-
|
|
27004
|
-
|
|
27005
|
-
|
|
27006
|
-
|
|
27007
|
-
}
|
|
27008
|
-
|
|
27009
|
-
if (response.headersSent)
|
|
27010
|
-
return;
|
|
27011
|
-
const windowSeconds = Math.ceil(windowMs / 1000);
|
|
27012
|
-
const resetSeconds = getResetSeconds(windowMs, info.resetTime);
|
|
27013
|
-
response.setHeader("RateLimit-Policy", `${info.limit};w=${windowSeconds}`);
|
|
27014
|
-
response.setHeader("RateLimit", `limit=${info.limit}, remaining=${info.remaining}, reset=${resetSeconds}`);
|
|
27015
|
-
};
|
|
27016
|
-
var setDraft8Headers = (response, info, windowMs, name, key) => {
|
|
27017
|
-
if (response.headersSent)
|
|
27018
|
-
return;
|
|
27019
|
-
const windowSeconds = Math.ceil(windowMs / 1000);
|
|
27020
|
-
const resetSeconds = getResetSeconds(windowMs, info.resetTime);
|
|
27021
|
-
const partitionKey = getPartitionKey(key);
|
|
27022
|
-
const header = `r=${info.remaining}; t=${resetSeconds}`;
|
|
27023
|
-
const policy = `q=${info.limit}; w=${windowSeconds}; pk=:${partitionKey}:`;
|
|
27024
|
-
response.append("RateLimit", `"${name}"; ${header}`);
|
|
27025
|
-
response.append("RateLimit-Policy", `"${name}"; ${policy}`);
|
|
27026
|
-
};
|
|
27027
|
-
var setRetryAfterHeader = (response, info, windowMs) => {
|
|
27028
|
-
if (response.headersSent)
|
|
27029
|
-
return;
|
|
27030
|
-
const resetSeconds = getResetSeconds(windowMs, info.resetTime);
|
|
27031
|
-
response.setHeader("Retry-After", resetSeconds.toString());
|
|
27032
|
-
};
|
|
27033
|
-
var omitUndefinedProperties = (passedOptions) => {
|
|
27034
|
-
const omittedOptions = {};
|
|
27035
|
-
for (const k of Object.keys(passedOptions)) {
|
|
27036
|
-
const key = k;
|
|
27037
|
-
if (passedOptions[key] !== undefined) {
|
|
27038
|
-
omittedOptions[key] = passedOptions[key];
|
|
26945
|
+
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
26946
|
+
for (const config of PATH_CONFIGS) {
|
|
26947
|
+
const configPathRaw = config.getPath().replace(/\\/g, "/");
|
|
26948
|
+
const configPath = configPathRaw.endsWith("/") ? configPathRaw : `${configPathRaw}/`;
|
|
26949
|
+
if (normalizedPath === configPathRaw || normalizedPath.startsWith(configPath)) {
|
|
26950
|
+
const relative = normalizedPath === configPathRaw ? "" : normalizedPath.slice(configPath.length);
|
|
26951
|
+
if (relative) {
|
|
26952
|
+
const match = relative.match(config.pattern);
|
|
26953
|
+
if (match) {
|
|
26954
|
+
const [, id, filename] = match;
|
|
26955
|
+
return `${config.apiPrefix}${encodeURIComponent(id)}${"/"}${encodeURIComponent(filename)}`;
|
|
26956
|
+
}
|
|
26957
|
+
}
|
|
27039
26958
|
}
|
|
27040
26959
|
}
|
|
27041
|
-
return
|
|
27042
|
-
}
|
|
27043
|
-
|
|
27044
|
-
|
|
27045
|
-
|
|
27046
|
-
|
|
27047
|
-
|
|
27048
|
-
|
|
27049
|
-
|
|
26960
|
+
return filePath;
|
|
26961
|
+
}
|
|
26962
|
+
function attachmentsToApiUrls(attachments) {
|
|
26963
|
+
if (!attachments)
|
|
26964
|
+
return attachments;
|
|
26965
|
+
if (Array.isArray(attachments)) {
|
|
26966
|
+
return attachments.map((attachment) => {
|
|
26967
|
+
if (typeof attachment === "string") {
|
|
26968
|
+
return transformPathToApiUrl(attachment);
|
|
26969
|
+
}
|
|
26970
|
+
if (attachment?.url) {
|
|
26971
|
+
return { ...attachment, url: transformPathToApiUrl(attachment.url) };
|
|
26972
|
+
}
|
|
26973
|
+
return attachment;
|
|
26974
|
+
});
|
|
26975
|
+
}
|
|
26976
|
+
if (typeof attachments === "string") {
|
|
26977
|
+
return transformPathToApiUrl(attachments);
|
|
26978
|
+
}
|
|
26979
|
+
if (attachments?.url) {
|
|
26980
|
+
return { ...attachments, url: transformPathToApiUrl(attachments.url) };
|
|
26981
|
+
}
|
|
26982
|
+
return attachments;
|
|
26983
|
+
}
|
|
26984
|
+
function transformMessageAttachments(message) {
|
|
26985
|
+
if (!message || typeof message !== "object") {
|
|
26986
|
+
return message;
|
|
27050
26987
|
}
|
|
27051
|
-
|
|
27052
|
-
|
|
27053
|
-
|
|
27054
|
-
|
|
27055
|
-
var singleCountKeys = /* @__PURE__ */ new WeakMap;
|
|
27056
|
-
var validations = {
|
|
27057
|
-
enabled: {
|
|
27058
|
-
default: true
|
|
27059
|
-
},
|
|
27060
|
-
disable() {
|
|
27061
|
-
for (const k of Object.keys(this.enabled))
|
|
27062
|
-
this.enabled[k] = false;
|
|
27063
|
-
},
|
|
27064
|
-
ip(ip) {
|
|
27065
|
-
if (ip === undefined) {
|
|
27066
|
-
throw new ValidationError("ERR_ERL_UNDEFINED_IP_ADDRESS", `An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.`);
|
|
27067
|
-
}
|
|
27068
|
-
if (!isIP(ip)) {
|
|
27069
|
-
throw new ValidationError("ERR_ERL_INVALID_IP_ADDRESS", `An invalid 'request.ip' (${ip}) was detected. Consider passing a custom 'keyGenerator' function to the rate limiter.`);
|
|
27070
|
-
}
|
|
27071
|
-
},
|
|
27072
|
-
trustProxy(request) {
|
|
27073
|
-
if (request.app.get("trust proxy") === true) {
|
|
27074
|
-
throw new ValidationError("ERR_ERL_PERMISSIVE_TRUST_PROXY", `The Express 'trust proxy' setting is true, which allows anyone to trivially bypass IP-based rate limiting.`);
|
|
27075
|
-
}
|
|
27076
|
-
},
|
|
27077
|
-
xForwardedForHeader(request) {
|
|
27078
|
-
if (request.headers["x-forwarded-for"] && request.app.get("trust proxy") === false) {
|
|
27079
|
-
throw new ValidationError("ERR_ERL_UNEXPECTED_X_FORWARDED_FOR", `The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.`);
|
|
26988
|
+
if (message.content && typeof message.content === "object" && "attachments" in message.content) {
|
|
26989
|
+
const content = message.content;
|
|
26990
|
+
if (content.attachments) {
|
|
26991
|
+
content.attachments = attachmentsToApiUrls(content.attachments);
|
|
27080
26992
|
}
|
|
27081
|
-
}
|
|
27082
|
-
|
|
27083
|
-
|
|
27084
|
-
|
|
26993
|
+
}
|
|
26994
|
+
if (message.metadata?.attachments) {
|
|
26995
|
+
message.metadata.attachments = attachmentsToApiUrls(message.metadata.attachments);
|
|
26996
|
+
}
|
|
26997
|
+
return message;
|
|
26998
|
+
}
|
|
26999
|
+
|
|
27000
|
+
// src/api/messaging/core.ts
|
|
27001
|
+
function createMessagingCoreRouter(serverInstance) {
|
|
27002
|
+
const router = express10.Router();
|
|
27003
|
+
router.post("/submit", async (req, res) => {
|
|
27004
|
+
const {
|
|
27005
|
+
channel_id,
|
|
27006
|
+
server_id,
|
|
27007
|
+
author_id,
|
|
27008
|
+
content,
|
|
27009
|
+
in_reply_to_message_id,
|
|
27010
|
+
source_type,
|
|
27011
|
+
raw_message,
|
|
27012
|
+
metadata
|
|
27013
|
+
} = req.body;
|
|
27014
|
+
const isValidServerId = server_id === serverInstance.serverId;
|
|
27015
|
+
if (!validateUuid9(channel_id) || !validateUuid9(author_id) || !content || !isValidServerId || !source_type || !raw_message) {
|
|
27016
|
+
return res.status(400).json({
|
|
27017
|
+
success: false,
|
|
27018
|
+
error: "Missing required fields: channel_id, server_id, author_id, content, source_type, raw_message"
|
|
27019
|
+
});
|
|
27085
27020
|
}
|
|
27086
|
-
|
|
27087
|
-
|
|
27088
|
-
|
|
27089
|
-
|
|
27021
|
+
if (in_reply_to_message_id && !validateUuid9(in_reply_to_message_id)) {
|
|
27022
|
+
return res.status(400).json({
|
|
27023
|
+
success: false,
|
|
27024
|
+
error: "Invalid in_reply_to_message_id format"
|
|
27025
|
+
});
|
|
27090
27026
|
}
|
|
27091
|
-
|
|
27092
|
-
|
|
27093
|
-
|
|
27094
|
-
|
|
27095
|
-
|
|
27027
|
+
try {
|
|
27028
|
+
const newRootMessageData = {
|
|
27029
|
+
channelId: validateUuid9(channel_id),
|
|
27030
|
+
authorId: validateUuid9(author_id),
|
|
27031
|
+
content,
|
|
27032
|
+
rawMessage: raw_message,
|
|
27033
|
+
sourceType: source_type || "agent_response",
|
|
27034
|
+
inReplyToRootMessageId: in_reply_to_message_id ? validateUuid9(in_reply_to_message_id) || undefined : undefined,
|
|
27035
|
+
metadata
|
|
27036
|
+
};
|
|
27037
|
+
const createdMessage = await serverInstance.createMessage(newRootMessageData);
|
|
27038
|
+
const transformedAttachments = attachmentsToApiUrls(metadata?.attachments ?? raw_message?.attachments);
|
|
27039
|
+
if (serverInstance.socketIO) {
|
|
27040
|
+
serverInstance.socketIO.to(channel_id).emit("messageBroadcast", {
|
|
27041
|
+
senderId: author_id,
|
|
27042
|
+
senderName: metadata?.agentName || "Agent",
|
|
27043
|
+
text: content,
|
|
27044
|
+
roomId: channel_id,
|
|
27045
|
+
serverId: server_id,
|
|
27046
|
+
createdAt: new Date(createdMessage.createdAt).getTime(),
|
|
27047
|
+
source: createdMessage.sourceType,
|
|
27048
|
+
id: createdMessage.id,
|
|
27049
|
+
thought: raw_message?.thought,
|
|
27050
|
+
actions: raw_message?.actions,
|
|
27051
|
+
attachments: transformedAttachments
|
|
27052
|
+
});
|
|
27053
|
+
}
|
|
27054
|
+
res.status(201).json({ success: true, data: createdMessage });
|
|
27055
|
+
} catch (error) {
|
|
27056
|
+
logger8.error("[Messages Router /submit] Error submitting agent message:", error instanceof Error ? error.message : String(error));
|
|
27057
|
+
res.status(500).json({ success: false, error: "Failed to submit agent message" });
|
|
27096
27058
|
}
|
|
27097
|
-
|
|
27098
|
-
|
|
27099
|
-
|
|
27100
|
-
|
|
27101
|
-
|
|
27102
|
-
|
|
27103
|
-
|
|
27059
|
+
});
|
|
27060
|
+
router.post("/action", async (req, res) => {
|
|
27061
|
+
const {
|
|
27062
|
+
messageId,
|
|
27063
|
+
channel_id,
|
|
27064
|
+
server_id,
|
|
27065
|
+
author_id,
|
|
27066
|
+
content,
|
|
27067
|
+
in_reply_to_message_id,
|
|
27068
|
+
source_type,
|
|
27069
|
+
raw_message,
|
|
27070
|
+
metadata
|
|
27071
|
+
} = req.body;
|
|
27072
|
+
const isValidServerId = server_id === serverInstance.serverId;
|
|
27073
|
+
if (!validateUuid9(channel_id) || !validateUuid9(author_id) || !content || !isValidServerId || !source_type || !raw_message) {
|
|
27074
|
+
return res.status(400).json({
|
|
27075
|
+
success: false,
|
|
27076
|
+
error: "Missing required fields: channel_id, server_id, author_id, content, source_type, raw_message"
|
|
27077
|
+
});
|
|
27104
27078
|
}
|
|
27105
|
-
|
|
27106
|
-
|
|
27107
|
-
if (!keys) {
|
|
27108
|
-
keys = [];
|
|
27109
|
-
storeKeys.set(storeKey, keys);
|
|
27079
|
+
if (in_reply_to_message_id && !validateUuid9(in_reply_to_message_id)) {
|
|
27080
|
+
return res.status(400).json({ success: false, error: "Invalid in_reply_to_message_id format" });
|
|
27110
27081
|
}
|
|
27111
|
-
|
|
27112
|
-
|
|
27113
|
-
throw new ValidationError("ERR_ERL_DOUBLE_COUNT", `The hit count for ${key} was incremented more than once for a single request.`);
|
|
27082
|
+
if (messageId && !validateUuid9(messageId)) {
|
|
27083
|
+
return res.status(400).json({ success: false, error: "Invalid messageId format" });
|
|
27114
27084
|
}
|
|
27115
|
-
|
|
27116
|
-
|
|
27117
|
-
|
|
27118
|
-
|
|
27119
|
-
|
|
27085
|
+
try {
|
|
27086
|
+
const baseData = {
|
|
27087
|
+
messageId,
|
|
27088
|
+
channelId: validateUuid9(channel_id),
|
|
27089
|
+
authorId: validateUuid9(author_id),
|
|
27090
|
+
content,
|
|
27091
|
+
rawMessage: raw_message,
|
|
27092
|
+
sourceType: source_type || "agent_response",
|
|
27093
|
+
inReplyToRootMessageId: in_reply_to_message_id ? validateUuid9(in_reply_to_message_id) || undefined : undefined,
|
|
27094
|
+
metadata
|
|
27095
|
+
};
|
|
27096
|
+
const savedMessage = await serverInstance.createMessage(baseData);
|
|
27097
|
+
const transformedAttachments = attachmentsToApiUrls(metadata?.attachments ?? raw_message?.attachments);
|
|
27098
|
+
if (serverInstance.socketIO) {
|
|
27099
|
+
serverInstance.socketIO.to(channel_id).emit("messageBroadcast", {
|
|
27100
|
+
senderId: author_id,
|
|
27101
|
+
senderName: metadata?.agentName || "Agent",
|
|
27102
|
+
text: savedMessage.content,
|
|
27103
|
+
roomId: channel_id,
|
|
27104
|
+
serverId: server_id,
|
|
27105
|
+
createdAt: new Date(savedMessage.createdAt).getTime(),
|
|
27106
|
+
source: savedMessage.sourceType,
|
|
27107
|
+
id: savedMessage.id,
|
|
27108
|
+
thought: raw_message?.thought,
|
|
27109
|
+
actions: raw_message?.actions,
|
|
27110
|
+
attachments: transformedAttachments,
|
|
27111
|
+
updatedAt: new Date(savedMessage.updatedAt).getTime(),
|
|
27112
|
+
rawMessage: raw_message
|
|
27113
|
+
});
|
|
27114
|
+
}
|
|
27115
|
+
return res.status(201).json({ success: true, data: savedMessage });
|
|
27116
|
+
} catch (error) {
|
|
27117
|
+
logger8.error("[POST /actions] Error creating action:", error instanceof Error ? error.message : String(error));
|
|
27118
|
+
return res.status(500).json({ success: false, error: "Failed to create action" });
|
|
27120
27119
|
}
|
|
27121
|
-
}
|
|
27122
|
-
|
|
27123
|
-
|
|
27124
|
-
|
|
27120
|
+
});
|
|
27121
|
+
router.patch("/action/:id", async (req, res) => {
|
|
27122
|
+
const { id } = req.params;
|
|
27123
|
+
if (!validateUuid9(id)) {
|
|
27124
|
+
return res.status(400).json({ success: false, error: "Invalid message id" });
|
|
27125
27125
|
}
|
|
27126
|
-
|
|
27127
|
-
|
|
27128
|
-
|
|
27129
|
-
|
|
27126
|
+
const {
|
|
27127
|
+
content,
|
|
27128
|
+
raw_message,
|
|
27129
|
+
source_type,
|
|
27130
|
+
in_reply_to_message_id,
|
|
27131
|
+
metadata,
|
|
27132
|
+
author_id,
|
|
27133
|
+
server_id
|
|
27134
|
+
} = req.body ?? {};
|
|
27135
|
+
if (in_reply_to_message_id && !validateUuid9(in_reply_to_message_id)) {
|
|
27136
|
+
return res.status(400).json({ success: false, error: "Invalid in_reply_to_message_id format" });
|
|
27130
27137
|
}
|
|
27131
|
-
|
|
27132
|
-
|
|
27133
|
-
if (typeof version !== "string" || !SUPPORTED_DRAFT_VERSIONS.includes(version)) {
|
|
27134
|
-
const versionString = SUPPORTED_DRAFT_VERSIONS.join(", ");
|
|
27135
|
-
throw new ValidationError("ERR_ERL_HEADERS_UNSUPPORTED_DRAFT_VERSION", `standardHeaders: only the following versions of the IETF draft specification are supported: ${versionString}.`);
|
|
27138
|
+
if (author_id && !validateUuid9(author_id)) {
|
|
27139
|
+
return res.status(400).json({ success: false, error: "Invalid author_id format" });
|
|
27136
27140
|
}
|
|
27137
|
-
|
|
27138
|
-
|
|
27139
|
-
if (!resetTime) {
|
|
27140
|
-
throw new ValidationError("ERR_ERL_HEADERS_NO_RESET", `standardHeaders: 'draft-7' requires a 'resetTime', but the store did not provide one. The 'windowMs' value will be used instead, which may cause clients to wait longer than necessary.`);
|
|
27141
|
+
if (server_id && server_id !== serverInstance.serverId) {
|
|
27142
|
+
return res.status(403).json({ success: false, error: "Forbidden: server_id does not match current server" });
|
|
27141
27143
|
}
|
|
27142
|
-
|
|
27143
|
-
|
|
27144
|
-
|
|
27145
|
-
|
|
27146
|
-
|
|
27147
|
-
|
|
27148
|
-
|
|
27144
|
+
try {
|
|
27145
|
+
const updated = await serverInstance.updateMessage(id, {
|
|
27146
|
+
content,
|
|
27147
|
+
rawMessage: raw_message,
|
|
27148
|
+
sourceType: source_type,
|
|
27149
|
+
inReplyToRootMessageId: in_reply_to_message_id ? validateUuid9(in_reply_to_message_id) || undefined : undefined,
|
|
27150
|
+
metadata
|
|
27151
|
+
});
|
|
27152
|
+
if (!updated) {
|
|
27153
|
+
return res.status(404).json({ success: false, error: "Message not found" });
|
|
27149
27154
|
}
|
|
27150
|
-
|
|
27151
|
-
|
|
27152
|
-
|
|
27153
|
-
|
|
27154
|
-
|
|
27155
|
-
|
|
27156
|
-
|
|
27155
|
+
const transformedAttachments = attachmentsToApiUrls(metadata?.attachments ?? raw_message?.attachments);
|
|
27156
|
+
if (serverInstance.socketIO) {
|
|
27157
|
+
serverInstance.socketIO.to(updated.channelId).emit("messageBroadcast", {
|
|
27158
|
+
senderId: author_id || updated.authorId,
|
|
27159
|
+
senderName: metadata?.agentName || "Agent",
|
|
27160
|
+
text: updated.content,
|
|
27161
|
+
roomId: updated.channelId,
|
|
27162
|
+
serverId: server_id,
|
|
27163
|
+
createdAt: new Date(updated.createdAt).getTime(),
|
|
27164
|
+
source: updated.sourceType,
|
|
27165
|
+
id: updated.id,
|
|
27166
|
+
thought: raw_message?.thought,
|
|
27167
|
+
actions: raw_message?.actions,
|
|
27168
|
+
attachments: transformedAttachments,
|
|
27169
|
+
updatedAt: new Date(updated.updatedAt).getTime(),
|
|
27170
|
+
rawMessage: raw_message
|
|
27171
|
+
});
|
|
27157
27172
|
}
|
|
27158
|
-
|
|
27159
|
-
}
|
|
27160
|
-
|
|
27161
|
-
|
|
27162
|
-
if (ipv6Subnet === false) {
|
|
27163
|
-
return;
|
|
27164
|
-
}
|
|
27165
|
-
if (!Number.isInteger(ipv6Subnet) || ipv6Subnet < 32 || ipv6Subnet > 64) {
|
|
27166
|
-
throw new ValidationError("ERR_ERL_IPV6_SUBNET", `Unexpected ipv6Subnet value: ${ipv6Subnet}. Expected an integer between 32 and 64 (usually 48-64).`);
|
|
27167
|
-
}
|
|
27168
|
-
},
|
|
27169
|
-
ipv6SubnetOrKeyGenerator(options) {
|
|
27170
|
-
if (options.ipv6Subnet !== undefined && options.keyGenerator) {
|
|
27171
|
-
throw new ValidationError("ERR_ERL_IPV6SUBNET_OR_KEYGENERATOR", `Incompatible options: the 'ipv6Subnet' option is ignored when a custom 'keyGenerator' function is also set.`);
|
|
27172
|
-
}
|
|
27173
|
-
},
|
|
27174
|
-
keyGeneratorIpFallback(keyGenerator) {
|
|
27175
|
-
if (!keyGenerator) {
|
|
27176
|
-
return;
|
|
27177
|
-
}
|
|
27178
|
-
const src = keyGenerator.toString();
|
|
27179
|
-
if ((src.includes("req.ip") || src.includes("request.ip")) && !src.includes("ipKeyGenerator")) {
|
|
27180
|
-
throw new ValidationError("ERR_ERL_KEY_GEN_IPV6", "Custom keyGenerator appears to use request IP without calling the ipKeyGenerator helper function for IPv6 addresses. This could allow IPv6 users to bypass limits.");
|
|
27173
|
+
return res.status(200).json({ success: true, data: updated });
|
|
27174
|
+
} catch (error) {
|
|
27175
|
+
logger8.error("[PATCH /action/:id] Error updating action:", error instanceof Error ? error.message : String(error));
|
|
27176
|
+
return res.status(500).json({ success: false, error: "Failed to update action" });
|
|
27181
27177
|
}
|
|
27182
|
-
}
|
|
27183
|
-
|
|
27184
|
-
const
|
|
27185
|
-
if (
|
|
27186
|
-
|
|
27178
|
+
});
|
|
27179
|
+
router.post("/ingest-external", async (req, res) => {
|
|
27180
|
+
const messagePayload = req.body;
|
|
27181
|
+
if (!messagePayload.channel_id || !messagePayload.server_id || !messagePayload.author_id || !messagePayload.content) {
|
|
27182
|
+
return res.status(400).json({ success: false, error: "Invalid external message payload" });
|
|
27187
27183
|
}
|
|
27188
|
-
|
|
27189
|
-
|
|
27190
|
-
|
|
27191
|
-
|
|
27192
|
-
|
|
27193
|
-
|
|
27194
|
-
|
|
27195
|
-
|
|
27196
|
-
|
|
27197
|
-
|
|
27198
|
-
default: true,
|
|
27199
|
-
..._enabled
|
|
27200
|
-
};
|
|
27201
|
-
}
|
|
27202
|
-
const wrappedValidations = { enabled };
|
|
27203
|
-
for (const [name, validation] of Object.entries(validations)) {
|
|
27204
|
-
if (typeof validation === "function")
|
|
27205
|
-
wrappedValidations[name] = (...args) => {
|
|
27206
|
-
if (!(enabled[name] ?? enabled.default)) {
|
|
27207
|
-
return;
|
|
27208
|
-
}
|
|
27209
|
-
try {
|
|
27210
|
-
validation.apply(wrappedValidations, args);
|
|
27211
|
-
} catch (error) {
|
|
27212
|
-
if (error instanceof ChangeWarning)
|
|
27213
|
-
console.warn(error);
|
|
27214
|
-
else
|
|
27215
|
-
console.error(error);
|
|
27216
|
-
}
|
|
27184
|
+
try {
|
|
27185
|
+
const messageToCreate = {
|
|
27186
|
+
channelId: messagePayload.channel_id,
|
|
27187
|
+
authorId: messagePayload.author_id,
|
|
27188
|
+
content: messagePayload.content,
|
|
27189
|
+
rawMessage: messagePayload.raw_message,
|
|
27190
|
+
sourceId: messagePayload.source_id,
|
|
27191
|
+
sourceType: messagePayload.source_type,
|
|
27192
|
+
inReplyToRootMessageId: messagePayload.in_reply_to_message_id ? validateUuid9(messagePayload.in_reply_to_message_id) || undefined : undefined,
|
|
27193
|
+
metadata: messagePayload.metadata
|
|
27217
27194
|
};
|
|
27218
|
-
|
|
27219
|
-
|
|
27220
|
-
|
|
27221
|
-
|
|
27222
|
-
|
|
27223
|
-
|
|
27224
|
-
|
|
27225
|
-
|
|
27226
|
-
|
|
27227
|
-
|
|
27228
|
-
|
|
27229
|
-
|
|
27230
|
-
|
|
27231
|
-
|
|
27232
|
-
|
|
27233
|
-
|
|
27234
|
-
|
|
27195
|
+
const createdRootMessage = await serverInstance.createMessage(messageToCreate);
|
|
27196
|
+
const messageForBus = {
|
|
27197
|
+
id: createdRootMessage.id,
|
|
27198
|
+
channel_id: createdRootMessage.channelId,
|
|
27199
|
+
server_id: messagePayload.server_id,
|
|
27200
|
+
author_id: createdRootMessage.authorId,
|
|
27201
|
+
author_display_name: messagePayload.author_display_name,
|
|
27202
|
+
content: createdRootMessage.content,
|
|
27203
|
+
raw_message: createdRootMessage.rawMessage,
|
|
27204
|
+
source_id: createdRootMessage.sourceId,
|
|
27205
|
+
source_type: createdRootMessage.sourceType,
|
|
27206
|
+
in_reply_to_message_id: createdRootMessage.inReplyToRootMessageId,
|
|
27207
|
+
created_at: new Date(createdRootMessage.createdAt).getTime(),
|
|
27208
|
+
metadata: createdRootMessage.metadata
|
|
27209
|
+
};
|
|
27210
|
+
bus_default.emit("new_message", messageForBus);
|
|
27211
|
+
logger8.info("[Messages Router /ingest-external] Published to internal message bus:", createdRootMessage.id);
|
|
27212
|
+
if (serverInstance.socketIO) {
|
|
27213
|
+
serverInstance.socketIO.to(messageForBus.channel_id).emit("messageBroadcast", {
|
|
27214
|
+
senderId: messageForBus.author_id,
|
|
27215
|
+
senderName: messageForBus.author_display_name || "User",
|
|
27216
|
+
text: messageForBus.content,
|
|
27217
|
+
roomId: messageForBus.channel_id,
|
|
27218
|
+
serverId: messageForBus.server_id,
|
|
27219
|
+
createdAt: messageForBus.created_at,
|
|
27220
|
+
source: messageForBus.source_type,
|
|
27221
|
+
id: messageForBus.id
|
|
27235
27222
|
});
|
|
27223
|
+
}
|
|
27224
|
+
res.status(202).json({
|
|
27225
|
+
success: true,
|
|
27226
|
+
message: "Message ingested and published to bus",
|
|
27227
|
+
data: { messageId: createdRootMessage.id }
|
|
27236
27228
|
});
|
|
27229
|
+
} catch (error) {
|
|
27230
|
+
logger8.error("[Messages Router /ingest-external] Error ingesting external message:", error instanceof Error ? error.message : String(error));
|
|
27231
|
+
res.status(500).json({ success: false, error: "Failed to ingest message" });
|
|
27237
27232
|
}
|
|
27238
|
-
|
|
27239
|
-
|
|
27240
|
-
|
|
27241
|
-
|
|
27242
|
-
|
|
27243
|
-
|
|
27244
|
-
|
|
27245
|
-
|
|
27246
|
-
|
|
27247
|
-
|
|
27248
|
-
|
|
27249
|
-
|
|
27250
|
-
};
|
|
27251
|
-
|
|
27252
|
-
|
|
27253
|
-
|
|
27254
|
-
|
|
27255
|
-
|
|
27256
|
-
|
|
27257
|
-
};
|
|
27258
|
-
|
|
27259
|
-
|
|
27260
|
-
|
|
27261
|
-
|
|
27262
|
-
|
|
27263
|
-
validations2.onLimitReached(notUndefinedOptions.onLimitReached);
|
|
27264
|
-
if (notUndefinedOptions.ipv6Subnet !== undefined && typeof notUndefinedOptions.ipv6Subnet !== "function") {
|
|
27265
|
-
validations2.ipv6Subnet(notUndefinedOptions.ipv6Subnet);
|
|
27266
|
-
}
|
|
27267
|
-
validations2.keyGeneratorIpFallback(notUndefinedOptions.keyGenerator);
|
|
27268
|
-
validations2.ipv6SubnetOrKeyGenerator(notUndefinedOptions);
|
|
27269
|
-
let standardHeaders = notUndefinedOptions.standardHeaders ?? false;
|
|
27270
|
-
if (standardHeaders === true)
|
|
27271
|
-
standardHeaders = "draft-6";
|
|
27272
|
-
const config = {
|
|
27273
|
-
windowMs: 60 * 1000,
|
|
27274
|
-
limit: passedOptions.max ?? 5,
|
|
27275
|
-
message: "Too many requests, please try again later.",
|
|
27276
|
-
statusCode: 429,
|
|
27277
|
-
legacyHeaders: passedOptions.headers ?? true,
|
|
27278
|
-
identifier(request, _response) {
|
|
27279
|
-
let duration = "";
|
|
27280
|
-
const property = config.requestPropertyName;
|
|
27281
|
-
const { limit } = request[property];
|
|
27282
|
-
const seconds = config.windowMs / 1000;
|
|
27283
|
-
const minutes = config.windowMs / (1000 * 60);
|
|
27284
|
-
const hours = config.windowMs / (1000 * 60 * 60);
|
|
27285
|
-
const days = config.windowMs / (1000 * 60 * 60 * 24);
|
|
27286
|
-
if (seconds < 60)
|
|
27287
|
-
duration = `${seconds}sec`;
|
|
27288
|
-
else if (minutes < 60)
|
|
27289
|
-
duration = `${minutes}min`;
|
|
27290
|
-
else if (hours < 24)
|
|
27291
|
-
duration = `${hours}hr${hours > 1 ? "s" : ""}`;
|
|
27292
|
-
else
|
|
27293
|
-
duration = `${days}day${days > 1 ? "s" : ""}`;
|
|
27294
|
-
return `${limit}-in-${duration}`;
|
|
27295
|
-
},
|
|
27296
|
-
requestPropertyName: "rateLimit",
|
|
27297
|
-
skipFailedRequests: false,
|
|
27298
|
-
skipSuccessfulRequests: false,
|
|
27299
|
-
requestWasSuccessful: (_request, response) => response.statusCode < 400,
|
|
27300
|
-
skip: (_request, _response) => false,
|
|
27301
|
-
async keyGenerator(request, response) {
|
|
27302
|
-
validations2.ip(request.ip);
|
|
27303
|
-
validations2.trustProxy(request);
|
|
27304
|
-
validations2.xForwardedForHeader(request);
|
|
27305
|
-
validations2.forwardedHeader(request);
|
|
27306
|
-
const ip = request.ip;
|
|
27307
|
-
let subnet = 56;
|
|
27308
|
-
if (isIPv62(ip)) {
|
|
27309
|
-
subnet = typeof config.ipv6Subnet === "function" ? await config.ipv6Subnet(request, response) : config.ipv6Subnet;
|
|
27310
|
-
if (typeof config.ipv6Subnet === "function")
|
|
27311
|
-
validations2.ipv6Subnet(subnet);
|
|
27312
|
-
}
|
|
27313
|
-
return ipKeyGenerator(ip, subnet);
|
|
27314
|
-
},
|
|
27315
|
-
ipv6Subnet: 56,
|
|
27316
|
-
async handler(request, response, _next, _optionsUsed) {
|
|
27317
|
-
response.status(config.statusCode);
|
|
27318
|
-
const message = typeof config.message === "function" ? await config.message(request, response) : config.message;
|
|
27319
|
-
if (!response.writableEnded)
|
|
27320
|
-
response.send(message);
|
|
27321
|
-
},
|
|
27322
|
-
passOnStoreError: false,
|
|
27323
|
-
...notUndefinedOptions,
|
|
27324
|
-
standardHeaders,
|
|
27325
|
-
store: promisifyStore(notUndefinedOptions.store ?? new MemoryStore(validations2)),
|
|
27326
|
-
validations: validations2
|
|
27327
|
-
};
|
|
27328
|
-
if (typeof config.store.increment !== "function" || typeof config.store.decrement !== "function" || typeof config.store.resetKey !== "function" || config.store.resetAll !== undefined && typeof config.store.resetAll !== "function" || config.store.init !== undefined && typeof config.store.init !== "function") {
|
|
27329
|
-
throw new TypeError("An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface.");
|
|
27330
|
-
}
|
|
27331
|
-
return config;
|
|
27332
|
-
};
|
|
27333
|
-
var handleAsyncErrors = (fn) => async (request, response, next) => {
|
|
27334
|
-
try {
|
|
27335
|
-
await Promise.resolve(fn(request, response, next)).catch(next);
|
|
27336
|
-
} catch (error) {
|
|
27337
|
-
next(error);
|
|
27338
|
-
}
|
|
27339
|
-
};
|
|
27340
|
-
var rateLimit = (passedOptions) => {
|
|
27341
|
-
const config = parseOptions(passedOptions ?? {});
|
|
27342
|
-
const options = getOptionsFromConfig(config);
|
|
27343
|
-
config.validations.creationStack(config.store);
|
|
27344
|
-
config.validations.unsharedStore(config.store);
|
|
27345
|
-
if (typeof config.store.init === "function")
|
|
27346
|
-
config.store.init(options);
|
|
27347
|
-
const middleware = handleAsyncErrors(async (request, response, next) => {
|
|
27348
|
-
const skip = await config.skip(request, response);
|
|
27349
|
-
if (skip) {
|
|
27350
|
-
next();
|
|
27351
|
-
return;
|
|
27233
|
+
});
|
|
27234
|
+
return router;
|
|
27235
|
+
}
|
|
27236
|
+
|
|
27237
|
+
// src/api/messaging/servers.ts
|
|
27238
|
+
import { logger as logger9, validateUuid as validateUuid10 } from "@elizaos/core";
|
|
27239
|
+
import express11 from "express";
|
|
27240
|
+
function createServersRouter(serverInstance) {
|
|
27241
|
+
const router = express11.Router();
|
|
27242
|
+
router.get("/central-servers", async (_req, res) => {
|
|
27243
|
+
try {
|
|
27244
|
+
const servers = await serverInstance.getServers();
|
|
27245
|
+
res.json({ success: true, data: { servers } });
|
|
27246
|
+
} catch (error) {
|
|
27247
|
+
logger9.error("[Messages Router /central-servers] Error fetching servers:", error instanceof Error ? error.message : String(error));
|
|
27248
|
+
res.status(500).json({ success: false, error: "Failed to fetch servers" });
|
|
27249
|
+
}
|
|
27250
|
+
});
|
|
27251
|
+
router.post("/servers", async (req, res) => {
|
|
27252
|
+
const { name, sourceType, sourceId, metadata } = req.body;
|
|
27253
|
+
if (!name || !sourceType) {
|
|
27254
|
+
return res.status(400).json({
|
|
27255
|
+
success: false,
|
|
27256
|
+
error: "Missing required fields: name, sourceType"
|
|
27257
|
+
});
|
|
27352
27258
|
}
|
|
27353
|
-
const augmentedRequest = request;
|
|
27354
|
-
const key = await config.keyGenerator(request, response);
|
|
27355
|
-
let totalHits = 0;
|
|
27356
|
-
let resetTime;
|
|
27357
27259
|
try {
|
|
27358
|
-
const
|
|
27359
|
-
|
|
27360
|
-
|
|
27260
|
+
const server = await serverInstance.createServer({
|
|
27261
|
+
name,
|
|
27262
|
+
sourceType,
|
|
27263
|
+
sourceId,
|
|
27264
|
+
metadata
|
|
27265
|
+
});
|
|
27266
|
+
res.status(201).json({ success: true, data: { server } });
|
|
27361
27267
|
} catch (error) {
|
|
27362
|
-
|
|
27363
|
-
|
|
27364
|
-
next();
|
|
27365
|
-
return;
|
|
27366
|
-
}
|
|
27367
|
-
throw error;
|
|
27268
|
+
logger9.error("[Messages Router /servers] Error creating server:", error instanceof Error ? error.message : String(error));
|
|
27269
|
+
res.status(500).json({ success: false, error: "Failed to create server" });
|
|
27368
27270
|
}
|
|
27369
|
-
|
|
27370
|
-
|
|
27371
|
-
const
|
|
27372
|
-
const
|
|
27373
|
-
|
|
27374
|
-
|
|
27375
|
-
|
|
27376
|
-
|
|
27377
|
-
|
|
27378
|
-
resetTime,
|
|
27379
|
-
key
|
|
27380
|
-
};
|
|
27381
|
-
Object.defineProperty(info, "current", {
|
|
27382
|
-
configurable: false,
|
|
27383
|
-
enumerable: false,
|
|
27384
|
-
value: totalHits
|
|
27385
|
-
});
|
|
27386
|
-
augmentedRequest[config.requestPropertyName] = info;
|
|
27387
|
-
if (config.legacyHeaders && !response.headersSent) {
|
|
27388
|
-
setLegacyHeaders(response, info);
|
|
27271
|
+
});
|
|
27272
|
+
router.post("/servers/:serverId/agents", async (req, res) => {
|
|
27273
|
+
const serverId = validateUuid10(req.params.serverId);
|
|
27274
|
+
const { agentId } = req.body;
|
|
27275
|
+
if (!serverId || !validateUuid10(agentId)) {
|
|
27276
|
+
return res.status(400).json({
|
|
27277
|
+
success: false,
|
|
27278
|
+
error: "Invalid serverId or agentId format"
|
|
27279
|
+
});
|
|
27389
27280
|
}
|
|
27390
|
-
if (
|
|
27391
|
-
|
|
27392
|
-
|
|
27393
|
-
|
|
27394
|
-
|
|
27281
|
+
if (serverId !== serverInstance.serverId) {
|
|
27282
|
+
return res.status(403).json({
|
|
27283
|
+
success: false,
|
|
27284
|
+
error: "Cannot modify agents for a different server"
|
|
27285
|
+
});
|
|
27286
|
+
}
|
|
27287
|
+
try {
|
|
27288
|
+
await serverInstance.addAgentToServer(serverId, agentId);
|
|
27289
|
+
const messageForBus = {
|
|
27290
|
+
type: "agent_added_to_server",
|
|
27291
|
+
serverId,
|
|
27292
|
+
agentId
|
|
27293
|
+
};
|
|
27294
|
+
bus_default.emit("server_agent_update", messageForBus);
|
|
27295
|
+
res.status(201).json({
|
|
27296
|
+
success: true,
|
|
27297
|
+
data: {
|
|
27298
|
+
serverId,
|
|
27299
|
+
agentId,
|
|
27300
|
+
message: "Agent added to server successfully"
|
|
27395
27301
|
}
|
|
27396
|
-
|
|
27397
|
-
|
|
27398
|
-
|
|
27399
|
-
|
|
27302
|
+
});
|
|
27303
|
+
} catch (error) {
|
|
27304
|
+
logger9.error(`[MessagesRouter] Error adding agent ${agentId} to server ${serverId}:`, error instanceof Error ? error.message : String(error));
|
|
27305
|
+
res.status(500).json({ success: false, error: "Failed to add agent to server" });
|
|
27306
|
+
}
|
|
27307
|
+
});
|
|
27308
|
+
router.delete("/servers/:serverId/agents/:agentId", async (req, res) => {
|
|
27309
|
+
const serverId = validateUuid10(req.params.serverId);
|
|
27310
|
+
const agentId = validateUuid10(req.params.agentId);
|
|
27311
|
+
if (!serverId || !agentId) {
|
|
27312
|
+
return res.status(400).json({
|
|
27313
|
+
success: false,
|
|
27314
|
+
error: "Invalid serverId or agentId format"
|
|
27315
|
+
});
|
|
27316
|
+
}
|
|
27317
|
+
if (serverId !== serverInstance.serverId) {
|
|
27318
|
+
return res.status(403).json({
|
|
27319
|
+
success: false,
|
|
27320
|
+
error: "Cannot modify agents for a different server"
|
|
27321
|
+
});
|
|
27322
|
+
}
|
|
27323
|
+
try {
|
|
27324
|
+
await serverInstance.removeAgentFromServer(serverId, agentId);
|
|
27325
|
+
const messageForBus = {
|
|
27326
|
+
type: "agent_removed_from_server",
|
|
27327
|
+
serverId,
|
|
27328
|
+
agentId
|
|
27329
|
+
};
|
|
27330
|
+
bus_default.emit("server_agent_update", messageForBus);
|
|
27331
|
+
res.status(200).json({
|
|
27332
|
+
success: true,
|
|
27333
|
+
data: {
|
|
27334
|
+
serverId,
|
|
27335
|
+
agentId,
|
|
27336
|
+
message: "Agent removed from server successfully"
|
|
27400
27337
|
}
|
|
27401
|
-
|
|
27402
|
-
|
|
27403
|
-
|
|
27404
|
-
|
|
27405
|
-
|
|
27406
|
-
|
|
27338
|
+
});
|
|
27339
|
+
} catch (error) {
|
|
27340
|
+
logger9.error(`[MessagesRouter] Error removing agent ${agentId} from server ${serverId}:`, error instanceof Error ? error.message : String(error));
|
|
27341
|
+
res.status(500).json({ success: false, error: "Failed to remove agent from server" });
|
|
27342
|
+
}
|
|
27343
|
+
});
|
|
27344
|
+
router.get("/servers/:serverId/agents", async (req, res) => {
|
|
27345
|
+
const serverId = validateUuid10(req.params.serverId);
|
|
27346
|
+
if (!serverId) {
|
|
27347
|
+
return res.status(400).json({
|
|
27348
|
+
success: false,
|
|
27349
|
+
error: "Invalid serverId format"
|
|
27350
|
+
});
|
|
27351
|
+
}
|
|
27352
|
+
if (serverId !== serverInstance.serverId) {
|
|
27353
|
+
return res.status(403).json({
|
|
27354
|
+
success: false,
|
|
27355
|
+
error: "Cannot access agents for a different server"
|
|
27356
|
+
});
|
|
27357
|
+
}
|
|
27358
|
+
try {
|
|
27359
|
+
const agents = await serverInstance.getAgentsForServer(serverId);
|
|
27360
|
+
res.json({
|
|
27361
|
+
success: true,
|
|
27362
|
+
data: {
|
|
27363
|
+
serverId,
|
|
27364
|
+
agents
|
|
27407
27365
|
}
|
|
27408
|
-
|
|
27409
|
-
|
|
27410
|
-
|
|
27366
|
+
});
|
|
27367
|
+
} catch (error) {
|
|
27368
|
+
logger9.error(`[MessagesRouter] Error fetching agents for server ${serverId}:`, error instanceof Error ? error.message : String(error));
|
|
27369
|
+
res.status(500).json({ success: false, error: "Failed to fetch server agents" });
|
|
27370
|
+
}
|
|
27371
|
+
});
|
|
27372
|
+
router.get("/agents/:agentId/servers", async (req, res) => {
|
|
27373
|
+
const agentId = validateUuid10(req.params.agentId);
|
|
27374
|
+
if (!agentId) {
|
|
27375
|
+
return res.status(400).json({
|
|
27376
|
+
success: false,
|
|
27377
|
+
error: "Invalid agentId format"
|
|
27378
|
+
});
|
|
27379
|
+
}
|
|
27380
|
+
try {
|
|
27381
|
+
const servers = await serverInstance.getServersForAgent(agentId);
|
|
27382
|
+
res.json({
|
|
27383
|
+
success: true,
|
|
27384
|
+
data: {
|
|
27385
|
+
agentId,
|
|
27386
|
+
servers
|
|
27411
27387
|
}
|
|
27412
|
-
}
|
|
27388
|
+
});
|
|
27389
|
+
} catch (error) {
|
|
27390
|
+
logger9.error(`[MessagesRouter] Error fetching servers for agent ${agentId}:`, error instanceof Error ? error.message : String(error));
|
|
27391
|
+
res.status(500).json({ success: false, error: "Failed to fetch agent servers" });
|
|
27413
27392
|
}
|
|
27414
|
-
|
|
27415
|
-
|
|
27416
|
-
|
|
27417
|
-
|
|
27418
|
-
|
|
27419
|
-
|
|
27393
|
+
});
|
|
27394
|
+
return router;
|
|
27395
|
+
}
|
|
27396
|
+
|
|
27397
|
+
// src/api/messaging/channels.ts
|
|
27398
|
+
import {
|
|
27399
|
+
composePromptFromState,
|
|
27400
|
+
ModelType,
|
|
27401
|
+
ChannelType as ChannelType2,
|
|
27402
|
+
logger as logger15,
|
|
27403
|
+
validateUuid as validateUuid13,
|
|
27404
|
+
getUploadsChannelsDir as getUploadsChannelsDir2
|
|
27405
|
+
} from "@elizaos/core";
|
|
27406
|
+
import express12 from "express";
|
|
27407
|
+
|
|
27408
|
+
// src/middleware/auth.ts
|
|
27409
|
+
import { logger as logger10 } from "@elizaos/core";
|
|
27410
|
+
function apiKeyAuthMiddleware(req, res, next) {
|
|
27411
|
+
const serverAuthToken = process.env.ELIZA_SERVER_AUTH_TOKEN;
|
|
27412
|
+
if (!serverAuthToken) {
|
|
27413
|
+
return next();
|
|
27414
|
+
}
|
|
27415
|
+
if (req.method === "OPTIONS") {
|
|
27416
|
+
return next();
|
|
27417
|
+
}
|
|
27418
|
+
const apiKey = req.headers?.["x-api-key"];
|
|
27419
|
+
if (!apiKey || apiKey !== serverAuthToken) {
|
|
27420
|
+
logger10.warn(`Unauthorized access attempt: Missing or invalid X-API-KEY from ${req.ip}`);
|
|
27421
|
+
return res.status(401).send("Unauthorized: Invalid or missing X-API-KEY");
|
|
27422
|
+
}
|
|
27423
|
+
next();
|
|
27424
|
+
}
|
|
27425
|
+
// src/middleware/security.ts
|
|
27426
|
+
import { logger as logger11 } from "@elizaos/core";
|
|
27427
|
+
var securityMiddleware = () => {
|
|
27428
|
+
return (req, res, next) => {
|
|
27429
|
+
res.setHeader("X-Content-Type-Options", "nosniff");
|
|
27430
|
+
res.setHeader("X-Frame-Options", "SAMEORIGIN");
|
|
27431
|
+
res.setHeader("X-XSS-Protection", "1; mode=block");
|
|
27432
|
+
res.setHeader("Referrer-Policy", "no-referrer");
|
|
27433
|
+
res.removeHeader("X-Powered-By");
|
|
27434
|
+
res.removeHeader("Server");
|
|
27435
|
+
const userAgent = req.get("User-Agent");
|
|
27436
|
+
const forwarded = req.get("X-Forwarded-For");
|
|
27437
|
+
const realIp = req.get("X-Real-IP");
|
|
27438
|
+
const clientIp = forwarded || realIp || req.ip;
|
|
27439
|
+
if (userAgent && (userAgent.includes("..") || userAgent.includes("<script"))) {
|
|
27440
|
+
logger11.warn(`[SECURITY] Suspicious User-Agent from ${clientIp}: ${userAgent}`);
|
|
27441
|
+
}
|
|
27442
|
+
const url = req.originalUrl || req.url;
|
|
27443
|
+
const queryString = JSON.stringify(req.query);
|
|
27444
|
+
const suspiciousIndicators = [
|
|
27445
|
+
{ pattern: "..", name: "Path traversal" },
|
|
27446
|
+
{ pattern: "<script", name: "XSS attempt" },
|
|
27447
|
+
{ pattern: "javascript:", name: "JavaScript injection" }
|
|
27448
|
+
];
|
|
27449
|
+
const sqlKeywords = ["union", "select", "drop", "delete", "insert", "update"];
|
|
27450
|
+
let hasSqlPattern = false;
|
|
27451
|
+
const lowerUrl = url.toLowerCase();
|
|
27452
|
+
const lowerQuery = queryString.toLowerCase();
|
|
27453
|
+
for (let i = 0;i < sqlKeywords.length - 1; i++) {
|
|
27454
|
+
const keyword1 = sqlKeywords[i];
|
|
27455
|
+
for (let j = i + 1;j < sqlKeywords.length; j++) {
|
|
27456
|
+
const keyword2 = sqlKeywords[j];
|
|
27457
|
+
if (lowerUrl.includes(keyword1) && lowerUrl.includes(keyword2) || lowerQuery.includes(keyword1) && lowerQuery.includes(keyword2)) {
|
|
27458
|
+
hasSqlPattern = true;
|
|
27459
|
+
break;
|
|
27420
27460
|
}
|
|
27421
|
-
};
|
|
27422
|
-
if (config.skipFailedRequests) {
|
|
27423
|
-
response.on("finish", async () => {
|
|
27424
|
-
if (!await config.requestWasSuccessful(request, response))
|
|
27425
|
-
await decrementKey();
|
|
27426
|
-
});
|
|
27427
|
-
response.on("close", async () => {
|
|
27428
|
-
if (!response.writableEnded)
|
|
27429
|
-
await decrementKey();
|
|
27430
|
-
});
|
|
27431
|
-
response.on("error", async () => {
|
|
27432
|
-
await decrementKey();
|
|
27433
|
-
});
|
|
27434
|
-
}
|
|
27435
|
-
if (config.skipSuccessfulRequests) {
|
|
27436
|
-
response.on("finish", async () => {
|
|
27437
|
-
if (await config.requestWasSuccessful(request, response))
|
|
27438
|
-
await decrementKey();
|
|
27439
|
-
});
|
|
27440
27461
|
}
|
|
27462
|
+
if (hasSqlPattern)
|
|
27463
|
+
break;
|
|
27441
27464
|
}
|
|
27442
|
-
|
|
27443
|
-
|
|
27444
|
-
|
|
27445
|
-
|
|
27465
|
+
for (const indicator of suspiciousIndicators) {
|
|
27466
|
+
if (url.includes(indicator.pattern) || queryString.includes(indicator.pattern)) {
|
|
27467
|
+
logger11.warn(`[SECURITY] ${indicator.name} detected from ${clientIp}: ${url}`);
|
|
27468
|
+
break;
|
|
27446
27469
|
}
|
|
27447
|
-
|
|
27448
|
-
|
|
27470
|
+
}
|
|
27471
|
+
if (hasSqlPattern) {
|
|
27472
|
+
logger11.warn(`[SECURITY] SQL injection pattern detected from ${clientIp}: ${url}`);
|
|
27449
27473
|
}
|
|
27450
27474
|
next();
|
|
27451
|
-
});
|
|
27452
|
-
const getThrowFn = () => {
|
|
27453
|
-
throw new Error("The current store does not support the get/getKey method");
|
|
27454
27475
|
};
|
|
27455
|
-
middleware.resetKey = config.store.resetKey.bind(config.store);
|
|
27456
|
-
middleware.getKey = typeof config.store.get === "function" ? config.store.get.bind(config.store) : getThrowFn;
|
|
27457
|
-
return middleware;
|
|
27458
27476
|
};
|
|
27459
|
-
var rate_limit_default = rateLimit;
|
|
27460
|
-
|
|
27461
27477
|
// src/middleware/rate-limit.ts
|
|
27462
27478
|
import { logger as logger13 } from "@elizaos/core";
|
|
27463
27479
|
|
|
@@ -27603,7 +27619,6 @@ var ALLOWED_MEDIA_MIME_TYPES = [
|
|
|
27603
27619
|
import multer from "multer";
|
|
27604
27620
|
import fs from "fs";
|
|
27605
27621
|
import path2 from "path";
|
|
27606
|
-
var DEFAULT_SERVER_ID3 = "00000000-0000-0000-0000-000000000000";
|
|
27607
27622
|
var channelStorage = multer.memoryStorage();
|
|
27608
27623
|
var channelUploadMiddleware = multer({
|
|
27609
27624
|
storage: channelStorage,
|
|
@@ -27647,13 +27662,19 @@ function createChannelsRouter(elizaOS, serverInstance) {
|
|
|
27647
27662
|
metadata,
|
|
27648
27663
|
source_type
|
|
27649
27664
|
} = req.body;
|
|
27650
|
-
const isValidServerId = server_id ===
|
|
27651
|
-
if (!channelIdParam || !validateUuid13(author_id) || !content || !
|
|
27665
|
+
const isValidServerId = server_id === serverInstance.serverId;
|
|
27666
|
+
if (!channelIdParam || !validateUuid13(author_id) || !content || !validateUuid13(server_id)) {
|
|
27652
27667
|
return res.status(400).json({
|
|
27653
27668
|
success: false,
|
|
27654
27669
|
error: "Missing required fields: channelId, server_id, author_id, content"
|
|
27655
27670
|
});
|
|
27656
27671
|
}
|
|
27672
|
+
if (!isValidServerId) {
|
|
27673
|
+
return res.status(403).json({
|
|
27674
|
+
success: false,
|
|
27675
|
+
error: "Forbidden: server_id does not match current server"
|
|
27676
|
+
});
|
|
27677
|
+
}
|
|
27657
27678
|
try {
|
|
27658
27679
|
logger15.info(`[Messages Router] Checking if channel ${channelIdParam} exists before creating message`);
|
|
27659
27680
|
let channelExists = false;
|
|
@@ -27799,7 +27820,7 @@ function createChannelsRouter(elizaOS, serverInstance) {
|
|
|
27799
27820
|
}
|
|
27800
27821
|
});
|
|
27801
27822
|
router.get("/central-servers/:serverId/channels", async (req, res) => {
|
|
27802
|
-
const serverId =
|
|
27823
|
+
const serverId = validateUuid13(req.params.serverId);
|
|
27803
27824
|
if (!serverId) {
|
|
27804
27825
|
return res.status(400).json({ success: false, error: "Invalid serverId" });
|
|
27805
27826
|
}
|
|
@@ -27858,7 +27879,7 @@ function createChannelsRouter(elizaOS, serverInstance) {
|
|
|
27858
27879
|
router.get("/dm-channel", async (req, res) => {
|
|
27859
27880
|
const targetUserId = validateUuid13(req.query.targetUserId);
|
|
27860
27881
|
const currentUserId = validateUuid13(req.query.currentUserId);
|
|
27861
|
-
const providedDmServerId =
|
|
27882
|
+
const providedDmServerId = validateUuid13(req.query.dmServerId);
|
|
27862
27883
|
if (!targetUserId || !currentUserId) {
|
|
27863
27884
|
res.status(400).json({ success: false, error: "Missing targetUserId or currentUserId" });
|
|
27864
27885
|
return;
|
|
@@ -27867,15 +27888,15 @@ function createChannelsRouter(elizaOS, serverInstance) {
|
|
|
27867
27888
|
res.status(400).json({ success: false, error: "Cannot create DM channel with oneself" });
|
|
27868
27889
|
return;
|
|
27869
27890
|
}
|
|
27870
|
-
let dmServerIdToUse =
|
|
27891
|
+
let dmServerIdToUse = serverInstance.serverId;
|
|
27871
27892
|
try {
|
|
27872
27893
|
if (providedDmServerId) {
|
|
27873
27894
|
const existingServer = await serverInstance.getServerById(providedDmServerId);
|
|
27874
27895
|
if (existingServer) {
|
|
27875
27896
|
dmServerIdToUse = providedDmServerId;
|
|
27876
27897
|
} else {
|
|
27877
|
-
logger15.warn(`Provided dmServerId ${providedDmServerId} not found, using
|
|
27878
|
-
dmServerIdToUse =
|
|
27898
|
+
logger15.warn(`Provided dmServerId ${providedDmServerId} not found, using current server ID.`);
|
|
27899
|
+
dmServerIdToUse = serverInstance.serverId;
|
|
27879
27900
|
}
|
|
27880
27901
|
}
|
|
27881
27902
|
const channel = await serverInstance.findOrCreateCentralDmChannel(currentUserId, targetUserId, dmServerIdToUse);
|
|
@@ -27898,13 +27919,25 @@ function createChannelsRouter(elizaOS, serverInstance) {
|
|
|
27898
27919
|
server_id,
|
|
27899
27920
|
metadata
|
|
27900
27921
|
} = req.body;
|
|
27901
|
-
|
|
27902
|
-
|
|
27922
|
+
if (!validateUuid13(server_id)) {
|
|
27923
|
+
return res.status(400).json({
|
|
27924
|
+
success: false,
|
|
27925
|
+
error: "Invalid server_id format"
|
|
27926
|
+
});
|
|
27927
|
+
}
|
|
27928
|
+
const isValidServerId = server_id === serverInstance.serverId;
|
|
27929
|
+
if (!name || !Array.isArray(participantCentralUserIds) || participantCentralUserIds.some((id) => !validateUuid13(id))) {
|
|
27903
27930
|
return res.status(400).json({
|
|
27904
27931
|
success: false,
|
|
27905
27932
|
error: 'Invalid payload. Required: name, server_id (UUID or "0"), participantCentralUserIds (array of UUIDs). Optional: type, metadata.'
|
|
27906
27933
|
});
|
|
27907
27934
|
}
|
|
27935
|
+
if (!isValidServerId) {
|
|
27936
|
+
return res.status(403).json({
|
|
27937
|
+
success: false,
|
|
27938
|
+
error: "Forbidden: server_id does not match current server"
|
|
27939
|
+
});
|
|
27940
|
+
}
|
|
27908
27941
|
try {
|
|
27909
27942
|
const channelData = {
|
|
27910
27943
|
messageServerId: server_id,
|
|
@@ -28542,7 +28575,6 @@ var DEFAULT_MAX_DURATION_MINUTES = safeParseInt(process.env.SESSION_MAX_DURATION
|
|
|
28542
28575
|
var DEFAULT_WARNING_THRESHOLD_MINUTES = safeParseInt(process.env.SESSION_WARNING_THRESHOLD_MINUTES, 5, 1, 60);
|
|
28543
28576
|
var CLEANUP_INTERVAL_MS = safeParseInt(process.env.SESSION_CLEANUP_INTERVAL_MINUTES, 5, 1, 60) * 60 * 1000;
|
|
28544
28577
|
var sessions = new Map;
|
|
28545
|
-
var DEFAULT_SERVER_ID4 = "00000000-0000-0000-0000-000000000000";
|
|
28546
28578
|
var agentTimeoutConfigs = new Map;
|
|
28547
28579
|
var activeCleanupIntervals = new Set;
|
|
28548
28580
|
var processHandlersRegistered = false;
|
|
@@ -28778,7 +28810,7 @@ function createSessionsRouter(elizaOS, serverInstance) {
|
|
|
28778
28810
|
id: channelId,
|
|
28779
28811
|
name: `session-${sessionId}`,
|
|
28780
28812
|
type: ChannelType3.DM,
|
|
28781
|
-
messageServerId:
|
|
28813
|
+
messageServerId: serverInstance.serverId,
|
|
28782
28814
|
metadata: {
|
|
28783
28815
|
sessionId,
|
|
28784
28816
|
agentId: body.agentId,
|
|
@@ -29208,7 +29240,7 @@ var JobValidation = {
|
|
|
29208
29240
|
};
|
|
29209
29241
|
|
|
29210
29242
|
// src/api/messaging/jobs.ts
|
|
29211
|
-
var
|
|
29243
|
+
var DEFAULT_SERVER_ID = "00000000-0000-0000-0000-000000000000";
|
|
29212
29244
|
var JOB_CLEANUP_INTERVAL_MS = 60000;
|
|
29213
29245
|
var ABSOLUTE_MAX_LISTENER_TIMEOUT_MS = 5 * 60 * 1000;
|
|
29214
29246
|
var MAX_JOBS_IN_MEMORY = 1e4;
|
|
@@ -29411,7 +29443,7 @@ function createJobsRouter(elizaOS, serverInstance) {
|
|
|
29411
29443
|
id: channelId,
|
|
29412
29444
|
name: `job-${jobId}`,
|
|
29413
29445
|
type: ChannelType4.DM,
|
|
29414
|
-
messageServerId:
|
|
29446
|
+
messageServerId: DEFAULT_SERVER_ID,
|
|
29415
29447
|
metadata: {
|
|
29416
29448
|
jobId,
|
|
29417
29449
|
agentId,
|
|
@@ -29448,7 +29480,7 @@ function createJobsRouter(elizaOS, serverInstance) {
|
|
|
29448
29480
|
bus_default.emit("new_message", {
|
|
29449
29481
|
id: userMessage.id,
|
|
29450
29482
|
channel_id: channelId,
|
|
29451
|
-
server_id:
|
|
29483
|
+
server_id: DEFAULT_SERVER_ID,
|
|
29452
29484
|
author_id: userId,
|
|
29453
29485
|
content: body.content,
|
|
29454
29486
|
created_at: new Date(userMessage.createdAt).getTime(),
|
|
@@ -30624,7 +30656,7 @@ import express31 from "express";
|
|
|
30624
30656
|
// package.json
|
|
30625
30657
|
var package_default = {
|
|
30626
30658
|
name: "@elizaos/server",
|
|
30627
|
-
version: "1.6.4-alpha.
|
|
30659
|
+
version: "1.6.4-alpha.17",
|
|
30628
30660
|
description: "ElizaOS Server - Core server infrastructure for ElizaOS agents",
|
|
30629
30661
|
publishConfig: {
|
|
30630
30662
|
access: "public",
|
|
@@ -30744,8 +30776,6 @@ import {
|
|
|
30744
30776
|
ChannelType as ChannelType7,
|
|
30745
30777
|
EventType
|
|
30746
30778
|
} from "@elizaos/core";
|
|
30747
|
-
var DEFAULT_SERVER_ID6 = "00000000-0000-0000-0000-000000000000";
|
|
30748
|
-
|
|
30749
30779
|
class SocketIORouter {
|
|
30750
30780
|
elizaOS;
|
|
30751
30781
|
connections;
|
|
@@ -30844,8 +30874,8 @@ class SocketIORouter {
|
|
|
30844
30874
|
}
|
|
30845
30875
|
socket.join(channelId);
|
|
30846
30876
|
logger29.info(`[SocketIO] Socket ${socket.id} joined Socket.IO channel: ${channelId}`);
|
|
30847
|
-
if (entityId && (serverId ||
|
|
30848
|
-
const finalServerId = serverId ||
|
|
30877
|
+
if (entityId && (serverId || this.serverInstance.serverId)) {
|
|
30878
|
+
const finalServerId = serverId || this.serverInstance.serverId;
|
|
30849
30879
|
const isDm = metadata?.isDm || metadata?.channelType === ChannelType7.DM;
|
|
30850
30880
|
logger29.info(`[SocketIO] Emitting ENTITY_JOINED event for entityId: ${entityId}, serverId: ${finalServerId}, isDm: ${isDm}`);
|
|
30851
30881
|
const runtime = this.elizaOS.getAgents()[0];
|
|
@@ -30867,7 +30897,7 @@ class SocketIORouter {
|
|
|
30867
30897
|
logger29.warn(`[SocketIO] No runtime available to emit ENTITY_JOINED event`);
|
|
30868
30898
|
}
|
|
30869
30899
|
} else {
|
|
30870
|
-
logger29.debug(`[SocketIO] Missing entityId (${entityId}) or serverId (${serverId ||
|
|
30900
|
+
logger29.debug(`[SocketIO] Missing entityId (${entityId}) or serverId (${serverId || this.serverInstance.serverId}) - not emitting ENTITY_JOINED event`);
|
|
30871
30901
|
}
|
|
30872
30902
|
const successMessage = `Socket ${socket.id} successfully joined channel ${channelId}.`;
|
|
30873
30903
|
const responsePayload = {
|
|
@@ -30885,7 +30915,7 @@ class SocketIORouter {
|
|
|
30885
30915
|
const { senderId, senderName, message, serverId, source, metadata, attachments } = payload;
|
|
30886
30916
|
logger29.info(`[SocketIO ${socket.id}] Received SEND_MESSAGE for central submission: channel ${channelId} from ${senderName || senderId}`);
|
|
30887
30917
|
logger29.info(`[SocketIO ${socket.id}] Full payload for debugging:`, JSON.stringify(payload, null, 2));
|
|
30888
|
-
const isValidServerId = serverId ===
|
|
30918
|
+
const isValidServerId = serverId === this.serverInstance.serverId || validateUuid23(serverId);
|
|
30889
30919
|
if (!validateUuid23(channelId) || !isValidServerId || !validateUuid23(senderId) || !message) {
|
|
30890
30920
|
this.sendErrorResponse(socket, `For SEND_MESSAGE: channelId, serverId (server_id), senderId (author_id), and message are required.`);
|
|
30891
30921
|
return;
|
|
@@ -31313,16 +31343,27 @@ import {
|
|
|
31313
31343
|
validateUuid as validateUuid25
|
|
31314
31344
|
} from "@elizaos/core";
|
|
31315
31345
|
var globalElizaOS = null;
|
|
31346
|
+
var globalAgentServer = null;
|
|
31316
31347
|
function setGlobalElizaOS(elizaOS) {
|
|
31317
31348
|
globalElizaOS = elizaOS;
|
|
31318
31349
|
logger31.info("[MessageBusService] Global ElizaOS instance set");
|
|
31319
31350
|
}
|
|
31351
|
+
function setGlobalAgentServer(agentServer) {
|
|
31352
|
+
globalAgentServer = agentServer;
|
|
31353
|
+
logger31.info("[MessageBusService] Global AgentServer instance set");
|
|
31354
|
+
}
|
|
31320
31355
|
function getGlobalElizaOS() {
|
|
31321
31356
|
if (!globalElizaOS) {
|
|
31322
31357
|
throw new Error("ElizaOS not initialized. Call setGlobalElizaOS() before using MessageBusService.");
|
|
31323
31358
|
}
|
|
31324
31359
|
return globalElizaOS;
|
|
31325
31360
|
}
|
|
31361
|
+
function getGlobalAgentServer() {
|
|
31362
|
+
if (!globalAgentServer) {
|
|
31363
|
+
throw new Error("AgentServer not initialized. Call setGlobalAgentServer() before using MessageBusService.");
|
|
31364
|
+
}
|
|
31365
|
+
return globalAgentServer;
|
|
31366
|
+
}
|
|
31326
31367
|
|
|
31327
31368
|
class MessageBusService extends Service {
|
|
31328
31369
|
static serviceType = "message-bus-service";
|
|
@@ -31332,8 +31373,10 @@ class MessageBusService extends Service {
|
|
|
31332
31373
|
boundHandleMessageDeleted;
|
|
31333
31374
|
boundHandleChannelCleared;
|
|
31334
31375
|
subscribedServers = new Set;
|
|
31376
|
+
serverInstance;
|
|
31335
31377
|
constructor(runtime) {
|
|
31336
31378
|
super(runtime);
|
|
31379
|
+
this.serverInstance = getGlobalAgentServer();
|
|
31337
31380
|
this.boundHandleIncomingMessage = (data) => {
|
|
31338
31381
|
this.handleIncomingMessage(data).catch((error) => {
|
|
31339
31382
|
logger31.error(`[${this.runtime.character.name}] Error handling incoming message:`, error instanceof Error ? error.message : String(error));
|
|
@@ -31366,9 +31409,8 @@ class MessageBusService extends Service {
|
|
|
31366
31409
|
try {
|
|
31367
31410
|
const serverApiUrl = this.getCentralMessageServerUrl();
|
|
31368
31411
|
this.validChannelIds.clear();
|
|
31369
|
-
const DEFAULT_SERVER_ID7 = "00000000-0000-0000-0000-000000000000";
|
|
31370
31412
|
const serversToCheck = new Set(this.subscribedServers);
|
|
31371
|
-
serversToCheck.add(
|
|
31413
|
+
serversToCheck.add(this.serverInstance.serverId);
|
|
31372
31414
|
for (const serverId of serversToCheck) {
|
|
31373
31415
|
try {
|
|
31374
31416
|
const channelsUrl = new URL(`/api/messaging/central-servers/${encodeURIComponent(serverId)}/channels`, serverApiUrl);
|
|
@@ -31444,20 +31486,17 @@ class MessageBusService extends Service {
|
|
|
31444
31486
|
const data = await response.json();
|
|
31445
31487
|
if (data.success && data.data?.servers) {
|
|
31446
31488
|
this.subscribedServers = new Set(data.data.servers);
|
|
31447
|
-
|
|
31448
|
-
this.subscribedServers.
|
|
31449
|
-
logger31.info(`[${this.runtime.character.name}] MessageBusService: Agent is subscribed to ${this.subscribedServers.size} servers (including default server)`);
|
|
31489
|
+
this.subscribedServers.add(this.serverInstance.serverId);
|
|
31490
|
+
logger31.info(`[${this.runtime.character.name}] MessageBusService: Agent is subscribed to ${this.subscribedServers.size} servers (including server ${this.serverInstance.serverId})`);
|
|
31450
31491
|
}
|
|
31451
31492
|
} else {
|
|
31452
|
-
|
|
31453
|
-
this.
|
|
31454
|
-
logger31.warn(`[${this.runtime.character.name}] MessageBusService: Failed to fetch agent servers, but added default server`);
|
|
31493
|
+
this.subscribedServers.add(this.serverInstance.serverId);
|
|
31494
|
+
logger31.warn(`[${this.runtime.character.name}] MessageBusService: Failed to fetch agent servers, but added server ${this.serverInstance.serverId}`);
|
|
31455
31495
|
}
|
|
31456
31496
|
} catch (error) {
|
|
31457
31497
|
logger31.error(`[${this.runtime.character.name}] MessageBusService: Error fetching agent servers:`, error instanceof Error ? error.message : String(error));
|
|
31458
|
-
|
|
31459
|
-
this.
|
|
31460
|
-
logger31.info(`[${this.runtime.character.name}] MessageBusService: Added default server after error`);
|
|
31498
|
+
this.subscribedServers.add(this.serverInstance.serverId);
|
|
31499
|
+
logger31.info(`[${this.runtime.character.name}] MessageBusService: Added server ${this.serverInstance.serverId} after error`);
|
|
31461
31500
|
}
|
|
31462
31501
|
}
|
|
31463
31502
|
async handleServerAgentUpdate(data) {
|
|
@@ -48493,8 +48532,632 @@ function _init2(options = {}, getDefaultIntegrationsImpl) {
|
|
|
48493
48532
|
return client;
|
|
48494
48533
|
}
|
|
48495
48534
|
// src/index.ts
|
|
48496
|
-
import sqlPlugin, {
|
|
48535
|
+
import sqlPlugin, {
|
|
48536
|
+
createDatabaseAdapter,
|
|
48537
|
+
DatabaseMigrationService,
|
|
48538
|
+
installRLSFunctions,
|
|
48539
|
+
getOrCreateRlsOwner,
|
|
48540
|
+
setOwnerContext,
|
|
48541
|
+
assignAgentToOwner,
|
|
48542
|
+
applyRLSToNewTables,
|
|
48543
|
+
uninstallRLS
|
|
48544
|
+
} from "@elizaos/plugin-sql";
|
|
48497
48545
|
import { encryptedCharacter, stringToUuid as stringToUuid2 } from "@elizaos/core";
|
|
48546
|
+
|
|
48547
|
+
// ../../node_modules/drizzle-orm/entity.js
|
|
48548
|
+
var entityKind = Symbol.for("drizzle:entityKind");
|
|
48549
|
+
var hasOwnEntityKind = Symbol.for("drizzle:hasOwnEntityKind");
|
|
48550
|
+
function is(value, type) {
|
|
48551
|
+
if (!value || typeof value !== "object") {
|
|
48552
|
+
return false;
|
|
48553
|
+
}
|
|
48554
|
+
if (value instanceof type) {
|
|
48555
|
+
return true;
|
|
48556
|
+
}
|
|
48557
|
+
if (!Object.prototype.hasOwnProperty.call(type, entityKind)) {
|
|
48558
|
+
throw new Error(`Class "${type.name ?? "<unknown>"}" doesn't look like a Drizzle entity. If this is incorrect and the class is provided by Drizzle, please report this as a bug.`);
|
|
48559
|
+
}
|
|
48560
|
+
let cls = Object.getPrototypeOf(value).constructor;
|
|
48561
|
+
if (cls) {
|
|
48562
|
+
while (cls) {
|
|
48563
|
+
if (entityKind in cls && cls[entityKind] === type[entityKind]) {
|
|
48564
|
+
return true;
|
|
48565
|
+
}
|
|
48566
|
+
cls = Object.getPrototypeOf(cls);
|
|
48567
|
+
}
|
|
48568
|
+
}
|
|
48569
|
+
return false;
|
|
48570
|
+
}
|
|
48571
|
+
|
|
48572
|
+
// ../../node_modules/drizzle-orm/column.js
|
|
48573
|
+
class Column {
|
|
48574
|
+
constructor(table, config3) {
|
|
48575
|
+
this.table = table;
|
|
48576
|
+
this.config = config3;
|
|
48577
|
+
this.name = config3.name;
|
|
48578
|
+
this.keyAsName = config3.keyAsName;
|
|
48579
|
+
this.notNull = config3.notNull;
|
|
48580
|
+
this.default = config3.default;
|
|
48581
|
+
this.defaultFn = config3.defaultFn;
|
|
48582
|
+
this.onUpdateFn = config3.onUpdateFn;
|
|
48583
|
+
this.hasDefault = config3.hasDefault;
|
|
48584
|
+
this.primary = config3.primaryKey;
|
|
48585
|
+
this.isUnique = config3.isUnique;
|
|
48586
|
+
this.uniqueName = config3.uniqueName;
|
|
48587
|
+
this.uniqueType = config3.uniqueType;
|
|
48588
|
+
this.dataType = config3.dataType;
|
|
48589
|
+
this.columnType = config3.columnType;
|
|
48590
|
+
this.generated = config3.generated;
|
|
48591
|
+
this.generatedIdentity = config3.generatedIdentity;
|
|
48592
|
+
}
|
|
48593
|
+
static [entityKind] = "Column";
|
|
48594
|
+
name;
|
|
48595
|
+
keyAsName;
|
|
48596
|
+
primary;
|
|
48597
|
+
notNull;
|
|
48598
|
+
default;
|
|
48599
|
+
defaultFn;
|
|
48600
|
+
onUpdateFn;
|
|
48601
|
+
hasDefault;
|
|
48602
|
+
isUnique;
|
|
48603
|
+
uniqueName;
|
|
48604
|
+
uniqueType;
|
|
48605
|
+
dataType;
|
|
48606
|
+
columnType;
|
|
48607
|
+
enumValues = undefined;
|
|
48608
|
+
generated = undefined;
|
|
48609
|
+
generatedIdentity = undefined;
|
|
48610
|
+
config;
|
|
48611
|
+
mapFromDriverValue(value) {
|
|
48612
|
+
return value;
|
|
48613
|
+
}
|
|
48614
|
+
mapToDriverValue(value) {
|
|
48615
|
+
return value;
|
|
48616
|
+
}
|
|
48617
|
+
shouldDisableInsert() {
|
|
48618
|
+
return this.config.generated !== undefined && this.config.generated.type !== "byDefault";
|
|
48619
|
+
}
|
|
48620
|
+
}
|
|
48621
|
+
|
|
48622
|
+
// ../../node_modules/drizzle-orm/table.utils.js
|
|
48623
|
+
var TableName = Symbol.for("drizzle:Name");
|
|
48624
|
+
|
|
48625
|
+
// ../../node_modules/drizzle-orm/tracing-utils.js
|
|
48626
|
+
function iife(fn, ...args) {
|
|
48627
|
+
return fn(...args);
|
|
48628
|
+
}
|
|
48629
|
+
|
|
48630
|
+
// ../../node_modules/drizzle-orm/pg-core/unique-constraint.js
|
|
48631
|
+
function uniqueKeyName(table, columns) {
|
|
48632
|
+
return `${table[TableName]}_${columns.join("_")}_unique`;
|
|
48633
|
+
}
|
|
48634
|
+
|
|
48635
|
+
// ../../node_modules/drizzle-orm/pg-core/columns/common.js
|
|
48636
|
+
class PgColumn extends Column {
|
|
48637
|
+
constructor(table, config3) {
|
|
48638
|
+
if (!config3.uniqueName) {
|
|
48639
|
+
config3.uniqueName = uniqueKeyName(table, [config3.name]);
|
|
48640
|
+
}
|
|
48641
|
+
super(table, config3);
|
|
48642
|
+
this.table = table;
|
|
48643
|
+
}
|
|
48644
|
+
static [entityKind] = "PgColumn";
|
|
48645
|
+
}
|
|
48646
|
+
|
|
48647
|
+
class ExtraConfigColumn extends PgColumn {
|
|
48648
|
+
static [entityKind] = "ExtraConfigColumn";
|
|
48649
|
+
getSQLType() {
|
|
48650
|
+
return this.getSQLType();
|
|
48651
|
+
}
|
|
48652
|
+
indexConfig = {
|
|
48653
|
+
order: this.config.order ?? "asc",
|
|
48654
|
+
nulls: this.config.nulls ?? "last",
|
|
48655
|
+
opClass: this.config.opClass
|
|
48656
|
+
};
|
|
48657
|
+
defaultConfig = {
|
|
48658
|
+
order: "asc",
|
|
48659
|
+
nulls: "last",
|
|
48660
|
+
opClass: undefined
|
|
48661
|
+
};
|
|
48662
|
+
asc() {
|
|
48663
|
+
this.indexConfig.order = "asc";
|
|
48664
|
+
return this;
|
|
48665
|
+
}
|
|
48666
|
+
desc() {
|
|
48667
|
+
this.indexConfig.order = "desc";
|
|
48668
|
+
return this;
|
|
48669
|
+
}
|
|
48670
|
+
nullsFirst() {
|
|
48671
|
+
this.indexConfig.nulls = "first";
|
|
48672
|
+
return this;
|
|
48673
|
+
}
|
|
48674
|
+
nullsLast() {
|
|
48675
|
+
this.indexConfig.nulls = "last";
|
|
48676
|
+
return this;
|
|
48677
|
+
}
|
|
48678
|
+
op(opClass) {
|
|
48679
|
+
this.indexConfig.opClass = opClass;
|
|
48680
|
+
return this;
|
|
48681
|
+
}
|
|
48682
|
+
}
|
|
48683
|
+
|
|
48684
|
+
// ../../node_modules/drizzle-orm/pg-core/columns/enum.js
|
|
48685
|
+
class PgEnumObjectColumn extends PgColumn {
|
|
48686
|
+
static [entityKind] = "PgEnumObjectColumn";
|
|
48687
|
+
enum;
|
|
48688
|
+
enumValues = this.config.enum.enumValues;
|
|
48689
|
+
constructor(table, config3) {
|
|
48690
|
+
super(table, config3);
|
|
48691
|
+
this.enum = config3.enum;
|
|
48692
|
+
}
|
|
48693
|
+
getSQLType() {
|
|
48694
|
+
return this.enum.enumName;
|
|
48695
|
+
}
|
|
48696
|
+
}
|
|
48697
|
+
var isPgEnumSym = Symbol.for("drizzle:isPgEnum");
|
|
48698
|
+
function isPgEnum(obj) {
|
|
48699
|
+
return !!obj && typeof obj === "function" && isPgEnumSym in obj && obj[isPgEnumSym] === true;
|
|
48700
|
+
}
|
|
48701
|
+
class PgEnumColumn extends PgColumn {
|
|
48702
|
+
static [entityKind] = "PgEnumColumn";
|
|
48703
|
+
enum = this.config.enum;
|
|
48704
|
+
enumValues = this.config.enum.enumValues;
|
|
48705
|
+
constructor(table, config3) {
|
|
48706
|
+
super(table, config3);
|
|
48707
|
+
this.enum = config3.enum;
|
|
48708
|
+
}
|
|
48709
|
+
getSQLType() {
|
|
48710
|
+
return this.enum.enumName;
|
|
48711
|
+
}
|
|
48712
|
+
}
|
|
48713
|
+
|
|
48714
|
+
// ../../node_modules/drizzle-orm/subquery.js
|
|
48715
|
+
class Subquery {
|
|
48716
|
+
static [entityKind] = "Subquery";
|
|
48717
|
+
constructor(sql, fields, alias, isWith = false, usedTables = []) {
|
|
48718
|
+
this._ = {
|
|
48719
|
+
brand: "Subquery",
|
|
48720
|
+
sql,
|
|
48721
|
+
selectedFields: fields,
|
|
48722
|
+
alias,
|
|
48723
|
+
isWith,
|
|
48724
|
+
usedTables
|
|
48725
|
+
};
|
|
48726
|
+
}
|
|
48727
|
+
}
|
|
48728
|
+
|
|
48729
|
+
// ../../node_modules/drizzle-orm/version.js
|
|
48730
|
+
var version = "0.44.7";
|
|
48731
|
+
|
|
48732
|
+
// ../../node_modules/drizzle-orm/tracing.js
|
|
48733
|
+
var otel;
|
|
48734
|
+
var rawTracer;
|
|
48735
|
+
var tracer = {
|
|
48736
|
+
startActiveSpan(name, fn) {
|
|
48737
|
+
if (!otel) {
|
|
48738
|
+
return fn();
|
|
48739
|
+
}
|
|
48740
|
+
if (!rawTracer) {
|
|
48741
|
+
rawTracer = otel.trace.getTracer("drizzle-orm", version);
|
|
48742
|
+
}
|
|
48743
|
+
return iife((otel2, rawTracer2) => rawTracer2.startActiveSpan(name, (span) => {
|
|
48744
|
+
try {
|
|
48745
|
+
return fn(span);
|
|
48746
|
+
} catch (e) {
|
|
48747
|
+
span.setStatus({
|
|
48748
|
+
code: otel2.SpanStatusCode.ERROR,
|
|
48749
|
+
message: e instanceof Error ? e.message : "Unknown error"
|
|
48750
|
+
});
|
|
48751
|
+
throw e;
|
|
48752
|
+
} finally {
|
|
48753
|
+
span.end();
|
|
48754
|
+
}
|
|
48755
|
+
}), otel, rawTracer);
|
|
48756
|
+
}
|
|
48757
|
+
};
|
|
48758
|
+
|
|
48759
|
+
// ../../node_modules/drizzle-orm/view-common.js
|
|
48760
|
+
var ViewBaseConfig = Symbol.for("drizzle:ViewBaseConfig");
|
|
48761
|
+
|
|
48762
|
+
// ../../node_modules/drizzle-orm/table.js
|
|
48763
|
+
var Schema = Symbol.for("drizzle:Schema");
|
|
48764
|
+
var Columns = Symbol.for("drizzle:Columns");
|
|
48765
|
+
var ExtraConfigColumns = Symbol.for("drizzle:ExtraConfigColumns");
|
|
48766
|
+
var OriginalName = Symbol.for("drizzle:OriginalName");
|
|
48767
|
+
var BaseName = Symbol.for("drizzle:BaseName");
|
|
48768
|
+
var IsAlias = Symbol.for("drizzle:IsAlias");
|
|
48769
|
+
var ExtraConfigBuilder = Symbol.for("drizzle:ExtraConfigBuilder");
|
|
48770
|
+
var IsDrizzleTable = Symbol.for("drizzle:IsDrizzleTable");
|
|
48771
|
+
|
|
48772
|
+
class Table {
|
|
48773
|
+
static [entityKind] = "Table";
|
|
48774
|
+
static Symbol = {
|
|
48775
|
+
Name: TableName,
|
|
48776
|
+
Schema,
|
|
48777
|
+
OriginalName,
|
|
48778
|
+
Columns,
|
|
48779
|
+
ExtraConfigColumns,
|
|
48780
|
+
BaseName,
|
|
48781
|
+
IsAlias,
|
|
48782
|
+
ExtraConfigBuilder
|
|
48783
|
+
};
|
|
48784
|
+
[TableName];
|
|
48785
|
+
[OriginalName];
|
|
48786
|
+
[Schema];
|
|
48787
|
+
[Columns];
|
|
48788
|
+
[ExtraConfigColumns];
|
|
48789
|
+
[BaseName];
|
|
48790
|
+
[IsAlias] = false;
|
|
48791
|
+
[IsDrizzleTable] = true;
|
|
48792
|
+
[ExtraConfigBuilder] = undefined;
|
|
48793
|
+
constructor(name, schema, baseName) {
|
|
48794
|
+
this[TableName] = this[OriginalName] = name;
|
|
48795
|
+
this[Schema] = schema;
|
|
48796
|
+
this[BaseName] = baseName;
|
|
48797
|
+
}
|
|
48798
|
+
}
|
|
48799
|
+
|
|
48800
|
+
// ../../node_modules/drizzle-orm/sql/sql.js
|
|
48801
|
+
function isSQLWrapper(value) {
|
|
48802
|
+
return value !== null && value !== undefined && typeof value.getSQL === "function";
|
|
48803
|
+
}
|
|
48804
|
+
function mergeQueries(queries) {
|
|
48805
|
+
const result = { sql: "", params: [] };
|
|
48806
|
+
for (const query of queries) {
|
|
48807
|
+
result.sql += query.sql;
|
|
48808
|
+
result.params.push(...query.params);
|
|
48809
|
+
if (query.typings?.length) {
|
|
48810
|
+
if (!result.typings) {
|
|
48811
|
+
result.typings = [];
|
|
48812
|
+
}
|
|
48813
|
+
result.typings.push(...query.typings);
|
|
48814
|
+
}
|
|
48815
|
+
}
|
|
48816
|
+
return result;
|
|
48817
|
+
}
|
|
48818
|
+
|
|
48819
|
+
class StringChunk {
|
|
48820
|
+
static [entityKind] = "StringChunk";
|
|
48821
|
+
value;
|
|
48822
|
+
constructor(value) {
|
|
48823
|
+
this.value = Array.isArray(value) ? value : [value];
|
|
48824
|
+
}
|
|
48825
|
+
getSQL() {
|
|
48826
|
+
return new SQL([this]);
|
|
48827
|
+
}
|
|
48828
|
+
}
|
|
48829
|
+
|
|
48830
|
+
class SQL {
|
|
48831
|
+
constructor(queryChunks) {
|
|
48832
|
+
this.queryChunks = queryChunks;
|
|
48833
|
+
for (const chunk of queryChunks) {
|
|
48834
|
+
if (is(chunk, Table)) {
|
|
48835
|
+
const schemaName = chunk[Table.Symbol.Schema];
|
|
48836
|
+
this.usedTables.push(schemaName === undefined ? chunk[Table.Symbol.Name] : schemaName + "." + chunk[Table.Symbol.Name]);
|
|
48837
|
+
}
|
|
48838
|
+
}
|
|
48839
|
+
}
|
|
48840
|
+
static [entityKind] = "SQL";
|
|
48841
|
+
decoder = noopDecoder;
|
|
48842
|
+
shouldInlineParams = false;
|
|
48843
|
+
usedTables = [];
|
|
48844
|
+
append(query) {
|
|
48845
|
+
this.queryChunks.push(...query.queryChunks);
|
|
48846
|
+
return this;
|
|
48847
|
+
}
|
|
48848
|
+
toQuery(config3) {
|
|
48849
|
+
return tracer.startActiveSpan("drizzle.buildSQL", (span) => {
|
|
48850
|
+
const query = this.buildQueryFromSourceParams(this.queryChunks, config3);
|
|
48851
|
+
span?.setAttributes({
|
|
48852
|
+
"drizzle.query.text": query.sql,
|
|
48853
|
+
"drizzle.query.params": JSON.stringify(query.params)
|
|
48854
|
+
});
|
|
48855
|
+
return query;
|
|
48856
|
+
});
|
|
48857
|
+
}
|
|
48858
|
+
buildQueryFromSourceParams(chunks, _config) {
|
|
48859
|
+
const config3 = Object.assign({}, _config, {
|
|
48860
|
+
inlineParams: _config.inlineParams || this.shouldInlineParams,
|
|
48861
|
+
paramStartIndex: _config.paramStartIndex || { value: 0 }
|
|
48862
|
+
});
|
|
48863
|
+
const {
|
|
48864
|
+
casing,
|
|
48865
|
+
escapeName,
|
|
48866
|
+
escapeParam,
|
|
48867
|
+
prepareTyping,
|
|
48868
|
+
inlineParams,
|
|
48869
|
+
paramStartIndex
|
|
48870
|
+
} = config3;
|
|
48871
|
+
return mergeQueries(chunks.map((chunk) => {
|
|
48872
|
+
if (is(chunk, StringChunk)) {
|
|
48873
|
+
return { sql: chunk.value.join(""), params: [] };
|
|
48874
|
+
}
|
|
48875
|
+
if (is(chunk, Name)) {
|
|
48876
|
+
return { sql: escapeName(chunk.value), params: [] };
|
|
48877
|
+
}
|
|
48878
|
+
if (chunk === undefined) {
|
|
48879
|
+
return { sql: "", params: [] };
|
|
48880
|
+
}
|
|
48881
|
+
if (Array.isArray(chunk)) {
|
|
48882
|
+
const result = [new StringChunk("(")];
|
|
48883
|
+
for (const [i, p] of chunk.entries()) {
|
|
48884
|
+
result.push(p);
|
|
48885
|
+
if (i < chunk.length - 1) {
|
|
48886
|
+
result.push(new StringChunk(", "));
|
|
48887
|
+
}
|
|
48888
|
+
}
|
|
48889
|
+
result.push(new StringChunk(")"));
|
|
48890
|
+
return this.buildQueryFromSourceParams(result, config3);
|
|
48891
|
+
}
|
|
48892
|
+
if (is(chunk, SQL)) {
|
|
48893
|
+
return this.buildQueryFromSourceParams(chunk.queryChunks, {
|
|
48894
|
+
...config3,
|
|
48895
|
+
inlineParams: inlineParams || chunk.shouldInlineParams
|
|
48896
|
+
});
|
|
48897
|
+
}
|
|
48898
|
+
if (is(chunk, Table)) {
|
|
48899
|
+
const schemaName = chunk[Table.Symbol.Schema];
|
|
48900
|
+
const tableName = chunk[Table.Symbol.Name];
|
|
48901
|
+
return {
|
|
48902
|
+
sql: schemaName === undefined || chunk[IsAlias] ? escapeName(tableName) : escapeName(schemaName) + "." + escapeName(tableName),
|
|
48903
|
+
params: []
|
|
48904
|
+
};
|
|
48905
|
+
}
|
|
48906
|
+
if (is(chunk, Column)) {
|
|
48907
|
+
const columnName = casing.getColumnCasing(chunk);
|
|
48908
|
+
if (_config.invokeSource === "indexes") {
|
|
48909
|
+
return { sql: escapeName(columnName), params: [] };
|
|
48910
|
+
}
|
|
48911
|
+
const schemaName = chunk.table[Table.Symbol.Schema];
|
|
48912
|
+
return {
|
|
48913
|
+
sql: chunk.table[IsAlias] || schemaName === undefined ? escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName) : escapeName(schemaName) + "." + escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName),
|
|
48914
|
+
params: []
|
|
48915
|
+
};
|
|
48916
|
+
}
|
|
48917
|
+
if (is(chunk, View)) {
|
|
48918
|
+
const schemaName = chunk[ViewBaseConfig].schema;
|
|
48919
|
+
const viewName = chunk[ViewBaseConfig].name;
|
|
48920
|
+
return {
|
|
48921
|
+
sql: schemaName === undefined || chunk[ViewBaseConfig].isAlias ? escapeName(viewName) : escapeName(schemaName) + "." + escapeName(viewName),
|
|
48922
|
+
params: []
|
|
48923
|
+
};
|
|
48924
|
+
}
|
|
48925
|
+
if (is(chunk, Param)) {
|
|
48926
|
+
if (is(chunk.value, Placeholder)) {
|
|
48927
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
48928
|
+
}
|
|
48929
|
+
const mappedValue = chunk.value === null ? null : chunk.encoder.mapToDriverValue(chunk.value);
|
|
48930
|
+
if (is(mappedValue, SQL)) {
|
|
48931
|
+
return this.buildQueryFromSourceParams([mappedValue], config3);
|
|
48932
|
+
}
|
|
48933
|
+
if (inlineParams) {
|
|
48934
|
+
return { sql: this.mapInlineParam(mappedValue, config3), params: [] };
|
|
48935
|
+
}
|
|
48936
|
+
let typings = ["none"];
|
|
48937
|
+
if (prepareTyping) {
|
|
48938
|
+
typings = [prepareTyping(chunk.encoder)];
|
|
48939
|
+
}
|
|
48940
|
+
return { sql: escapeParam(paramStartIndex.value++, mappedValue), params: [mappedValue], typings };
|
|
48941
|
+
}
|
|
48942
|
+
if (is(chunk, Placeholder)) {
|
|
48943
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
48944
|
+
}
|
|
48945
|
+
if (is(chunk, SQL.Aliased) && chunk.fieldAlias !== undefined) {
|
|
48946
|
+
return { sql: escapeName(chunk.fieldAlias), params: [] };
|
|
48947
|
+
}
|
|
48948
|
+
if (is(chunk, Subquery)) {
|
|
48949
|
+
if (chunk._.isWith) {
|
|
48950
|
+
return { sql: escapeName(chunk._.alias), params: [] };
|
|
48951
|
+
}
|
|
48952
|
+
return this.buildQueryFromSourceParams([
|
|
48953
|
+
new StringChunk("("),
|
|
48954
|
+
chunk._.sql,
|
|
48955
|
+
new StringChunk(") "),
|
|
48956
|
+
new Name(chunk._.alias)
|
|
48957
|
+
], config3);
|
|
48958
|
+
}
|
|
48959
|
+
if (isPgEnum(chunk)) {
|
|
48960
|
+
if (chunk.schema) {
|
|
48961
|
+
return { sql: escapeName(chunk.schema) + "." + escapeName(chunk.enumName), params: [] };
|
|
48962
|
+
}
|
|
48963
|
+
return { sql: escapeName(chunk.enumName), params: [] };
|
|
48964
|
+
}
|
|
48965
|
+
if (isSQLWrapper(chunk)) {
|
|
48966
|
+
if (chunk.shouldOmitSQLParens?.()) {
|
|
48967
|
+
return this.buildQueryFromSourceParams([chunk.getSQL()], config3);
|
|
48968
|
+
}
|
|
48969
|
+
return this.buildQueryFromSourceParams([
|
|
48970
|
+
new StringChunk("("),
|
|
48971
|
+
chunk.getSQL(),
|
|
48972
|
+
new StringChunk(")")
|
|
48973
|
+
], config3);
|
|
48974
|
+
}
|
|
48975
|
+
if (inlineParams) {
|
|
48976
|
+
return { sql: this.mapInlineParam(chunk, config3), params: [] };
|
|
48977
|
+
}
|
|
48978
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
48979
|
+
}));
|
|
48980
|
+
}
|
|
48981
|
+
mapInlineParam(chunk, { escapeString }) {
|
|
48982
|
+
if (chunk === null) {
|
|
48983
|
+
return "null";
|
|
48984
|
+
}
|
|
48985
|
+
if (typeof chunk === "number" || typeof chunk === "boolean") {
|
|
48986
|
+
return chunk.toString();
|
|
48987
|
+
}
|
|
48988
|
+
if (typeof chunk === "string") {
|
|
48989
|
+
return escapeString(chunk);
|
|
48990
|
+
}
|
|
48991
|
+
if (typeof chunk === "object") {
|
|
48992
|
+
const mappedValueAsString = chunk.toString();
|
|
48993
|
+
if (mappedValueAsString === "[object Object]") {
|
|
48994
|
+
return escapeString(JSON.stringify(chunk));
|
|
48995
|
+
}
|
|
48996
|
+
return escapeString(mappedValueAsString);
|
|
48997
|
+
}
|
|
48998
|
+
throw new Error("Unexpected param value: " + chunk);
|
|
48999
|
+
}
|
|
49000
|
+
getSQL() {
|
|
49001
|
+
return this;
|
|
49002
|
+
}
|
|
49003
|
+
as(alias) {
|
|
49004
|
+
if (alias === undefined) {
|
|
49005
|
+
return this;
|
|
49006
|
+
}
|
|
49007
|
+
return new SQL.Aliased(this, alias);
|
|
49008
|
+
}
|
|
49009
|
+
mapWith(decoder) {
|
|
49010
|
+
this.decoder = typeof decoder === "function" ? { mapFromDriverValue: decoder } : decoder;
|
|
49011
|
+
return this;
|
|
49012
|
+
}
|
|
49013
|
+
inlineParams() {
|
|
49014
|
+
this.shouldInlineParams = true;
|
|
49015
|
+
return this;
|
|
49016
|
+
}
|
|
49017
|
+
if(condition) {
|
|
49018
|
+
return condition ? this : undefined;
|
|
49019
|
+
}
|
|
49020
|
+
}
|
|
49021
|
+
|
|
49022
|
+
class Name {
|
|
49023
|
+
constructor(value) {
|
|
49024
|
+
this.value = value;
|
|
49025
|
+
}
|
|
49026
|
+
static [entityKind] = "Name";
|
|
49027
|
+
brand;
|
|
49028
|
+
getSQL() {
|
|
49029
|
+
return new SQL([this]);
|
|
49030
|
+
}
|
|
49031
|
+
}
|
|
49032
|
+
var noopDecoder = {
|
|
49033
|
+
mapFromDriverValue: (value) => value
|
|
49034
|
+
};
|
|
49035
|
+
var noopEncoder = {
|
|
49036
|
+
mapToDriverValue: (value) => value
|
|
49037
|
+
};
|
|
49038
|
+
var noopMapper = {
|
|
49039
|
+
...noopDecoder,
|
|
49040
|
+
...noopEncoder
|
|
49041
|
+
};
|
|
49042
|
+
|
|
49043
|
+
class Param {
|
|
49044
|
+
constructor(value, encoder = noopEncoder) {
|
|
49045
|
+
this.value = value;
|
|
49046
|
+
this.encoder = encoder;
|
|
49047
|
+
}
|
|
49048
|
+
static [entityKind] = "Param";
|
|
49049
|
+
brand;
|
|
49050
|
+
getSQL() {
|
|
49051
|
+
return new SQL([this]);
|
|
49052
|
+
}
|
|
49053
|
+
}
|
|
49054
|
+
function sql(strings, ...params) {
|
|
49055
|
+
const queryChunks = [];
|
|
49056
|
+
if (params.length > 0 || strings.length > 0 && strings[0] !== "") {
|
|
49057
|
+
queryChunks.push(new StringChunk(strings[0]));
|
|
49058
|
+
}
|
|
49059
|
+
for (const [paramIndex, param2] of params.entries()) {
|
|
49060
|
+
queryChunks.push(param2, new StringChunk(strings[paramIndex + 1]));
|
|
49061
|
+
}
|
|
49062
|
+
return new SQL(queryChunks);
|
|
49063
|
+
}
|
|
49064
|
+
((sql2) => {
|
|
49065
|
+
function empty() {
|
|
49066
|
+
return new SQL([]);
|
|
49067
|
+
}
|
|
49068
|
+
sql2.empty = empty;
|
|
49069
|
+
function fromList(list) {
|
|
49070
|
+
return new SQL(list);
|
|
49071
|
+
}
|
|
49072
|
+
sql2.fromList = fromList;
|
|
49073
|
+
function raw(str) {
|
|
49074
|
+
return new SQL([new StringChunk(str)]);
|
|
49075
|
+
}
|
|
49076
|
+
sql2.raw = raw;
|
|
49077
|
+
function join4(chunks, separator) {
|
|
49078
|
+
const result = [];
|
|
49079
|
+
for (const [i, chunk] of chunks.entries()) {
|
|
49080
|
+
if (i > 0 && separator !== undefined) {
|
|
49081
|
+
result.push(separator);
|
|
49082
|
+
}
|
|
49083
|
+
result.push(chunk);
|
|
49084
|
+
}
|
|
49085
|
+
return new SQL(result);
|
|
49086
|
+
}
|
|
49087
|
+
sql2.join = join4;
|
|
49088
|
+
function identifier(value) {
|
|
49089
|
+
return new Name(value);
|
|
49090
|
+
}
|
|
49091
|
+
sql2.identifier = identifier;
|
|
49092
|
+
function placeholder2(name2) {
|
|
49093
|
+
return new Placeholder(name2);
|
|
49094
|
+
}
|
|
49095
|
+
sql2.placeholder = placeholder2;
|
|
49096
|
+
function param2(value, encoder) {
|
|
49097
|
+
return new Param(value, encoder);
|
|
49098
|
+
}
|
|
49099
|
+
sql2.param = param2;
|
|
49100
|
+
})(sql || (sql = {}));
|
|
49101
|
+
((SQL2) => {
|
|
49102
|
+
|
|
49103
|
+
class Aliased {
|
|
49104
|
+
constructor(sql2, fieldAlias) {
|
|
49105
|
+
this.sql = sql2;
|
|
49106
|
+
this.fieldAlias = fieldAlias;
|
|
49107
|
+
}
|
|
49108
|
+
static [entityKind] = "SQL.Aliased";
|
|
49109
|
+
isSelectionField = false;
|
|
49110
|
+
getSQL() {
|
|
49111
|
+
return this.sql;
|
|
49112
|
+
}
|
|
49113
|
+
clone() {
|
|
49114
|
+
return new Aliased(this.sql, this.fieldAlias);
|
|
49115
|
+
}
|
|
49116
|
+
}
|
|
49117
|
+
SQL2.Aliased = Aliased;
|
|
49118
|
+
})(SQL || (SQL = {}));
|
|
49119
|
+
|
|
49120
|
+
class Placeholder {
|
|
49121
|
+
constructor(name2) {
|
|
49122
|
+
this.name = name2;
|
|
49123
|
+
}
|
|
49124
|
+
static [entityKind] = "Placeholder";
|
|
49125
|
+
getSQL() {
|
|
49126
|
+
return new SQL([this]);
|
|
49127
|
+
}
|
|
49128
|
+
}
|
|
49129
|
+
var IsDrizzleView = Symbol.for("drizzle:IsDrizzleView");
|
|
49130
|
+
|
|
49131
|
+
class View {
|
|
49132
|
+
static [entityKind] = "View";
|
|
49133
|
+
[ViewBaseConfig];
|
|
49134
|
+
[IsDrizzleView] = true;
|
|
49135
|
+
constructor({ name: name2, schema, selectedFields, query }) {
|
|
49136
|
+
this[ViewBaseConfig] = {
|
|
49137
|
+
name: name2,
|
|
49138
|
+
originalName: name2,
|
|
49139
|
+
schema,
|
|
49140
|
+
selectedFields,
|
|
49141
|
+
query,
|
|
49142
|
+
isExisting: !query,
|
|
49143
|
+
isAlias: false
|
|
49144
|
+
};
|
|
49145
|
+
}
|
|
49146
|
+
getSQL() {
|
|
49147
|
+
return new SQL([this]);
|
|
49148
|
+
}
|
|
49149
|
+
}
|
|
49150
|
+
Column.prototype.getSQL = function() {
|
|
49151
|
+
return new SQL([this]);
|
|
49152
|
+
};
|
|
49153
|
+
Table.prototype.getSQL = function() {
|
|
49154
|
+
return new SQL([this]);
|
|
49155
|
+
};
|
|
49156
|
+
Subquery.prototype.getSQL = function() {
|
|
49157
|
+
return new SQL([this]);
|
|
49158
|
+
};
|
|
49159
|
+
|
|
49160
|
+
// src/index.ts
|
|
48498
49161
|
import { existsSync as existsSync4 } from "node:fs";
|
|
48499
49162
|
var import_dotenv2 = __toESM(require_main(), 1);
|
|
48500
49163
|
import { ElizaOS as ElizaOS4 } from "@elizaos/core";
|
|
@@ -48535,7 +49198,7 @@ function resolvePgliteDir(dir, fallbackDir) {
|
|
|
48535
49198
|
return resolved;
|
|
48536
49199
|
}
|
|
48537
49200
|
var __dirname3 = dirname3(fileURLToPath2(import.meta.url));
|
|
48538
|
-
var
|
|
49201
|
+
var DEFAULT_SERVER_ID2 = "00000000-0000-0000-0000-000000000000";
|
|
48539
49202
|
function isWebUIEnabled() {
|
|
48540
49203
|
const isProduction = false;
|
|
48541
49204
|
const uiEnabledEnv = process.env.ELIZA_UI_ENABLE;
|
|
@@ -48554,6 +49217,8 @@ class AgentServer {
|
|
|
48554
49217
|
clientPath;
|
|
48555
49218
|
elizaOS;
|
|
48556
49219
|
database;
|
|
49220
|
+
rlsOwnerId;
|
|
49221
|
+
serverId = DEFAULT_SERVER_ID2;
|
|
48557
49222
|
loadCharacterTryPath;
|
|
48558
49223
|
jsonToCharacter;
|
|
48559
49224
|
async startAgents(agents, options) {
|
|
@@ -48585,6 +49250,9 @@ class AgentServer {
|
|
|
48585
49250
|
});
|
|
48586
49251
|
logger33.info(`Persisted agent ${runtime.character.name} (${runtime.agentId}) to database`);
|
|
48587
49252
|
}
|
|
49253
|
+
if (this.rlsOwnerId) {
|
|
49254
|
+
await assignAgentToOwner(this.database, runtime.agentId, this.rlsOwnerId);
|
|
49255
|
+
}
|
|
48588
49256
|
} catch (error2) {
|
|
48589
49257
|
logger33.error({ error: error2 }, `Failed to persist agent ${runtime.agentId} to database`);
|
|
48590
49258
|
}
|
|
@@ -48657,6 +49325,43 @@ class AgentServer {
|
|
|
48657
49325
|
logger33.error({ error: migrationError }, "[INIT] Failed to run database migrations:");
|
|
48658
49326
|
throw new Error(`Database migration failed: ${migrationError instanceof Error ? migrationError.message : String(migrationError)}`);
|
|
48659
49327
|
}
|
|
49328
|
+
const rlsEnabled = process.env.ENABLE_RLS_ISOLATION === "true";
|
|
49329
|
+
const rlsOwnerIdString = process.env.RLS_OWNER_ID;
|
|
49330
|
+
if (rlsEnabled) {
|
|
49331
|
+
if (!config3?.postgresUrl) {
|
|
49332
|
+
logger33.error("[RLS] ENABLE_RLS_ISOLATION requires PostgreSQL (not compatible with PGLite)");
|
|
49333
|
+
throw new Error("RLS isolation requires PostgreSQL database");
|
|
49334
|
+
}
|
|
49335
|
+
if (!rlsOwnerIdString) {
|
|
49336
|
+
logger33.error("[RLS] ENABLE_RLS_ISOLATION requires RLS_OWNER_ID environment variable");
|
|
49337
|
+
throw new Error("RLS_OWNER_ID environment variable is required when RLS is enabled");
|
|
49338
|
+
}
|
|
49339
|
+
const owner_id = stringToUuid2(rlsOwnerIdString);
|
|
49340
|
+
logger33.info("[INIT] Initializing RLS multi-tenant isolation...");
|
|
49341
|
+
logger33.info(`[RLS] Tenant ID: ${owner_id.slice(0, 8)}… (from RLS_OWNER_ID="${rlsOwnerIdString}")`);
|
|
49342
|
+
logger33.warn("[RLS] Ensure your PostgreSQL user is NOT a superuser!");
|
|
49343
|
+
logger33.warn("[RLS] Superusers bypass ALL RLS policies, defeating isolation.");
|
|
49344
|
+
try {
|
|
49345
|
+
await installRLSFunctions(this.database);
|
|
49346
|
+
await getOrCreateRlsOwner(this.database, owner_id);
|
|
49347
|
+
this.rlsOwnerId = owner_id;
|
|
49348
|
+
await setOwnerContext(this.database, owner_id);
|
|
49349
|
+
await applyRLSToNewTables(this.database);
|
|
49350
|
+
logger33.success("[INIT] RLS multi-tenant isolation initialized successfully");
|
|
49351
|
+
} catch (rlsError) {
|
|
49352
|
+
logger33.error({ error: rlsError }, "[INIT] Failed to initialize RLS:");
|
|
49353
|
+
throw new Error(`RLS initialization failed: ${rlsError instanceof Error ? rlsError.message : String(rlsError)}`);
|
|
49354
|
+
}
|
|
49355
|
+
} else if (config3?.postgresUrl) {
|
|
49356
|
+
logger33.info("[INIT] RLS multi-tenant isolation disabled (legacy mode)");
|
|
49357
|
+
try {
|
|
49358
|
+
logger33.info("[INIT] Cleaning up RLS policies and functions...");
|
|
49359
|
+
await uninstallRLS(this.database);
|
|
49360
|
+
logger33.success("[INIT] RLS cleanup completed");
|
|
49361
|
+
} catch (cleanupError) {
|
|
49362
|
+
logger33.debug("[INIT] RLS cleanup skipped (RLS not installed or already cleaned)");
|
|
49363
|
+
}
|
|
49364
|
+
}
|
|
48660
49365
|
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
48661
49366
|
logger33.info("[INIT] Ensuring default server exists...");
|
|
48662
49367
|
await this.ensureDefaultServer();
|
|
@@ -48667,6 +49372,7 @@ class AgentServer {
|
|
|
48667
49372
|
this.elizaOS = new ElizaOS3;
|
|
48668
49373
|
this.elizaOS.enableEditableMode();
|
|
48669
49374
|
setGlobalElizaOS(this.elizaOS);
|
|
49375
|
+
setGlobalAgentServer(this);
|
|
48670
49376
|
logger33.success("[INIT] ElizaOS initialized");
|
|
48671
49377
|
await this.initializeServer(config3);
|
|
48672
49378
|
await new Promise((resolve2) => setTimeout(resolve2, 250));
|
|
@@ -48679,36 +49385,42 @@ class AgentServer {
|
|
|
48679
49385
|
}
|
|
48680
49386
|
async ensureDefaultServer() {
|
|
48681
49387
|
try {
|
|
48682
|
-
|
|
49388
|
+
const rlsEnabled = process.env.ENABLE_RLS_ISOLATION === "true";
|
|
49389
|
+
this.serverId = rlsEnabled && this.rlsOwnerId ? this.rlsOwnerId : "00000000-0000-0000-0000-000000000000";
|
|
49390
|
+
const serverName = rlsEnabled && this.rlsOwnerId ? `Server ${this.rlsOwnerId.substring(0, 8)}` : "Default Server";
|
|
49391
|
+
logger33.info(`[AgentServer] Checking for server ${this.serverId}...`);
|
|
48683
49392
|
const servers = await this.database.getMessageServers();
|
|
48684
49393
|
logger33.debug(`[AgentServer] Found ${servers.length} existing servers`);
|
|
48685
49394
|
servers.forEach((s) => {
|
|
48686
49395
|
logger33.debug(`[AgentServer] Existing server: ID=${s.id}, Name=${s.name}`);
|
|
48687
49396
|
});
|
|
48688
|
-
const defaultServer = servers.find((s) => s.id ===
|
|
49397
|
+
const defaultServer = servers.find((s) => s.id === this.serverId);
|
|
48689
49398
|
if (!defaultServer) {
|
|
48690
|
-
logger33.info(
|
|
49399
|
+
logger33.info(`[AgentServer] Creating server with UUID ${this.serverId}...`);
|
|
48691
49400
|
try {
|
|
48692
|
-
|
|
49401
|
+
const db = this.database.db;
|
|
49402
|
+
await db.execute(sql`
|
|
48693
49403
|
INSERT INTO message_servers (id, name, source_type, created_at, updated_at)
|
|
48694
|
-
VALUES (
|
|
49404
|
+
VALUES (${this.serverId}, ${serverName}, ${"eliza_default"}, NOW(), NOW())
|
|
48695
49405
|
ON CONFLICT (id) DO NOTHING
|
|
48696
49406
|
`);
|
|
48697
|
-
logger33.success("[AgentServer]
|
|
48698
|
-
const checkResult = await
|
|
48699
|
-
|
|
49407
|
+
logger33.success("[AgentServer] Server created via parameterized query");
|
|
49408
|
+
const checkResult = await db.execute(sql`
|
|
49409
|
+
SELECT id, name FROM message_servers WHERE id = ${this.serverId}
|
|
49410
|
+
`);
|
|
49411
|
+
logger33.debug("[AgentServer] Parameterized query check result:", checkResult);
|
|
48700
49412
|
} catch (sqlError) {
|
|
48701
49413
|
logger33.error("[AgentServer] Raw SQL insert failed:", sqlError);
|
|
48702
49414
|
try {
|
|
48703
49415
|
const server = await this.database.createMessageServer({
|
|
48704
|
-
id:
|
|
48705
|
-
name:
|
|
49416
|
+
id: this.serverId,
|
|
49417
|
+
name: serverName,
|
|
48706
49418
|
sourceType: "eliza_default"
|
|
48707
49419
|
});
|
|
48708
|
-
logger33.success("[AgentServer]
|
|
49420
|
+
logger33.success("[AgentServer] Server created via ORM with ID:", server.id);
|
|
48709
49421
|
} catch (ormError) {
|
|
48710
49422
|
logger33.error("[AgentServer] Both SQL and ORM creation failed:", ormError);
|
|
48711
|
-
throw new Error(`Failed to create
|
|
49423
|
+
throw new Error(`Failed to create server: ${ormError.message}`);
|
|
48712
49424
|
}
|
|
48713
49425
|
}
|
|
48714
49426
|
const verifyServers = await this.database.getMessageServers();
|
|
@@ -48716,14 +49428,14 @@ class AgentServer {
|
|
|
48716
49428
|
verifyServers.forEach((s) => {
|
|
48717
49429
|
logger33.debug(`[AgentServer] Server after creation: ID=${s.id}, Name=${s.name}`);
|
|
48718
49430
|
});
|
|
48719
|
-
const verifyDefault = verifyServers.find((s) => s.id ===
|
|
49431
|
+
const verifyDefault = verifyServers.find((s) => s.id === this.serverId);
|
|
48720
49432
|
if (!verifyDefault) {
|
|
48721
|
-
throw new Error(`Failed to create or verify
|
|
49433
|
+
throw new Error(`Failed to create or verify server with ID ${this.serverId}`);
|
|
48722
49434
|
} else {
|
|
48723
|
-
logger33.success("[AgentServer]
|
|
49435
|
+
logger33.success("[AgentServer] Server creation verified successfully");
|
|
48724
49436
|
}
|
|
48725
49437
|
} else {
|
|
48726
|
-
logger33.info("[AgentServer]
|
|
49438
|
+
logger33.info("[AgentServer] Server already exists with ID:", defaultServer.id);
|
|
48727
49439
|
}
|
|
48728
49440
|
} catch (error2) {
|
|
48729
49441
|
logger33.error({ error: error2 }, "[AgentServer] Error ensuring default server:");
|
|
@@ -48819,6 +49531,38 @@ class AgentServer {
|
|
|
48819
49531
|
this.app.use(express34.json({
|
|
48820
49532
|
limit: process.env.EXPRESS_MAX_PAYLOAD || "2mb"
|
|
48821
49533
|
}));
|
|
49534
|
+
const healthCheckRateLimiter = rate_limit_default({
|
|
49535
|
+
windowMs: 60 * 1000,
|
|
49536
|
+
max: 100,
|
|
49537
|
+
message: "Too many health check requests from this IP, please try again later.",
|
|
49538
|
+
standardHeaders: true,
|
|
49539
|
+
legacyHeaders: false,
|
|
49540
|
+
skip: (req) => {
|
|
49541
|
+
const ip = req.ip || "";
|
|
49542
|
+
return ip === "127.0.0.1" || ip === "::1" || ip.startsWith("10.") || ip.startsWith("172.") || ip.startsWith("192.168.");
|
|
49543
|
+
}
|
|
49544
|
+
});
|
|
49545
|
+
this.app.get("/healthz", healthCheckRateLimiter, (_req, res) => {
|
|
49546
|
+
res.json({
|
|
49547
|
+
status: "ok",
|
|
49548
|
+
timestamp: new Date().toISOString()
|
|
49549
|
+
});
|
|
49550
|
+
});
|
|
49551
|
+
this.app.get("/health", healthCheckRateLimiter, (_req, res) => {
|
|
49552
|
+
const agents = this.elizaOS?.getAgents() || [];
|
|
49553
|
+
const isHealthy = agents.length > 0;
|
|
49554
|
+
const healthcheck = {
|
|
49555
|
+
status: isHealthy ? "OK" : "DEGRADED",
|
|
49556
|
+
version: process.env.APP_VERSION || "unknown",
|
|
49557
|
+
timestamp: new Date().toISOString(),
|
|
49558
|
+
dependencies: {
|
|
49559
|
+
agents: isHealthy ? "healthy" : "no_agents"
|
|
49560
|
+
},
|
|
49561
|
+
agentCount: agents.length
|
|
49562
|
+
};
|
|
49563
|
+
res.status(isHealthy ? 200 : 503).json(healthcheck);
|
|
49564
|
+
});
|
|
49565
|
+
logger33.info("Public health check endpoints enabled: /healthz and /health (rate limited: 100 req/min)");
|
|
48822
49566
|
const serverAuthToken = process.env.ELIZA_SERVER_AUTH_TOKEN;
|
|
48823
49567
|
if (serverAuthToken) {
|
|
48824
49568
|
logger33.info("Server authentication enabled. Requires X-API-KEY header for /api routes.");
|
|
@@ -49030,8 +49774,8 @@ class AgentServer {
|
|
|
49030
49774
|
const nvmPath = path8.join(os3.homedir(), ".nvm/versions/node");
|
|
49031
49775
|
if (existsSync4(nvmPath)) {
|
|
49032
49776
|
const versions = fs6.readdirSync(nvmPath);
|
|
49033
|
-
for (const
|
|
49034
|
-
const cliPath = path8.join(nvmPath,
|
|
49777
|
+
for (const version2 of versions) {
|
|
49778
|
+
const cliPath = path8.join(nvmPath, version2, "lib/node_modules/@elizaos/server/dist/client");
|
|
49035
49779
|
if (existsSync4(path8.join(cliPath, "index.html"))) {
|
|
49036
49780
|
return cliPath;
|
|
49037
49781
|
}
|
|
@@ -49213,8 +49957,8 @@ class AgentServer {
|
|
|
49213
49957
|
}
|
|
49214
49958
|
}
|
|
49215
49959
|
logger33.success(`Successfully registered agent ${runtime.character.name} (${runtime.agentId}) with core services.`);
|
|
49216
|
-
await this.addAgentToServer(
|
|
49217
|
-
logger33.info(`[AgentServer] Auto-associated agent ${runtime.character.name} with server ID: ${
|
|
49960
|
+
await this.addAgentToServer(this.serverId, runtime.agentId);
|
|
49961
|
+
logger33.info(`[AgentServer] Auto-associated agent ${runtime.character.name} with server ID: ${this.serverId}`);
|
|
49218
49962
|
} catch (error2) {
|
|
49219
49963
|
logger33.error({ error: error2 }, "Failed to register agent:");
|
|
49220
49964
|
throw error2;
|