initial
This commit is contained in:
138
apps/server/src/routes/sessions.ts
Normal file
138
apps/server/src/routes/sessions.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
import type { FastifyInstance } from 'fastify';
|
||||
import { z } from 'zod';
|
||||
import type { Sql } from '../db.js';
|
||||
import type { Config } from '../config.js';
|
||||
import type { Session } from '../types/api.js';
|
||||
import { getSetting } from './settings.js';
|
||||
|
||||
const CreateBody = z.object({
|
||||
name: z.string().min(1).max(200).optional(),
|
||||
model: z.string().min(1).max(200).optional(),
|
||||
system_prompt: z.string().max(8000).optional(),
|
||||
});
|
||||
|
||||
const PatchBody = z.object({
|
||||
name: z.string().min(1).max(200).optional(),
|
||||
model: z.string().min(1).max(200).optional(),
|
||||
system_prompt: z.string().max(8000).optional(),
|
||||
});
|
||||
|
||||
async function resolveDefaultModel(sql: Sql, config: Config): Promise<string> {
|
||||
const fromDb = await getSetting<string>(sql, 'default_model');
|
||||
if (typeof fromDb === 'string' && fromDb.length > 0) return fromDb;
|
||||
return config.DEFAULT_MODEL;
|
||||
}
|
||||
|
||||
export function registerSessionRoutes(
|
||||
app: FastifyInstance,
|
||||
sql: Sql,
|
||||
config: Config
|
||||
): void {
|
||||
app.get<{ Params: { id: string } }>(
|
||||
'/api/projects/:id/sessions',
|
||||
async (req, reply) => {
|
||||
const project = await sql`SELECT id FROM projects WHERE id = ${req.params.id}`;
|
||||
if (project.length === 0) {
|
||||
reply.code(404);
|
||||
return { error: 'project not found' };
|
||||
}
|
||||
const rows = await sql<Session[]>`
|
||||
SELECT id, project_id, name, model, system_prompt, created_at, updated_at
|
||||
FROM sessions
|
||||
WHERE project_id = ${req.params.id}
|
||||
ORDER BY updated_at DESC
|
||||
`;
|
||||
return rows;
|
||||
}
|
||||
);
|
||||
|
||||
app.post<{ Params: { id: string } }>(
|
||||
'/api/projects/:id/sessions',
|
||||
async (req, reply) => {
|
||||
const parsed = CreateBody.safeParse(req.body ?? {});
|
||||
if (!parsed.success) {
|
||||
reply.code(400);
|
||||
return { error: 'invalid body', details: parsed.error.flatten() };
|
||||
}
|
||||
const project = await sql`SELECT id FROM projects WHERE id = ${req.params.id}`;
|
||||
if (project.length === 0) {
|
||||
reply.code(404);
|
||||
return { error: 'project not found' };
|
||||
}
|
||||
|
||||
let model = parsed.data.model;
|
||||
if (!model) {
|
||||
const lastUsed = await sql<{ model: string }[]>`
|
||||
SELECT model FROM sessions
|
||||
WHERE project_id = ${req.params.id}
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1
|
||||
`;
|
||||
model = lastUsed[0]?.model ?? (await resolveDefaultModel(sql, config));
|
||||
}
|
||||
|
||||
const name = parsed.data.name ?? 'New session';
|
||||
const systemPrompt = parsed.data.system_prompt ?? '';
|
||||
|
||||
const [row] = await sql<Session[]>`
|
||||
INSERT INTO sessions (project_id, name, model, system_prompt)
|
||||
VALUES (${req.params.id}, ${name}, ${model}, ${systemPrompt})
|
||||
RETURNING id, project_id, name, model, system_prompt, created_at, updated_at
|
||||
`;
|
||||
reply.code(201);
|
||||
return row;
|
||||
}
|
||||
);
|
||||
|
||||
app.get<{ Params: { id: string } }>('/api/sessions/:id', async (req, reply) => {
|
||||
const rows = await sql<Session[]>`
|
||||
SELECT id, project_id, name, model, system_prompt, created_at, updated_at
|
||||
FROM sessions WHERE id = ${req.params.id}
|
||||
`;
|
||||
if (rows.length === 0) {
|
||||
reply.code(404);
|
||||
return { error: 'session not found' };
|
||||
}
|
||||
return rows[0];
|
||||
});
|
||||
|
||||
app.patch<{ Params: { id: string } }>(
|
||||
'/api/sessions/:id',
|
||||
async (req, reply) => {
|
||||
const parsed = PatchBody.safeParse(req.body);
|
||||
if (!parsed.success) {
|
||||
reply.code(400);
|
||||
return { error: 'invalid body', details: parsed.error.flatten() };
|
||||
}
|
||||
const { name, model, system_prompt } = parsed.data;
|
||||
const rows = await sql<Session[]>`
|
||||
UPDATE sessions
|
||||
SET
|
||||
name = COALESCE(${name ?? null}, name),
|
||||
model = COALESCE(${model ?? null}, model),
|
||||
system_prompt = COALESCE(${system_prompt ?? null}, system_prompt),
|
||||
updated_at = NOW()
|
||||
WHERE id = ${req.params.id}
|
||||
RETURNING id, project_id, name, model, system_prompt, created_at, updated_at
|
||||
`;
|
||||
if (rows.length === 0) {
|
||||
reply.code(404);
|
||||
return { error: 'session not found' };
|
||||
}
|
||||
return rows[0];
|
||||
}
|
||||
);
|
||||
|
||||
app.delete<{ Params: { id: string } }>(
|
||||
'/api/sessions/:id',
|
||||
async (req, reply) => {
|
||||
const result = await sql`DELETE FROM sessions WHERE id = ${req.params.id}`;
|
||||
if (result.count === 0) {
|
||||
reply.code(404);
|
||||
return { error: 'not found' };
|
||||
}
|
||||
reply.code(204);
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user