@elizaos/server 1.0.12 → 1.0.14

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 CHANGED
@@ -4,7 +4,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __commonJS = (cb, mod) => function __require() {
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
8
14
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
15
  };
10
16
  var __copyProps = (to, from, except, desc) => {
@@ -381,13 +387,11 @@ var import_cors2 = __toESM(require_lib(), 1);
381
387
  import {
382
388
  logger as logger29
383
389
  } from "@elizaos/core";
384
- import bodyParser2 from "body-parser";
385
390
  import express30 from "express";
386
- import fileUpload2 from "express-fileupload";
387
391
  import helmet2 from "helmet";
388
- import * as fs6 from "fs";
392
+ import * as fs9 from "fs";
389
393
  import http from "http";
390
- import path6, { basename, dirname, extname, join } from "path";
394
+ import path9, { basename, dirname, extname, join } from "path";
391
395
  import { fileURLToPath as fileURLToPath2 } from "url";
392
396
 
393
397
  // src/api/index.ts
@@ -499,7 +503,7 @@ function createAgentCrudRouter(agents, serverInstance) {
499
503
  });
500
504
  router.post("/", async (req, res) => {
501
505
  logger.debug("[AGENT CREATE] Creating new agent");
502
- const { characterPath, characterJson } = req.body;
506
+ const { characterPath, characterJson, agent } = req.body;
503
507
  if (!db) {
504
508
  return sendError(res, 500, "DB_ERROR", "Database not available");
505
509
  }
@@ -511,6 +515,9 @@ function createAgentCrudRouter(agents, serverInstance) {
511
515
  } else if (characterPath) {
512
516
  logger.debug(`[AGENT CREATE] Loading character from path: ${characterPath}`);
513
517
  character = await serverInstance?.loadCharacterTryPath(characterPath);
518
+ } else if (agent) {
519
+ logger.debug("[AGENT CREATE] Parsing character from agent object");
520
+ character = await serverInstance?.jsonToCharacter(agent);
514
521
  } else {
515
522
  throw new Error("No character configuration provided");
516
523
  }
@@ -524,12 +531,12 @@ function createAgentCrudRouter(agents, serverInstance) {
524
531
  }
525
532
  const ensureAgentExists = async (character2) => {
526
533
  const agentId = stringToUuid(character2.name);
527
- let agent = await db.getAgent(agentId);
528
- if (!agent) {
534
+ let agent2 = await db.getAgent(agentId);
535
+ if (!agent2) {
529
536
  await db.createAgent({ ...character2, id: agentId });
530
- agent = await db.getAgent(agentId);
537
+ agent2 = await db.getAgent(agentId);
531
538
  }
532
- return agent;
539
+ return agent2;
533
540
  };
534
541
  const newAgent = await ensureAgentExists(character);
535
542
  if (!newAgent) {
@@ -1183,6 +1190,30 @@ function createAgentMemoryRouter(agents) {
1183
1190
  );
1184
1191
  }
1185
1192
  });
1193
+ router.delete("/:agentId/memories/:memoryId", async (req, res) => {
1194
+ try {
1195
+ const agentId = validateUuid6(req.params.agentId);
1196
+ const memoryId = validateUuid6(req.params.memoryId);
1197
+ if (!agentId || !memoryId) {
1198
+ return sendError(res, 400, "INVALID_ID", "Invalid agent ID or memory ID format");
1199
+ }
1200
+ const runtime = agents.get(agentId);
1201
+ if (!runtime) {
1202
+ return sendError(res, 404, "NOT_FOUND", "Agent not found");
1203
+ }
1204
+ await runtime.deleteMemory(memoryId);
1205
+ sendSuccess(res, { message: "Memory deleted successfully" });
1206
+ } catch (error) {
1207
+ logger6.error(`[DELETE MEMORY] Error deleting memory ${req.params.memoryId}:`, error);
1208
+ sendError(
1209
+ res,
1210
+ 500,
1211
+ "DELETE_ERROR",
1212
+ "Error deleting memory",
1213
+ error instanceof Error ? error.message : String(error)
1214
+ );
1215
+ }
1216
+ });
1186
1217
  return router;
1187
1218
  }
1188
1219
 
@@ -1683,189 +1714,16 @@ import {
1683
1714
  composePromptFromState,
1684
1715
  ModelType,
1685
1716
  ChannelType as ChannelType2,
1686
- logger as logger14,
1687
- validateUuid as validateUuid13
1717
+ logger as logger12,
1718
+ validateUuid as validateUuid12
1688
1719
  } from "@elizaos/core";
1689
1720
  import express11 from "express";
1690
1721
 
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
1722
  // src/api/shared/middleware.ts
1865
- import { validateUuid as validateUuid12, logger as logger13 } from "@elizaos/core";
1723
+ import { validateUuid as validateUuid11, logger as logger11 } from "@elizaos/core";
1866
1724
 
1867
1725
  // src/api/shared/validation.ts
