Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Goat Plugin + AWS S3 Service error when env vars absent #985

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions agent/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,9 +384,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)
);
}
Comment on lines +387 to +392
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: In order to not duplicate the secret check, you could do

Suggested change
let goatPlugin: any | undefined;
if (getSecret(character, "ALCHEMY_API_KEY")) {
goatPlugin = await createGoatPlugin((secret) =>
getSecret(character, secret)
);
}
const getGoatPlugin = async () => await createGoatPlugin((secret) =>
getSecret(character, secret)
);

and then later on line 440 do

            getSecret(character, "ALCHEMY_API_KEY") ? getGoatPlugin() : null,


return new AgentRuntime({
databaseAdapter: db,
Expand Down
9 changes: 9 additions & 0 deletions packages/plugin-node/src/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
63 changes: 37 additions & 26 deletions packages/plugin-node/src/services/awsS3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> {
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<boolean> {
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({
Expand All @@ -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(
Expand All @@ -71,6 +67,13 @@ export class AwsS3Service extends Service implements IAwsS3Service {
expiresIn: number = 900
): Promise<UploadResult> {
try {
if (!await this.initializeS3Client()) {
return {
success: false,
error: "AWS S3 credentials not configured",
};
}

if (!fs.existsSync(filePath)) {
return {
success: false,
Expand Down Expand Up @@ -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",
};
}
}
Expand All @@ -135,6 +135,10 @@ export class AwsS3Service extends Service implements IAwsS3Service {
fileName: string,
expiresIn: number = 900
): Promise<string> {
if (!await this.initializeS3Client()) {
throw new Error("AWS S3 credentials not configured");
}

const command = new GetObjectCommand({
Bucket: this.bucket,
Key: fileName,
Expand Down Expand Up @@ -171,6 +175,13 @@ export class AwsS3Service extends Service implements IAwsS3Service {
expiresIn: number = 900
): Promise<JsonUploadResult> {
try {
if (!await this.initializeS3Client()) {
return {
success: false,
error: "AWS S3 credentials not configured",
};
}

// Validate input
if (!jsonData) {
return {
Expand Down