remcode
Version:
Turn your AI assistant into a codebase expert. Intelligent code analysis, semantic search, and software engineering guidance through MCP integration.
251 lines (250 loc) • 9.2 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultNotificationConfigs = exports.NotificationService = void 0;
const logger_1 = require("../utils/logger");
const logger = (0, logger_1.getLogger)('NotificationService');
class NotificationService {
constructor(config = {}) {
this.config = config;
logger.info('NotificationService initialized', {
slack: !!config.slack,
email: !!config.email,
github: !!config.github
});
}
/**
* Send notification via all configured channels
*/
async sendNotification(payload) {
logger.info('Sending notification', {
type: payload.type,
title: payload.title,
repository: payload.repository
});
const results = {};
let overallSuccess = true;
// Send Slack notification
if (this.config.slack) {
try {
await this.sendSlackNotification(payload);
results.slack = { success: true };
logger.info('Slack notification sent successfully');
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error('Failed to send Slack notification', error);
results.slack = { success: false, error: errorMessage };
overallSuccess = false;
}
}
// Send email notification
if (this.config.email?.enabled) {
try {
await this.sendEmailNotification(payload);
results.email = { success: true };
logger.info('Email notification sent successfully');
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error('Failed to send email notification', error);
results.email = { success: false, error: errorMessage };
overallSuccess = false;
}
}
// Create GitHub issue for critical failures
if (this.config.github?.createIssue && payload.type === 'failure') {
try {
await this.createGitHubIssue(payload);
results.github = { success: true };
logger.info('GitHub issue created successfully');
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error('Failed to create GitHub issue', error);
results.github = { success: false, error: errorMessage };
overallSuccess = false;
}
}
return { success: overallSuccess, results };
}
/**
* Send Slack notification
*/
async sendSlackNotification(payload) {
if (!this.config.slack?.webhook) {
throw new Error('Slack webhook URL not configured');
}
const color = this.getSlackColor(payload.type);
const emoji = this.getSlackEmoji(payload.type);
const slackPayload = {
channel: this.config.slack.channel,
username: this.config.slack.username || 'Remcode Bot',
attachments: [
{
color,
title: `${emoji} ${payload.title}`,
text: payload.message,
fields: [
{
title: 'Repository',
value: payload.repository,
short: true
},
...(payload.runId ? [{
title: 'Run ID',
value: payload.runId.toString(),
short: true
}] : []),
...(payload.url ? [{
title: 'View Details',
value: `<${payload.url}|Open in GitHub>`,
short: true
}] : [])
],
ts: Math.floor(Date.now() / 1000)
}
]
};
const response = await fetch(this.config.slack.webhook, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(slackPayload)
});
if (!response.ok) {
throw new Error(`Slack API responded with status ${response.status}`);
}
}
/**
* Send email notification (placeholder implementation)
*/
async sendEmailNotification(payload) {
// For now, this is a placeholder. In a real implementation, you would:
// 1. Use a service like SendGrid, SES, or SMTP
// 2. Generate HTML email templates
// 3. Handle email delivery and retries
logger.info('Email notification would be sent', {
recipients: this.config.email?.recipients,
subject: payload.title,
type: payload.type
});
// Simulate email sending
await new Promise(resolve => setTimeout(resolve, 100));
}
/**
* Create GitHub issue for critical failures
*/
async createGitHubIssue(payload) {
// For now, this is a placeholder. In a real implementation, you would:
// 1. Use GitHub API to create issues
// 2. Include workflow logs and error details
// 3. Assign appropriate labels and assignees
logger.info('GitHub issue would be created', {
repository: payload.repository,
title: payload.title,
assignees: this.config.github?.assignees,
labels: this.config.github?.labels
});
// Simulate issue creation
await new Promise(resolve => setTimeout(resolve, 100));
}
/**
* Get Slack color based on notification type
*/
getSlackColor(type) {
switch (type) {
case 'success': return 'good';
case 'failure': return 'danger';
case 'warning': return 'warning';
case 'info': return '#36a64f';
default: return '#36a64f';
}
}
/**
* Get Slack emoji based on notification type
*/
getSlackEmoji(type) {
switch (type) {
case 'success': return '✅';
case 'failure': return '❌';
case 'warning': return '⚠️';
case 'info': return 'ℹ️';
default: return '📋';
}
}
/**
* Create notification for workflow completion
*/
static createWorkflowNotification(repository, runId, status, duration, stats) {
const type = status === 'success' ? 'success' : 'failure';
const title = status === 'success'
? `✅ Remcode Processing Completed`
: `❌ Remcode Processing Failed`;
let message = `Repository: ${repository}\n`;
message += `Duration: ${Math.round(duration / 60)} minutes\n`;
if (stats && status === 'success') {
message += `Files processed: ${stats.totalFiles || 'N/A'}\n`;
message += `Embeddings created: ${stats.totalEmbeddings || 'N/A'}\n`;
}
return {
type,
title,
message,
repository,
runId,
url: `https://github.com/${repository}/actions/runs/${runId}`
};
}
/**
* Create notification for workflow health issues
*/
static createHealthNotification(repository, issues, recommendations) {
const title = `⚠️ Workflow Health Alert`;
let message = `Repository: ${repository}\n\n`;
message += `Issues detected:\n${issues.map(issue => `• ${issue}`).join('\n')}\n\n`;
if (recommendations.length > 0) {
message += `Recommendations:\n${recommendations.map(rec => `• ${rec}`).join('\n')}`;
}
return {
type: 'warning',
title,
message,
repository,
metadata: { issues, recommendations }
};
}
}
exports.NotificationService = NotificationService;
/**
* Default notification configurations for common scenarios
*/
exports.defaultNotificationConfigs = {
/**
* Basic Slack-only configuration
*/
slackOnly: (webhookUrl, channel) => ({
slack: {
webhook: webhookUrl,
channel,
username: 'Remcode Bot'
}
}),
/**
* Comprehensive notification configuration
*/
comprehensive: (config) => ({
slack: config.slackWebhook ? {
webhook: config.slackWebhook,
username: 'Remcode Bot'
} : undefined,
email: config.emailRecipients ? {
enabled: true,
recipients: config.emailRecipients
} : undefined,
github: config.createGitHubIssues ? {
createIssue: true,
labels: ['remcode', 'workflow-failure', 'automated']
} : undefined
})
};
;