From ca49c0e68cc5df2b62eaeef8950de5786441cf67 Mon Sep 17 00:00:00 2001 From: John Naulty Date: Tue, 10 Dec 2024 22:50:26 -0800 Subject: [PATCH 1/2] feat: make NodePlugin and GoatPlugin creation conditional - NodePlugin is now only created when all required AWS credentials are present (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_S3_BUCKET) - GoatPlugin is now only created when ALCHEMY_API_KEY is present - Added type annotations for plugins to handle undefined cases These changes prevent unnecessary plugin initialization when required credentials are missing and improve type safety. Issues introduced in: https://github.com/ai16z/eliza/pull/941 and https://github.com/ai16z/eliza/pull/898 --- agent/src/index.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/agent/src/index.ts b/agent/src/index.ts index 26d62c0995..f3ae5f04b3 100644 --- a/agent/src/index.ts +++ b/agent/src/index.ts @@ -371,7 +371,12 @@ export async function createAgent( character.name ); - nodePlugin ??= createNodePlugin(); + nodePlugin ??= ( + getSecret(character, "AWS_ACCESS_KEY_ID") && + getSecret(character, "AWS_SECRET_ACCESS_KEY") && + getSecret(character, "AWS_REGION") && + getSecret(character, "AWS_S3_BUCKET") + ) ? createNodePlugin() : undefined; const teeMode = getSecret(character, "TEE_MODE") || "OFF"; const walletSecretSalt = getSecret(character, "WALLET_SECRET_SALT"); @@ -384,9 +389,12 @@ export async function createAgent( throw new Error("Invalid TEE configuration"); } - const goatPlugin = await createGoatPlugin((secret) => - getSecret(character, secret) - ); + let goatPlugin: any | undefined; + if (getSecret(character, "ALCHEMY_API_KEY")) { + goatPlugin = await createGoatPlugin((secret) => + getSecret(character, secret) + ); + } return new AgentRuntime({ databaseAdapter: db, From 7a37c496cc8e0eb3237de55e4ef45fef79ebb517 Mon Sep 17 00:00:00 2001 From: John Naulty Date: Tue, 10 Dec 2024 23:14:35 -0800 Subject: [PATCH 2/2] do not activate aws s3 service in plugin-node if env vars not present --- agent/src/index.ts | 7 +-- packages/plugin-node/src/environment.ts | 9 ++++ packages/plugin-node/src/services/awsS3.ts | 63 +++++++++++++--------- 3 files changed, 47 insertions(+), 32 deletions(-) diff --git a/agent/src/index.ts b/agent/src/index.ts index f3ae5f04b3..683a7bcf2c 100644 --- a/agent/src/index.ts +++ b/agent/src/index.ts @@ -371,12 +371,7 @@ export async function createAgent( character.name ); - nodePlugin ??= ( - getSecret(character, "AWS_ACCESS_KEY_ID") && - getSecret(character, "AWS_SECRET_ACCESS_KEY") && - getSecret(character, "AWS_REGION") && - getSecret(character, "AWS_S3_BUCKET") - ) ? createNodePlugin() : undefined; + nodePlugin ??= createNodePlugin(); const teeMode = getSecret(character, "TEE_MODE") || "OFF"; const walletSecretSalt = getSecret(character, "WALLET_SECRET_SALT"); diff --git a/packages/plugin-node/src/environment.ts b/packages/plugin-node/src/environment.ts index 5d30bb93ed..ef524d03a3 100644 --- a/packages/plugin-node/src/environment.ts +++ b/packages/plugin-node/src/environment.ts @@ -71,6 +71,15 @@ export async function validateNodeConfig( // VITS settings VITS_VOICE: voiceSettings?.model || process.env.VITS_VOICE, VITS_MODEL: process.env.VITS_MODEL, + + // AWS settings (only include if present) + ...(runtime.getSetting("AWS_ACCESS_KEY_ID") && { + AWS_ACCESS_KEY_ID: runtime.getSetting("AWS_ACCESS_KEY_ID"), + AWS_SECRET_ACCESS_KEY: runtime.getSetting("AWS_SECRET_ACCESS_KEY"), + AWS_REGION: runtime.getSetting("AWS_REGION"), + AWS_S3_BUCKET: runtime.getSetting("AWS_S3_BUCKET"), + AWS_S3_UPLOAD_PATH: runtime.getSetting("AWS_S3_UPLOAD_PATH"), + }), }; return nodeEnvSchema.parse(config); diff --git a/packages/plugin-node/src/services/awsS3.ts b/packages/plugin-node/src/services/awsS3.ts index 16a50e13a3..57600ada5b 100644 --- a/packages/plugin-node/src/services/awsS3.ts +++ b/packages/plugin-node/src/services/awsS3.ts @@ -26,32 +26,28 @@ interface JsonUploadResult extends UploadResult { export class AwsS3Service extends Service implements IAwsS3Service { static serviceType: ServiceType = ServiceType.AWS_S3; - private s3Client: S3Client; - private bucket: string; - private fileUploadPath: string; - getInstance(): IAwsS3Service { - return AwsS3Service.getInstance(); - } + private s3Client: S3Client | null = null; + private bucket: string = ''; + private fileUploadPath: string = ''; private runtime: IAgentRuntime | null = null; async initialize(runtime: IAgentRuntime): Promise { console.log("Initializing AwsS3Service"); this.runtime = runtime; - const AWS_ACCESS_KEY_ID = runtime.getSetting("AWS_ACCESS_KEY_ID"); - const AWS_SECRET_ACCESS_KEY = runtime.getSetting( - "AWS_SECRET_ACCESS_KEY" - ); - const AWS_REGION = runtime.getSetting("AWS_REGION"); - const AWS_S3_BUCKET = runtime.getSetting("AWS_S3_BUCKET"); - if ( - !AWS_ACCESS_KEY_ID || - !AWS_SECRET_ACCESS_KEY || - !AWS_REGION || - !AWS_S3_BUCKET - ) { - throw new Error( - "Missing required AWS credentials in environment variables" - ); + this.fileUploadPath = runtime.getSetting("AWS_S3_UPLOAD_PATH") ?? ""; + } + + private async initializeS3Client(): Promise { + if (this.s3Client) return true; + if (!this.runtime) return false; + + const AWS_ACCESS_KEY_ID = this.runtime.getSetting("AWS_ACCESS_KEY_ID"); + const AWS_SECRET_ACCESS_KEY = this.runtime.getSetting("AWS_SECRET_ACCESS_KEY"); + const AWS_REGION = this.runtime.getSetting("AWS_REGION"); + const AWS_S3_BUCKET = this.runtime.getSetting("AWS_S3_BUCKET"); + + if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY || !AWS_REGION || !AWS_S3_BUCKET) { + return false; } this.s3Client = new S3Client({ @@ -61,8 +57,8 @@ export class AwsS3Service extends Service implements IAwsS3Service { secretAccessKey: AWS_SECRET_ACCESS_KEY, }, }); - this.fileUploadPath = runtime.getSetting("AWS_S3_UPLOAD_PATH") ?? ""; this.bucket = AWS_S3_BUCKET; + return true; } async uploadFile( @@ -71,6 +67,13 @@ export class AwsS3Service extends Service implements IAwsS3Service { expiresIn: number = 900 ): Promise { try { + if (!await this.initializeS3Client()) { + return { + success: false, + error: "AWS S3 credentials not configured", + }; + } + if (!fs.existsSync(filePath)) { return { success: false, @@ -120,10 +123,7 @@ export class AwsS3Service extends Service implements IAwsS3Service { } catch (error) { return { success: false, - error: - error instanceof Error - ? error.message - : "Unknown error occurred", + error: error instanceof Error ? error.message : "Unknown error occurred", }; } } @@ -135,6 +135,10 @@ export class AwsS3Service extends Service implements IAwsS3Service { fileName: string, expiresIn: number = 900 ): Promise { + if (!await this.initializeS3Client()) { + throw new Error("AWS S3 credentials not configured"); + } + const command = new GetObjectCommand({ Bucket: this.bucket, Key: fileName, @@ -171,6 +175,13 @@ export class AwsS3Service extends Service implements IAwsS3Service { expiresIn: number = 900 ): Promise { try { + if (!await this.initializeS3Client()) { + return { + success: false, + error: "AWS S3 credentials not configured", + }; + } + // Validate input if (!jsonData) { return {