feat: setup unified classes for LLM providers and session processing, add tests for LLM unifier helper functions

This commit is contained in:
Haileyesus
2026-04-06 17:37:58 +03:00
parent 753c58fc1a
commit 6d00c17137
50 changed files with 4689 additions and 1721 deletions

View File

@@ -0,0 +1,97 @@
import express, { type NextFunction, type Request, type Response } from 'express';
import { asyncHandler } from '@/shared/http/async-handler.js';
import { AppError } from '@/shared/utils/app-error.js';
import { createApiErrorResponse, createApiSuccessResponse } from '@/shared/http/api-response.js';
import { logger } from '@/shared/utils/logger.js';
import { workspaceService } from '@/modules/workspaces/workspaces.service.js';
const router = express.Router();
const getTrimmedString = (value: unknown): string => {
if (typeof value !== 'string') {
return '';
}
return value.trim();
};
const parseWorkspacePathFromBody = (req: Request): string => {
const body = req.body as Record<string, unknown> | undefined;
const workspacePath = getTrimmedString(body?.workspacePath);
if (!workspacePath) {
throw new AppError('workspacePath is required.', {
code: 'WORKSPACE_PATH_REQUIRED',
statusCode: 400,
});
}
return workspacePath;
};
const parseWorkspaceCustomNameFromBody = (req: Request): string | null => {
const body = req.body as Record<string, unknown> | undefined;
const customName = getTrimmedString(body?.workspaceCustomName);
return customName || null;
};
router.get(
'/',
asyncHandler(async (_req: Request, res: Response) => {
const workspaces = workspaceService.listWorkspaces();
res.json(createApiSuccessResponse({ workspaces }));
}),
);
router.patch(
'/star',
asyncHandler(async (req: Request, res: Response) => {
const workspacePath = parseWorkspacePathFromBody(req);
const isStarred = workspaceService.toggleWorkspaceStar(workspacePath);
res.json(createApiSuccessResponse({ workspacePath, isStarred }));
}),
);
router.patch(
'/name',
asyncHandler(async (req: Request, res: Response) => {
const workspacePath = parseWorkspacePathFromBody(req);
const workspaceCustomName = parseWorkspaceCustomNameFromBody(req);
workspaceService.updateWorkspaceCustomName(workspacePath, workspaceCustomName);
res.json(createApiSuccessResponse({ workspacePath, workspaceCustomName }));
}),
);
router.delete(
'/',
asyncHandler(async (req: Request, res: Response) => {
const workspacePath = parseWorkspacePathFromBody(req);
const result = await workspaceService.deleteWorkspace(workspacePath);
res.json(createApiSuccessResponse(result));
}),
);
/**
* Normalizes route-level failures to a consistent JSON API shape.
*/
router.use((error: unknown, _req: Request, res: Response, _next: NextFunction) => {
if (res.headersSent) {
return;
}
if (error instanceof AppError) {
res
.status(error.statusCode)
.json(createApiErrorResponse(error.code, error.message, undefined, error.details));
return;
}
const message = error instanceof Error ? error.message : 'Unexpected workspaces route failure.';
logger.error(message, {
module: 'workspaces.routes',
});
res.status(500).json(createApiErrorResponse('INTERNAL_ERROR', message));
});
export default router;