gadget/gadget-code/src/controllers/api/v1/chat-session.ts
2026-05-01 14:31:00 -04:00

322 lines
7.9 KiB
TypeScript

// src/controllers/api/v1/chat-session.ts
// Copyright (C) 2026 Robert Colbert <rob.colbert@openplatform.us>
// All Rights Reserved
import { Request, Response } from "express";
import { DtpController } from "../../../lib/controller.js";
import ChatSessionService from "../../../services/chat-session.js";
import { ChatSessionMode } from "@gadget/api";
class ChatSessionController extends DtpController {
get name(): string {
return "ChatSessionController";
}
get slug(): string {
return "ctrl:api:v1:chat-session";
}
get route(): string {
return "/chat-sessions";
}
async start(): Promise<void> {
this.router.get("/", this.requireUser(), this.listSessions.bind(this));
this.router.post("/", this.requireUser(), this.createSession.bind(this));
this.router.get("/:id", this.requireUser(), this.getSession.bind(this));
this.router.put("/:id", this.requireUser(), this.updateSession.bind(this));
this.router.delete(
"/:id",
this.requireUser(),
this.deleteSession.bind(this),
);
this.router.get(
"/:id/turns",
this.requireUser(),
this.getSessionTurns.bind(this),
);
}
/**
* GET /api/v1/chat-sessions?projectId=:projectId
* List chat sessions for a project or user.
*/
private async listSessions(req: Request, res: Response): Promise<void> {
try {
const user = req.user;
if (!user) {
res.status(401).json({ success: false, message: "Unauthorized" });
return;
}
const projectId = req.query.projectId as string | undefined;
let sessions;
if (projectId) {
sessions = await ChatSessionService.getByProject(projectId);
} else {
sessions = await ChatSessionService.getByUser(user._id);
}
res.json({
success: true,
data: sessions,
});
} catch (error) {
const err = error as Error;
this.log.error("failed to list chat sessions", { error: err.message });
res.status(500).json({
success: false,
message: err.message,
});
}
}
/**
* POST /api/v1/chat-sessions
* Create a new chat session.
*/
private async createSession(req: Request, res: Response): Promise<void> {
try {
const user = req.user;
if (!user) {
res.status(401).json({ success: false, message: "Unauthorized" });
return;
}
const { projectId, providerId, selectedModel, mode, name } = req.body;
if (!projectId) {
res.status(400).json({
success: false,
message: "projectId is required",
});
return;
}
if (!providerId) {
res.status(400).json({
success: false,
message: "providerId is required",
});
return;
}
if (!selectedModel) {
res.status(400).json({
success: false,
message: "selectedModel is required",
});
return;
}
const sessionMode = mode
? ChatSessionMode[mode as keyof typeof ChatSessionMode]
: ChatSessionMode.Build;
const session = await ChatSessionService.create(
user._id,
projectId,
providerId,
selectedModel,
sessionMode,
name,
);
res.status(201).json({
success: true,
data: session,
});
} catch (error) {
const err = error as Error;
this.log.error("failed to create chat session", { error: err.message });
res.status(500).json({
success: false,
message: err.message,
});
}
}
/**
* GET /api/v1/chat-sessions/:id
* Get a specific chat session.
*/
private async getSession(req: Request, res: Response): Promise<void> {
try {
const id = Array.isArray(req.params.id)
? req.params.id[0]
: req.params.id;
if (!id) {
res.status(400).json({
success: false,
message: "Session ID is required",
});
return;
}
const session = await ChatSessionService.getById(id);
res.json({
success: true,
data: session,
});
} catch (error) {
const err = error as Error;
this.log.error("failed to get chat session", { error: err.message });
if (err.message.includes("not found")) {
res.status(404).json({
success: false,
message: err.message,
});
} else {
res.status(500).json({
success: false,
message: err.message,
});
}
}
}
/**
* PUT /api/v1/chat-sessions/:id
* Update a chat session.
*/
private async updateSession(req: Request, res: Response): Promise<void> {
try {
const id = Array.isArray(req.params.id)
? req.params.id[0]
: req.params.id;
if (!id) {
res.status(400).json({
success: false,
message: "Session ID is required",
});
return;
}
const updates = req.body;
// Validate allowed updates
const allowedUpdates: Partial<{
name: string;
provider: string;
selectedModel: string;
mode: ChatSessionMode;
}> = {};
if (updates.name !== undefined) {
allowedUpdates.name = updates.name;
}
if (updates.provider !== undefined) {
allowedUpdates.provider = updates.provider;
}
if (updates.selectedModel !== undefined) {
allowedUpdates.selectedModel = updates.selectedModel;
}
if (updates.mode !== undefined) {
allowedUpdates.mode =
ChatSessionMode[updates.mode as keyof typeof ChatSessionMode];
}
const session = await ChatSessionService.update(id, allowedUpdates);
res.json({
success: true,
data: session,
});
} catch (error) {
const err = error as Error;
this.log.error("failed to update chat session", { error: err.message });
if (err.message.includes("not found")) {
res.status(404).json({
success: false,
message: err.message,
});
} else {
res.status(500).json({
success: false,
message: err.message,
});
}
}
}
/**
* DELETE /api/v1/chat-sessions/:id
* Delete a chat session.
*/
private async deleteSession(req: Request, res: Response): Promise<void> {
try {
const id = Array.isArray(req.params.id)
? req.params.id[0]
: req.params.id;
if (!id) {
res.status(400).json({
success: false,
message: "Session ID is required",
});
return;
}
await ChatSessionService.delete(id);
res.json({
success: true,
message: "Chat session deleted",
});
} catch (error) {
const err = error as Error;
this.log.error("failed to delete chat session", { error: err.message });
if (err.message.includes("not found")) {
res.status(404).json({
success: false,
message: err.message,
});
} else {
res.status(500).json({
success: false,
message: err.message,
});
}
}
}
/**
* GET /api/v1/chat-sessions/:id/turns
* Get all turns for a chat session.
*/
private async getSessionTurns(req: Request, res: Response): Promise<void> {
try {
const id = Array.isArray(req.params.id)
? req.params.id[0]
: req.params.id;
if (!id) {
res.status(400).json({
success: false,
message: "Session ID is required",
});
return;
}
const turns = await ChatSessionService.getTurns(id);
res.json({
success: true,
data: turns,
});
} catch (error) {
const err = error as Error;
this.log.error("failed to get chat session turns", {
error: err.message,
});
res.status(500).json({
success: false,
message: err.message,
});
}
}
}
export default ChatSessionController;