@elizaos/server 1.0.12 → 1.0.13
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.js +456 -587
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -381,13 +381,11 @@ var import_cors2 = __toESM(require_lib(), 1);
|
|
|
381
381
|
import {
|
|
382
382
|
logger as logger29
|
|
383
383
|
} from "@elizaos/core";
|
|
384
|
-
import bodyParser2 from "body-parser";
|
|
385
384
|
import express30 from "express";
|
|
386
|
-
import fileUpload2 from "express-fileupload";
|
|
387
385
|
import helmet2 from "helmet";
|
|
388
|
-
import * as
|
|
386
|
+
import * as fs9 from "fs";
|
|
389
387
|
import http from "http";
|
|
390
|
-
import
|
|
388
|
+
import path9, { basename, dirname, extname, join } from "path";
|
|
391
389
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
392
390
|
|
|
393
391
|
// src/api/index.ts
|
|
@@ -499,7 +497,7 @@ function createAgentCrudRouter(agents, serverInstance) {
|
|
|
499
497
|
});
|
|
500
498
|
router.post("/", async (req, res) => {
|
|
501
499
|
logger.debug("[AGENT CREATE] Creating new agent");
|
|
502
|
-
const { characterPath, characterJson } = req.body;
|
|
500
|
+
const { characterPath, characterJson, agent } = req.body;
|
|
503
501
|
if (!db) {
|
|
504
502
|
return sendError(res, 500, "DB_ERROR", "Database not available");
|
|
505
503
|
}
|
|
@@ -511,6 +509,9 @@ function createAgentCrudRouter(agents, serverInstance) {
|
|
|
511
509
|
} else if (characterPath) {
|
|
512
510
|
logger.debug(`[AGENT CREATE] Loading character from path: ${characterPath}`);
|
|
513
511
|
character = await serverInstance?.loadCharacterTryPath(characterPath);
|
|
512
|
+
} else if (agent) {
|
|
513
|
+
logger.debug("[AGENT CREATE] Parsing character from agent object");
|
|
514
|
+
character = await serverInstance?.jsonToCharacter(agent);
|
|
514
515
|
} else {
|
|
515
516
|
throw new Error("No character configuration provided");
|
|
516
517
|
}
|
|
@@ -524,12 +525,12 @@ function createAgentCrudRouter(agents, serverInstance) {
|
|
|
524
525
|
}
|
|
525
526
|
const ensureAgentExists = async (character2) => {
|
|
526
527
|
const agentId = stringToUuid(character2.name);
|
|
527
|
-
let
|
|
528
|
-
if (!
|
|
528
|
+
let agent2 = await db.getAgent(agentId);
|
|
529
|
+
if (!agent2) {
|
|
529
530
|
await db.createAgent({ ...character2, id: agentId });
|
|
530
|
-
|
|
531
|
+
agent2 = await db.getAgent(agentId);
|
|
531
532
|
}
|
|
532
|
-
return
|
|
533
|
+
return agent2;
|
|
533
534
|
};
|
|
534
535
|
const newAgent = await ensureAgentExists(character);
|
|
535
536
|
if (!newAgent) {
|
|
@@ -1183,6 +1184,30 @@ function createAgentMemoryRouter(agents) {
|
|
|
1183
1184
|
);
|
|
1184
1185
|
}
|
|
1185
1186
|
});
|
|
1187
|
+
router.delete("/:agentId/memories/:memoryId", async (req, res) => {
|
|
1188
|
+
try {
|
|
1189
|
+
const agentId = validateUuid6(req.params.agentId);
|
|
1190
|
+
const memoryId = validateUuid6(req.params.memoryId);
|
|
1191
|
+
if (!agentId || !memoryId) {
|
|
1192
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID or memory ID format");
|
|
1193
|
+
}
|
|
1194
|
+
const runtime = agents.get(agentId);
|
|
1195
|
+
if (!runtime) {
|
|
1196
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
1197
|
+
}
|
|
1198
|
+
await runtime.deleteMemory(memoryId);
|
|
1199
|
+
sendSuccess(res, { message: "Memory deleted successfully" });
|
|
1200
|
+
} catch (error) {
|
|
1201
|
+
logger6.error(`[DELETE MEMORY] Error deleting memory ${req.params.memoryId}:`, error);
|
|
1202
|
+
sendError(
|
|
1203
|
+
res,
|
|
1204
|
+
500,
|
|
1205
|
+
"DELETE_ERROR",
|
|
1206
|
+
"Error deleting memory",
|
|
1207
|
+
error instanceof Error ? error.message : String(error)
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
});
|
|
1186
1211
|
return router;
|
|
1187
1212
|
}
|
|
1188
1213
|
|
|
@@ -1683,189 +1708,16 @@ import {
|
|
|
1683
1708
|
composePromptFromState,
|
|
1684
1709
|
ModelType,
|
|
1685
1710
|
ChannelType as ChannelType2,
|
|
1686
|
-
logger as
|
|
1687
|
-
validateUuid as
|
|
1711
|
+
logger as logger12,
|
|
1712
|
+
validateUuid as validateUuid12
|
|
1688
1713
|
} from "@elizaos/core";
|
|
1689
1714
|
import express11 from "express";
|
|
1690
1715
|
|
|
1691
|
-
// src/upload.ts
|
|
1692
|
-
import fs2 from "fs";
|
|
1693
|
-
import path2 from "path";
|
|
1694
|
-
import fileUpload from "express-fileupload";
|
|
1695
|
-
import { validateUuid as validateUuid10, logger as logger11 } from "@elizaos/core";
|
|
1696
|
-
|
|
1697
|
-
// src/api/shared/file-utils.ts
|
|
1698
|
-
import fs from "fs";
|
|
1699
|
-
import path from "path";
|
|
1700
|
-
import { logger as logger10 } from "@elizaos/core";
|
|
1701
|
-
function createSecureUploadDir(id, type) {
|
|
1702
|
-
if (id.includes("..") || id.includes("/") || id.includes("\\") || id.includes("\0")) {
|
|
1703
|
-
throw new Error(`Invalid ${type.slice(0, -1)} ID: contains illegal characters`);
|
|
1704
|
-
}
|
|
1705
|
-
const basePath = path.resolve(process.cwd(), ".eliza", "data", "uploads", type);
|
|
1706
|
-
const targetPath = path.join(basePath, id);
|
|
1707
|
-
if (!targetPath.startsWith(basePath)) {
|
|
1708
|
-
throw new Error(`Invalid ${type.slice(0, -1)} ID: path traversal detected`);
|
|
1709
|
-
}
|
|
1710
|
-
return targetPath;
|
|
1711
|
-
}
|
|
1712
|
-
function sanitizeFilename(filename) {
|
|
1713
|
-
let sanitized = filename.replace(/[\0\/\\:*?"<>|]/g, "_");
|
|
1714
|
-
sanitized = sanitized.replace(/^[.\s]+/, "");
|
|
1715
|
-
if (sanitized.length > 255) {
|
|
1716
|
-
const ext = path.extname(sanitized);
|
|
1717
|
-
const name = path.basename(sanitized, ext);
|
|
1718
|
-
sanitized = name.substring(0, 255 - ext.length) + ext;
|
|
1719
|
-
}
|
|
1720
|
-
if (!sanitized || sanitized.trim() === "") {
|
|
1721
|
-
sanitized = "file";
|
|
1722
|
-
}
|
|
1723
|
-
return sanitized;
|
|
1724
|
-
}
|
|
1725
|
-
var cleanupFile = (filePath) => {
|
|
1726
|
-
if (!filePath) return;
|
|
1727
|
-
try {
|
|
1728
|
-
const resolvedPath = path.resolve(filePath);
|
|
1729
|
-
const normalizedPath = path.normalize(resolvedPath);
|
|
1730
|
-
if (normalizedPath.includes("..") || !normalizedPath.startsWith(process.cwd())) {
|
|
1731
|
-
logger10.warn(`[SECURITY] Potentially unsafe file path blocked: ${filePath}`);
|
|
1732
|
-
return;
|
|
1733
|
-
}
|
|
1734
|
-
if (fs.existsSync(normalizedPath)) {
|
|
1735
|
-
fs.unlinkSync(normalizedPath);
|
|
1736
|
-
logger10.debug(`[FILE] Successfully cleaned up file: ${normalizedPath}`);
|
|
1737
|
-
}
|
|
1738
|
-
} catch (error) {
|
|
1739
|
-
logger10.error(`Error cleaning up file ${filePath}:`, error);
|
|
1740
|
-
}
|
|
1741
|
-
};
|
|
1742
|
-
var cleanupUploadedFile = (file) => {
|
|
1743
|
-
if (file.tempFilePath) {
|
|
1744
|
-
cleanupFile(file.tempFilePath);
|
|
1745
|
-
}
|
|
1746
|
-
};
|
|
1747
|
-
|
|
1748
|
-
// src/api/shared/constants.ts
|
|
1749
|
-
var MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
1750
|
-
var MAX_FILE_SIZE_DISPLAY = "50MB";
|
|
1751
|
-
var ALLOWED_AUDIO_MIME_TYPES = [
|
|
1752
|
-
"audio/mpeg",
|
|
1753
|
-
"audio/mp3",
|
|
1754
|
-
"audio/wav",
|
|
1755
|
-
"audio/ogg",
|
|
1756
|
-
"audio/webm",
|
|
1757
|
-
"audio/mp4",
|
|
1758
|
-
"audio/aac",
|
|
1759
|
-
"audio/flac",
|
|
1760
|
-
"audio/x-wav",
|
|
1761
|
-
"audio/wave"
|
|
1762
|
-
];
|
|
1763
|
-
var ALLOWED_MEDIA_MIME_TYPES = [
|
|
1764
|
-
...ALLOWED_AUDIO_MIME_TYPES,
|
|
1765
|
-
"image/jpeg",
|
|
1766
|
-
"image/png",
|
|
1767
|
-
"image/gif",
|
|
1768
|
-
"image/webp",
|
|
1769
|
-
"video/mp4",
|
|
1770
|
-
"video/webm",
|
|
1771
|
-
"application/pdf",
|
|
1772
|
-
"text/plain"
|
|
1773
|
-
];
|
|
1774
|
-
|
|
1775
|
-
// src/upload.ts
|
|
1776
|
-
function generateSecureFilename(originalName) {
|
|
1777
|
-
const uniqueSuffix = `${Date.now()}-${Math.round(Math.random() * 1e9)}`;
|
|
1778
|
-
const sanitizedName = sanitizeFilename(originalName);
|
|
1779
|
-
return `${uniqueSuffix}-${sanitizedName}`;
|
|
1780
|
-
}
|
|
1781
|
-
function ensureUploadDir(id, type) {
|
|
1782
|
-
if (!validateUuid10(id)) {
|
|
1783
|
-
throw new Error(`Invalid ${type.slice(0, -1)} ID format`);
|
|
1784
|
-
}
|
|
1785
|
-
const uploadDir = createSecureUploadDir(id, type);
|
|
1786
|
-
if (!fs2.existsSync(uploadDir)) {
|
|
1787
|
-
fs2.mkdirSync(uploadDir, { recursive: true });
|
|
1788
|
-
}
|
|
1789
|
-
logger11.debug(`[UPLOAD] Secure ${type.slice(0, -1)} upload directory created: ${uploadDir}`);
|
|
1790
|
-
return uploadDir;
|
|
1791
|
-
}
|
|
1792
|
-
var agentAudioUpload = () => fileUpload({
|
|
1793
|
-
limits: {
|
|
1794
|
-
fileSize: MAX_FILE_SIZE,
|
|
1795
|
-
// 50MB max file size
|
|
1796
|
-
files: 1
|
|
1797
|
-
// Only allow 1 file per request
|
|
1798
|
-
},
|
|
1799
|
-
useTempFiles: true,
|
|
1800
|
-
tempFileDir: "/tmp/",
|
|
1801
|
-
parseNested: true,
|
|
1802
|
-
abortOnLimit: true,
|
|
1803
|
-
createParentPath: true,
|
|
1804
|
-
preserveExtension: true,
|
|
1805
|
-
safeFileNames: true,
|
|
1806
|
-
uploadTimeout: 6e4
|
|
1807
|
-
// 60 seconds timeout
|
|
1808
|
-
});
|
|
1809
|
-
var agentMediaUpload = () => fileUpload({
|
|
1810
|
-
limits: {
|
|
1811
|
-
fileSize: MAX_FILE_SIZE,
|
|
1812
|
-
// 50MB max file size
|
|
1813
|
-
files: 1
|
|
1814
|
-
// Only allow 1 file per request
|
|
1815
|
-
},
|
|
1816
|
-
useTempFiles: true,
|
|
1817
|
-
tempFileDir: "/tmp/",
|
|
1818
|
-
parseNested: true,
|
|
1819
|
-
abortOnLimit: true,
|
|
1820
|
-
createParentPath: true,
|
|
1821
|
-
preserveExtension: true,
|
|
1822
|
-
safeFileNames: true,
|
|
1823
|
-
uploadTimeout: 6e4
|
|
1824
|
-
// 60 seconds timeout
|
|
1825
|
-
});
|
|
1826
|
-
var channelUpload = () => fileUpload({
|
|
1827
|
-
limits: {
|
|
1828
|
-
fileSize: MAX_FILE_SIZE,
|
|
1829
|
-
// 50MB max file size
|
|
1830
|
-
files: 1
|
|
1831
|
-
// Only allow 1 file per request
|
|
1832
|
-
},
|
|
1833
|
-
useTempFiles: true,
|
|
1834
|
-
tempFileDir: "/tmp/",
|
|
1835
|
-
parseNested: true,
|
|
1836
|
-
abortOnLimit: true,
|
|
1837
|
-
createParentPath: true,
|
|
1838
|
-
preserveExtension: true,
|
|
1839
|
-
safeFileNames: true,
|
|
1840
|
-
uploadTimeout: 6e4
|
|
1841
|
-
// 60 seconds timeout
|
|
1842
|
-
});
|
|
1843
|
-
function validateAudioFile(file) {
|
|
1844
|
-
return ALLOWED_AUDIO_MIME_TYPES.includes(file.mimetype);
|
|
1845
|
-
}
|
|
1846
|
-
function validateMediaFile(file) {
|
|
1847
|
-
return ALLOWED_MEDIA_MIME_TYPES.includes(file.mimetype);
|
|
1848
|
-
}
|
|
1849
|
-
async function processUploadedFile(file, targetId, type) {
|
|
1850
|
-
try {
|
|
1851
|
-
const uploadDir = ensureUploadDir(targetId, type);
|
|
1852
|
-
const filename = generateSecureFilename(file.name);
|
|
1853
|
-
const finalPath = path2.join(uploadDir, filename);
|
|
1854
|
-
await file.mv(finalPath);
|
|
1855
|
-
const url = `/media/uploads/${type}/${targetId}/${filename}`;
|
|
1856
|
-
logger11.debug(`[UPLOAD] File processed successfully: ${filename}`);
|
|
1857
|
-
return { filename, path: finalPath, url };
|
|
1858
|
-
} catch (error) {
|
|
1859
|
-
logger11.error("[UPLOAD] Error processing uploaded file:", error);
|
|
1860
|
-
throw error;
|
|
1861
|
-
}
|
|
1862
|
-
}
|
|
1863
|
-
|
|
1864
1716
|
// src/api/shared/middleware.ts
|
|
1865
|
-
import { validateUuid as
|
|
1717
|
+
import { validateUuid as validateUuid11, logger as logger11 } from "@elizaos/core";
|
|
1866
1718
|
|
|
1867
1719
|
// src/api/shared/validation.ts
|
|
1868
|
-
import { validateUuid as
|
|
1720
|
+
import { validateUuid as validateUuid10, logger as logger10 } from "@elizaos/core";
|
|
1869
1721
|
var getRuntime = (agents, agentId) => {
|
|
1870
1722
|
const runtime = agents.get(agentId);
|
|
1871
1723
|
if (!runtime) {
|
|
@@ -1889,7 +1741,7 @@ var securityMiddleware = () => {
|
|
|
1889
1741
|
const realIp = req.get("X-Real-IP");
|
|
1890
1742
|
const clientIp = forwarded || realIp || req.ip;
|
|
1891
1743
|
if (userAgent && (userAgent.includes("..") || userAgent.includes("<script"))) {
|
|
1892
|
-
|
|
1744
|
+
logger11.warn(`[SECURITY] Suspicious User-Agent from ${clientIp}: ${userAgent}`);
|
|
1893
1745
|
}
|
|
1894
1746
|
const url = req.originalUrl || req.url;
|
|
1895
1747
|
const queryString = JSON.stringify(req.query);
|
|
@@ -1915,12 +1767,12 @@ var securityMiddleware = () => {
|
|
|
1915
1767
|
}
|
|
1916
1768
|
for (const indicator of suspiciousIndicators) {
|
|
1917
1769
|
if (url.includes(indicator.pattern) || queryString.includes(indicator.pattern)) {
|
|
1918
|
-
|
|
1770
|
+
logger11.warn(`[SECURITY] ${indicator.name} detected from ${clientIp}: ${url}`);
|
|
1919
1771
|
break;
|
|
1920
1772
|
}
|
|
1921
1773
|
}
|
|
1922
1774
|
if (hasSqlPattern) {
|
|
1923
|
-
|
|
1775
|
+
logger11.warn(`[SECURITY] SQL injection pattern detected from ${clientIp}: ${url}`);
|
|
1924
1776
|
}
|
|
1925
1777
|
next();
|
|
1926
1778
|
};
|
|
@@ -1969,7 +1821,7 @@ var createApiRateLimit = () => {
|
|
|
1969
1821
|
// Disable the `X-RateLimit-*` headers
|
|
1970
1822
|
handler: (req, res) => {
|
|
1971
1823
|
const clientIp = req.ip || "unknown";
|
|
1972
|
-
|
|
1824
|
+
logger11.warn(`[SECURITY] Rate limit exceeded for IP: ${clientIp}`);
|
|
1973
1825
|
res.status(429).json({
|
|
1974
1826
|
success: false,
|
|
1975
1827
|
error: {
|
|
@@ -1997,7 +1849,7 @@ var createFileSystemRateLimit = () => {
|
|
|
1997
1849
|
legacyHeaders: false,
|
|
1998
1850
|
handler: (req, res) => {
|
|
1999
1851
|
const clientIp = req.ip || "unknown";
|
|
2000
|
-
|
|
1852
|
+
logger11.warn(
|
|
2001
1853
|
`[SECURITY] File system rate limit exceeded for IP: ${clientIp}, endpoint: ${req.path}`
|
|
2002
1854
|
);
|
|
2003
1855
|
res.status(429).json({
|
|
@@ -2027,7 +1879,7 @@ var createUploadRateLimit = () => {
|
|
|
2027
1879
|
legacyHeaders: false,
|
|
2028
1880
|
handler: (req, res) => {
|
|
2029
1881
|
const clientIp = req.ip || "unknown";
|
|
2030
|
-
|
|
1882
|
+
logger11.warn(
|
|
2031
1883
|
`[SECURITY] Upload rate limit exceeded for IP: ${clientIp}, endpoint: ${req.path}`
|
|
2032
1884
|
);
|
|
2033
1885
|
res.status(429).json({
|
|
@@ -2041,14 +1893,73 @@ var createUploadRateLimit = () => {
|
|
|
2041
1893
|
});
|
|
2042
1894
|
};
|
|
2043
1895
|
|
|
1896
|
+
// src/api/shared/constants.ts
|
|
1897
|
+
var MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
1898
|
+
var MAX_FILE_SIZE_DISPLAY = "50MB";
|
|
1899
|
+
var ALLOWED_AUDIO_MIME_TYPES = [
|
|
1900
|
+
"audio/mpeg",
|
|
1901
|
+
"audio/mp3",
|
|
1902
|
+
"audio/wav",
|
|
1903
|
+
"audio/ogg",
|
|
1904
|
+
"audio/webm",
|
|
1905
|
+
"audio/mp4",
|
|
1906
|
+
"audio/aac",
|
|
1907
|
+
"audio/flac",
|
|
1908
|
+
"audio/x-wav",
|
|
1909
|
+
"audio/wave"
|
|
1910
|
+
];
|
|
1911
|
+
var ALLOWED_MEDIA_MIME_TYPES = [
|
|
1912
|
+
...ALLOWED_AUDIO_MIME_TYPES,
|
|
1913
|
+
"image/jpeg",
|
|
1914
|
+
"image/png",
|
|
1915
|
+
"image/gif",
|
|
1916
|
+
"image/webp",
|
|
1917
|
+
"video/mp4",
|
|
1918
|
+
"video/webm",
|
|
1919
|
+
"application/pdf",
|
|
1920
|
+
"text/plain"
|
|
1921
|
+
];
|
|
1922
|
+
|
|
2044
1923
|
// src/api/messaging/channels.ts
|
|
1924
|
+
import multer from "multer";
|
|
1925
|
+
import fs from "fs";
|
|
1926
|
+
import path from "path";
|
|
2045
1927
|
var DEFAULT_SERVER_ID3 = "00000000-0000-0000-0000-000000000000";
|
|
1928
|
+
var channelStorage = multer.memoryStorage();
|
|
1929
|
+
var channelUploadMiddleware = multer({
|
|
1930
|
+
storage: channelStorage,
|
|
1931
|
+
limits: {
|
|
1932
|
+
fileSize: MAX_FILE_SIZE,
|
|
1933
|
+
files: 1
|
|
1934
|
+
},
|
|
1935
|
+
fileFilter: (req, file, cb) => {
|
|
1936
|
+
if (ALLOWED_MEDIA_MIME_TYPES.includes(file.mimetype)) {
|
|
1937
|
+
cb(null, true);
|
|
1938
|
+
} else {
|
|
1939
|
+
cb(new Error("Invalid file type"), false);
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
});
|
|
1943
|
+
async function saveChannelUploadedFile(file, channelId) {
|
|
1944
|
+
const uploadDir = path.join(process.cwd(), ".eliza/data/uploads/channels", channelId);
|
|
1945
|
+
if (!fs.existsSync(uploadDir)) {
|
|
1946
|
+
fs.mkdirSync(uploadDir, { recursive: true });
|
|
1947
|
+
}
|
|
1948
|
+
const timestamp = Date.now();
|
|
1949
|
+
const random = Math.round(Math.random() * 1e9);
|
|
1950
|
+
const ext = path.extname(file.originalname);
|
|
1951
|
+
const filename = `${timestamp}-${random}${ext}`;
|
|
1952
|
+
const filePath = path.join(uploadDir, filename);
|
|
1953
|
+
fs.writeFileSync(filePath, file.buffer);
|
|
1954
|
+
const url = `/media/uploads/channels/${channelId}/${filename}`;
|
|
1955
|
+
return { filename, url };
|
|
1956
|
+
}
|
|
2046
1957
|
function createChannelsRouter(agents, serverInstance) {
|
|
2047
1958
|
const router = express11.Router();
|
|
2048
1959
|
router.post(
|
|
2049
1960
|
"/central-channels/:channelId/messages",
|
|
2050
1961
|
async (req, res) => {
|
|
2051
|
-
const channelIdParam =
|
|
1962
|
+
const channelIdParam = validateUuid12(req.params.channelId);
|
|
2052
1963
|
const {
|
|
2053
1964
|
author_id,
|
|
2054
1965
|
// This is the GUI user's central ID
|
|
@@ -2063,40 +1974,40 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2063
1974
|
source_type
|
|
2064
1975
|
// Should be something like 'eliza_gui'
|
|
2065
1976
|
} = req.body;
|
|
2066
|
-
const isValidServerId = server_id === DEFAULT_SERVER_ID3 ||
|
|
2067
|
-
if (!channelIdParam || !
|
|
1977
|
+
const isValidServerId = server_id === DEFAULT_SERVER_ID3 || validateUuid12(server_id);
|
|
1978
|
+
if (!channelIdParam || !validateUuid12(author_id) || !content || !isValidServerId) {
|
|
2068
1979
|
return res.status(400).json({
|
|
2069
1980
|
success: false,
|
|
2070
1981
|
error: "Missing required fields: channelId, server_id, author_id, content"
|
|
2071
1982
|
});
|
|
2072
1983
|
}
|
|
2073
1984
|
try {
|
|
2074
|
-
|
|
1985
|
+
logger12.info(
|
|
2075
1986
|
`[Messages Router] Checking if channel ${channelIdParam} exists before creating message`
|
|
2076
1987
|
);
|
|
2077
1988
|
let channelExists = false;
|
|
2078
1989
|
try {
|
|
2079
1990
|
const existingChannel = await serverInstance.getChannelDetails(channelIdParam);
|
|
2080
1991
|
channelExists = !!existingChannel;
|
|
2081
|
-
|
|
1992
|
+
logger12.info(`[Messages Router] Channel ${channelIdParam} exists: ${channelExists}`);
|
|
2082
1993
|
} catch (error) {
|
|
2083
1994
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2084
|
-
|
|
1995
|
+
logger12.info(
|
|
2085
1996
|
`[Messages Router] Channel ${channelIdParam} does not exist, will create it. Error: ${errorMessage}`
|
|
2086
1997
|
);
|
|
2087
1998
|
}
|
|
2088
1999
|
if (!channelExists) {
|
|
2089
|
-
|
|
2000
|
+
logger12.info(
|
|
2090
2001
|
`[Messages Router] Auto-creating channel ${channelIdParam} with serverId ${server_id}`
|
|
2091
2002
|
);
|
|
2092
2003
|
try {
|
|
2093
2004
|
const servers = await serverInstance.getServers();
|
|
2094
2005
|
const serverExists = servers.some((s) => s.id === server_id);
|
|
2095
|
-
|
|
2006
|
+
logger12.info(
|
|
2096
2007
|
`[Messages Router] Server ${server_id} exists: ${serverExists}. Available servers: ${servers.map((s) => s.id).join(", ")}`
|
|
2097
2008
|
);
|
|
2098
2009
|
if (!serverExists) {
|
|
2099
|
-
|
|
2010
|
+
logger12.error(
|
|
2100
2011
|
`[Messages Router] Server ${server_id} does not exist, cannot create channel`
|
|
2101
2012
|
);
|
|
2102
2013
|
return res.status(500).json({ success: false, error: `Server ${server_id} does not exist` });
|
|
@@ -2117,38 +2028,38 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2117
2028
|
...metadata
|
|
2118
2029
|
}
|
|
2119
2030
|
};
|
|
2120
|
-
|
|
2031
|
+
logger12.info(
|
|
2121
2032
|
"[Messages Router] Creating channel with data:",
|
|
2122
2033
|
JSON.stringify(channelData, null, 2)
|
|
2123
2034
|
);
|
|
2124
2035
|
const participants = [author_id];
|
|
2125
2036
|
if (isDmChannel) {
|
|
2126
2037
|
const otherParticipant = metadata?.targetUserId || metadata?.recipientId;
|
|
2127
|
-
if (otherParticipant &&
|
|
2038
|
+
if (otherParticipant && validateUuid12(otherParticipant)) {
|
|
2128
2039
|
participants.push(otherParticipant);
|
|
2129
|
-
|
|
2040
|
+
logger12.info(
|
|
2130
2041
|
`[Messages Router] DM channel will include participants: ${participants.join(", ")}`
|
|
2131
2042
|
);
|
|
2132
2043
|
} else {
|
|
2133
|
-
|
|
2044
|
+
logger12.warn(
|
|
2134
2045
|
`[Messages Router] DM channel missing second participant, only adding author: ${author_id}`
|
|
2135
2046
|
);
|
|
2136
2047
|
}
|
|
2137
2048
|
}
|
|
2138
2049
|
await serverInstance.createChannel(channelData, participants);
|
|
2139
|
-
|
|
2050
|
+
logger12.info(
|
|
2140
2051
|
`[Messages Router] Auto-created ${isDmChannel ? ChannelType2.DM : ChannelType2.GROUP} channel ${channelIdParam} for message submission with ${participants.length} participants`
|
|
2141
2052
|
);
|
|
2142
2053
|
} catch (createError) {
|
|
2143
2054
|
const errorMessage = createError instanceof Error ? createError.message : String(createError);
|
|
2144
|
-
|
|
2055
|
+
logger12.error(
|
|
2145
2056
|
`[Messages Router] Failed to auto-create channel ${channelIdParam}:`,
|
|
2146
2057
|
createError
|
|
2147
2058
|
);
|
|
2148
2059
|
return res.status(500).json({ success: false, error: `Failed to create channel: ${errorMessage}` });
|
|
2149
2060
|
}
|
|
2150
2061
|
} else {
|
|
2151
|
-
|
|
2062
|
+
logger12.info(
|
|
2152
2063
|
`[Messages Router] Channel ${channelIdParam} already exists, proceeding with message creation`
|
|
2153
2064
|
);
|
|
2154
2065
|
}
|
|
@@ -2156,7 +2067,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2156
2067
|
channelId: channelIdParam,
|
|
2157
2068
|
authorId: author_id,
|
|
2158
2069
|
content,
|
|
2159
|
-
inReplyToRootMessageId: in_reply_to_message_id ?
|
|
2070
|
+
inReplyToRootMessageId: in_reply_to_message_id ? validateUuid12(in_reply_to_message_id) || void 0 : void 0,
|
|
2160
2071
|
rawMessage: raw_message,
|
|
2161
2072
|
metadata,
|
|
2162
2073
|
sourceType: source_type || "eliza_gui"
|
|
@@ -2182,7 +2093,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2182
2093
|
// Will be undefined here, which is fine
|
|
2183
2094
|
};
|
|
2184
2095
|
bus_default.emit("new_message", messageForBus);
|
|
2185
|
-
|
|
2096
|
+
logger12.info(
|
|
2186
2097
|
"[Messages Router /central-channels/:channelId/messages] GUI Message published to internal bus:",
|
|
2187
2098
|
messageForBus.id
|
|
2188
2099
|
);
|
|
@@ -2202,7 +2113,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2202
2113
|
}
|
|
2203
2114
|
res.status(201).json({ success: true, data: messageForBus });
|
|
2204
2115
|
} catch (error) {
|
|
2205
|
-
|
|
2116
|
+
logger12.error(
|
|
2206
2117
|
"[Messages Router /central-channels/:channelId/messages] Error processing GUI message:",
|
|
2207
2118
|
error
|
|
2208
2119
|
);
|
|
@@ -2213,7 +2124,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2213
2124
|
router.get(
|
|
2214
2125
|
"/central-channels/:channelId/messages",
|
|
2215
2126
|
async (req, res) => {
|
|
2216
|
-
const channelId =
|
|
2127
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2217
2128
|
const limit = req.query.limit ? Number.parseInt(req.query.limit, 10) : 50;
|
|
2218
2129
|
const before = req.query.before ? Number.parseInt(req.query.before, 10) : void 0;
|
|
2219
2130
|
const beforeDate = before ? new Date(before) : void 0;
|
|
@@ -2240,7 +2151,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2240
2151
|
});
|
|
2241
2152
|
res.json({ success: true, data: { messages: messagesForGui } });
|
|
2242
2153
|
} catch (error) {
|
|
2243
|
-
|
|
2154
|
+
logger12.error(
|
|
2244
2155
|
`[Messages Router /central-channels/:channelId/messages] Error fetching messages for channel ${channelId}:`,
|
|
2245
2156
|
error
|
|
2246
2157
|
);
|
|
@@ -2251,7 +2162,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2251
2162
|
router.get(
|
|
2252
2163
|
"/central-servers/:serverId/channels",
|
|
2253
2164
|
async (req, res) => {
|
|
2254
|
-
const serverId = req.params.serverId === DEFAULT_SERVER_ID3 ? DEFAULT_SERVER_ID3 :
|
|
2165
|
+
const serverId = req.params.serverId === DEFAULT_SERVER_ID3 ? DEFAULT_SERVER_ID3 : validateUuid12(req.params.serverId);
|
|
2255
2166
|
if (!serverId) {
|
|
2256
2167
|
return res.status(400).json({ success: false, error: "Invalid serverId" });
|
|
2257
2168
|
}
|
|
@@ -2259,7 +2170,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2259
2170
|
const channels = await serverInstance.getChannelsForServer(serverId);
|
|
2260
2171
|
res.json({ success: true, data: { channels } });
|
|
2261
2172
|
} catch (error) {
|
|
2262
|
-
|
|
2173
|
+
logger12.error(
|
|
2263
2174
|
`[Messages Router /central-servers/:serverId/channels] Error fetching channels for server ${serverId}:`,
|
|
2264
2175
|
error
|
|
2265
2176
|
);
|
|
@@ -2289,7 +2200,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2289
2200
|
error: "Missing required fields: type."
|
|
2290
2201
|
});
|
|
2291
2202
|
}
|
|
2292
|
-
if (!
|
|
2203
|
+
if (!validateUuid12(serverId)) {
|
|
2293
2204
|
return res.status(400).json({
|
|
2294
2205
|
success: false,
|
|
2295
2206
|
error: "Invalid serverId format"
|
|
@@ -2307,14 +2218,14 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2307
2218
|
});
|
|
2308
2219
|
res.status(201).json({ success: true, data: { channel } });
|
|
2309
2220
|
} catch (error) {
|
|
2310
|
-
|
|
2221
|
+
logger12.error("[Messages Router /channels] Error creating channel:", error);
|
|
2311
2222
|
res.status(500).json({ success: false, error: "Failed to create channel" });
|
|
2312
2223
|
}
|
|
2313
2224
|
});
|
|
2314
2225
|
router.get("/dm-channel", async (req, res) => {
|
|
2315
|
-
const targetUserId =
|
|
2316
|
-
const currentUserId =
|
|
2317
|
-
const providedDmServerId = req.query.dmServerId === DEFAULT_SERVER_ID3 ? DEFAULT_SERVER_ID3 :
|
|
2226
|
+
const targetUserId = validateUuid12(req.query.targetUserId);
|
|
2227
|
+
const currentUserId = validateUuid12(req.query.currentUserId);
|
|
2228
|
+
const providedDmServerId = req.query.dmServerId === DEFAULT_SERVER_ID3 ? DEFAULT_SERVER_ID3 : validateUuid12(req.query.dmServerId);
|
|
2318
2229
|
if (!targetUserId || !currentUserId) {
|
|
2319
2230
|
res.status(400).json({ success: false, error: "Missing targetUserId or currentUserId" });
|
|
2320
2231
|
return;
|
|
@@ -2330,7 +2241,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2330
2241
|
if (existingServer) {
|
|
2331
2242
|
dmServerIdToUse = providedDmServerId;
|
|
2332
2243
|
} else {
|
|
2333
|
-
|
|
2244
|
+
logger12.warn(
|
|
2334
2245
|
`Provided dmServerId ${providedDmServerId} not found, using default DM server logic.`
|
|
2335
2246
|
);
|
|
2336
2247
|
dmServerIdToUse = DEFAULT_SERVER_ID3;
|
|
@@ -2348,7 +2259,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2348
2259
|
stack: error.stack,
|
|
2349
2260
|
originalError: error
|
|
2350
2261
|
} : { message: String(error) };
|
|
2351
|
-
|
|
2262
|
+
logger12.error("Error finding/creating DM channel:", errorDetails);
|
|
2352
2263
|
res.status(500).json({ success: false, error: "Failed to find or create DM channel" });
|
|
2353
2264
|
}
|
|
2354
2265
|
});
|
|
@@ -2360,8 +2271,8 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2360
2271
|
server_id,
|
|
2361
2272
|
metadata
|
|
2362
2273
|
} = req.body;
|
|
2363
|
-
const isValidServerId = server_id === DEFAULT_SERVER_ID3 ||
|
|
2364
|
-
if (!name || !isValidServerId || !Array.isArray(participantCentralUserIds) || participantCentralUserIds.some((id) => !
|
|
2274
|
+
const isValidServerId = server_id === DEFAULT_SERVER_ID3 || validateUuid12(server_id);
|
|
2275
|
+
if (!name || !isValidServerId || !Array.isArray(participantCentralUserIds) || participantCentralUserIds.some((id) => !validateUuid12(id))) {
|
|
2365
2276
|
return res.status(400).json({
|
|
2366
2277
|
success: false,
|
|
2367
2278
|
error: 'Invalid payload. Required: name, server_id (UUID or "0"), participantCentralUserIds (array of UUIDs). Optional: type, metadata.'
|
|
@@ -2384,7 +2295,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2384
2295
|
res.status(201).json({ success: true, data: newChannel });
|
|
2385
2296
|
} catch (error) {
|
|
2386
2297
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2387
|
-
|
|
2298
|
+
logger12.error(
|
|
2388
2299
|
"[Messages Router /central-channels] Error creating group channel:",
|
|
2389
2300
|
errorMessage
|
|
2390
2301
|
);
|
|
@@ -2394,7 +2305,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2394
2305
|
router.get(
|
|
2395
2306
|
"/central-channels/:channelId/details",
|
|
2396
2307
|
async (req, res) => {
|
|
2397
|
-
const channelId =
|
|
2308
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2398
2309
|
if (!channelId) {
|
|
2399
2310
|
return res.status(400).json({ success: false, error: "Invalid channelId" });
|
|
2400
2311
|
}
|
|
@@ -2405,7 +2316,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2405
2316
|
}
|
|
2406
2317
|
res.json({ success: true, data: channelDetails });
|
|
2407
2318
|
} catch (error) {
|
|
2408
|
-
|
|
2319
|
+
logger12.error(`[Messages Router] Error fetching details for channel ${channelId}:`, error);
|
|
2409
2320
|
res.status(500).json({ success: false, error: "Failed to fetch channel details" });
|
|
2410
2321
|
}
|
|
2411
2322
|
}
|
|
@@ -2413,7 +2324,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2413
2324
|
router.get(
|
|
2414
2325
|
"/central-channels/:channelId/participants",
|
|
2415
2326
|
async (req, res) => {
|
|
2416
|
-
const channelId =
|
|
2327
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2417
2328
|
if (!channelId) {
|
|
2418
2329
|
return res.status(400).json({ success: false, error: "Invalid channelId" });
|
|
2419
2330
|
}
|
|
@@ -2421,7 +2332,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2421
2332
|
const participants = await serverInstance.getChannelParticipants(channelId);
|
|
2422
2333
|
res.json({ success: true, data: participants });
|
|
2423
2334
|
} catch (error) {
|
|
2424
|
-
|
|
2335
|
+
logger12.error(
|
|
2425
2336
|
`[Messages Router] Error fetching participants for channel ${channelId}:`,
|
|
2426
2337
|
error
|
|
2427
2338
|
);
|
|
@@ -2432,9 +2343,9 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2432
2343
|
router.post(
|
|
2433
2344
|
"/central-channels/:channelId/agents",
|
|
2434
2345
|
async (req, res) => {
|
|
2435
|
-
const channelId =
|
|
2346
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2436
2347
|
const { agentId } = req.body;
|
|
2437
|
-
if (!channelId || !
|
|
2348
|
+
if (!channelId || !validateUuid12(agentId)) {
|
|
2438
2349
|
return res.status(400).json({
|
|
2439
2350
|
success: false,
|
|
2440
2351
|
error: "Invalid channelId or agentId format"
|
|
@@ -2449,7 +2360,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2449
2360
|
});
|
|
2450
2361
|
}
|
|
2451
2362
|
await serverInstance.addParticipantsToChannel(channelId, [agentId]);
|
|
2452
|
-
|
|
2363
|
+
logger12.info(`[Messages Router] Added agent ${agentId} to channel ${channelId}`);
|
|
2453
2364
|
res.status(201).json({
|
|
2454
2365
|
success: true,
|
|
2455
2366
|
data: {
|
|
@@ -2459,7 +2370,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2459
2370
|
}
|
|
2460
2371
|
});
|
|
2461
2372
|
} catch (error) {
|
|
2462
|
-
|
|
2373
|
+
logger12.error(
|
|
2463
2374
|
`[Messages Router] Error adding agent ${agentId} to channel ${channelId}:`,
|
|
2464
2375
|
error
|
|
2465
2376
|
);
|
|
@@ -2474,8 +2385,8 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2474
2385
|
router.delete(
|
|
2475
2386
|
"/central-channels/:channelId/agents/:agentId",
|
|
2476
2387
|
async (req, res) => {
|
|
2477
|
-
const channelId =
|
|
2478
|
-
const agentId =
|
|
2388
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2389
|
+
const agentId = validateUuid12(req.params.agentId);
|
|
2479
2390
|
if (!channelId || !agentId) {
|
|
2480
2391
|
return res.status(400).json({
|
|
2481
2392
|
success: false,
|
|
@@ -2501,7 +2412,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2501
2412
|
await serverInstance.updateChannel(channelId, {
|
|
2502
2413
|
participantCentralUserIds: updatedParticipants
|
|
2503
2414
|
});
|
|
2504
|
-
|
|
2415
|
+
logger12.info(`[Messages Router] Removed agent ${agentId} from channel ${channelId}`);
|
|
2505
2416
|
res.status(200).json({
|
|
2506
2417
|
success: true,
|
|
2507
2418
|
data: {
|
|
@@ -2511,7 +2422,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2511
2422
|
}
|
|
2512
2423
|
});
|
|
2513
2424
|
} catch (error) {
|
|
2514
|
-
|
|
2425
|
+
logger12.error(
|
|
2515
2426
|
`[Messages Router] Error removing agent ${agentId} from channel ${channelId}:`,
|
|
2516
2427
|
error
|
|
2517
2428
|
);
|
|
@@ -2526,7 +2437,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2526
2437
|
router.get(
|
|
2527
2438
|
"/central-channels/:channelId/agents",
|
|
2528
2439
|
async (req, res) => {
|
|
2529
|
-
const channelId =
|
|
2440
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2530
2441
|
if (!channelId) {
|
|
2531
2442
|
return res.status(400).json({
|
|
2532
2443
|
success: false,
|
|
@@ -2545,7 +2456,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2545
2456
|
}
|
|
2546
2457
|
});
|
|
2547
2458
|
} catch (error) {
|
|
2548
|
-
|
|
2459
|
+
logger12.error(`[Messages Router] Error fetching agents for channel ${channelId}:`, error);
|
|
2549
2460
|
res.status(500).json({
|
|
2550
2461
|
success: false,
|
|
2551
2462
|
error: "Failed to fetch channel agents"
|
|
@@ -2556,20 +2467,20 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2556
2467
|
router.delete(
|
|
2557
2468
|
"/central-channels/:channelId/messages/:messageId",
|
|
2558
2469
|
async (req, res) => {
|
|
2559
|
-
const channelId =
|
|
2560
|
-
const messageId =
|
|
2470
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2471
|
+
const messageId = validateUuid12(req.params.messageId);
|
|
2561
2472
|
if (!channelId || !messageId) {
|
|
2562
2473
|
return res.status(400).json({ success: false, error: "Invalid channelId or messageId" });
|
|
2563
2474
|
}
|
|
2564
2475
|
try {
|
|
2565
2476
|
await serverInstance.deleteMessage(messageId);
|
|
2566
|
-
|
|
2477
|
+
logger12.info(`[Messages Router] Deleted message ${messageId} from central database`);
|
|
2567
2478
|
const deletedMessagePayload = {
|
|
2568
2479
|
messageId,
|
|
2569
2480
|
channelId
|
|
2570
2481
|
};
|
|
2571
2482
|
bus_default.emit("message_deleted", deletedMessagePayload);
|
|
2572
|
-
|
|
2483
|
+
logger12.info(
|
|
2573
2484
|
`[Messages Router] Emitted message_deleted event to internal bus for message ${messageId}`
|
|
2574
2485
|
);
|
|
2575
2486
|
if (serverInstance.socketIO) {
|
|
@@ -2580,7 +2491,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2580
2491
|
}
|
|
2581
2492
|
res.status(204).send();
|
|
2582
2493
|
} catch (error) {
|
|
2583
|
-
|
|
2494
|
+
logger12.error(
|
|
2584
2495
|
`[Messages Router] Error deleting message ${messageId} from channel ${channelId}:`,
|
|
2585
2496
|
error
|
|
2586
2497
|
);
|
|
@@ -2591,7 +2502,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2591
2502
|
router.delete(
|
|
2592
2503
|
"/central-channels/:channelId/messages",
|
|
2593
2504
|
async (req, res) => {
|
|
2594
|
-
const channelId =
|
|
2505
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2595
2506
|
if (!channelId) {
|
|
2596
2507
|
return res.status(400).json({ success: false, error: "Invalid channelId" });
|
|
2597
2508
|
}
|
|
@@ -2601,7 +2512,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2601
2512
|
channelId
|
|
2602
2513
|
};
|
|
2603
2514
|
bus_default.emit("channel_cleared", channelClearedPayload);
|
|
2604
|
-
|
|
2515
|
+
logger12.info(
|
|
2605
2516
|
`[Messages Router] Emitted channel_cleared event to internal bus for channel ${channelId}`
|
|
2606
2517
|
);
|
|
2607
2518
|
if (serverInstance.socketIO) {
|
|
@@ -2611,7 +2522,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2611
2522
|
}
|
|
2612
2523
|
res.status(204).send();
|
|
2613
2524
|
} catch (error) {
|
|
2614
|
-
|
|
2525
|
+
logger12.error(`[Messages Router] Error clearing messages for channel ${channelId}:`, error);
|
|
2615
2526
|
res.status(500).json({ success: false, error: "Failed to clear messages" });
|
|
2616
2527
|
}
|
|
2617
2528
|
}
|
|
@@ -2619,7 +2530,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2619
2530
|
router.patch(
|
|
2620
2531
|
"/central-channels/:channelId",
|
|
2621
2532
|
async (req, res) => {
|
|
2622
|
-
const channelId =
|
|
2533
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2623
2534
|
if (!channelId) {
|
|
2624
2535
|
return res.status(400).json({ success: false, error: "Invalid channelId" });
|
|
2625
2536
|
}
|
|
@@ -2638,7 +2549,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2638
2549
|
}
|
|
2639
2550
|
res.json({ success: true, data: updatedChannel });
|
|
2640
2551
|
} catch (error) {
|
|
2641
|
-
|
|
2552
|
+
logger12.error(`[Messages Router] Error updating channel ${channelId}:`, error);
|
|
2642
2553
|
res.status(500).json({ success: false, error: "Failed to update channel" });
|
|
2643
2554
|
}
|
|
2644
2555
|
}
|
|
@@ -2646,7 +2557,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2646
2557
|
router.delete(
|
|
2647
2558
|
"/central-channels/:channelId",
|
|
2648
2559
|
async (req, res) => {
|
|
2649
|
-
const channelId =
|
|
2560
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2650
2561
|
if (!channelId) {
|
|
2651
2562
|
return res.status(400).json({ success: false, error: "Invalid channelId" });
|
|
2652
2563
|
}
|
|
@@ -2654,14 +2565,14 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2654
2565
|
const messages = await serverInstance.getMessagesForChannel(channelId);
|
|
2655
2566
|
const messageCount = messages.length;
|
|
2656
2567
|
await serverInstance.deleteChannel(channelId);
|
|
2657
|
-
|
|
2568
|
+
logger12.info(
|
|
2658
2569
|
`[Messages Router] Deleted channel ${channelId} with ${messageCount} messages from central database`
|
|
2659
2570
|
);
|
|
2660
2571
|
const channelClearedPayload = {
|
|
2661
2572
|
channelId
|
|
2662
2573
|
};
|
|
2663
2574
|
bus_default.emit("channel_cleared", channelClearedPayload);
|
|
2664
|
-
|
|
2575
|
+
logger12.info(
|
|
2665
2576
|
`[Messages Router] Emitted channel_cleared event to internal bus for deleted channel ${channelId}`
|
|
2666
2577
|
);
|
|
2667
2578
|
if (serverInstance.socketIO) {
|
|
@@ -2671,7 +2582,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2671
2582
|
}
|
|
2672
2583
|
res.status(204).send();
|
|
2673
2584
|
} catch (error) {
|
|
2674
|
-
|
|
2585
|
+
logger12.error(`[Messages Router] Error deleting channel ${channelId}:`, error);
|
|
2675
2586
|
res.status(500).json({ success: false, error: "Failed to delete channel" });
|
|
2676
2587
|
}
|
|
2677
2588
|
}
|
|
@@ -2680,44 +2591,24 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2680
2591
|
"/channels/:channelId/upload-media",
|
|
2681
2592
|
createUploadRateLimit(),
|
|
2682
2593
|
createFileSystemRateLimit(),
|
|
2683
|
-
|
|
2594
|
+
channelUploadMiddleware.single("file"),
|
|
2684
2595
|
async (req, res) => {
|
|
2685
|
-
const channelId =
|
|
2596
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2686
2597
|
if (!channelId) {
|
|
2687
2598
|
res.status(400).json({ success: false, error: "Invalid channelId format" });
|
|
2688
2599
|
return;
|
|
2689
2600
|
}
|
|
2690
|
-
|
|
2691
|
-
if (req.files && !Array.isArray(req.files)) {
|
|
2692
|
-
mediaFile = req.files.file;
|
|
2693
|
-
} else if (Array.isArray(req.files) && req.files.length > 0) {
|
|
2694
|
-
mediaFile = req.files[0];
|
|
2695
|
-
} else {
|
|
2696
|
-
res.status(400).json({ success: false, error: "No media file provided" });
|
|
2697
|
-
return;
|
|
2698
|
-
}
|
|
2699
|
-
if (!mediaFile) {
|
|
2601
|
+
if (!req.file) {
|
|
2700
2602
|
res.status(400).json({ success: false, error: "No media file provided" });
|
|
2701
2603
|
return;
|
|
2702
2604
|
}
|
|
2703
2605
|
try {
|
|
2704
|
-
if (!
|
|
2705
|
-
cleanupUploadedFile(mediaFile);
|
|
2706
|
-
res.status(400).json({ success: false, error: `Invalid file type: ${mediaFile.mimetype}` });
|
|
2707
|
-
return;
|
|
2708
|
-
}
|
|
2709
|
-
if (!mediaFile.name || mediaFile.name.includes("..") || mediaFile.name.includes("/")) {
|
|
2710
|
-
cleanupUploadedFile(mediaFile);
|
|
2606
|
+
if (!req.file.originalname || req.file.originalname.includes("..") || req.file.originalname.includes("/")) {
|
|
2711
2607
|
res.status(400).json({ success: false, error: "Invalid filename detected" });
|
|
2712
2608
|
return;
|
|
2713
2609
|
}
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
res.status(400).json({ success: false, error: "File too large" });
|
|
2717
|
-
return;
|
|
2718
|
-
}
|
|
2719
|
-
const result = await processUploadedFile(mediaFile, channelId, "channels");
|
|
2720
|
-
logger14.info(
|
|
2610
|
+
const result = await saveChannelUploadedFile(req.file, channelId);
|
|
2611
|
+
logger12.info(
|
|
2721
2612
|
`[MessagesRouter /upload-media] Secure file uploaded for channel ${channelId}: ${result.filename}. URL: ${result.url}`
|
|
2722
2613
|
);
|
|
2723
2614
|
res.json({
|
|
@@ -2725,21 +2616,18 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2725
2616
|
data: {
|
|
2726
2617
|
url: result.url,
|
|
2727
2618
|
// Relative URL, client prepends server origin
|
|
2728
|
-
type:
|
|
2619
|
+
type: req.file.mimetype,
|
|
2729
2620
|
filename: result.filename,
|
|
2730
|
-
originalName:
|
|
2731
|
-
size:
|
|
2621
|
+
originalName: req.file.originalname,
|
|
2622
|
+
size: req.file.size
|
|
2732
2623
|
}
|
|
2733
2624
|
});
|
|
2734
2625
|
} catch (error) {
|
|
2735
2626
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2736
|
-
|
|
2627
|
+
logger12.error(
|
|
2737
2628
|
`[MessagesRouter /upload-media] Error processing upload for channel ${channelId}: ${errorMessage}`,
|
|
2738
2629
|
error
|
|
2739
2630
|
);
|
|
2740
|
-
if (mediaFile) {
|
|
2741
|
-
cleanupUploadedFile(mediaFile);
|
|
2742
|
-
}
|
|
2743
2631
|
res.status(500).json({ success: false, error: "Failed to process media upload" });
|
|
2744
2632
|
}
|
|
2745
2633
|
}
|
|
@@ -2747,7 +2635,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2747
2635
|
router.post(
|
|
2748
2636
|
"/central-channels/:channelId/generate-title",
|
|
2749
2637
|
async (req, res) => {
|
|
2750
|
-
const channelId =
|
|
2638
|
+
const channelId = validateUuid12(req.params.channelId);
|
|
2751
2639
|
const { agentId } = req.body;
|
|
2752
2640
|
if (!channelId) {
|
|
2753
2641
|
return res.status(400).json({
|
|
@@ -2755,7 +2643,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2755
2643
|
error: "Invalid channel ID format"
|
|
2756
2644
|
});
|
|
2757
2645
|
}
|
|
2758
|
-
if (!agentId || !
|
|
2646
|
+
if (!agentId || !validateUuid12(agentId)) {
|
|
2759
2647
|
return res.status(400).json({
|
|
2760
2648
|
success: false,
|
|
2761
2649
|
error: "Valid agent ID is required"
|
|
@@ -2769,7 +2657,7 @@ function createChannelsRouter(agents, serverInstance) {
|
|
|
2769
2657
|
error: "Agent not found or not active"
|
|
2770
2658
|
});
|
|
2771
2659
|
}
|
|
2772
|
-
|
|
2660
|
+
logger12.info(`[CHANNEL SUMMARIZE] Summarizing channel ${channelId}`);
|
|
2773
2661
|
const limit = req.query.limit ? Number.parseInt(req.query.limit, 10) : 50;
|
|
2774
2662
|
const before = req.query.before ? Number.parseInt(req.query.before, 10) : void 0;
|
|
2775
2663
|
const beforeDate = before ? new Date(before) : void 0;
|
|
@@ -2823,22 +2711,22 @@ Respond with just the title, nothing else.
|
|
|
2823
2711
|
// Keep titles short
|
|
2824
2712
|
});
|
|
2825
2713
|
if (!newTitle || newTitle.trim().length === 0) {
|
|
2826
|
-
|
|
2714
|
+
logger12.warn(`[ChatTitleEvaluator] Failed to generate title for room ${channelId}`);
|
|
2827
2715
|
return;
|
|
2828
2716
|
}
|
|
2829
2717
|
const cleanTitle = newTitle.trim().replace(/^["']|["']$/g, "");
|
|
2830
|
-
|
|
2718
|
+
logger12.info(`[ChatTitleEvaluator] Generated title: "${cleanTitle}" for room ${channelId}`);
|
|
2831
2719
|
const result = {
|
|
2832
2720
|
title: cleanTitle,
|
|
2833
2721
|
channelId
|
|
2834
2722
|
};
|
|
2835
|
-
|
|
2723
|
+
logger12.success(`[CHANNEL SUMMARIZE] Successfully summarized channel ${channelId}`);
|
|
2836
2724
|
res.json({
|
|
2837
2725
|
success: true,
|
|
2838
2726
|
data: result
|
|
2839
2727
|
});
|
|
2840
2728
|
} catch (error) {
|
|
2841
|
-
|
|
2729
|
+
logger12.error("[CHANNEL SUMMARIZE] Error summarizing channel:", error);
|
|
2842
2730
|
res.status(500).json({
|
|
2843
2731
|
success: false,
|
|
2844
2732
|
error: "Failed to summarize channel",
|
|
@@ -2866,58 +2754,74 @@ function messagingRouter(agents, serverInstance) {
|
|
|
2866
2754
|
import express15 from "express";
|
|
2867
2755
|
|
|
2868
2756
|
// src/api/media/agents.ts
|
|
2869
|
-
import { validateUuid as
|
|
2757
|
+
import { validateUuid as validateUuid13, logger as logger13, getContentTypeFromMimeType } from "@elizaos/core";
|
|
2870
2758
|
import express13 from "express";
|
|
2759
|
+
import multer2 from "multer";
|
|
2760
|
+
import fs2 from "fs";
|
|
2761
|
+
import path2 from "path";
|
|
2762
|
+
var storage = multer2.memoryStorage();
|
|
2763
|
+
var upload = multer2({
|
|
2764
|
+
storage,
|
|
2765
|
+
limits: {
|
|
2766
|
+
fileSize: MAX_FILE_SIZE,
|
|
2767
|
+
files: 1
|
|
2768
|
+
},
|
|
2769
|
+
fileFilter: (req, file, cb) => {
|
|
2770
|
+
if (ALLOWED_MEDIA_MIME_TYPES.includes(file.mimetype)) {
|
|
2771
|
+
cb(null, true);
|
|
2772
|
+
} else {
|
|
2773
|
+
cb(new Error("Invalid file type"), false);
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
});
|
|
2777
|
+
async function saveUploadedFile(file, agentId) {
|
|
2778
|
+
const uploadDir = path2.join(process.cwd(), ".eliza/data/uploads/agents", agentId);
|
|
2779
|
+
if (!fs2.existsSync(uploadDir)) {
|
|
2780
|
+
fs2.mkdirSync(uploadDir, { recursive: true });
|
|
2781
|
+
}
|
|
2782
|
+
const timestamp = Date.now();
|
|
2783
|
+
const random = Math.round(Math.random() * 1e9);
|
|
2784
|
+
const ext = path2.extname(file.originalname);
|
|
2785
|
+
const filename = `${timestamp}-${random}${ext}`;
|
|
2786
|
+
const filePath = path2.join(uploadDir, filename);
|
|
2787
|
+
fs2.writeFileSync(filePath, file.buffer);
|
|
2788
|
+
const url = `/media/uploads/agents/${agentId}/${filename}`;
|
|
2789
|
+
return { filename, url };
|
|
2790
|
+
}
|
|
2871
2791
|
function createAgentMediaRouter() {
|
|
2872
2792
|
const router = express13.Router();
|
|
2873
|
-
router.post("/:agentId/upload-media",
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
const agentId = validateUuid14(agentMediaReq.params.agentId);
|
|
2793
|
+
router.post("/:agentId/upload-media", upload.single("file"), async (req, res) => {
|
|
2794
|
+
logger13.debug("[MEDIA UPLOAD] Processing media upload with multer");
|
|
2795
|
+
const agentId = validateUuid13(req.params.agentId);
|
|
2877
2796
|
if (!agentId) {
|
|
2878
2797
|
return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
|
|
2879
2798
|
}
|
|
2880
|
-
|
|
2881
|
-
if (agentMediaReq.files && !Array.isArray(agentMediaReq.files)) {
|
|
2882
|
-
mediaFile = agentMediaReq.files.file;
|
|
2883
|
-
} else if (Array.isArray(agentMediaReq.files) && agentMediaReq.files.length > 0) {
|
|
2884
|
-
mediaFile = agentMediaReq.files[0];
|
|
2885
|
-
} else {
|
|
2886
|
-
return sendError(res, 400, "INVALID_REQUEST", "No media file provided");
|
|
2887
|
-
}
|
|
2888
|
-
if (!mediaFile) {
|
|
2799
|
+
if (!req.file) {
|
|
2889
2800
|
return sendError(res, 400, "INVALID_REQUEST", "No media file provided");
|
|
2890
2801
|
}
|
|
2891
|
-
const
|
|
2892
|
-
if (!validateMediaFile(mediaFile)) {
|
|
2893
|
-
cleanupUploadedFile(mediaFile);
|
|
2894
|
-
return sendError(res, 400, "INVALID_FILE_TYPE", "Unsupported media file type");
|
|
2895
|
-
}
|
|
2896
|
-
const mediaType = getContentTypeFromMimeType(mimetype);
|
|
2802
|
+
const mediaType = getContentTypeFromMimeType(req.file.mimetype);
|
|
2897
2803
|
if (!mediaType) {
|
|
2898
|
-
cleanupUploadedFile(mediaFile);
|
|
2899
2804
|
return sendError(
|
|
2900
2805
|
res,
|
|
2901
2806
|
400,
|
|
2902
2807
|
"UNSUPPORTED_MEDIA_TYPE",
|
|
2903
|
-
`Unsupported media MIME type: ${mimetype}`
|
|
2808
|
+
`Unsupported media MIME type: ${req.file.mimetype}`
|
|
2904
2809
|
);
|
|
2905
2810
|
}
|
|
2906
2811
|
try {
|
|
2907
|
-
const result = await
|
|
2908
|
-
|
|
2812
|
+
const result = await saveUploadedFile(req.file, agentId);
|
|
2813
|
+
logger13.info(
|
|
2909
2814
|
`[MEDIA UPLOAD] Successfully uploaded ${mediaType}: ${result.filename}. URL: ${result.url}`
|
|
2910
2815
|
);
|
|
2911
2816
|
sendSuccess(res, {
|
|
2912
2817
|
url: result.url,
|
|
2913
2818
|
type: mediaType,
|
|
2914
2819
|
filename: result.filename,
|
|
2915
|
-
originalName:
|
|
2916
|
-
size:
|
|
2820
|
+
originalName: req.file.originalname,
|
|
2821
|
+
size: req.file.size
|
|
2917
2822
|
});
|
|
2918
2823
|
} catch (error) {
|
|
2919
|
-
|
|
2920
|
-
cleanupUploadedFile(mediaFile);
|
|
2824
|
+
logger13.error(`[MEDIA UPLOAD] Error processing upload: ${error}`);
|
|
2921
2825
|
sendError(
|
|
2922
2826
|
res,
|
|
2923
2827
|
500,
|
|
@@ -2931,9 +2835,41 @@ function createAgentMediaRouter() {
|
|
|
2931
2835
|
}
|
|
2932
2836
|
|
|
2933
2837
|
// src/api/media/channels.ts
|
|
2934
|
-
import { validateUuid as
|
|
2838
|
+
import { validateUuid as validateUuid14, logger as logger14 } from "@elizaos/core";
|
|
2935
2839
|
import express14 from "express";
|
|
2936
2840
|
import rateLimit2 from "express-rate-limit";
|
|
2841
|
+
import multer3 from "multer";
|
|
2842
|
+
import fs3 from "fs";
|
|
2843
|
+
import path3 from "path";
|
|
2844
|
+
var storage2 = multer3.memoryStorage();
|
|
2845
|
+
var upload2 = multer3({
|
|
2846
|
+
storage: storage2,
|
|
2847
|
+
limits: {
|
|
2848
|
+
fileSize: MAX_FILE_SIZE,
|
|
2849
|
+
files: 1
|
|
2850
|
+
},
|
|
2851
|
+
fileFilter: (req, file, cb) => {
|
|
2852
|
+
if (ALLOWED_MEDIA_MIME_TYPES.includes(file.mimetype)) {
|
|
2853
|
+
cb(null, true);
|
|
2854
|
+
} else {
|
|
2855
|
+
cb(new Error("Invalid file type"), false);
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2858
|
+
});
|
|
2859
|
+
async function saveUploadedFile2(file, channelId) {
|
|
2860
|
+
const uploadDir = path3.join(process.cwd(), ".eliza/data/uploads/channels", channelId);
|
|
2861
|
+
if (!fs3.existsSync(uploadDir)) {
|
|
2862
|
+
fs3.mkdirSync(uploadDir, { recursive: true });
|
|
2863
|
+
}
|
|
2864
|
+
const timestamp = Date.now();
|
|
2865
|
+
const random = Math.round(Math.random() * 1e9);
|
|
2866
|
+
const ext = path3.extname(file.originalname);
|
|
2867
|
+
const filename = `${timestamp}-${random}${ext}`;
|
|
2868
|
+
const filePath = path3.join(uploadDir, filename);
|
|
2869
|
+
fs3.writeFileSync(filePath, file.buffer);
|
|
2870
|
+
const url = `/media/uploads/channels/${channelId}/${filename}`;
|
|
2871
|
+
return { filename, url };
|
|
2872
|
+
}
|
|
2937
2873
|
function createChannelMediaRouter() {
|
|
2938
2874
|
const router = express14.Router();
|
|
2939
2875
|
const uploadMediaRateLimiter = rateLimit2({
|
|
@@ -2947,35 +2883,20 @@ function createChannelMediaRouter() {
|
|
|
2947
2883
|
"/:channelId/upload-media",
|
|
2948
2884
|
uploadMediaRateLimiter,
|
|
2949
2885
|
// Apply rate limiter
|
|
2950
|
-
|
|
2886
|
+
upload2.single("file"),
|
|
2951
2887
|
async (req, res) => {
|
|
2952
|
-
const
|
|
2953
|
-
const channelId = validateUuid15(channelMediaReq.params.channelId);
|
|
2888
|
+
const channelId = validateUuid14(req.params.channelId);
|
|
2954
2889
|
if (!channelId) {
|
|
2955
2890
|
res.status(400).json({ success: false, error: "Invalid channelId format" });
|
|
2956
2891
|
return;
|
|
2957
2892
|
}
|
|
2958
|
-
|
|
2959
|
-
if (channelMediaReq.files && !Array.isArray(channelMediaReq.files)) {
|
|
2960
|
-
mediaFile = channelMediaReq.files.file;
|
|
2961
|
-
} else if (Array.isArray(channelMediaReq.files) && channelMediaReq.files.length > 0) {
|
|
2962
|
-
mediaFile = channelMediaReq.files[0];
|
|
2963
|
-
} else {
|
|
2964
|
-
res.status(400).json({ success: false, error: "No media file provided" });
|
|
2965
|
-
return;
|
|
2966
|
-
}
|
|
2967
|
-
if (!mediaFile) {
|
|
2893
|
+
if (!req.file) {
|
|
2968
2894
|
res.status(400).json({ success: false, error: "No media file provided" });
|
|
2969
2895
|
return;
|
|
2970
2896
|
}
|
|
2971
|
-
if (!validateMediaFile(mediaFile)) {
|
|
2972
|
-
cleanupUploadedFile(mediaFile);
|
|
2973
|
-
res.status(400).json({ success: false, error: `Invalid file type: ${mediaFile.mimetype}` });
|
|
2974
|
-
return;
|
|
2975
|
-
}
|
|
2976
2897
|
try {
|
|
2977
|
-
const result = await
|
|
2978
|
-
|
|
2898
|
+
const result = await saveUploadedFile2(req.file, channelId);
|
|
2899
|
+
logger14.info(
|
|
2979
2900
|
`[Channel Media Upload] File uploaded for channel ${channelId}: ${result.filename}. URL: ${result.url}`
|
|
2980
2901
|
);
|
|
2981
2902
|
res.json({
|
|
@@ -2983,18 +2904,17 @@ function createChannelMediaRouter() {
|
|
|
2983
2904
|
data: {
|
|
2984
2905
|
url: result.url,
|
|
2985
2906
|
// Relative URL, client prepends server origin
|
|
2986
|
-
type:
|
|
2907
|
+
type: req.file.mimetype,
|
|
2987
2908
|
filename: result.filename,
|
|
2988
|
-
originalName:
|
|
2989
|
-
size:
|
|
2909
|
+
originalName: req.file.originalname,
|
|
2910
|
+
size: req.file.size
|
|
2990
2911
|
}
|
|
2991
2912
|
});
|
|
2992
2913
|
} catch (error) {
|
|
2993
|
-
|
|
2914
|
+
logger14.error(
|
|
2994
2915
|
`[Channel Media Upload] Error processing upload for channel ${channelId}: ${error.message}`,
|
|
2995
2916
|
error
|
|
2996
2917
|
);
|
|
2997
|
-
cleanupUploadedFile(mediaFile);
|
|
2998
2918
|
res.status(500).json({ success: false, error: "Failed to process media upload" });
|
|
2999
2919
|
}
|
|
3000
2920
|
}
|
|
@@ -3016,6 +2936,40 @@ import express17 from "express";
|
|
|
3016
2936
|
// src/api/memory/groups.ts
|
|
3017
2937
|
import { validateUuid as validateUuid16, logger as logger17, createUniqueUuid as createUniqueUuid4, ChannelType as ChannelType3 } from "@elizaos/core";
|
|
3018
2938
|
import express16 from "express";
|
|
2939
|
+
|
|
2940
|
+
// src/api/shared/file-utils.ts
|
|
2941
|
+
import fs4 from "fs";
|
|
2942
|
+
import path4 from "path";
|
|
2943
|
+
import { logger as logger15 } from "@elizaos/core";
|
|
2944
|
+
var cleanupUploadedFile = (file) => {
|
|
2945
|
+
logger15.debug(`[FILE] Multer file ${file.originalname} in memory, no cleanup needed`);
|
|
2946
|
+
};
|
|
2947
|
+
|
|
2948
|
+
// src/upload.ts
|
|
2949
|
+
import fs5 from "fs";
|
|
2950
|
+
import path5 from "path";
|
|
2951
|
+
import multer4 from "multer";
|
|
2952
|
+
import { validateUuid as validateUuid15, logger as logger16 } from "@elizaos/core";
|
|
2953
|
+
var storage3 = multer4.memoryStorage();
|
|
2954
|
+
var agentAudioUpload = () => multer4({
|
|
2955
|
+
storage: storage3,
|
|
2956
|
+
limits: {
|
|
2957
|
+
fileSize: MAX_FILE_SIZE,
|
|
2958
|
+
files: 1
|
|
2959
|
+
},
|
|
2960
|
+
fileFilter: (req, file, cb) => {
|
|
2961
|
+
if (ALLOWED_AUDIO_MIME_TYPES.includes(file.mimetype)) {
|
|
2962
|
+
cb(null, true);
|
|
2963
|
+
} else {
|
|
2964
|
+
cb(new Error("Invalid audio file type"), false);
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
});
|
|
2968
|
+
function validateAudioFile(file) {
|
|
2969
|
+
return ALLOWED_AUDIO_MIME_TYPES.includes(file.mimetype);
|
|
2970
|
+
}
|
|
2971
|
+
|
|
2972
|
+
// src/api/memory/groups.ts
|
|
3019
2973
|
function createGroupMemoryRouter(agents, serverInstance) {
|
|
3020
2974
|
const router = express16.Router();
|
|
3021
2975
|
const db = serverInstance?.database;
|
|
@@ -3147,184 +3101,110 @@ import express21 from "express";
|
|
|
3147
3101
|
// src/api/audio/processing.ts
|
|
3148
3102
|
import { logger as logger18, ModelType as ModelType2, validateUuid as validateUuid17 } from "@elizaos/core";
|
|
3149
3103
|
import express18 from "express";
|
|
3150
|
-
import
|
|
3104
|
+
import fs6 from "fs";
|
|
3151
3105
|
import os from "os";
|
|
3152
|
-
import
|
|
3153
|
-
function validateSecureFilePath(filePath) {
|
|
3154
|
-
if (!filePath) {
|
|
3155
|
-
throw new Error("File path is required");
|
|
3156
|
-
}
|
|
3157
|
-
const resolvedPath = path3.resolve(filePath);
|
|
3158
|
-
const normalizedPath = path3.normalize(resolvedPath);
|
|
3159
|
-
if (normalizedPath.includes("..") || normalizedPath !== resolvedPath) {
|
|
3160
|
-
throw new Error("Invalid file path: path traversal detected");
|
|
3161
|
-
}
|
|
3162
|
-
const allowedBasePaths = [process.cwd(), os.tmpdir(), os.homedir()];
|
|
3163
|
-
const isPathAllowed = allowedBasePaths.some(
|
|
3164
|
-
(basePath) => normalizedPath.startsWith(path3.resolve(basePath))
|
|
3165
|
-
);
|
|
3166
|
-
if (!isPathAllowed) {
|
|
3167
|
-
throw new Error("Invalid file path: path outside allowed directories");
|
|
3168
|
-
}
|
|
3169
|
-
try {
|
|
3170
|
-
const stats = fs3.statSync(normalizedPath);
|
|
3171
|
-
if (!stats.isFile()) {
|
|
3172
|
-
throw new Error("Path does not point to a regular file");
|
|
3173
|
-
}
|
|
3174
|
-
} catch (error) {
|
|
3175
|
-
throw new Error(`File access error: ${error instanceof Error ? error.message : String(error)}`);
|
|
3176
|
-
}
|
|
3177
|
-
return normalizedPath;
|
|
3178
|
-
}
|
|
3179
|
-
function getUploadedFile(req) {
|
|
3180
|
-
if (req.files && !Array.isArray(req.files)) {
|
|
3181
|
-
return req.files.file;
|
|
3182
|
-
} else if (Array.isArray(req.files) && req.files.length > 0) {
|
|
3183
|
-
return req.files[0];
|
|
3184
|
-
}
|
|
3185
|
-
return null;
|
|
3186
|
-
}
|
|
3106
|
+
import path6 from "path";
|
|
3187
3107
|
function createAudioProcessingRouter(agents) {
|
|
3188
3108
|
const router = express18.Router();
|
|
3189
3109
|
router.use(createUploadRateLimit());
|
|
3190
3110
|
router.use(createFileSystemRateLimit());
|
|
3191
|
-
router.post(
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3111
|
+
router.post("/:agentId/audio-messages", agentAudioUpload().single("file"), async (req, res) => {
|
|
3112
|
+
const audioReq = req;
|
|
3113
|
+
logger18.debug("[AUDIO MESSAGE] Processing audio message");
|
|
3114
|
+
const agentId = validateUuid17(req.params.agentId);
|
|
3115
|
+
if (!agentId) {
|
|
3116
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
|
|
3117
|
+
}
|
|
3118
|
+
const audioFile = audioReq.file;
|
|
3119
|
+
if (!audioFile) {
|
|
3120
|
+
return sendError(res, 400, "INVALID_REQUEST", "No audio file provided");
|
|
3121
|
+
}
|
|
3122
|
+
const runtime = agents.get(agentId);
|
|
3123
|
+
if (!runtime) {
|
|
3124
|
+
cleanupUploadedFile(audioFile);
|
|
3125
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
3126
|
+
}
|
|
3127
|
+
try {
|
|
3128
|
+
if (!validateAudioFile(audioFile)) {
|
|
3208
3129
|
cleanupUploadedFile(audioFile);
|
|
3209
|
-
return sendError(res,
|
|
3130
|
+
return sendError(res, 400, "INVALID_FILE_TYPE", "Invalid audio file type");
|
|
3210
3131
|
}
|
|
3211
|
-
|
|
3212
|
-
if (!validateAudioFile(audioFile)) {
|
|
3213
|
-
cleanupUploadedFile(audioFile);
|
|
3214
|
-
return sendError(res, 400, "INVALID_FILE_TYPE", "Invalid audio file type");
|
|
3215
|
-
}
|
|
3216
|
-
let securePath;
|
|
3217
|
-
try {
|
|
3218
|
-
const filePath = audioFile.tempFilePath || "";
|
|
3219
|
-
securePath = validateSecureFilePath(filePath);
|
|
3220
|
-
} catch (pathError) {
|
|
3221
|
-
cleanupUploadedFile(audioFile);
|
|
3222
|
-
return sendError(
|
|
3223
|
-
res,
|
|
3224
|
-
403,
|
|
3225
|
-
"INVALID_PATH",
|
|
3226
|
-
`Invalid file path: ${pathError instanceof Error ? pathError.message : String(pathError)}`
|
|
3227
|
-
);
|
|
3228
|
-
}
|
|
3229
|
-
const stats = await fs3.promises.stat(securePath);
|
|
3230
|
-
if (stats.size > MAX_FILE_SIZE) {
|
|
3231
|
-
cleanupUploadedFile(audioFile);
|
|
3232
|
-
return sendError(
|
|
3233
|
-
res,
|
|
3234
|
-
413,
|
|
3235
|
-
"FILE_TOO_LARGE",
|
|
3236
|
-
`Audio file too large (max ${MAX_FILE_SIZE_DISPLAY})`
|
|
3237
|
-
);
|
|
3238
|
-
}
|
|
3239
|
-
const audioBuffer = await fs3.promises.readFile(securePath);
|
|
3240
|
-
const transcription = await runtime.useModel(ModelType2.TRANSCRIPTION, audioBuffer);
|
|
3241
|
-
logger18.info(`[AUDIO MESSAGE] Transcription for agent ${agentId}: ${transcription}`);
|
|
3132
|
+
if (audioFile.size > MAX_FILE_SIZE) {
|
|
3242
3133
|
cleanupUploadedFile(audioFile);
|
|
3243
|
-
|
|
3244
|
-
} catch (error) {
|
|
3245
|
-
logger18.error("[AUDIO MESSAGE] Error processing audio:", error);
|
|
3246
|
-
cleanupUploadedFile(audioFile);
|
|
3247
|
-
sendError(
|
|
3134
|
+
return sendError(
|
|
3248
3135
|
res,
|
|
3249
|
-
|
|
3250
|
-
"
|
|
3251
|
-
|
|
3252
|
-
error instanceof Error ? error.message : String(error)
|
|
3136
|
+
413,
|
|
3137
|
+
"FILE_TOO_LARGE",
|
|
3138
|
+
`Audio file too large (max ${MAX_FILE_SIZE_DISPLAY})`
|
|
3253
3139
|
);
|
|
3254
3140
|
}
|
|
3141
|
+
const transcription = await runtime.useModel(ModelType2.TRANSCRIPTION, audioFile.buffer);
|
|
3142
|
+
logger18.info(`[AUDIO MESSAGE] Transcription for agent ${agentId}: ${transcription}`);
|
|
3143
|
+
cleanupUploadedFile(audioFile);
|
|
3144
|
+
sendSuccess(res, { transcription, message: "Audio transcribed, further processing TBD." });
|
|
3145
|
+
} catch (error) {
|
|
3146
|
+
logger18.error("[AUDIO MESSAGE] Error processing audio:", error);
|
|
3147
|
+
cleanupUploadedFile(audioFile);
|
|
3148
|
+
sendError(
|
|
3149
|
+
res,
|
|
3150
|
+
500,
|
|
3151
|
+
"PROCESSING_ERROR",
|
|
3152
|
+
"Error processing audio message",
|
|
3153
|
+
error instanceof Error ? error.message : String(error)
|
|
3154
|
+
);
|
|
3255
3155
|
}
|
|
3256
|
-
);
|
|
3257
|
-
router.post(
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3156
|
+
});
|
|
3157
|
+
router.post("/:agentId/transcriptions", agentAudioUpload().single("file"), async (req, res) => {
|
|
3158
|
+
const audioReq = req;
|
|
3159
|
+
logger18.debug("[TRANSCRIPTION] Request to transcribe audio");
|
|
3160
|
+
const agentId = validateUuid17(req.params.agentId);
|
|
3161
|
+
if (!agentId) {
|
|
3162
|
+
return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
|
|
3163
|
+
}
|
|
3164
|
+
const audioFile = audioReq.file;
|
|
3165
|
+
if (!audioFile) {
|
|
3166
|
+
return sendError(res, 400, "INVALID_REQUEST", "No audio file provided");
|
|
3167
|
+
}
|
|
3168
|
+
const runtime = agents.get(agentId);
|
|
3169
|
+
if (!runtime) {
|
|
3170
|
+
cleanupUploadedFile(audioFile);
|
|
3171
|
+
return sendError(res, 404, "NOT_FOUND", "Agent not found");
|
|
3172
|
+
}
|
|
3173
|
+
try {
|
|
3174
|
+
logger18.debug("[TRANSCRIPTION] Reading audio file");
|
|
3175
|
+
if (!validateAudioFile(audioFile)) {
|
|
3274
3176
|
cleanupUploadedFile(audioFile);
|
|
3275
|
-
return sendError(res,
|
|
3177
|
+
return sendError(res, 400, "INVALID_FILE_TYPE", "Invalid audio file type");
|
|
3276
3178
|
}
|
|
3277
|
-
|
|
3278
|
-
logger18.debug("[TRANSCRIPTION] Reading audio file");
|
|
3279
|
-
if (!validateAudioFile(audioFile)) {
|
|
3280
|
-
cleanupUploadedFile(audioFile);
|
|
3281
|
-
return sendError(res, 400, "INVALID_FILE_TYPE", "Invalid audio file type");
|
|
3282
|
-
}
|
|
3283
|
-
let securePath;
|
|
3284
|
-
try {
|
|
3285
|
-
const filePath = audioFile.tempFilePath || "";
|
|
3286
|
-
securePath = validateSecureFilePath(filePath);
|
|
3287
|
-
} catch (pathError) {
|
|
3288
|
-
cleanupUploadedFile(audioFile);
|
|
3289
|
-
return sendError(
|
|
3290
|
-
res,
|
|
3291
|
-
403,
|
|
3292
|
-
"INVALID_PATH",
|
|
3293
|
-
`Invalid file path: ${pathError instanceof Error ? pathError.message : String(pathError)}`
|
|
3294
|
-
);
|
|
3295
|
-
}
|
|
3296
|
-
const stats = await fs3.promises.stat(securePath);
|
|
3297
|
-
if (stats.size > MAX_FILE_SIZE) {
|
|
3298
|
-
cleanupUploadedFile(audioFile);
|
|
3299
|
-
return sendError(
|
|
3300
|
-
res,
|
|
3301
|
-
413,
|
|
3302
|
-
"FILE_TOO_LARGE",
|
|
3303
|
-
`Audio file too large (max ${MAX_FILE_SIZE_DISPLAY})`
|
|
3304
|
-
);
|
|
3305
|
-
}
|
|
3306
|
-
const audioBuffer = await fs3.promises.readFile(securePath);
|
|
3307
|
-
logger18.debug("[TRANSCRIPTION] Transcribing audio");
|
|
3308
|
-
const transcription = await runtime.useModel(ModelType2.TRANSCRIPTION, audioBuffer);
|
|
3179
|
+
if (audioFile.size > MAX_FILE_SIZE) {
|
|
3309
3180
|
cleanupUploadedFile(audioFile);
|
|
3310
|
-
|
|
3311
|
-
return sendError(res, 500, "PROCESSING_ERROR", "Failed to transcribe audio");
|
|
3312
|
-
}
|
|
3313
|
-
logger18.success("[TRANSCRIPTION] Successfully transcribed audio");
|
|
3314
|
-
sendSuccess(res, { text: transcription });
|
|
3315
|
-
} catch (error) {
|
|
3316
|
-
logger18.error("[TRANSCRIPTION] Error transcribing audio:", error);
|
|
3317
|
-
cleanupUploadedFile(audioFile);
|
|
3318
|
-
sendError(
|
|
3181
|
+
return sendError(
|
|
3319
3182
|
res,
|
|
3320
|
-
|
|
3321
|
-
"
|
|
3322
|
-
|
|
3323
|
-
error instanceof Error ? error.message : String(error)
|
|
3183
|
+
413,
|
|
3184
|
+
"FILE_TOO_LARGE",
|
|
3185
|
+
`Audio file too large (max ${MAX_FILE_SIZE_DISPLAY})`
|
|
3324
3186
|
);
|
|
3325
3187
|
}
|
|
3188
|
+
logger18.debug("[TRANSCRIPTION] Transcribing audio");
|
|
3189
|
+
const transcription = await runtime.useModel(ModelType2.TRANSCRIPTION, audioFile.buffer);
|
|
3190
|
+
cleanupUploadedFile(audioFile);
|
|
3191
|
+
if (!transcription) {
|
|
3192
|
+
return sendError(res, 500, "PROCESSING_ERROR", "Failed to transcribe audio");
|
|
3193
|
+
}
|
|
3194
|
+
logger18.success("[TRANSCRIPTION] Successfully transcribed audio");
|
|
3195
|
+
sendSuccess(res, { text: transcription });
|
|
3196
|
+
} catch (error) {
|
|
3197
|
+
logger18.error("[TRANSCRIPTION] Error transcribing audio:", error);
|
|
3198
|
+
cleanupUploadedFile(audioFile);
|
|
3199
|
+
sendError(
|
|
3200
|
+
res,
|
|
3201
|
+
500,
|
|
3202
|
+
"PROCESSING_ERROR",
|
|
3203
|
+
"Error transcribing audio",
|
|
3204
|
+
error instanceof Error ? error.message : String(error)
|
|
3205
|
+
);
|
|
3326
3206
|
}
|
|
3327
|
-
);
|
|
3207
|
+
});
|
|
3328
3208
|
return router;
|
|
3329
3209
|
}
|
|
3330
3210
|
|
|
@@ -3821,15 +3701,15 @@ import express28 from "express";
|
|
|
3821
3701
|
import { logger as logger23 } from "@elizaos/core";
|
|
3822
3702
|
import express27 from "express";
|
|
3823
3703
|
import { existsSync, writeFileSync } from "fs";
|
|
3824
|
-
import
|
|
3704
|
+
import path7 from "path";
|
|
3825
3705
|
import dotenv from "dotenv";
|
|
3826
|
-
import
|
|
3706
|
+
import fs7 from "fs/promises";
|
|
3827
3707
|
async function parseEnvFile(filePath) {
|
|
3828
3708
|
try {
|
|
3829
3709
|
if (!existsSync(filePath)) {
|
|
3830
3710
|
return {};
|
|
3831
3711
|
}
|
|
3832
|
-
const content = await
|
|
3712
|
+
const content = await fs7.readFile(filePath, "utf-8");
|
|
3833
3713
|
if (content.trim() === "") {
|
|
3834
3714
|
return {};
|
|
3835
3715
|
}
|
|
@@ -3849,17 +3729,17 @@ function getLocalEnvPath() {
|
|
|
3849
3729
|
function resolveEnvFile(startDir = process.cwd()) {
|
|
3850
3730
|
let currentDir = startDir;
|
|
3851
3731
|
while (true) {
|
|
3852
|
-
const candidate =
|
|
3732
|
+
const candidate = path7.join(currentDir, ".env");
|
|
3853
3733
|
if (existsSync(candidate)) {
|
|
3854
3734
|
return candidate;
|
|
3855
3735
|
}
|
|
3856
|
-
const parentDir =
|
|
3736
|
+
const parentDir = path7.dirname(currentDir);
|
|
3857
3737
|
if (parentDir === currentDir) {
|
|
3858
3738
|
break;
|
|
3859
3739
|
}
|
|
3860
3740
|
currentDir = parentDir;
|
|
3861
3741
|
}
|
|
3862
|
-
return
|
|
3742
|
+
return path7.join(startDir, ".env");
|
|
3863
3743
|
}
|
|
3864
3744
|
function createEnvironmentRouter() {
|
|
3865
3745
|
const router = express27.Router();
|
|
@@ -4610,6 +4490,7 @@ function createApiRouter(agents, serverInstance) {
|
|
|
4610
4490
|
);
|
|
4611
4491
|
router.use(createApiRateLimit());
|
|
4612
4492
|
router.use(securityMiddleware());
|
|
4493
|
+
router.use("/media", mediaRouter());
|
|
4613
4494
|
router.use(validateContentTypeMiddleware());
|
|
4614
4495
|
router.use(
|
|
4615
4496
|
bodyParser.json({
|
|
@@ -4629,7 +4510,6 @@ function createApiRouter(agents, serverInstance) {
|
|
|
4629
4510
|
);
|
|
4630
4511
|
router.use("/agents", agentsRouter(agents, serverInstance));
|
|
4631
4512
|
router.use("/messaging", messagingRouter(agents, serverInstance));
|
|
4632
|
-
router.use("/media", mediaRouter());
|
|
4633
4513
|
router.use("/memory", memoryRouter(agents, serverInstance));
|
|
4634
4514
|
router.use("/audio", audioRouter(agents));
|
|
4635
4515
|
router.use("/server", runtimeRouter(agents, serverInstance));
|
|
@@ -5033,7 +4913,14 @@ var MessageBusService = class _MessageBusService extends Service {
|
|
|
5033
4913
|
await this.runtime.emitEvent(EventType2.MESSAGE_RECEIVED, {
|
|
5034
4914
|
runtime: this.runtime,
|
|
5035
4915
|
message: agentMemory,
|
|
5036
|
-
callback: callbackForCentralBus
|
|
4916
|
+
callback: callbackForCentralBus,
|
|
4917
|
+
onComplete: async () => {
|
|
4918
|
+
const room = await this.runtime.getRoom(agentRoomId);
|
|
4919
|
+
const world = await this.runtime.getWorld(agentWorldId);
|
|
4920
|
+
const channelId = room?.channelId;
|
|
4921
|
+
const serverId = world?.serverId;
|
|
4922
|
+
await this.notifyMessageComplete(channelId, serverId);
|
|
4923
|
+
}
|
|
5037
4924
|
});
|
|
5038
4925
|
} catch (error) {
|
|
5039
4926
|
logger27.error(
|
|
@@ -5110,7 +4997,6 @@ var MessageBusService = class _MessageBusService extends Service {
|
|
|
5110
4997
|
logger27.error(
|
|
5111
4998
|
`[${this.runtime.character.name}] MessageBusService: Cannot map agent room/world to central IDs for response. AgentRoomID: ${agentRoomId}, AgentWorldID: ${agentWorldId}. Room or World object missing, or channelId/serverId not found on them.`
|
|
5112
4999
|
);
|
|
5113
|
-
await this.notifyMessageComplete(channelId, serverId);
|
|
5114
5000
|
return;
|
|
5115
5001
|
}
|
|
5116
5002
|
const shouldSkip = content.actions?.includes("IGNORE") || !content.text || content.text.trim() === "";
|
|
@@ -5118,7 +5004,6 @@ var MessageBusService = class _MessageBusService extends Service {
|
|
|
5118
5004
|
logger27.info(
|
|
5119
5005
|
`[${this.runtime.character.name}] MessageBusService: Skipping response (reason: ${content.actions?.includes("IGNORE") ? "IGNORE action" : "No text"})`
|
|
5120
5006
|
);
|
|
5121
|
-
await this.notifyMessageComplete(channelId, serverId);
|
|
5122
5007
|
return;
|
|
5123
5008
|
}
|
|
5124
5009
|
let centralInReplyToRootMessageId = void 0;
|
|
@@ -5263,8 +5148,8 @@ var messageBusConnectorPlugin = {
|
|
|
5263
5148
|
};
|
|
5264
5149
|
|
|
5265
5150
|
// src/loader.ts
|
|
5266
|
-
import
|
|
5267
|
-
import
|
|
5151
|
+
import fs8 from "fs";
|
|
5152
|
+
import path8 from "path";
|
|
5268
5153
|
import { fileURLToPath } from "url";
|
|
5269
5154
|
import {
|
|
5270
5155
|
logger as logger28,
|
|
@@ -5272,10 +5157,10 @@ import {
|
|
|
5272
5157
|
validateCharacter
|
|
5273
5158
|
} from "@elizaos/core";
|
|
5274
5159
|
var __filename = fileURLToPath(import.meta.url);
|
|
5275
|
-
var __dirname =
|
|
5160
|
+
var __dirname = path8.dirname(__filename);
|
|
5276
5161
|
function tryLoadFile(filePath) {
|
|
5277
5162
|
try {
|
|
5278
|
-
return
|
|
5163
|
+
return fs8.readFileSync(filePath, "utf8");
|
|
5279
5164
|
} catch (e) {
|
|
5280
5165
|
throw new Error(`Error loading file ${filePath}: ${e}`);
|
|
5281
5166
|
}
|
|
@@ -5372,36 +5257,36 @@ async function loadCharacter(filePath) {
|
|
|
5372
5257
|
}
|
|
5373
5258
|
return jsonToCharacter(parseResult.data);
|
|
5374
5259
|
}
|
|
5375
|
-
function handleCharacterLoadError(
|
|
5260
|
+
function handleCharacterLoadError(path10, error) {
|
|
5376
5261
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
5377
5262
|
if (errorMsg.includes("ENOENT") || errorMsg.includes("no such file")) {
|
|
5378
|
-
logger28.error(`Character file not found: ${
|
|
5263
|
+
logger28.error(`Character file not found: ${path10}`);
|
|
5379
5264
|
throw new Error(
|
|
5380
|
-
`Character '${
|
|
5265
|
+
`Character '${path10}' not found. Please check if the file exists and the path is correct.`
|
|
5381
5266
|
);
|
|
5382
5267
|
} else if (errorMsg.includes("Character validation failed")) {
|
|
5383
|
-
logger28.error(`Character validation failed for: ${
|
|
5384
|
-
throw new Error(`Character file '${
|
|
5268
|
+
logger28.error(`Character validation failed for: ${path10}`);
|
|
5269
|
+
throw new Error(`Character file '${path10}' contains invalid character data. ${errorMsg}`);
|
|
5385
5270
|
} else if (errorMsg.includes("JSON")) {
|
|
5386
|
-
logger28.error(`JSON parsing error in character file: ${
|
|
5387
|
-
throw new Error(`Character file '${
|
|
5271
|
+
logger28.error(`JSON parsing error in character file: ${path10}`);
|
|
5272
|
+
throw new Error(`Character file '${path10}' has malformed JSON. Please check the file content.`);
|
|
5388
5273
|
} else if (errorMsg.includes("Invalid JSON")) {
|
|
5389
|
-
logger28.error(`Invalid JSON in character file: ${
|
|
5274
|
+
logger28.error(`Invalid JSON in character file: ${path10}`);
|
|
5390
5275
|
throw new Error(
|
|
5391
|
-
`Character file '${
|
|
5276
|
+
`Character file '${path10}' has invalid JSON format. Please check the file content.`
|
|
5392
5277
|
);
|
|
5393
5278
|
} else {
|
|
5394
|
-
logger28.error(`Error loading character from ${
|
|
5395
|
-
throw new Error(`Failed to load character '${
|
|
5279
|
+
logger28.error(`Error loading character from ${path10}: ${errorMsg}`);
|
|
5280
|
+
throw new Error(`Failed to load character '${path10}': ${errorMsg}`);
|
|
5396
5281
|
}
|
|
5397
5282
|
}
|
|
5398
|
-
async function safeLoadCharacter(
|
|
5283
|
+
async function safeLoadCharacter(path10) {
|
|
5399
5284
|
try {
|
|
5400
|
-
const character = await loadCharacter(
|
|
5401
|
-
logger28.info(`Successfully loaded character from: ${
|
|
5285
|
+
const character = await loadCharacter(path10);
|
|
5286
|
+
logger28.info(`Successfully loaded character from: ${path10}`);
|
|
5402
5287
|
return character;
|
|
5403
5288
|
} catch (e) {
|
|
5404
|
-
return handleCharacterLoadError(
|
|
5289
|
+
return handleCharacterLoadError(path10, e);
|
|
5405
5290
|
}
|
|
5406
5291
|
}
|
|
5407
5292
|
async function loadCharacterTryPath(characterPath) {
|
|
@@ -5421,27 +5306,27 @@ async function loadCharacterTryPath(characterPath) {
|
|
|
5421
5306
|
const jsonPath = hasJsonExtension ? characterPath : `${characterPath}.json`;
|
|
5422
5307
|
const basePathsToTry = [
|
|
5423
5308
|
basePath,
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5309
|
+
path8.resolve(process.cwd(), basePath),
|
|
5310
|
+
path8.resolve(process.cwd(), "..", "..", basePath),
|
|
5311
|
+
path8.resolve(process.cwd(), "..", "..", "..", basePath),
|
|
5312
|
+
path8.resolve(process.cwd(), "agent", basePath),
|
|
5313
|
+
path8.resolve(__dirname, basePath),
|
|
5314
|
+
path8.resolve(__dirname, "characters", path8.basename(basePath)),
|
|
5315
|
+
path8.resolve(__dirname, "../characters", path8.basename(basePath)),
|
|
5316
|
+
path8.resolve(__dirname, "../../characters", path8.basename(basePath)),
|
|
5317
|
+
path8.resolve(__dirname, "../../../characters", path8.basename(basePath))
|
|
5433
5318
|
];
|
|
5434
5319
|
const jsonPathsToTry = hasJsonExtension ? [] : [
|
|
5435
5320
|
jsonPath,
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5321
|
+
path8.resolve(process.cwd(), jsonPath),
|
|
5322
|
+
path8.resolve(process.cwd(), "..", "..", jsonPath),
|
|
5323
|
+
path8.resolve(process.cwd(), "..", "..", "..", jsonPath),
|
|
5324
|
+
path8.resolve(process.cwd(), "agent", jsonPath),
|
|
5325
|
+
path8.resolve(__dirname, jsonPath),
|
|
5326
|
+
path8.resolve(__dirname, "characters", path8.basename(jsonPath)),
|
|
5327
|
+
path8.resolve(__dirname, "../characters", path8.basename(jsonPath)),
|
|
5328
|
+
path8.resolve(__dirname, "../../characters", path8.basename(jsonPath)),
|
|
5329
|
+
path8.resolve(__dirname, "../../../characters", path8.basename(jsonPath))
|
|
5445
5330
|
];
|
|
5446
5331
|
const pathsToTry = Array.from(/* @__PURE__ */ new Set([...basePathsToTry, ...jsonPathsToTry]));
|
|
5447
5332
|
let lastError = null;
|
|
@@ -5466,11 +5351,11 @@ function commaSeparatedStringToArray(commaSeparated) {
|
|
|
5466
5351
|
}
|
|
5467
5352
|
async function readCharactersFromStorage(characterPaths) {
|
|
5468
5353
|
try {
|
|
5469
|
-
const uploadDir =
|
|
5470
|
-
await
|
|
5471
|
-
const fileNames = await
|
|
5354
|
+
const uploadDir = path8.join(process.cwd(), ".eliza", "data", "characters");
|
|
5355
|
+
await fs8.promises.mkdir(uploadDir, { recursive: true });
|
|
5356
|
+
const fileNames = await fs8.promises.readdir(uploadDir);
|
|
5472
5357
|
for (const fileName of fileNames) {
|
|
5473
|
-
characterPaths.push(
|
|
5358
|
+
characterPaths.push(path8.join(uploadDir, fileName));
|
|
5474
5359
|
}
|
|
5475
5360
|
} catch (err) {
|
|
5476
5361
|
logger28.error(`Error reading directory: ${err.message}`);
|
|
@@ -5526,11 +5411,11 @@ function expandTildePath(filepath) {
|
|
|
5526
5411
|
if (filepath === "~") {
|
|
5527
5412
|
return process.cwd();
|
|
5528
5413
|
} else if (filepath.startsWith("~/")) {
|
|
5529
|
-
return
|
|
5414
|
+
return path9.join(process.cwd(), filepath.slice(2));
|
|
5530
5415
|
} else if (filepath.startsWith("~~")) {
|
|
5531
5416
|
return filepath;
|
|
5532
5417
|
} else {
|
|
5533
|
-
return
|
|
5418
|
+
return path9.join(process.cwd(), filepath.slice(1));
|
|
5534
5419
|
}
|
|
5535
5420
|
}
|
|
5536
5421
|
return filepath;
|
|
@@ -5540,11 +5425,11 @@ function resolvePgliteDir(dir, fallbackDir) {
|
|
|
5540
5425
|
if (existsSync3(envPath)) {
|
|
5541
5426
|
dotenv2.config({ path: envPath });
|
|
5542
5427
|
}
|
|
5543
|
-
const base = dir ?? process.env.PGLITE_DATA_DIR ?? fallbackDir ??
|
|
5428
|
+
const base = dir ?? process.env.PGLITE_DATA_DIR ?? fallbackDir ?? path9.join(process.cwd(), ".eliza", ".elizadb");
|
|
5544
5429
|
const resolved = expandTildePath(base);
|
|
5545
|
-
const legacyPath =
|
|
5430
|
+
const legacyPath = path9.join(process.cwd(), ".elizadb");
|
|
5546
5431
|
if (resolved === legacyPath) {
|
|
5547
|
-
const newPath =
|
|
5432
|
+
const newPath = path9.join(process.cwd(), ".eliza", ".elizadb");
|
|
5548
5433
|
process.env.PGLITE_DATA_DIR = newPath;
|
|
5549
5434
|
return newPath;
|
|
5550
5435
|
}
|
|
@@ -5784,26 +5669,10 @@ var AgentServer = class {
|
|
|
5784
5669
|
})
|
|
5785
5670
|
);
|
|
5786
5671
|
this.app.use(
|
|
5787
|
-
|
|
5672
|
+
express30.json({
|
|
5788
5673
|
limit: process.env.EXPRESS_MAX_PAYLOAD || "100kb"
|
|
5789
5674
|
})
|
|
5790
5675
|
);
|
|
5791
|
-
this.app.use(
|
|
5792
|
-
fileUpload2({
|
|
5793
|
-
useTempFiles: true,
|
|
5794
|
-
tempFileDir: "/tmp/",
|
|
5795
|
-
createParentPath: true,
|
|
5796
|
-
preserveExtension: true,
|
|
5797
|
-
safeFileNames: true,
|
|
5798
|
-
limits: {
|
|
5799
|
-
fileSize: 50 * 1024 * 1024
|
|
5800
|
-
// 50MB default limit
|
|
5801
|
-
},
|
|
5802
|
-
abortOnLimit: true,
|
|
5803
|
-
uploadTimeout: 6e4
|
|
5804
|
-
// 60 seconds
|
|
5805
|
-
})
|
|
5806
|
-
);
|
|
5807
5676
|
const serverAuthToken = process.env.ELIZA_SERVER_AUTH_TOKEN;
|
|
5808
5677
|
if (serverAuthToken) {
|
|
5809
5678
|
logger29.info("Server authentication enabled. Requires X-API-KEY header for /api routes.");
|
|
@@ -5815,10 +5684,10 @@ var AgentServer = class {
|
|
|
5815
5684
|
"Server authentication is disabled. Set ELIZA_SERVER_AUTH_TOKEN environment variable to enable."
|
|
5816
5685
|
);
|
|
5817
5686
|
}
|
|
5818
|
-
const uploadsBasePath =
|
|
5819
|
-
const generatedBasePath =
|
|
5820
|
-
|
|
5821
|
-
|
|
5687
|
+
const uploadsBasePath = path9.join(process.cwd(), ".eliza", "data", "uploads", "agents");
|
|
5688
|
+
const generatedBasePath = path9.join(process.cwd(), ".eliza", "data", "generated");
|
|
5689
|
+
fs9.mkdirSync(uploadsBasePath, { recursive: true });
|
|
5690
|
+
fs9.mkdirSync(generatedBasePath, { recursive: true });
|
|
5822
5691
|
this.app.get(
|
|
5823
5692
|
"/media/uploads/agents/:agentId/:filename",
|
|
5824
5693
|
// @ts-expect-error - this is a valid express route
|
|
@@ -5835,7 +5704,7 @@ var AgentServer = class {
|
|
|
5835
5704
|
if (!filePath.startsWith(agentUploadsPath)) {
|
|
5836
5705
|
return res.status(403).json({ error: "Access denied" });
|
|
5837
5706
|
}
|
|
5838
|
-
if (!
|
|
5707
|
+
if (!fs9.existsSync(filePath)) {
|
|
5839
5708
|
return res.status(404).json({ error: "File does not exist!!!!!!!" });
|
|
5840
5709
|
}
|
|
5841
5710
|
res.sendFile(sanitizedFilename, { root: agentUploadsPath }, (err) => {
|
|
@@ -5939,7 +5808,7 @@ var AgentServer = class {
|
|
|
5939
5808
|
}
|
|
5940
5809
|
}
|
|
5941
5810
|
};
|
|
5942
|
-
const clientPath =
|
|
5811
|
+
const clientPath = path9.resolve(__dirname2, "../../cli/dist");
|
|
5943
5812
|
this.app.use(express30.static(clientPath, staticOptions));
|
|
5944
5813
|
const pluginRouteHandler = createPluginRouteHandler(this.agents);
|
|
5945
5814
|
this.app.use(pluginRouteHandler);
|
|
@@ -5982,8 +5851,8 @@ var AgentServer = class {
|
|
|
5982
5851
|
res.setHeader("Content-Type", "application/javascript");
|
|
5983
5852
|
return res.status(404).send(`// JavaScript module not found: ${req.path}`);
|
|
5984
5853
|
}
|
|
5985
|
-
const cliDistPath =
|
|
5986
|
-
res.sendFile(
|
|
5854
|
+
const cliDistPath = path9.resolve(__dirname2, "../../cli/dist");
|
|
5855
|
+
res.sendFile(path9.join(cliDistPath, "index.html"));
|
|
5987
5856
|
});
|
|
5988
5857
|
this.server = http.createServer(this.app);
|
|
5989
5858
|
this.socketIO = setupSocketIO(this.server, this.agents, this);
|