@elizaos/server 1.6.2-alpha.16 → 1.6.2-alpha.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -21,17 +21,21 @@ export declare function resolvePgliteDir(dir?: string, fallbackDir?: string): st
21
21
  */
22
22
  export type ServerMiddleware = (req: express.Request, res: express.Response, next: express.NextFunction) => void;
23
23
  /**
24
- * Interface for defining server configuration options.
25
- * @typedef {Object} ServerOptions
26
- * @property {ServerMiddleware[]} [middlewares] - Optional array of server middlewares.
27
- * @property {string} [dataDir] - Optional directory for storing server data.
28
- * @property {string} [postgresUrl] - Optional URL for connecting to a PostgreSQL database.
24
+ * Interface for defining server configuration.
25
+ * Used for unified server initialization and startup.
29
26
  */
30
- export interface ServerOptions {
27
+ export interface ServerConfig {
31
28
  middlewares?: ServerMiddleware[];
32
29
  dataDir?: string;
33
30
  postgresUrl?: string;
34
31
  clientPath?: string;
32
+ port?: number;
33
+ agents?: Array<{
34
+ character: Character;
35
+ plugins?: (Plugin | string)[];
36
+ init?: (runtime: IAgentRuntime) => Promise<void>;
37
+ }>;
38
+ isTestMode?: boolean;
35
39
  }
36
40
  /**
37
41
  * Determines if the web UI should be enabled based on environment variables.
@@ -57,12 +61,15 @@ export declare class AgentServer {
57
61
  jsonToCharacter: (character: unknown) => Promise<Character>;
58
62
  /**
59
63
  * Start multiple agents in batch (true parallel)
60
- * @param characters - Array of character configurations
61
- * @param plugins - Optional plugins to load
64
+ * @param agents - Array of agent configurations (character + optional plugins/init)
62
65
  * @param options - Optional configuration (e.g., isTestMode for test dependencies)
63
66
  * @returns Array of started agent runtimes
64
67
  */
65
- startAgents(characters: Character[], plugins?: (Plugin | string)[], options?: {
68
+ startAgents(agents: Array<{
69
+ character: Character;
70
+ plugins?: (Plugin | string)[];
71
+ init?: (runtime: IAgentRuntime) => Promise<void>;
72
+ }>, options?: {
66
73
  isTestMode?: boolean;
67
74
  }): Promise<IAgentRuntime[]>;
68
75
  /**
@@ -88,18 +95,20 @@ export declare class AgentServer {
88
95
  */
89
96
  constructor();
90
97
  /**
91
- * Initializes the database and server.
98
+ * Initializes the database and server (internal use only).
92
99
  *
93
- * @param {ServerOptions} [options] - Optional server options.
100
+ * @param {ServerConfig} [config] - Optional server configuration.
94
101
  * @returns {Promise<void>} A promise that resolves when initialization is complete.
102
+ * @private
95
103
  */
96
- initialize(options?: ServerOptions): Promise<void>;
104
+ private initialize;
97
105
  private ensureDefaultServer;
98
106
  /**
99
- * Initializes the server with the provided options.
107
+ * Initializes the server with the provided configuration.
100
108
  *
101
- * @param {ServerOptions} [options] - Optional server options.
109
+ * @param {ServerConfig} [config] - Optional server configuration.
102
110
  * @returns {Promise<void>} - A promise that resolves once the server is initialized.
111
+ * @private
103
112
  */
104
113
  private initializeServer;
105
114
  /**
@@ -125,13 +134,33 @@ export declare class AgentServer {
125
134
  */
126
135
  registerMiddleware(middleware: ServerMiddleware): void;
127
136
  /**
128
- * Starts the server on the specified port.
137
+ * Starts the server with unified configuration.
138
+ * Handles initialization, port resolution, and optional agent startup.
129
139
  *
130
- * @param {number} port - The port number on which the server should listen.
140
+ * @param {ServerConfig} config - Server configuration including port, agents, and infrastructure options.
131
141
  * @returns {Promise<void>} A promise that resolves when the server is listening.
132
- * @throws {Error} If the port is invalid or if there is an error while starting the server.
142
+ * @throws {Error} If there is an error during initialization or startup.
133
143
  */
134
- start(port: number): Promise<void>;
144
+ start(config?: ServerConfig): Promise<void>;
145
+ /**
146
+ * Resolves and finds an available port.
147
+ * - If port is provided (number): validates and returns it (strict - fails if unavailable)
148
+ * - If port is undefined: finds next available port starting from env/default (auto-discovery)
149
+ */
150
+ private resolveAndFindPort;
151
+ /**
152
+ * Finds an available port starting from the requested port.
153
+ * Tries incrementing ports up to maxAttempts.
154
+ */
155
+ private findAvailablePort;
156
+ /**
157
+ * Checks if a port is available by attempting to bind to it.
158
+ */
159
+ private isPortAvailable;
160
+ /**
161
+ * Starts the HTTP server on the specified port.
162
+ */
163
+ private startHttpServer;
135
164
  /**
136
165
  * Stops the server if it is running. Closes the server connection,
137
166
  * stops the database connection, and logs a success message.
package/dist/index.js CHANGED
@@ -23620,6 +23620,7 @@ var helmet = Object.assign(function helmet2(options = {}) {
23620
23620
  import * as fs6 from "node:fs";
23621
23621
  import http4 from "node:http";
23622
23622
  import os3 from "node:os";
23623
+ import net3 from "node:net";
23623
23624
  import path8, { basename as basename2, dirname as dirname3, extname, join as join4 } from "node:path";
23624
23625
  import { fileURLToPath as fileURLToPath2 } from "node:url";
23625
23626
 
@@ -23825,7 +23826,7 @@ function createAgentCrudRouter(elizaOS, serverInstance) {
23825
23826
  try {
23826
23827
  await serverInstance?.unregisterAgent(agentId);
23827
23828
  const { enabled, status: status2, createdAt, updatedAt, ...characterData } = updatedAgent;
23828
- const runtimes = await serverInstance?.startAgents([characterData]);
23829
+ const runtimes = await serverInstance?.startAgents([{ character: characterData }]);
23829
23830
  if (!runtimes || runtimes.length === 0) {
23830
23831
  throw new Error("Failed to restart agent after configuration change");
23831
23832
  }
@@ -23834,7 +23835,7 @@ function createAgentCrudRouter(elizaOS, serverInstance) {
23834
23835
  logger.error({ error: restartError, agentId }, `[AGENT UPDATE] Failed to restart agent ${agentId}, attempting to restore previous state`);
23835
23836
  try {
23836
23837
  const { enabled, status: status2, createdAt, updatedAt, ...previousCharacterData } = currentAgent;
23837
- await serverInstance?.startAgents([previousCharacterData]);
23838
+ await serverInstance?.startAgents([{ character: previousCharacterData }]);
23838
23839
  logger.warn(`[AGENT UPDATE] Restored agent ${agentId} to previous state`);
23839
23840
  } catch (restoreError) {
23840
23841
  logger.error({ error: restoreError, agentId }, `[AGENT UPDATE] Failed to restore agent ${agentId} - agent may be in broken state`);
@@ -23956,7 +23957,7 @@ import { validateUuid as validateUuid2, logger as logger2 } from "@elizaos/core"
23956
23957
  import express2 from "express";
23957
23958
  function createAgentLifecycleRouter(elizaOS, serverInstance) {
23958
23959
  const router = express2.Router();
23959
- const db = serverInstance?.database;
23960
+ const db = serverInstance.database;
23960
23961
  router.post("/:agentId/start", async (req, res) => {
23961
23962
  const agentId = validateUuid2(req.params.agentId);
23962
23963
  if (!agentId) {
@@ -23980,7 +23981,7 @@ function createAgentLifecycleRouter(elizaOS, serverInstance) {
23980
23981
  status: "active"
23981
23982
  });
23982
23983
  }
23983
- await serverInstance?.startAgents([agent]);
23984
+ await serverInstance.startAgents([{ character: agent }]);
23984
23985
  const runtime = elizaOS.getAgent(agentId);
23985
23986
  if (!runtime) {
23986
23987
  throw new Error("Failed to start agent");
@@ -28855,7 +28856,7 @@ import express30 from "express";
28855
28856
  // package.json
28856
28857
  var package_default = {
28857
28858
  name: "@elizaos/server",
28858
- version: "1.6.2-alpha.16",
28859
+ version: "1.6.2-alpha.18",
28859
28860
  description: "ElizaOS Server - Core server infrastructure for ElizaOS agents",
28860
28861
  publishConfig: {
28861
28862
  access: "public",
@@ -45942,16 +45943,21 @@ class AgentServer {
45942
45943
  database;
45943
45944
  loadCharacterTryPath;
45944
45945
  jsonToCharacter;
45945
- async startAgents(characters, plugins = [], options) {
45946
+ async startAgents(agents, options) {
45946
45947
  if (!this.elizaOS) {
45947
45948
  throw new Error("Server not properly initialized");
45948
45949
  }
45949
- const agentConfigs = characters.map((character) => {
45950
- character.id ??= stringToUuid2(character.name);
45951
- const allPlugins = [...character.plugins || [], ...plugins, sqlPlugin];
45950
+ const agentConfigs = agents.map((agent) => {
45951
+ agent.character.id ??= stringToUuid2(agent.character.name);
45952
+ const allPlugins = [
45953
+ ...agent.character.plugins || [],
45954
+ ...agent.plugins || [],
45955
+ sqlPlugin
45956
+ ];
45952
45957
  return {
45953
- character: encryptedCharacter(character),
45954
- plugins: allPlugins
45958
+ character: encryptedCharacter(agent.character),
45959
+ plugins: allPlugins,
45960
+ init: agent.init
45955
45961
  };
45956
45962
  });
45957
45963
  const agentIds = await this.elizaOS.addAgents(agentConfigs, options);
@@ -46009,14 +46015,14 @@ class AgentServer {
46009
46015
  throw error2;
46010
46016
  }
46011
46017
  }
46012
- async initialize(options) {
46018
+ async initialize(config3) {
46013
46019
  if (this.isInitialized) {
46014
46020
  logger30.warn("AgentServer is already initialized, skipping initialization");
46015
46021
  return;
46016
46022
  }
46017
46023
  try {
46018
46024
  logger30.debug("Initializing AgentServer (async operations)...");
46019
- const agentDataDir = resolvePgliteDir(options?.dataDir);
46025
+ const agentDataDir = resolvePgliteDir(config3?.dataDir);
46020
46026
  logger30.info(`[INIT] Database Dir for SQL plugin: ${agentDataDir}`);
46021
46027
  const dbDir = path8.dirname(agentDataDir);
46022
46028
  if (!fs6.existsSync(dbDir)) {
@@ -46026,7 +46032,7 @@ class AgentServer {
46026
46032
  const tempServerAgentId = "00000000-0000-0000-0000-000000000000";
46027
46033
  this.database = createDatabaseAdapter({
46028
46034
  dataDir: agentDataDir,
46029
- postgresUrl: options?.postgresUrl
46035
+ postgresUrl: config3?.postgresUrl
46030
46036
  }, tempServerAgentId);
46031
46037
  await this.database.init();
46032
46038
  logger30.success("Database initialized for server operations");
@@ -46052,7 +46058,7 @@ class AgentServer {
46052
46058
  this.elizaOS = new ElizaOS2;
46053
46059
  this.elizaOS.enableEditableMode();
46054
46060
  logger30.success("[INIT] ElizaOS initialized");
46055
- await this.initializeServer(options);
46061
+ await this.initializeServer(config3);
46056
46062
  await new Promise((resolve2) => setTimeout(resolve2, 250));
46057
46063
  this.isInitialized = true;
46058
46064
  } catch (error2) {
@@ -46114,10 +46120,10 @@ class AgentServer {
46114
46120
  throw error2;
46115
46121
  }
46116
46122
  }
46117
- async initializeServer(options) {
46123
+ async initializeServer(config3) {
46118
46124
  try {
46119
- if (options?.clientPath) {
46120
- this.clientPath = options.clientPath;
46125
+ if (config3?.clientPath) {
46126
+ this.clientPath = config3.clientPath;
46121
46127
  }
46122
46128
  this.app = express33();
46123
46129
  const DEFAULT_SENTRY_DSN = "https://c20e2d51b66c14a783b0689d536f7e5c@o4509349865259008.ingest.us.sentry.io/4509352524120064";
@@ -46187,9 +46193,9 @@ class AgentServer {
46187
46193
  referrerPolicy: { policy: "no-referrer-when-downgrade" },
46188
46194
  xssFilter: true
46189
46195
  }));
46190
- if (options?.middlewares) {
46196
+ if (config3?.middlewares) {
46191
46197
  logger30.debug("Applying custom middlewares...");
46192
- for (const middleware2 of options.middlewares) {
46198
+ for (const middleware2 of config3.middlewares) {
46193
46199
  this.app.use(middleware2);
46194
46200
  }
46195
46201
  }
@@ -46279,10 +46285,10 @@ class AgentServer {
46279
46285
  return;
46280
46286
  }
46281
46287
  const absolutePath = path8.resolve(filePath);
46282
- const options2 = {
46288
+ const options = {
46283
46289
  dotfiles: "deny"
46284
46290
  };
46285
- res.sendFile(absolutePath, options2, (err) => {
46291
+ res.sendFile(absolutePath, options, (err) => {
46286
46292
  if (err) {
46287
46293
  const ext2 = extname(filename).toLowerCase();
46288
46294
  const mimeType = ext2 === ".png" ? "image/png" : ext2 === ".jpg" || ext2 === ".jpeg" ? "image/jpeg" : "application/octet-stream";
@@ -46631,12 +46637,73 @@ class AgentServer {
46631
46637
  registerMiddleware(middleware2) {
46632
46638
  this.app.use(middleware2);
46633
46639
  }
46634
- start(port) {
46640
+ async start(config3) {
46641
+ if (!this.isInitialized) {
46642
+ await this.initialize(config3);
46643
+ }
46644
+ if (!config3?.isTestMode) {
46645
+ const port = await this.resolveAndFindPort(config3?.port);
46646
+ await this.startHttpServer(port);
46647
+ }
46648
+ if (config3?.agents && config3.agents.length > 0) {
46649
+ await this.startAgents(config3.agents, { isTestMode: config3.isTestMode });
46650
+ logger30.info(`Started ${config3.agents.length} agents`);
46651
+ }
46652
+ }
46653
+ async resolveAndFindPort(port) {
46654
+ if (port !== undefined) {
46655
+ if (typeof port !== "number" || port < 1 || port > 65535) {
46656
+ throw new Error(`Invalid port number: ${port}. Must be between 1 and 65535.`);
46657
+ }
46658
+ return port;
46659
+ }
46660
+ let requestedPort = 3000;
46661
+ const envPort = process.env.SERVER_PORT;
46662
+ if (envPort) {
46663
+ const parsed = parseInt(envPort, 10);
46664
+ if (!isNaN(parsed) && parsed >= 1 && parsed <= 65535) {
46665
+ requestedPort = parsed;
46666
+ } else {
46667
+ logger30.warn(`Invalid SERVER_PORT "${envPort}", falling back to 3000`);
46668
+ }
46669
+ }
46670
+ return await this.findAvailablePort(requestedPort);
46671
+ }
46672
+ async findAvailablePort(startPort, maxAttempts = 10) {
46673
+ for (let attempt = 0;attempt < maxAttempts; attempt++) {
46674
+ const port = startPort + attempt;
46675
+ if (port > 65535) {
46676
+ throw new Error(`Could not find available port (exceeded max port 65535, tried up to ${port - 1})`);
46677
+ }
46678
+ if (await this.isPortAvailable(port)) {
46679
+ if (attempt > 0) {
46680
+ logger30.info(`Port ${startPort} is in use, using port ${port} instead`);
46681
+ }
46682
+ return port;
46683
+ }
46684
+ }
46685
+ throw new Error(`Could not find available port after ${maxAttempts} attempts starting from ${startPort}`);
46686
+ }
46687
+ async isPortAvailable(port) {
46688
+ return new Promise((resolve2) => {
46689
+ const server = net3.createServer();
46690
+ server.once("error", (err) => {
46691
+ if (err.code === "EADDRINUSE") {
46692
+ resolve2(false);
46693
+ } else {
46694
+ resolve2(false);
46695
+ }
46696
+ });
46697
+ server.once("listening", () => {
46698
+ server.close();
46699
+ resolve2(true);
46700
+ });
46701
+ server.listen(port);
46702
+ });
46703
+ }
46704
+ startHttpServer(port) {
46635
46705
  return new Promise((resolve2, reject) => {
46636
46706
  try {
46637
- if (!port || typeof port !== "number") {
46638
- throw new Error(`Invalid port number: ${port}`);
46639
- }
46640
46707
  logger30.debug(`Starting server on port ${port}...`);
46641
46708
  logger30.debug(`Current agents count: ${this.elizaOS?.getAgents().length || 0}`);
46642
46709
  logger30.debug(`Environment: ${"development"}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/server",
3
- "version": "1.6.2-alpha.16",
3
+ "version": "1.6.2-alpha.18",
4
4
  "description": "ElizaOS Server - Core server infrastructure for ElizaOS agents",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -44,7 +44,7 @@
44
44
  "dev": "bun run build.ts --watch"
45
45
  },
46
46
  "devDependencies": {
47
- "@elizaos/client": "1.6.2-alpha.16",
47
+ "@elizaos/client": "1.6.2-alpha.18",
48
48
  "@types/node": "^24.0.1",
49
49
  "prettier": "3.6.2",
50
50
  "tsx": "4.20.6",
@@ -52,10 +52,10 @@
52
52
  "which": "^5.0.0",
53
53
  "ws": "^8.18.0"
54
54
  },
55
- "gitHead": "ae35960ef5fc17aebdc30b73c8fa57b5fff4e34e",
55
+ "gitHead": "6d6022cc97a0b1ce0909bfe8a7be10392677a416",
56
56
  "dependencies": {
57
- "@elizaos/core": "1.6.2-alpha.16",
58
- "@elizaos/plugin-sql": "1.6.2-alpha.16",
57
+ "@elizaos/core": "1.6.2-alpha.18",
58
+ "@elizaos/plugin-sql": "1.6.2-alpha.18",
59
59
  "@sentry/node": "^10.16.0",
60
60
  "@types/express": "^5.0.2",
61
61
  "@types/helmet": "^4.0.0",