agent-ecosystem/src/main/http/notifications.ts
matt 7fa2f96ed4 feat(http): implement HTTP server and route handlers for configuration, notifications, projects, sessions, and SSH management
- Introduced an HTTP server to facilitate communication with the application.
- Added route handlers for managing application configuration, including getting and updating settings.
- Implemented notification operations with routes for retrieving, marking, and deleting notifications.
- Created project and session management routes to list projects, sessions, and their details.
- Developed SSH connection management routes for connecting, disconnecting, and retrieving SSH state and configuration.
- Enhanced the application architecture to support real-time event streaming via Server-Sent Events (SSE).

This commit significantly expands the application's capabilities by integrating an HTTP server and various management routes, improving user interaction and functionality.
2026-02-12 15:04:56 +09:00

121 lines
3.8 KiB
TypeScript

/**
* HTTP route handlers for Notification Operations.
*
* Routes:
* - GET /api/notifications - Get notifications (paginated)
* - POST /api/notifications/:id/read - Mark as read
* - POST /api/notifications/read-all - Mark all as read
* - DELETE /api/notifications/:id - Delete notification
* - DELETE /api/notifications - Clear all notifications
* - GET /api/notifications/unread-count - Get unread count
*/
import { getErrorMessage } from '@shared/utils/errorHandling';
import { createLogger } from '@shared/utils/logger';
import { coercePageLimit, validateNotificationId } from '../ipc/guards';
import { NotificationManager } from '../services';
import type { FastifyInstance } from 'fastify';
const logger = createLogger('HTTP:notifications');
export function registerNotificationRoutes(app: FastifyInstance): void {
// Get notifications
app.get<{ Querystring: { limit?: string; offset?: string } }>(
'/api/notifications',
async (request) => {
try {
const limit = coercePageLimit(
request.query.limit ? Number(request.query.limit) : undefined,
20
);
const rawOffset = request.query.offset ? Number(request.query.offset) : 0;
const offset =
typeof rawOffset === 'number' && Number.isFinite(rawOffset) && rawOffset >= 0
? Math.floor(rawOffset)
: 0;
const manager = NotificationManager.getInstance();
const result = await manager.getNotifications({ limit, offset });
return result;
} catch (error) {
logger.error('Error in GET /api/notifications:', getErrorMessage(error));
return {
notifications: [],
total: 0,
totalCount: 0,
unreadCount: 0,
hasMore: false,
};
}
}
);
// Mark read
app.post<{ Params: { id: string } }>('/api/notifications/:id/read', async (request) => {
try {
const validated = validateNotificationId(request.params.id);
if (!validated.valid) {
logger.error(`POST notifications/:id/read rejected: ${validated.error ?? 'unknown'}`);
return false;
}
const manager = NotificationManager.getInstance();
return await manager.markRead(validated.value!);
} catch (error) {
logger.error(`Error in POST notifications/${request.params.id}/read:`, error);
return false;
}
});
// Mark all read
app.post('/api/notifications/read-all', async () => {
try {
const manager = NotificationManager.getInstance();
return await manager.markAllRead();
} catch (error) {
logger.error('Error in POST /api/notifications/read-all:', error);
return false;
}
});
// Delete notification
app.delete<{ Params: { id: string } }>('/api/notifications/:id', async (request) => {
try {
const validated = validateNotificationId(request.params.id);
if (!validated.valid) {
logger.error(`DELETE notifications/:id rejected: ${validated.error ?? 'unknown'}`);
return false;
}
const manager = NotificationManager.getInstance();
return manager.deleteNotification(validated.value!);
} catch (error) {
logger.error(`Error in DELETE notifications/${request.params.id}:`, error);
return false;
}
});
// Clear all
app.delete('/api/notifications', async () => {
try {
const manager = NotificationManager.getInstance();
return await manager.clearAll();
} catch (error) {
logger.error('Error in DELETE /api/notifications:', error);
return false;
}
});
// Unread count
app.get('/api/notifications/unread-count', async () => {
try {
const manager = NotificationManager.getInstance();
return await manager.getUnreadCount();
} catch (error) {
logger.error('Error in GET /api/notifications/unread-count:', error);
return 0;
}
});
}