1868
- import { validateUuid as validateUuid11, logger as logger12 } from "@elizaos/core";
1726
+ import { validateUuid as validateUuid10, logger as logger10 } from "@elizaos/core";
1869
1727
  var getRuntime = (agents, agentId) => {
1870
1728
  const runtime = agents.get(agentId);
1871
1729
  if (!runtime) {
@@ -1889,7 +1747,7 @@ var securityMiddleware = () => {
1889
1747
  const realIp = req.get("X-Real-IP");
1890
1748
  const clientIp = forwarded || realIp || req.ip;
1891
1749
  if (userAgent && (userAgent.includes("..") || userAgent.includes("<script"))) {
1892
- logger13.warn(`[SECURITY] Suspicious User-Agent from ${clientIp}: ${userAgent}`);
1750
+ logger11.warn(`[SECURITY] Suspicious User-Agent from ${clientIp}: ${userAgent}`);
1893
1751
  }
1894
1752
  const url = req.originalUrl || req.url;
1895
1753
  const queryString = JSON.stringify(req.query);
@@ -1915,12 +1773,12 @@ var securityMiddleware = () => {
1915
1773
  }
1916
1774
  for (const indicator of suspiciousIndicators) {
1917
1775
  if (url.includes(indicator.pattern) || queryString.includes(indicator.pattern)) {
1918
- logger13.warn(`[SECURITY] ${indicator.name} detected from ${clientIp}: ${url}`);
1776
+ logger11.warn(`[SECURITY] ${indicator.name} detected from ${clientIp}: ${url}`);
1919
1777
  break;
1920
1778
  }
1921
1779
  }
1922
1780
  if (hasSqlPattern) {
1923
- logger13.warn(`[SECURITY] SQL injection pattern detected from ${clientIp}: ${url}`);
1781
+ logger11.warn(`[SECURITY] SQL injection pattern detected from ${clientIp}: ${url}`);
1924
1782
  }
1925
1783
  next();
1926
1784
  };
@@ -1969,7 +1827,7 @@ var createApiRateLimit = () => {
1969
1827
  // Disable the `X-RateLimit-*` headers
1970
1828
  handler: (req, res) => {
1971
1829
  const clientIp = req.ip || "unknown";
1972
- logger13.warn(`[SECURITY] Rate limit exceeded for IP: ${clientIp}`);
1830
+ logger11.warn(`[SECURITY] Rate limit exceeded for IP: ${clientIp}`);
1973
1831
  res.status(429).json({
1974
1832
  success: false,
1975
1833
  error: {
@@ -1997,7 +1855,7 @@ var createFileSystemRateLimit = () => {
1997
1855
  legacyHeaders: false,
1998
1856
  handler: (req, res) => {
1999
1857
  const clientIp = req.ip || "unknown";
2000
- logger13.warn(
1858
+ logger11.warn(
2001
1859
  `[SECURITY] File system rate limit exceeded for IP: ${clientIp}, endpoint: ${req.path}`
2002
1860
  );
2003
1861
  res.status(429).json({
@@ -2027,7 +1885,7 @@ var createUploadRateLimit = () => {
2027
1885
  legacyHeaders: false,
2028
1886
  handler: (req, res) => {
2029
1887
  const clientIp = req.ip || "unknown";
2030
- logger13.warn(
1888
+ logger11.warn(
2031
1889
  `[SECURITY] Upload rate limit exceeded for IP: ${clientIp}, endpoint: ${req.path}`
2032
1890
  );
2033
1891
  res.status(429).json({
@@ -2041,14 +1899,73 @@ var createUploadRateLimit = () => {
2041
1899
  });
2042
1900
  };
2043
1901
 
1902
+ // src/api/shared/constants.ts
1903
+ var MAX_FILE_SIZE = 50 * 1024 * 1024;
1904
+ var MAX_FILE_SIZE_DISPLAY = "50MB";
1905
+ var ALLOWED_AUDIO_MIME_TYPES = [
1906
+ "audio/mpeg",
1907
+ "audio/mp3",
1908
+ "audio/wav",
1909
+ "audio/ogg",
1910
+ "audio/webm",
1911
+ "audio/mp4",
1912
+ "audio/aac",
1913
+ "audio/flac",
1914
+ "audio/x-wav",
1915
+ "audio/wave"
1916
+ ];
1917
+ var ALLOWED_MEDIA_MIME_TYPES = [
1918
+ ...ALLOWED_AUDIO_MIME_TYPES,
1919
+ "image/jpeg",
1920
+ "image/png",
1921
+ "image/gif",
1922
+ "image/webp",
1923
+ "video/mp4",
1924
+ "video/webm",
1925
+ "application/pdf",
1926
+ "text/plain"
1927
+ ];
1928
+
2044
1929
  // src/api/messaging/channels.ts
1930
+ import multer from "multer";
1931
+ import fs from "fs";
1932
+ import path from "path";
2045
1933
  var DEFAULT_SERVER_ID3 = "00000000-0000-0000-0000-000000000000";
1934
+ var channelStorage = multer.memoryStorage();
1935
+ var channelUploadMiddleware = multer({
1936
+ storage: channelStorage,
1937
+ limits: {
1938
+ fileSize: MAX_FILE_SIZE,
1939
+ files: 1
1940
+ },
1941
+ fileFilter: (req, file, cb) => {
1942
+ if (ALLOWED_MEDIA_MIME_TYPES.includes(file.mimetype)) {
1943
+ cb(null, true);
1944
+ } else {
1945
+ cb(new Error("Invalid file type"), false);
1946
+ }
1947
+ }
1948
+ });
1949
+ async function saveChannelUploadedFile(file, channelId) {
1950
+ const uploadDir = path.join(process.cwd(), ".eliza/data/uploads/channels", channelId);
1951
+ if (!fs.existsSync(uploadDir)) {
1952
+ fs.mkdirSync(uploadDir, { recursive: true });
1953
+ }
1954
+ const timestamp = Date.now();
1955
+ const random = Math.round(Math.random() * 1e9);
1956
+ const ext = path.extname(file.originalname);
1957
+ const filename = `${timestamp}-${random}${ext}`;
1958
+ const filePath = path.join(uploadDir, filename);
1959
+ fs.writeFileSync(filePath, file.buffer);
1960
+ const url = `/media/uploads/channels/${channelId}/${filename}`;
1961
+ return { filename, url };
1962
+ }
2046
1963
  function createChannelsRouter(agents, serverInstance) {
2047
1964
  const router = express11.Router();
2048
1965
  router.post(
2049
1966
  "/central-channels/:channelId/messages",
2050
1967
  async (req, res) => {
2051
- const channelIdParam = validateUuid13(req.params.channelId);
1968
+ const channelIdParam = validateUuid12(req.params.channelId);
2052
1969
  const {
2053
1970
  author_id,
2054
1971
  // This is the GUI user's central ID
@@ -2063,40 +1980,40 @@ function createChannelsRouter(agents, serverInstance) {
2063
1980
  source_type
2064
1981
  // Should be something like 'eliza_gui'
2065
1982
  } = req.body;
2066
- const isValidServerId = server_id === DEFAULT_SERVER_ID3 || validateUuid13(server_id);
2067
- if (!channelIdParam || !validateUuid13(author_id) || !content || !isValidServerId) {
1983
+ const isValidServerId = server_id === DEFAULT_SERVER_ID3 || validateUuid12(server_id);
1984
+ if (!channelIdParam || !validateUuid12(author_id) || !content || !isValidServerId) {
2068
1985
  return res.status(400).json({
2069
1986
  success: false,
2070
1987
  error: "Missing required fields: channelId, server_id, author_id, content"
2071
1988
  });
2072
1989
  }
2073
1990
  try {
2074
- logger14.info(
1991
+ logger12.info(
2075
1992
  `[Messages Router] Checking if channel ${channelIdParam} exists before creating message`
2076
1993
  );
2077
1994
  let channelExists = false;
2078
1995
  try {
2079
1996
  const existingChannel = await serverInstance.getChannelDetails(channelIdParam);
2080
1997
  channelExists = !!existingChannel;
2081
- logger14.info(`[Messages Router] Channel ${channelIdParam} exists: ${channelExists}`);
1998
+ logger12.info(`[Messages Router] Channel ${channelIdParam} exists: ${channelExists}`);
2082
1999
  } catch (error) {
2083
2000
  const errorMessage = error instanceof Error ? error.message : String(error);
2084
- logger14.info(
2001
+ logger12.info(
2085
2002
  `[Messages Router] Channel ${channelIdParam} does not exist, will create it. Error: ${errorMessage}`
2086
2003
  );
2087
2004
  }
2088
2005
  if (!channelExists) {
2089
- logger14.info(
2006
+ logger12.info(
2090
2007
  `[Messages Router] Auto-creating channel ${channelIdParam} with serverId ${server_id}`
2091
2008
  );
2092
2009
  try {
2093
2010
  const servers = await serverInstance.getServers();
2094
2011
  const serverExists = servers.some((s) => s.id === server_id);
2095
- logger14.info(
2012
+ logger12.info(
2096
2013
  `[Messages Router] Server ${server_id} exists: ${serverExists}. Available servers: ${servers.map((s) => s.id).join(", ")}`
2097
2014
  );
2098
2015
  if (!serverExists) {
2099
- logger14.error(
2016
+ logger12.error(
2100
2017
  `[Messages Router] Server ${server_id} does not exist, cannot create channel`
2101
2018
  );
2102
2019
  return res.status(500).json({ success: false, error: `Server ${server_id} does not exist` });
@@ -2117,38 +2034,38 @@ function createChannelsRouter(agents, serverInstance) {
2117
2034
  ...metadata
2118
2035
  }
2119
2036
  };
2120
- logger14.info(
2037
+ logger12.info(
2121
2038
  "[Messages Router] Creating channel with data:",
2122
2039
  JSON.stringify(channelData, null, 2)
2123
2040
  );
2124
2041
  const participants = [author_id];
2125
2042
  if (isDmChannel) {
2126
2043
  const otherParticipant = metadata?.targetUserId || metadata?.recipientId;
2127
- if (otherParticipant && validateUuid13(otherParticipant)) {
2044
+ if (otherParticipant && validateUuid12(otherParticipant)) {
2128
2045
  participants.push(otherParticipant);
2129
- logger14.info(
2046
+ logger12.info(
2130
2047
  `[Messages Router] DM channel will include participants: ${participants.join(", ")}`
2131
2048
  );
2132
2049
  } else {
2133
- logger14.warn(
2050
+ logger12.warn(
2134
2051
  `[Messages Router] DM channel missing second participant, only adding author: ${author_id}`
2135
2052
  );
2136
2053
  }
2137
2054
  }
2138
2055
  await serverInstance.createChannel(channelData, participants);
2139
- logger14.info(
2056
+ logger12.info(
2140
2057
  `[Messages Router] Auto-created ${isDmChannel ? ChannelType2.DM : ChannelType2.GROUP} channel ${channelIdParam} for message submission with ${participants.length} participants`
2141
2058
  );
2142
2059
  } catch (createError) {
2143
2060
  const errorMessage = createError instanceof Error ? createError.message : String(createError);
2144
- logger14.error(
2061
+ logger12.error(
2145
2062
  `[Messages Router] Failed to auto-create channel ${channelIdParam}:`,
2146
2063
  createError
2147
2064
  );
2148
2065
  return res.status(500).json({ success: false, error: `Failed to create channel: ${errorMessage}` });
2149
2066
  }
2150
2067
  } else {
2151
- logger14.info(
2068
+ logger12.info(
2152
2069
  `[Messages Router] Channel ${channelIdParam} already exists, proceeding with message creation`
2153
2070
  );
2154
2071
  }
@@ -2156,7 +2073,7 @@ function createChannelsRouter(agents, serverInstance) {
2156
2073
  channelId: channelIdParam,
2157
2074
  authorId: author_id,
2158
2075
  content,
2159
- inReplyToRootMessageId: in_reply_to_message_id ? validateUuid13(in_reply_to_message_id) || void 0 : void 0,
2076
+ inReplyToRootMessageId: in_reply_to_message_id ? validateUuid12(in_reply_to_message_id) || void 0 : void 0,
2160
2077
  rawMessage: raw_message,
2161
2078
  metadata,
2162
2079
  sourceType: source_type || "eliza_gui"
@@ -2182,7 +2099,7 @@ function createChannelsRouter(agents, serverInstance) {
2182
2099
  // Will be undefined here, which is fine
2183
2100
  };
2184
2101
  bus_default.emit("new_message", messageForBus);
2185
- logger14.info(
2102
+ logger12.info(
2186
2103
  "[Messages Router /central-channels/:channelId/messages] GUI Message published to internal bus:",
2187
2104
  messageForBus.id
2188
2105
  );
@@ -2202,7 +2119,7 @@ function createChannelsRouter(agents, serverInstance) {
2202
2119
  }
2203
2120
  res.status(201).json({ success: true, data: messageForBus });
2204
2121
  } catch (error) {
2205
- logger14.error(
2122
+ logger12.error(
2206
2123
  "[Messages Router /central-channels/:channelId/messages] Error processing GUI message:",
2207
2124
  error
2208
2125
  );
@@ -2213,7 +2130,7 @@ function createChannelsRouter(agents, serverInstance) {
2213
2130
  router.get(
2214
2131
  "/central-channels/:channelId/messages",
2215
2132
  async (req, res) => {
2216
- const channelId = validateUuid13(req.params.channelId);
2133
+ const channelId = validateUuid12(req.params.channelId);
2217
2134
  const limit = req.query.limit ? Number.parseInt(req.query.limit, 10) : 50;
2218
2135
  const before = req.query.before ? Number.parseInt(req.query.before, 10) : void 0;
2219
2136
  const beforeDate = before ? new Date(before) : void 0;
@@ -2240,7 +2157,7 @@ function createChannelsRouter(agents, serverInstance) {
2240
2157
  });
2241
2158
  res.json({ success: true, data: { messages: messagesForGui } });
2242
2159
  } catch (error) {
2243
- logger14.error(
2160
+ logger12.error(
2244
2161
  `[Messages Router /central-channels/:channelId/messages] Error fetching messages for channel ${channelId}:`,
2245
2162
  error
2246
2163
  );
@@ -2251,7 +2168,7 @@ function createChannelsRouter(agents, serverInstance) {
2251
2168
  router.get(
2252
2169
  "/central-servers/:serverId/channels",
2253
2170
  async (req, res) => {
2254
- const serverId = req.params.serverId === DEFAULT_SERVER_ID3 ? DEFAULT_SERVER_ID3 : validateUuid13(req.params.serverId);
2171
+ const serverId = req.params.serverId === DEFAULT_SERVER_ID3 ? DEFAULT_SERVER_ID3 : validateUuid12(req.params.serverId);
2255
2172
  if (!serverId) {
2256
2173
  return res.status(400).json({ success: false, error: "Invalid serverId" });
2257
2174
  }
@@ -2259,7 +2176,7 @@ function createChannelsRouter(agents, serverInstance) {
2259
2176
  const channels = await serverInstance.getChannelsForServer(serverId);
2260
2177
  res.json({ success: true, data: { channels } });
2261
2178
  } catch (error) {
2262
- logger14.error(
2179
+ logger12.error(
2263
2180
  `[Messages Router /central-servers/:serverId/channels] Error fetching channels for server ${serverId}:`,
2264
2181
  error
2265
2182
  );
@@ -2289,7 +2206,7 @@ function createChannelsRouter(agents, serverInstance) {
2289
2206
  error: "Missing required fields: type."
2290
2207
  });
2291
2208
  }
2292
- if (!validateUuid13(serverId)) {
2209
+ if (!validateUuid12(serverId)) {
2293
2210
  return res.status(400).json({
2294
2211
  success: false,
2295
2212
  error: "Invalid serverId format"
@@ -2307,14 +2224,14 @@ function createChannelsRouter(agents, serverInstance) {
2307
2224
  });
2308
2225
  res.status(201).json({ success: true, data: { channel } });
2309
2226
  } catch (error) {
2310
- logger14.error("[Messages Router /channels] Error creating channel:", error);
2227
+ logger12.error("[Messages Router /channels] Error creating channel:", error);
2311
2228
  res.status(500).json({ success: false, error: "Failed to create channel" });
2312
2229
  }
2313
2230
  });
2314
2231
  router.get("/dm-channel", async (req, res) => {
2315
- const targetUserId = validateUuid13(req.query.targetUserId);
2316
- const currentUserId = validateUuid13(req.query.currentUserId);
2317
- const providedDmServerId = req.query.dmServerId === DEFAULT_SERVER_ID3 ? DEFAULT_SERVER_ID3 : validateUuid13(req.query.dmServerId);
2232
+ const targetUserId = validateUuid12(req.query.targetUserId);
2233
+ const currentUserId = validateUuid12(req.query.currentUserId);
2234
+ const providedDmServerId = req.query.dmServerId === DEFAULT_SERVER_ID3 ? DEFAULT_SERVER_ID3 : validateUuid12(req.query.dmServerId);
2318
2235
  if (!targetUserId || !currentUserId) {
2319
2236
  res.status(400).json({ success: false, error: "Missing targetUserId or currentUserId" });
2320
2237
  return;
@@ -2330,7 +2247,7 @@ function createChannelsRouter(agents, serverInstance) {
2330
2247
  if (existingServer) {
2331
2248
  dmServerIdToUse = providedDmServerId;
2332
2249
  } else {
2333
- logger14.warn(
2250
+ logger12.warn(
2334
2251
  `Provided dmServerId ${providedDmServerId} not found, using default DM server logic.`
2335
2252
  );
2336
2253
  dmServerIdToUse = DEFAULT_SERVER_ID3;
@@ -2348,7 +2265,7 @@ function createChannelsRouter(agents, serverInstance) {
2348
2265
  stack: error.stack,
2349
2266
  originalError: error
2350
2267
  } : { message: String(error) };
2351
- logger14.error("Error finding/creating DM channel:", errorDetails);
2268
+ logger12.error("Error finding/creating DM channel:", errorDetails);
2352
2269
  res.status(500).json({ success: false, error: "Failed to find or create DM channel" });
2353
2270
  }
2354
2271
  });
@@ -2360,8 +2277,8 @@ function createChannelsRouter(agents, serverInstance) {
2360
2277
  server_id,
2361
2278
  metadata
2362
2279
  } = req.body;
2363
- const isValidServerId = server_id === DEFAULT_SERVER_ID3 || validateUuid13(server_id);
2364
- if (!name || !isValidServerId || !Array.isArray(participantCentralUserIds) || participantCentralUserIds.some((id) => !validateUuid13(id))) {
2280
+ const isValidServerId = server_id === DEFAULT_SERVER_ID3 || validateUuid12(server_id);
2281
+ if (!name || !isValidServerId || !Array.isArray(participantCentralUserIds) || participantCentralUserIds.some((id) => !validateUuid12(id))) {
2365
2282
  return res.status(400).json({
2366
2283
  success: false,
2367
2284
  error: 'Invalid payload. Required: name, server_id (UUID or "0"), participantCentralUserIds (array of UUIDs). Optional: type, metadata.'
@@ -2384,7 +2301,7 @@ function createChannelsRouter(agents, serverInstance) {
2384
2301
  res.status(201).json({ success: true, data: newChannel });
2385
2302
  } catch (error) {
2386
2303
  const errorMessage = error instanceof Error ? error.message : String(error);
2387
- logger14.error(
2304
+ logger12.error(
2388
2305
  "[Messages Router /central-channels] Error creating group channel:",
2389
2306
  errorMessage
2390
2307
  );
@@ -2394,7 +2311,7 @@ function createChannelsRouter(agents, serverInstance) {
2394
2311
  router.get(
2395
2312
  "/central-channels/:channelId/details",
2396
2313
  async (req, res) => {
2397
- const channelId = validateUuid13(req.params.channelId);
2314
+ const channelId = validateUuid12(req.params.channelId);
2398
2315
  if (!channelId) {
2399
2316
  return res.status(400).json({ success: false, error: "Invalid channelId" });
2400
2317
  }
@@ -2405,7 +2322,7 @@ function createChannelsRouter(agents, serverInstance) {
2405
2322
  }
2406
2323
  res.json({ success: true, data: channelDetails });
2407
2324
  } catch (error) {
2408
- logger14.error(`[Messages Router] Error fetching details for channel ${channelId}:`, error);
2325
+ logger12.error(`[Messages Router] Error fetching details for channel ${channelId}:`, error);
2409
2326
  res.status(500).json({ success: false, error: "Failed to fetch channel details" });
2410
2327
  }
2411
2328
  }
@@ -2413,7 +2330,7 @@ function createChannelsRouter(agents, serverInstance) {
2413
2330
  router.get(
2414
2331
  "/central-channels/:channelId/participants",
2415
2332
  async (req, res) => {
2416
- const channelId = validateUuid13(req.params.channelId);
2333
+ const channelId = validateUuid12(req.params.channelId);
2417
2334
  if (!channelId) {
2418
2335
  return res.status(400).json({ success: false, error: "Invalid channelId" });
2419
2336
  }
@@ -2421,7 +2338,7 @@ function createChannelsRouter(agents, serverInstance) {
2421
2338
  const participants = await serverInstance.getChannelParticipants(channelId);
2422
2339
  res.json({ success: true, data: participants });
2423
2340
  } catch (error) {
2424
- logger14.error(
2341
+ logger12.error(
2425
2342
  `[Messages Router] Error fetching participants for channel ${channelId}:`,
2426
2343
  error
2427
2344
  );
@@ -2432,9 +2349,9 @@ function createChannelsRouter(agents, serverInstance) {
2432
2349
  router.post(
2433
2350
  "/central-channels/:channelId/agents",
2434
2351
  async (req, res) => {
2435
- const channelId = validateUuid13(req.params.channelId);
2352
+ const channelId = validateUuid12(req.params.channelId);
2436
2353
  const { agentId } = req.body;
2437
- if (!channelId || !validateUuid13(agentId)) {
2354
+ if (!channelId || !validateUuid12(agentId)) {
2438
2355
  return res.status(400).json({
2439
2356
  success: false,
2440
2357
  error: "Invalid channelId or agentId format"
@@ -2449,7 +2366,7 @@ function createChannelsRouter(agents, serverInstance) {
2449
2366
  });
2450
2367
  }
2451
2368
  await serverInstance.addParticipantsToChannel(channelId, [agentId]);
2452
- logger14.info(`[Messages Router] Added agent ${agentId} to channel ${channelId}`);
2369
+ logger12.info(`[Messages Router] Added agent ${agentId} to channel ${channelId}`);
2453
2370
  res.status(201).json({
2454
2371
  success: true,
2455
2372
  data: {
@@ -2459,7 +2376,7 @@ function createChannelsRouter(agents, serverInstance) {
2459
2376
  }
2460
2377
  });
2461
2378
  } catch (error) {
2462
- logger14.error(
2379
+ logger12.error(
2463
2380
  `[Messages Router] Error adding agent ${agentId} to channel ${channelId}:`,
2464
2381
  error
2465
2382
  );
@@ -2474,8 +2391,8 @@ function createChannelsRouter(agents, serverInstance) {
2474
2391
  router.delete(
2475
2392
  "/central-channels/:channelId/agents/:agentId",
2476
2393
  async (req, res) => {
2477
- const channelId = validateUuid13(req.params.channelId);
2478
- const agentId = validateUuid13(req.params.agentId);
2394
+ const channelId = validateUuid12(req.params.channelId);
2395
+ const agentId = validateUuid12(req.params.agentId);
2479
2396
  if (!channelId || !agentId) {
2480
2397
  return res.status(400).json({
2481
2398
  success: false,
@@ -2501,7 +2418,7 @@ function createChannelsRouter(agents, serverInstance) {
2501
2418
  await serverInstance.updateChannel(channelId, {
2502
2419
  participantCentralUserIds: updatedParticipants
2503
2420
  });
2504
- logger14.info(`[Messages Router] Removed agent ${agentId} from channel ${channelId}`);
2421
+ logger12.info(`[Messages Router] Removed agent ${agentId} from channel ${channelId}`);
2505
2422
  res.status(200).json({
2506
2423
  success: true,
2507
2424
  data: {
@@ -2511,7 +2428,7 @@ function createChannelsRouter(agents, serverInstance) {
2511
2428
  }
2512
2429
  });
2513
2430
  } catch (error) {
2514
- logger14.error(
2431
+ logger12.error(
2515
2432
  `[Messages Router] Error removing agent ${agentId} from channel ${channelId}:`,
2516
2433
  error
2517
2434
  );
@@ -2526,7 +2443,7 @@ function createChannelsRouter(agents, serverInstance) {
2526
2443
  router.get(
2527
2444
  "/central-channels/:channelId/agents",
2528
2445
  async (req, res) => {
2529
- const channelId = validateUuid13(req.params.channelId);
2446
+ const channelId = validateUuid12(req.params.channelId);
2530
2447
  if (!channelId) {
2531
2448
  return res.status(400).json({
2532
2449
  success: false,
@@ -2545,7 +2462,7 @@ function createChannelsRouter(agents, serverInstance) {
2545
2462
  }
2546
2463
  });
2547
2464
  } catch (error) {
2548
- logger14.error(`[Messages Router] Error fetching agents for channel ${channelId}:`, error);
2465
+ logger12.error(`[Messages Router] Error fetching agents for channel ${channelId}:`, error);
2549
2466
  res.status(500).json({
2550
2467
  success: false,
2551
2468
  error: "Failed to fetch channel agents"
@@ -2556,20 +2473,20 @@ function createChannelsRouter(agents, serverInstance) {
2556
2473
  router.delete(
2557
2474
  "/central-channels/:channelId/messages/:messageId",
2558
2475
  async (req, res) => {
2559
- const channelId = validateUuid13(req.params.channelId);
2560
- const messageId = validateUuid13(req.params.messageId);
2476
+ const channelId = validateUuid12(req.params.channelId);
2477
+ const messageId = validateUuid12(req.params.messageId);
2561
2478
  if (!channelId || !messageId) {
2562
2479
  return res.status(400).json({ success: false, error: "Invalid channelId or messageId" });
2563
2480
  }
2564
2481
  try {
2565
2482
  await serverInstance.deleteMessage(messageId);
2566
- logger14.info(`[Messages Router] Deleted message ${messageId} from central database`);
2483
+ logger12.info(`[Messages Router] Deleted message ${messageId} from central database`);
2567
2484
  const deletedMessagePayload = {
2568
2485
  messageId,
2569
2486
  channelId
2570
2487
  };
2571
2488
  bus_default.emit("message_deleted", deletedMessagePayload);
2572
- logger14.info(
2489
+ logger12.info(
2573
2490
  `[Messages Router] Emitted message_deleted event to internal bus for message ${messageId}`
2574
2491
  );
2575
2492
  if (serverInstance.socketIO) {
@@ -2580,7 +2497,7 @@ function createChannelsRouter(agents, serverInstance) {
2580
2497
  }
2581
2498
  res.status(204).send();
2582
2499
  } catch (error) {
2583
- logger14.error(
2500
+ logger12.error(
2584
2501
  `[Messages Router] Error deleting message ${messageId} from channel ${channelId}:`,
2585
2502
  error
2586
2503
  );
@@ -2591,7 +2508,7 @@ function createChannelsRouter(agents, serverInstance) {
2591
2508
  router.delete(
2592
2509
  "/central-channels/:channelId/messages",
2593
2510
  async (req, res) => {
2594
- const channelId = validateUuid13(req.params.channelId);
2511
+ const channelId = validateUuid12(req.params.channelId);
2595
2512
  if (!channelId) {
2596
2513
  return res.status(400).json({ success: false, error: "Invalid channelId" });
2597
2514
  }
@@ -2601,7 +2518,7 @@ function createChannelsRouter(agents, serverInstance) {
2601
2518
  channelId
2602
2519
  };
2603
2520
  bus_default.emit("channel_cleared", channelClearedPayload);
2604
- logger14.info(
2521
+ logger12.info(
2605
2522
  `[Messages Router] Emitted channel_cleared event to internal bus for channel ${channelId}`
2606
2523
  );
2607
2524
  if (serverInstance.socketIO) {
@@ -2611,7 +2528,7 @@ function createChannelsRouter(agents, serverInstance) {
2611
2528
  }
2612
2529
  res.status(204).send();
2613
2530
  } catch (error) {
2614
- logger14.error(`[Messages Router] Error clearing messages for channel ${channelId}:`, error);
2531
+ logger12.error(`[Messages Router] Error clearing messages for channel ${channelId}:`, error);
2615
2532
  res.status(500).json({ success: false, error: "Failed to clear messages" });
2616
2533
  }
2617
2534
  }
@@ -2619,7 +2536,7 @@ function createChannelsRouter(agents, serverInstance) {
2619
2536
  router.patch(
2620
2537
  "/central-channels/:channelId",
2621
2538
  async (req, res) => {
2622
- const channelId = validateUuid13(req.params.channelId);
2539
+ const channelId = validateUuid12(req.params.channelId);
2623
2540
  if (!channelId) {
2624
2541
  return res.status(400).json({ success: false, error: "Invalid channelId" });
2625
2542
  }
@@ -2638,7 +2555,7 @@ function createChannelsRouter(agents, serverInstance) {
2638
2555
  }
2639
2556
  res.json({ success: true, data: updatedChannel });
2640
2557
  } catch (error) {
2641
- logger14.error(`[Messages Router] Error updating channel ${channelId}:`, error);
2558
+ logger12.error(`[Messages Router] Error updating channel ${channelId}:`, error);
2642
2559
  res.status(500).json({ success: false, error: "Failed to update channel" });
2643
2560
  }
2644
2561
  }
@@ -2646,7 +2563,7 @@ function createChannelsRouter(agents, serverInstance) {
2646
2563
  router.delete(
2647
2564
  "/central-channels/:channelId",
2648
2565
  async (req, res) => {
2649
- const channelId = validateUuid13(req.params.channelId);
2566
+ const channelId = validateUuid12(req.params.channelId);
2650
2567
  if (!channelId) {
2651
2568
  return res.status(400).json({ success: false, error: "Invalid channelId" });
2652
2569
  }
@@ -2654,14 +2571,14 @@ function createChannelsRouter(agents, serverInstance) {
2654
2571
  const messages = await serverInstance.getMessagesForChannel(channelId);
2655
2572
  const messageCount = messages.length;
2656
2573
  await serverInstance.deleteChannel(channelId);
2657
- logger14.info(
2574
+ logger12.info(
2658
2575
  `[Messages Router] Deleted channel ${channelId} with ${messageCount} messages from central database`
2659
2576
  );
2660
2577
  const channelClearedPayload = {
2661
2578
  channelId
2662
2579
  };
2663
2580
  bus_default.emit("channel_cleared", channelClearedPayload);
2664
- logger14.info(
2581
+ logger12.info(
2665
2582
  `[Messages Router] Emitted channel_cleared event to internal bus for deleted channel ${channelId}`
2666
2583
  );
2667
2584
  if (serverInstance.socketIO) {
@@ -2671,7 +2588,7 @@ function createChannelsRouter(agents, serverInstance) {
2671
2588
  }
2672
2589
  res.status(204).send();
2673
2590
  } catch (error) {
2674
- logger14.error(`[Messages Router] Error deleting channel ${channelId}:`, error);
2591
+ logger12.error(`[Messages Router] Error deleting channel ${channelId}:`, error);
2675
2592
  res.status(500).json({ success: false, error: "Failed to delete channel" });
2676
2593
  }
2677
2594
  }
@@ -2680,44 +2597,24 @@ function createChannelsRouter(agents, serverInstance) {
2680
2597
  "/channels/:channelId/upload-media",
2681
2598
  createUploadRateLimit(),
2682
2599
  createFileSystemRateLimit(),
2683
- channelUpload(),
2600
+ channelUploadMiddleware.single("file"),
2684
2601
  async (req, res) => {
2685
- const channelId = validateUuid13(req.params.channelId);
2602
+ const channelId = validateUuid12(req.params.channelId);
2686
2603
  if (!channelId) {
2687
2604
  res.status(400).json({ success: false, error: "Invalid channelId format" });
2688
2605
  return;
2689
2606
  }
2690
- let mediaFile;
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) {
2607
+ if (!req.file) {
2700
2608
  res.status(400).json({ success: false, error: "No media file provided" });
2701
2609
  return;
2702
2610
  }
2703
2611
  try {
2704
- if (!validateMediaFile(mediaFile)) {
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);
2612
+ if (!req.file.originalname || req.file.originalname.includes("..") || req.file.originalname.includes("/")) {
2711
2613
  res.status(400).json({ success: false, error: "Invalid filename detected" });
2712
2614
  return;
2713
2615
  }
2714
- if (mediaFile.size > MAX_FILE_SIZE) {
2715
- cleanupUploadedFile(mediaFile);
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(
2616
+ const result = await saveChannelUploadedFile(req.file, channelId);
2617
+ logger12.info(
2721
2618
  `[MessagesRouter /upload-media] Secure file uploaded for channel ${channelId}: ${result.filename}. URL: ${result.url}`
2722
2619
  );
2723
2620
  res.json({
@@ -2725,21 +2622,18 @@ function createChannelsRouter(agents, serverInstance) {
2725
2622
  data: {
2726
2623
  url: result.url,
2727
2624
  // Relative URL, client prepends server origin
2728
- type: mediaFile.mimetype,
2625
+ type: req.file.mimetype,
2729
2626
  filename: result.filename,
2730
- originalName: mediaFile.name,
2731
- size: mediaFile.size
2627
+ originalName: req.file.originalname,
2628
+ size: req.file.size
2732
2629
  }
2733
2630
  });
2734
2631
  } catch (error) {
2735
2632
  const errorMessage = error instanceof Error ? error.message : String(error);
2736
- logger14.error(
2633
+ logger12.error(
2737
2634
  `[MessagesRouter /upload-media] Error processing upload for channel ${channelId}: ${errorMessage}`,
2738
2635
  error
2739
2636
  );
2740
- if (mediaFile) {
2741
- cleanupUploadedFile(mediaFile);
2742
- }
2743
2637
  res.status(500).json({ success: false, error: "Failed to process media upload" });
2744
2638
  }
2745
2639
  }
@@ -2747,7 +2641,7 @@ function createChannelsRouter(agents, serverInstance) {
2747
2641
  router.post(
2748
2642
  "/central-channels/:channelId/generate-title",
2749
2643
  async (req, res) => {
2750
- const channelId = validateUuid13(req.params.channelId);
2644
+ const channelId = validateUuid12(req.params.channelId);
2751
2645
  const { agentId } = req.body;
2752
2646
  if (!channelId) {
2753
2647
  return res.status(400).json({
@@ -2755,7 +2649,7 @@ function createChannelsRouter(agents, serverInstance) {
2755
2649
  error: "Invalid channel ID format"
2756
2650
  });
2757
2651
  }
2758
- if (!agentId || !validateUuid13(agentId)) {
2652
+ if (!agentId || !validateUuid12(agentId)) {
2759
2653
  return res.status(400).json({
2760
2654
  success: false,
2761
2655
  error: "Valid agent ID is required"
@@ -2769,7 +2663,7 @@ function createChannelsRouter(agents, serverInstance) {
2769
2663
  error: "Agent not found or not active"
2770
2664
  });
2771
2665
  }
2772
- logger14.info(`[CHANNEL SUMMARIZE] Summarizing channel ${channelId}`);
2666
+ logger12.info(`[CHANNEL SUMMARIZE] Summarizing channel ${channelId}`);
2773
2667
  const limit = req.query.limit ? Number.parseInt(req.query.limit, 10) : 50;
2774
2668
  const before = req.query.before ? Number.parseInt(req.query.before, 10) : void 0;
2775
2669
  const beforeDate = before ? new Date(before) : void 0;
@@ -2823,22 +2717,22 @@ Respond with just the title, nothing else.
2823
2717
  // Keep titles short
2824
2718
  });
2825
2719
  if (!newTitle || newTitle.trim().length === 0) {
2826
- logger14.warn(`[ChatTitleEvaluator] Failed to generate title for room ${channelId}`);
2720
+ logger12.warn(`[ChatTitleEvaluator] Failed to generate title for room ${channelId}`);
2827
2721
  return;
2828
2722
  }
2829
2723
  const cleanTitle = newTitle.trim().replace(/^["']|["']$/g, "");
2830
- logger14.info(`[ChatTitleEvaluator] Generated title: "${cleanTitle}" for room ${channelId}`);
2724
+ logger12.info(`[ChatTitleEvaluator] Generated title: "${cleanTitle}" for room ${channelId}`);
2831
2725
  const result = {
2832
2726
  title: cleanTitle,
2833
2727
  channelId
2834
2728
  };
2835
- logger14.success(`[CHANNEL SUMMARIZE] Successfully summarized channel ${channelId}`);
2729
+ logger12.success(`[CHANNEL SUMMARIZE] Successfully summarized channel ${channelId}`);
2836
2730
  res.json({
2837
2731
  success: true,
2838
2732
  data: result
2839
2733
  });
2840
2734
  } catch (error) {
2841
- logger14.error("[CHANNEL SUMMARIZE] Error summarizing channel:", error);
2735
+ logger12.error("[CHANNEL SUMMARIZE] Error summarizing channel:", error);
2842
2736
  res.status(500).json({
2843
2737
  success: false,
2844
2738
  error: "Failed to summarize channel",
@@ -2866,58 +2760,74 @@ function messagingRouter(agents, serverInstance) {
2866
2760
  import express15 from "express";
2867
2761
 
2868
2762
  // src/api/media/agents.ts
2869
- import { validateUuid as validateUuid14, logger as logger15, getContentTypeFromMimeType } from "@elizaos/core";
2763
+ import { validateUuid as validateUuid13, logger as logger13, getContentTypeFromMimeType } from "@elizaos/core";
2870
2764
  import express13 from "express";
2765
+ import multer2 from "multer";
2766
+ import fs2 from "fs";
2767
+ import path2 from "path";
2768
+ var storage = multer2.memoryStorage();
2769
+ var upload = multer2({
2770
+ storage,
2771
+ limits: {
2772
+ fileSize: MAX_FILE_SIZE,
2773
+ files: 1
2774
+ },
2775
+ fileFilter: (req, file, cb) => {
2776
+ if (ALLOWED_MEDIA_MIME_TYPES.includes(file.mimetype)) {
2777
+ cb(null, true);
2778
+ } else {
2779
+ cb(new Error("Invalid file type"), false);
2780
+ }
2781
+ }
2782
+ });
2783
+ async function saveUploadedFile(file, agentId) {
2784
+ const uploadDir = path2.join(process.cwd(), ".eliza/data/uploads/agents", agentId);
2785
+ if (!fs2.existsSync(uploadDir)) {
2786
+ fs2.mkdirSync(uploadDir, { recursive: true });
2787
+ }
2788
+ const timestamp = Date.now();
2789
+ const random = Math.round(Math.random() * 1e9);
2790
+ const ext = path2.extname(file.originalname);
2791
+ const filename = `${timestamp}-${random}${ext}`;
2792
+ const filePath = path2.join(uploadDir, filename);
2793
+ fs2.writeFileSync(filePath, file.buffer);
2794
+ const url = `/media/uploads/agents/${agentId}/${filename}`;
2795
+ return { filename, url };
2796
+ }
2871
2797
  function createAgentMediaRouter() {
2872
2798
  const router = express13.Router();
2873
- router.post("/:agentId/upload-media", agentMediaUpload(), async (req, res) => {
2874
- const agentMediaReq = req;
2875
- logger15.debug("[MEDIA UPLOAD] Processing media upload");
2876
- const agentId = validateUuid14(agentMediaReq.params.agentId);
2799
+ router.post("/:agentId/upload-media", upload.single("file"), async (req, res) => {
2800
+ logger13.debug("[MEDIA UPLOAD] Processing media upload with multer");
2801
+ const agentId = validateUuid13(req.params.agentId);
2877
2802
  if (!agentId) {
2878
2803
  return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
2879
2804
  }
2880
- let mediaFile;
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) {
2805
+ if (!req.file) {
2889
2806
  return sendError(res, 400, "INVALID_REQUEST", "No media file provided");
2890
2807
  }
2891
- const mimetype = mediaFile.mimetype;
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);
2808
+ const mediaType = getContentTypeFromMimeType(req.file.mimetype);
2897
2809
  if (!mediaType) {
2898
- cleanupUploadedFile(mediaFile);
2899
2810
  return sendError(
2900
2811
  res,
2901
2812
  400,
2902
2813
  "UNSUPPORTED_MEDIA_TYPE",
2903
- `Unsupported media MIME type: ${mimetype}`
2814
+ `Unsupported media MIME type: ${req.file.mimetype}`
2904
2815
  );
2905
2816
  }
2906
2817
  try {
2907
- const result = await processUploadedFile(mediaFile, agentId, "agents");
2908
- logger15.info(
2818
+ const result = await saveUploadedFile(req.file, agentId);
2819
+ logger13.info(
2909
2820
  `[MEDIA UPLOAD] Successfully uploaded ${mediaType}: ${result.filename}. URL: ${result.url}`
2910
2821
  );
2911
2822
  sendSuccess(res, {
2912
2823
  url: result.url,
2913
2824
  type: mediaType,
2914
2825
  filename: result.filename,
2915
- originalName: mediaFile.name,
2916
- size: mediaFile.size
2826
+ originalName: req.file.originalname,
2827
+ size: req.file.size
2917
2828
  });
2918
2829
  } catch (error) {
2919
- logger15.error(`[MEDIA UPLOAD] Error processing upload: ${error}`);
2920
- cleanupUploadedFile(mediaFile);
2830
+ logger13.error(`[MEDIA UPLOAD] Error processing upload: ${error}`);
2921
2831
  sendError(
2922
2832
  res,
2923
2833
  500,
@@ -2931,9 +2841,41 @@ function createAgentMediaRouter() {
2931
2841
  }
2932
2842
 
2933
2843
  // src/api/media/channels.ts
2934
- import { validateUuid as validateUuid15, logger as logger16 } from "@elizaos/core";
2844
+ import { validateUuid as validateUuid14, logger as logger14 } from "@elizaos/core";
2935
2845
  import express14 from "express";
2936
2846
  import rateLimit2 from "express-rate-limit";
2847
+ import multer3 from "multer";
2848
+ import fs3 from "fs";
2849
+ import path3 from "path";
2850
+ var storage2 = multer3.memoryStorage();
2851
+ var upload2 = multer3({
2852
+ storage: storage2,
2853
+ limits: {
2854
+ fileSize: MAX_FILE_SIZE,
2855
+ files: 1
2856
+ },
2857
+ fileFilter: (req, file, cb) => {
2858
+ if (ALLOWED_MEDIA_MIME_TYPES.includes(file.mimetype)) {
2859
+ cb(null, true);
2860
+ } else {
2861
+ cb(new Error("Invalid file type"), false);
2862
+ }
2863
+ }
2864
+ });
2865
+ async function saveUploadedFile2(file, channelId) {
2866
+ const uploadDir = path3.join(process.cwd(), ".eliza/data/uploads/channels", channelId);
2867
+ if (!fs3.existsSync(uploadDir)) {
2868
+ fs3.mkdirSync(uploadDir, { recursive: true });
2869
+ }
2870
+ const timestamp = Date.now();
2871
+ const random = Math.round(Math.random() * 1e9);
2872
+ const ext = path3.extname(file.originalname);
2873
+ const filename = `${timestamp}-${random}${ext}`;
2874
+ const filePath = path3.join(uploadDir, filename);
2875
+ fs3.writeFileSync(filePath, file.buffer);
2876
+ const url = `/media/uploads/channels/${channelId}/${filename}`;
2877
+ return { filename, url };
2878
+ }
2937
2879
  function createChannelMediaRouter() {
2938
2880
  const router = express14.Router();
2939
2881
  const uploadMediaRateLimiter = rateLimit2({
@@ -2947,35 +2889,20 @@ function createChannelMediaRouter() {
2947
2889
  "/:channelId/upload-media",
2948
2890
  uploadMediaRateLimiter,
2949
2891
  // Apply rate limiter
2950
- channelUpload(),
2892
+ upload2.single("file"),
2951
2893
  async (req, res) => {
2952
- const channelMediaReq = req;
2953
- const channelId = validateUuid15(channelMediaReq.params.channelId);
2894
+ const channelId = validateUuid14(req.params.channelId);
2954
2895
  if (!channelId) {
2955
2896
  res.status(400).json({ success: false, error: "Invalid channelId format" });
2956
2897
  return;
2957
2898
  }
2958
- let mediaFile;
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 {
2899
+ if (!req.file) {
2964
2900
  res.status(400).json({ success: false, error: "No media file provided" });
2965
2901
  return;
2966
2902
  }
2967
- if (!mediaFile) {
2968
- res.status(400).json({ success: false, error: "No media file provided" });
2969
- return;
2970
- }
2971
- if (!validateMediaFile(mediaFile)) {
2972
- cleanupUploadedFile(mediaFile);
2973
- res.status(400).json({ success: false, error: `Invalid file type: ${mediaFile.mimetype}` });
2974
- return;
2975
- }
2976
2903
  try {
2977
- const result = await processUploadedFile(mediaFile, channelId, "channels");
2978
- logger16.info(
2904
+ const result = await saveUploadedFile2(req.file, channelId);
2905
+ logger14.info(
2979
2906
  `[Channel Media Upload] File uploaded for channel ${channelId}: ${result.filename}. URL: ${result.url}`
2980
2907
  );
2981
2908
  res.json({
@@ -2983,18 +2910,17 @@ function createChannelMediaRouter() {
2983
2910
  data: {
2984
2911
  url: result.url,
2985
2912
  // Relative URL, client prepends server origin
2986
- type: mediaFile.mimetype,
2913
+ type: req.file.mimetype,
2987
2914
  filename: result.filename,
2988
- originalName: mediaFile.name,
2989
- size: mediaFile.size
2915
+ originalName: req.file.originalname,
2916
+ size: req.file.size
2990
2917
  }
2991
2918
  });
2992
2919
  } catch (error) {
2993
- logger16.error(
2920
+ logger14.error(
2994
2921
  `[Channel Media Upload] Error processing upload for channel ${channelId}: ${error.message}`,
2995
2922
  error
2996
2923
  );
2997
- cleanupUploadedFile(mediaFile);
2998
2924
  res.status(500).json({ success: false, error: "Failed to process media upload" });
2999
2925
  }
3000
2926
  }
@@ -3016,6 +2942,40 @@ import express17 from "express";
3016
2942
  // src/api/memory/groups.ts
3017
2943
  import { validateUuid as validateUuid16, logger as logger17, createUniqueUuid as createUniqueUuid4, ChannelType as ChannelType3 } from "@elizaos/core";
3018
2944
  import express16 from "express";
2945
+
2946
+ // src/api/shared/file-utils.ts
2947
+ import fs4 from "fs";
2948
+ import path4 from "path";
2949
+ import { logger as logger15 } from "@elizaos/core";
2950
+ var cleanupUploadedFile = (file) => {
2951
+ logger15.debug(`[FILE] Multer file ${file.originalname} in memory, no cleanup needed`);
2952
+ };
2953
+
2954
+ // src/upload.ts
2955
+ import fs5 from "fs";
2956
+ import path5 from "path";
2957
+ import multer4 from "multer";
2958
+ import { validateUuid as validateUuid15, logger as logger16 } from "@elizaos/core";
2959
+ var storage3 = multer4.memoryStorage();
2960
+ var agentAudioUpload = () => multer4({
2961
+ storage: storage3,
2962
+ limits: {
2963
+ fileSize: MAX_FILE_SIZE,
2964
+ files: 1
2965
+ },
2966
+ fileFilter: (req, file, cb) => {
2967
+ if (ALLOWED_AUDIO_MIME_TYPES.includes(file.mimetype)) {
2968
+ cb(null, true);
2969
+ } else {
2970
+ cb(new Error("Invalid audio file type"), false);
2971
+ }
2972
+ }
2973
+ });
2974
+ function validateAudioFile(file) {
2975
+ return ALLOWED_AUDIO_MIME_TYPES.includes(file.mimetype);
2976
+ }
2977
+
2978
+ // src/api/memory/groups.ts
3019
2979
  function createGroupMemoryRouter(agents, serverInstance) {
3020
2980
  const router = express16.Router();
3021
2981
  const db = serverInstance?.database;
@@ -3147,184 +3107,110 @@ import express21 from "express";
3147
3107
  // src/api/audio/processing.ts
3148
3108
  import { logger as logger18, ModelType as ModelType2, validateUuid as validateUuid17 } from "@elizaos/core";
3149
3109
  import express18 from "express";
3150
- import fs3 from "fs";
3110
+ import fs6 from "fs";
3151
3111
  import os from "os";
3152
- import path3 from "path";
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
- }
3112
+ import path6 from "path";
3187
3113
  function createAudioProcessingRouter(agents) {
3188
3114
  const router = express18.Router();
3189
3115
  router.use(createUploadRateLimit());
3190
3116
  router.use(createFileSystemRateLimit());
3191
- router.post(
3192
- "/:agentId/audio-messages",
3193
- agentAudioUpload(),
3194
- // Use agentAudioUpload
3195
- async (req, res) => {
3196
- const audioReq = req;
3197
- logger18.debug("[AUDIO MESSAGE] Processing audio message");
3198
- const agentId = validateUuid17(req.params.agentId);
3199
- if (!agentId) {
3200
- return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
3201
- }
3202
- const audioFile = getUploadedFile(audioReq);
3203
- if (!audioFile) {
3204
- return sendError(res, 400, "INVALID_REQUEST", "No audio file provided");
3205
- }
3206
- const runtime = agents.get(agentId);
3207
- if (!runtime) {
3117
+ router.post("/:agentId/audio-messages", agentAudioUpload().single("file"), async (req, res) => {
3118
+ const audioReq = req;
3119
+ logger18.debug("[AUDIO MESSAGE] Processing audio message");
3120
+ const agentId = validateUuid17(req.params.agentId);
3121
+ if (!agentId) {
3122
+ return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
3123
+ }
3124
+ const audioFile = audioReq.file;
3125
+ if (!audioFile) {
3126
+ return sendError(res, 400, "INVALID_REQUEST", "No audio file provided");
3127
+ }
3128
+ const runtime = agents.get(agentId);
3129
+ if (!runtime) {
3130
+ cleanupUploadedFile(audioFile);
3131
+ return sendError(res, 404, "NOT_FOUND", "Agent not found");
3132
+ }
3133
+ try {
3134
+ if (!validateAudioFile(audioFile)) {
3208
3135
  cleanupUploadedFile(audioFile);
3209
- return sendError(res, 404, "NOT_FOUND", "Agent not found");
3136
+ return sendError(res, 400, "INVALID_FILE_TYPE", "Invalid audio file type");
3210
3137
  }
3211
- try {
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}`);
3138
+ if (audioFile.size > MAX_FILE_SIZE) {
3242
3139
  cleanupUploadedFile(audioFile);
3243
- sendSuccess(res, { transcription, message: "Audio transcribed, further processing TBD." });
3244
- } catch (error) {
3245
- logger18.error("[AUDIO MESSAGE] Error processing audio:", error);
3246
- cleanupUploadedFile(audioFile);
3247
- sendError(
3140
+ return sendError(
3248
3141
  res,
3249
- 500,
3250
- "PROCESSING_ERROR",
3251
- "Error processing audio message",
3252
- error instanceof Error ? error.message : String(error)
3142
+ 413,
3143
+ "FILE_TOO_LARGE",
3144
+ `Audio file too large (max ${MAX_FILE_SIZE_DISPLAY})`
3253
3145
  );
3254
3146
  }
3147
+ const transcription = await runtime.useModel(ModelType2.TRANSCRIPTION, audioFile.buffer);
3148
+ logger18.info(`[AUDIO MESSAGE] Transcription for agent ${agentId}: ${transcription}`);
3149
+ cleanupUploadedFile(audioFile);
3150
+ sendSuccess(res, { transcription, message: "Audio transcribed, further processing TBD." });
3151
+ } catch (error) {
3152
+ logger18.error("[AUDIO MESSAGE] Error processing audio:", error);
3153
+ cleanupUploadedFile(audioFile);
3154
+ sendError(
3155
+ res,
3156
+ 500,
3157
+ "PROCESSING_ERROR",
3158
+ "Error processing audio message",
3159
+ error instanceof Error ? error.message : String(error)
3160
+ );
3255
3161
  }
3256
- );
3257
- router.post(
3258
- "/:agentId/transcriptions",
3259
- agentAudioUpload(),
3260
- // Use agentAudioUpload
3261
- async (req, res) => {
3262
- const audioReq = req;
3263
- logger18.debug("[TRANSCRIPTION] Request to transcribe audio");
3264
- const agentId = validateUuid17(req.params.agentId);
3265
- if (!agentId) {
3266
- return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
3267
- }
3268
- const audioFile = getUploadedFile(audioReq);
3269
- if (!audioFile) {
3270
- return sendError(res, 400, "INVALID_REQUEST", "No audio file provided");
3271
- }
3272
- const runtime = agents.get(agentId);
3273
- if (!runtime) {
3162
+ });
3163
+ router.post("/:agentId/transcriptions", agentAudioUpload().single("file"), async (req, res) => {
3164
+ const audioReq = req;
3165
+ logger18.debug("[TRANSCRIPTION] Request to transcribe audio");
3166
+ const agentId = validateUuid17(req.params.agentId);
3167
+ if (!agentId) {
3168
+ return sendError(res, 400, "INVALID_ID", "Invalid agent ID format");
3169
+ }
3170
+ const audioFile = audioReq.file;
3171
+ if (!audioFile) {
3172
+ return sendError(res, 400, "INVALID_REQUEST", "No audio file provided");
3173
+ }
3174
+ const runtime = agents.get(agentId);
3175
+ if (!runtime) {
3176
+ cleanupUploadedFile(audioFile);
3177
+ return sendError(res, 404, "NOT_FOUND", "Agent not found");
3178
+ }
3179
+ try {
3180
+ logger18.debug("[TRANSCRIPTION] Reading audio file");
3181
+ if (!validateAudioFile(audioFile)) {
3274
3182
  cleanupUploadedFile(audioFile);
3275
- return sendError(res, 404, "NOT_FOUND", "Agent not found");
3183
+ return sendError(res, 400, "INVALID_FILE_TYPE", "Invalid audio file type");
3276
3184
  }
3277
- try {
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);
3185
+ if (audioFile.size > MAX_FILE_SIZE) {
3309
3186
  cleanupUploadedFile(audioFile);
3310
- if (!transcription) {
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(
3187
+ return sendError(
3319
3188
  res,
3320
- 500,
3321
- "PROCESSING_ERROR",
3322
- "Error transcribing audio",
3323
- error instanceof Error ? error.message : String(error)
3189
+ 413,
3190
+ "FILE_TOO_LARGE",
3191
+ `Audio file too large (max ${MAX_FILE_SIZE_DISPLAY})`
3324
3192
  );
3325
3193
  }
3194
+ logger18.debug("[TRANSCRIPTION] Transcribing audio");
3195
+ const transcription = await runtime.useModel(ModelType2.TRANSCRIPTION, audioFile.buffer);
3196
+ cleanupUploadedFile(audioFile);
3197
+ if (!transcription) {
3198
+ return sendError(res, 500, "PROCESSING_ERROR", "Failed to transcribe audio");
3199
+ }
3200
+ logger18.success("[TRANSCRIPTION] Successfully transcribed audio");
3201
+ sendSuccess(res, { text: transcription });
3202
+ } catch (error) {
3203
+ logger18.error("[TRANSCRIPTION] Error transcribing audio:", error);
3204
+ cleanupUploadedFile(audioFile);
3205
+ sendError(
3206
+ res,
3207
+ 500,
3208
+ "PROCESSING_ERROR",
3209
+ "Error transcribing audio",
3210
+ error instanceof Error ? error.message : String(error)
3211
+ );
3326
3212
  }
3327
- );
3213
+ });
3328
3214
  return router;
3329
3215
  }
3330
3216
 
@@ -3821,15 +3707,15 @@ import express28 from "express";
3821
3707
  import { logger as logger23 } from "@elizaos/core";
3822
3708
  import express27 from "express";
3823
3709
  import { existsSync, writeFileSync } from "fs";
3824
- import path4 from "path";
3710
+ import path7 from "path";
3825
3711
  import dotenv from "dotenv";
3826
- import fs4 from "fs/promises";
3712
+ import fs7 from "fs/promises";
3827
3713
  async function parseEnvFile(filePath) {
3828
3714
  try {
3829
3715
  if (!existsSync(filePath)) {
3830
3716
  return {};
3831
3717
  }
3832
- const content = await fs4.readFile(filePath, "utf-8");
3718
+ const content = await fs7.readFile(filePath, "utf-8");
3833
3719
  if (content.trim() === "") {
3834
3720
  return {};
3835
3721
  }
@@ -3849,17 +3735,17 @@ function getLocalEnvPath() {
3849
3735
  function resolveEnvFile(startDir = process.cwd()) {
3850
3736
  let currentDir = startDir;
3851
3737
  while (true) {
3852
- const candidate = path4.join(currentDir, ".env");
3738
+ const candidate = path7.join(currentDir, ".env");
3853
3739
  if (existsSync(candidate)) {
3854
3740
  return candidate;
3855
3741
  }
3856
- const parentDir = path4.dirname(currentDir);
3742
+ const parentDir = path7.dirname(currentDir);
3857
3743
  if (parentDir === currentDir) {
3858
3744
  break;
3859
3745
  }
3860
3746
  currentDir = parentDir;
3861
3747
  }
3862
- return path4.join(startDir, ".env");
3748
+ return path7.join(startDir, ".env");
3863
3749
  }
3864
3750
  function createEnvironmentRouter() {
3865
3751
  const router = express27.Router();
@@ -4610,6 +4496,7 @@ function createApiRouter(agents, serverInstance) {
4610
4496
  );
4611
4497
  router.use(createApiRateLimit());
4612
4498
  router.use(securityMiddleware());
4499
+ router.use("/media", mediaRouter());
4613
4500
  router.use(validateContentTypeMiddleware());
4614
4501
  router.use(
4615
4502
  bodyParser.json({
@@ -4629,7 +4516,6 @@ function createApiRouter(agents, serverInstance) {
4629
4516
  );
4630
4517
  router.use("/agents", agentsRouter(agents, serverInstance));
4631
4518
  router.use("/messaging", messagingRouter(agents, serverInstance));
4632
- router.use("/media", mediaRouter());
4633
4519
  router.use("/memory", memoryRouter(agents, serverInstance));
4634
4520
  router.use("/audio", audioRouter(agents));
4635
4521
  router.use("/server", runtimeRouter(agents, serverInstance));
@@ -5033,7 +4919,14 @@ var MessageBusService = class _MessageBusService extends Service {
5033
4919
  await this.runtime.emitEvent(EventType2.MESSAGE_RECEIVED, {
5034
4920
  runtime: this.runtime,
5035
4921
  message: agentMemory,
5036
- callback: callbackForCentralBus
4922
+ callback: callbackForCentralBus,
4923
+ onComplete: async () => {
4924
+ const room = await this.runtime.getRoom(agentRoomId);
4925
+ const world = await this.runtime.getWorld(agentWorldId);
4926
+ const channelId = room?.channelId;
4927
+ const serverId = world?.serverId;
4928
+ await this.notifyMessageComplete(channelId, serverId);
4929
+ }
5037
4930
  });
5038
4931
  } catch (error) {
5039
4932
  logger27.error(
@@ -5110,7 +5003,6 @@ var MessageBusService = class _MessageBusService extends Service {
5110
5003
  logger27.error(
5111
5004
  `[${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
5005
  );
5113
- await this.notifyMessageComplete(channelId, serverId);
5114
5006
  return;
5115
5007
  }
5116
5008
  const shouldSkip = content.actions?.includes("IGNORE") || !content.text || content.text.trim() === "";
@@ -5118,7 +5010,6 @@ var MessageBusService = class _MessageBusService extends Service {
5118
5010
  logger27.info(
5119
5011
  `[${this.runtime.character.name}] MessageBusService: Skipping response (reason: ${content.actions?.includes("IGNORE") ? "IGNORE action" : "No text"})`
5120
5012
  );
5121
- await this.notifyMessageComplete(channelId, serverId);
5122
5013
  return;
5123
5014
  }
5124
5015
  let centralInReplyToRootMessageId = void 0;
@@ -5263,8 +5154,8 @@ var messageBusConnectorPlugin = {
5263
5154
  };
5264
5155
 
5265
5156
  // src/loader.ts
5266
- import fs5 from "fs";
5267
- import path5 from "path";
5157
+ import fs8 from "fs";
5158
+ import path8 from "path";
5268
5159
  import { fileURLToPath } from "url";
5269
5160
  import {
5270
5161
  logger as logger28,
@@ -5272,10 +5163,10 @@ import {
5272
5163
  validateCharacter
5273
5164
  } from "@elizaos/core";
5274
5165
  var __filename = fileURLToPath(import.meta.url);
5275
- var __dirname = path5.dirname(__filename);
5166
+ var __dirname = path8.dirname(__filename);
5276
5167
  function tryLoadFile(filePath) {
5277
5168
  try {
5278
- return fs5.readFileSync(filePath, "utf8");
5169
+ return fs8.readFileSync(filePath, "utf8");
5279
5170
  } catch (e) {
5280
5171
  throw new Error(`Error loading file ${filePath}: ${e}`);
5281
5172
  }
@@ -5372,36 +5263,36 @@ async function loadCharacter(filePath) {
5372
5263
  }
5373
5264
  return jsonToCharacter(parseResult.data);
5374
5265
  }
5375
- function handleCharacterLoadError(path7, error) {
5266
+ function handleCharacterLoadError(path10, error) {
5376
5267
  const errorMsg = error instanceof Error ? error.message : String(error);
5377
5268
  if (errorMsg.includes("ENOENT") || errorMsg.includes("no such file")) {
5378
- logger28.error(`Character file not found: ${path7}`);
5269
+ logger28.error(`Character file not found: ${path10}`);
5379
5270
  throw new Error(
5380
- `Character '${path7}' not found. Please check if the file exists and the path is correct.`
5271
+ `Character '${path10}' not found. Please check if the file exists and the path is correct.`
5381
5272
  );
5382
5273
  } else if (errorMsg.includes("Character validation failed")) {
5383
- logger28.error(`Character validation failed for: ${path7}`);
5384
- throw new Error(`Character file '${path7}' contains invalid character data. ${errorMsg}`);
5274
+ logger28.error(`Character validation failed for: ${path10}`);
5275
+ throw new Error(`Character file '${path10}' contains invalid character data. ${errorMsg}`);
5385
5276
  } else if (errorMsg.includes("JSON")) {
5386
- logger28.error(`JSON parsing error in character file: ${path7}`);
5387
- throw new Error(`Character file '${path7}' has malformed JSON. Please check the file content.`);
5277
+ logger28.error(`JSON parsing error in character file: ${path10}`);
5278
+ throw new Error(`Character file '${path10}' has malformed JSON. Please check the file content.`);
5388
5279
  } else if (errorMsg.includes("Invalid JSON")) {
5389
- logger28.error(`Invalid JSON in character file: ${path7}`);
5280
+ logger28.error(`Invalid JSON in character file: ${path10}`);
5390
5281
  throw new Error(
5391
- `Character file '${path7}' has invalid JSON format. Please check the file content.`
5282
+ `Character file '${path10}' has invalid JSON format. Please check the file content.`
5392
5283
  );
5393
5284
  } else {
5394
- logger28.error(`Error loading character from ${path7}: ${errorMsg}`);
5395
- throw new Error(`Failed to load character '${path7}': ${errorMsg}`);
5285
+ logger28.error(`Error loading character from ${path10}: ${errorMsg}`);
5286
+ throw new Error(`Failed to load character '${path10}': ${errorMsg}`);
5396
5287
  }
5397
5288
  }
5398
- async function safeLoadCharacter(path7) {
5289
+ async function safeLoadCharacter(path10) {
5399
5290
  try {
5400
- const character = await loadCharacter(path7);
5401
- logger28.info(`Successfully loaded character from: ${path7}`);
5291
+ const character = await loadCharacter(path10);
5292
+ logger28.info(`Successfully loaded character from: ${path10}`);
5402
5293
  return character;
5403
5294
  } catch (e) {
5404
- return handleCharacterLoadError(path7, e);
5295
+ return handleCharacterLoadError(path10, e);
5405
5296
  }
5406
5297
  }
5407
5298
  async function loadCharacterTryPath(characterPath) {
@@ -5421,27 +5312,27 @@ async function loadCharacterTryPath(characterPath) {
5421
5312
  const jsonPath = hasJsonExtension ? characterPath : `${characterPath}.json`;
5422
5313
  const basePathsToTry = [
5423
5314
  basePath,
5424
- path5.resolve(process.cwd(), basePath),
5425
- path5.resolve(process.cwd(), "..", "..", basePath),
5426
- path5.resolve(process.cwd(), "..", "..", "..", basePath),
5427
- path5.resolve(process.cwd(), "agent", basePath),
5428
- path5.resolve(__dirname, basePath),
5429
- path5.resolve(__dirname, "characters", path5.basename(basePath)),
5430
- path5.resolve(__dirname, "../characters", path5.basename(basePath)),
5431
- path5.resolve(__dirname, "../../characters", path5.basename(basePath)),
5432
- path5.resolve(__dirname, "../../../characters", path5.basename(basePath))
5315
+ path8.resolve(process.cwd(), basePath),
5316
+ path8.resolve(process.cwd(), "..", "..", basePath),
5317
+ path8.resolve(process.cwd(), "..", "..", "..", basePath),
5318
+ path8.resolve(process.cwd(), "agent", basePath),
5319
+ path8.resolve(__dirname, basePath),
5320
+ path8.resolve(__dirname, "characters", path8.basename(basePath)),
5321
+ path8.resolve(__dirname, "../characters", path8.basename(basePath)),
5322
+ path8.resolve(__dirname, "../../characters", path8.basename(basePath)),
5323
+ path8.resolve(__dirname, "../../../characters", path8.basename(basePath))
5433
5324
  ];
5434
5325
  const jsonPathsToTry = hasJsonExtension ? [] : [
5435
5326
  jsonPath,
5436
- path5.resolve(process.cwd(), jsonPath),
5437
- path5.resolve(process.cwd(), "..", "..", jsonPath),
5438
- path5.resolve(process.cwd(), "..", "..", "..", jsonPath),
5439
- path5.resolve(process.cwd(), "agent", jsonPath),
5440
- path5.resolve(__dirname, jsonPath),
5441
- path5.resolve(__dirname, "characters", path5.basename(jsonPath)),
5442
- path5.resolve(__dirname, "../characters", path5.basename(jsonPath)),
5443
- path5.resolve(__dirname, "../../characters", path5.basename(jsonPath)),
5444
- path5.resolve(__dirname, "../../../characters", path5.basename(jsonPath))
5327
+ path8.resolve(process.cwd(), jsonPath),
5328
+ path8.resolve(process.cwd(), "..", "..", jsonPath),
5329
+ path8.resolve(process.cwd(), "..", "..", "..", jsonPath),
5330
+ path8.resolve(process.cwd(), "agent", jsonPath),
5331
+ path8.resolve(__dirname, jsonPath),
5332
+ path8.resolve(__dirname, "characters", path8.basename(jsonPath)),
5333
+ path8.resolve(__dirname, "../characters", path8.basename(jsonPath)),
5334
+ path8.resolve(__dirname, "../../characters", path8.basename(jsonPath)),
5335
+ path8.resolve(__dirname, "../../../characters", path8.basename(jsonPath))
5445
5336
  ];
5446
5337
  const pathsToTry = Array.from(/* @__PURE__ */ new Set([...basePathsToTry, ...jsonPathsToTry]));
5447
5338
  let lastError = null;
@@ -5466,11 +5357,11 @@ function commaSeparatedStringToArray(commaSeparated) {
5466
5357
  }
5467
5358
  async function readCharactersFromStorage(characterPaths) {
5468
5359
  try {
5469
- const uploadDir = path5.join(process.cwd(), ".eliza", "data", "characters");
5470
- await fs5.promises.mkdir(uploadDir, { recursive: true });
5471
- const fileNames = await fs5.promises.readdir(uploadDir);
5360
+ const uploadDir = path8.join(process.cwd(), ".eliza", "data", "characters");
5361
+ await fs8.promises.mkdir(uploadDir, { recursive: true });
5362
+ const fileNames = await fs8.promises.readdir(uploadDir);
5472
5363
  for (const fileName of fileNames) {
5473
- characterPaths.push(path5.join(uploadDir, fileName));
5364
+ characterPaths.push(path8.join(uploadDir, fileName));
5474
5365
  }
5475
5366
  } catch (err) {
5476
5367
  logger28.error(`Error reading directory: ${err.message}`);
@@ -5526,11 +5417,11 @@ function expandTildePath(filepath) {
5526
5417
  if (filepath === "~") {
5527
5418
  return process.cwd();
5528
5419
  } else if (filepath.startsWith("~/")) {
5529
- return path6.join(process.cwd(), filepath.slice(2));
5420
+ return path9.join(process.cwd(), filepath.slice(2));
5530
5421
  } else if (filepath.startsWith("~~")) {
5531
5422
  return filepath;
5532
5423
  } else {
5533
- return path6.join(process.cwd(), filepath.slice(1));
5424
+ return path9.join(process.cwd(), filepath.slice(1));
5534
5425
  }
5535
5426
  }
5536
5427
  return filepath;
@@ -5540,11 +5431,11 @@ function resolvePgliteDir(dir, fallbackDir) {
5540
5431
  if (existsSync3(envPath)) {
5541
5432
  dotenv2.config({ path: envPath });
5542
5433
  }
5543
- const base = dir ?? process.env.PGLITE_DATA_DIR ?? fallbackDir ?? path6.join(process.cwd(), ".eliza", ".elizadb");
5434
+ const base = dir ?? process.env.PGLITE_DATA_DIR ?? fallbackDir ?? path9.join(process.cwd(), ".eliza", ".elizadb");
5544
5435
  const resolved = expandTildePath(base);
5545
- const legacyPath = path6.join(process.cwd(), ".elizadb");
5436
+ const legacyPath = path9.join(process.cwd(), ".elizadb");
5546
5437
  if (resolved === legacyPath) {
5547
- const newPath = path6.join(process.cwd(), ".eliza", ".elizadb");
5438
+ const newPath = path9.join(process.cwd(), ".eliza", ".elizadb");
5548
5439
  process.env.PGLITE_DATA_DIR = newPath;
5549
5440
  return newPath;
5550
5441
  }
@@ -5580,6 +5471,46 @@ var AgentServer = class {
5580
5471
  throw error;
5581
5472
  }
5582
5473
  }
5474
+ /**
5475
+ * Dynamically resolves the client path based on the installation context.
5476
+ * Handles both development and production scenarios.
5477
+ *
5478
+ * @returns {string} The resolved path to the client dist directory
5479
+ * @throws {Error} If no valid client path can be found
5480
+ */
5481
+ resolveClientPath() {
5482
+ try {
5483
+ const cliPackageJson = __require.resolve("@elizaos/cli/package.json");
5484
+ const cliDir = path9.dirname(cliPackageJson);
5485
+ const cliDistPath = path9.join(cliDir, "dist");
5486
+ if (fs9.existsSync(path9.join(cliDistPath, "index.html"))) {
5487
+ logger29.debug(`[CLIENT PATH] Resolved client path from npm package: ${cliDistPath}`);
5488
+ return cliDistPath;
5489
+ }
5490
+ } catch (e) {
5491
+ logger29.debug("[CLIENT PATH] Could not resolve @elizaos/cli package, trying other methods");
5492
+ }
5493
+ const relativePath = path9.resolve(__dirname2, "../../cli/dist");
5494
+ if (fs9.existsSync(path9.join(relativePath, "index.html"))) {
5495
+ logger29.debug(`[CLIENT PATH] Resolved client path from relative path: ${relativePath}`);
5496
+ return relativePath;
5497
+ }
5498
+ const cwdPath = path9.join(process.cwd(), "dist");
5499
+ if (fs9.existsSync(path9.join(cwdPath, "index.html"))) {
5500
+ logger29.debug(`[CLIENT PATH] Resolved client path from current directory: ${cwdPath}`);
5501
+ return cwdPath;
5502
+ }
5503
+ if (process.env.ELIZA_CLIENT_PATH) {
5504
+ const envPath = path9.resolve(process.env.ELIZA_CLIENT_PATH);
5505
+ if (fs9.existsSync(path9.join(envPath, "index.html"))) {
5506
+ logger29.debug(`[CLIENT PATH] Resolved client path from environment variable: ${envPath}`);
5507
+ return envPath;
5508
+ }
5509
+ }
5510
+ throw new Error(
5511
+ "Unable to locate client files. Please ensure @elizaos/cli is properly installed."
5512
+ );
5513
+ }
5583
5514
  /**
5584
5515
  * Initializes the database and server.
5585
5516
  *
@@ -5784,26 +5715,10 @@ var AgentServer = class {
5784
5715
  })
5785
5716
  );
5786
5717
  this.app.use(
5787
- bodyParser2.json({
5718
+ express30.json({
5788
5719
  limit: process.env.EXPRESS_MAX_PAYLOAD || "100kb"
5789
5720
  })
5790
5721
  );
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
5722
  const serverAuthToken = process.env.ELIZA_SERVER_AUTH_TOKEN;
5808
5723
  if (serverAuthToken) {
5809
5724
  logger29.info("Server authentication enabled. Requires X-API-KEY header for /api routes.");
@@ -5815,10 +5730,10 @@ var AgentServer = class {
5815
5730
  "Server authentication is disabled. Set ELIZA_SERVER_AUTH_TOKEN environment variable to enable."
5816
5731
  );
5817
5732
  }
5818
- const uploadsBasePath = path6.join(process.cwd(), ".eliza", "data", "uploads", "agents");
5819
- const generatedBasePath = path6.join(process.cwd(), ".eliza", "data", "generated");
5820
- fs6.mkdirSync(uploadsBasePath, { recursive: true });
5821
- fs6.mkdirSync(generatedBasePath, { recursive: true });
5733
+ const uploadsBasePath = path9.join(process.cwd(), ".eliza", "data", "uploads", "agents");
5734
+ const generatedBasePath = path9.join(process.cwd(), ".eliza", "data", "generated");
5735
+ fs9.mkdirSync(uploadsBasePath, { recursive: true });
5736
+ fs9.mkdirSync(generatedBasePath, { recursive: true });
5822
5737
  this.app.get(
5823
5738
  "/media/uploads/agents/:agentId/:filename",
5824
5739
  // @ts-expect-error - this is a valid express route
@@ -5835,7 +5750,7 @@ var AgentServer = class {
5835
5750
  if (!filePath.startsWith(agentUploadsPath)) {
5836
5751
  return res.status(403).json({ error: "Access denied" });
5837
5752
  }
5838
- if (!fs6.existsSync(filePath)) {
5753
+ if (!fs9.existsSync(filePath)) {
5839
5754
  return res.status(404).json({ error: "File does not exist!!!!!!!" });
5840
5755
  }
5841
5756
  res.sendFile(sanitizedFilename, { root: agentUploadsPath }, (err) => {
@@ -5939,8 +5854,14 @@ var AgentServer = class {
5939
5854
  }
5940
5855
  }
5941
5856
  };
5942
- const clientPath = path6.resolve(__dirname2, "../../cli/dist");
5943
- this.app.use(express30.static(clientPath, staticOptions));
5857
+ try {
5858
+ const clientPath = this.resolveClientPath();
5859
+ this.app.use(express30.static(clientPath, staticOptions));
5860
+ logger29.info(`[STATIC] Serving client files from: ${clientPath}`);
5861
+ } catch (error) {
5862
+ logger29.error("[STATIC] Failed to resolve client path:", error);
5863
+ logger29.warn("[STATIC] Client UI will not be available. API endpoints will still work.");
5864
+ }
5944
5865
  const pluginRouteHandler = createPluginRouteHandler(this.agents);
5945
5866
  this.app.use(pluginRouteHandler);
5946
5867
  const apiRouter = createApiRouter(this.agents, this);
@@ -5982,8 +5903,30 @@ var AgentServer = class {
5982
5903
  res.setHeader("Content-Type", "application/javascript");
5983
5904
  return res.status(404).send(`// JavaScript module not found: ${req.path}`);
5984
5905
  }
5985
- const cliDistPath = path6.resolve(__dirname2, "../../cli/dist");
5986
- res.sendFile(path6.join(cliDistPath, "index.html"));
5906
+ try {
5907
+ const cliDistPath = this.resolveClientPath();
5908
+ res.sendFile(path9.join(cliDistPath, "index.html"), (err) => {
5909
+ if (err && !res.headersSent) {
5910
+ logger29.error("[STATIC] Failed to serve index.html:", err);
5911
+ res.status(404).json({
5912
+ success: false,
5913
+ error: {
5914
+ message: "Client UI not available. Please ensure @elizaos/cli is properly installed.",
5915
+ code: 404
5916
+ }
5917
+ });
5918
+ }
5919
+ });
5920
+ } catch (error) {
5921
+ logger29.error("[STATIC] Failed to resolve client path for fallback route:", error);
5922
+ res.status(404).json({
5923
+ success: false,
5924
+ error: {
5925
+ message: "Client UI not available. API endpoints are still accessible at /api/*",
5926
+ code: 404
5927
+ }
5928
+ });
5929
+ }
5987
5930
  });
5988
5931
  this.server = http.createServer(this.app);
5989
5932
  this.socketIO = setupSocketIO(this.server, this.agents, this);