server: reconcile ai_sessions persistence to Chunk 9 AISession shape
Reshape the ai_sessions table (migration 003) and mapping/routes to the full AISession contract: title, kind, notes, created_at, last_message_at; drop legacy role/model/settings. toAISession now maps the new columns and routes create/patch/messages handlers use the new shape.
This commit is contained in:
+35
-17
@@ -92,11 +92,14 @@ const beatCreate = z.object({
|
||||
});
|
||||
const aiSessionCreate = z.object({
|
||||
id: z.string().optional(),
|
||||
role: z.string().min(1),
|
||||
model: z.string().min(1),
|
||||
settings: z.record(z.unknown()).default({}),
|
||||
messages: z.array(z.any()).optional(),
|
||||
suggestions: z.array(z.any()).optional(),
|
||||
title: z.string().default(""),
|
||||
kind: z.enum(["session", "agent"]).default("session"),
|
||||
messages: z.array(z.any()).default([]),
|
||||
suggestions: z.array(z.any()).default([]),
|
||||
notes: z.array(z.any()).default([]),
|
||||
createdAt: z.string().optional(),
|
||||
updatedAt: z.string().optional(),
|
||||
lastMessageAt: z.string().nullable().optional(),
|
||||
});
|
||||
const aiMessageAppend = z.object({ role: z.string(), content: z.string() });
|
||||
const aiSuggestionAdd = z.object({ kind: z.string(), text: z.string() });
|
||||
@@ -565,14 +568,15 @@ export function registerRoutes(app: FastifyInstance): void {
|
||||
const sid = body.id ?? ulid();
|
||||
const t = now();
|
||||
db.prepare(
|
||||
`INSERT INTO ai_sessions (id, project_id, role, model, settings, messages, suggestions, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`INSERT INTO ai_sessions (id, project_id, title, kind, messages, suggestions, notes, created_at, updated_at, last_message_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
project_id = excluded.project_id, role = excluded.role, model = excluded.model,
|
||||
settings = excluded.settings, messages = excluded.messages, suggestions = excluded.suggestions,
|
||||
updated_at = excluded.updated_at`,
|
||||
).run(sid, id, body.role, body.model, JSON.stringify(body.settings),
|
||||
JSON.stringify(body.messages ?? []), JSON.stringify(body.suggestions ?? []), t);
|
||||
title = excluded.title, kind = excluded.kind,
|
||||
messages = excluded.messages, suggestions = excluded.suggestions, notes = excluded.notes,
|
||||
updated_at = excluded.updated_at, last_message_at = excluded.last_message_at`,
|
||||
).run(sid, id, body.title, body.kind, JSON.stringify(body.messages),
|
||||
JSON.stringify(body.suggestions), JSON.stringify(body.notes),
|
||||
body.createdAt ?? t, t, body.lastMessageAt ?? null);
|
||||
const row = db.prepare("SELECT * FROM ai_sessions WHERE id = ?").get(sid) as AISessionRow;
|
||||
return { session: toAISession(row) };
|
||||
});
|
||||
@@ -590,11 +594,25 @@ export function registerRoutes(app: FastifyInstance): void {
|
||||
const row = db.prepare("SELECT * FROM ai_sessions WHERE id = ?").get(id) as AISessionRow | undefined;
|
||||
if (!row) throw app.httpErrors.create(404, { error: "not_found" });
|
||||
requireProjectAccess(app, req, row.project_id, true);
|
||||
const body = z.object({ settings: z.record(z.unknown()).optional(), model: z.string().optional() }).parse(req.body);
|
||||
const settings = body.settings ? JSON.stringify(body.settings) : row.settings;
|
||||
const model = body.model ?? row.model;
|
||||
const body = z.object({
|
||||
title: z.string().optional(),
|
||||
kind: z.enum(["session", "agent"]).optional(),
|
||||
messages: z.array(z.any()).optional(),
|
||||
suggestions: z.array(z.any()).optional(),
|
||||
notes: z.array(z.any()).optional(),
|
||||
lastMessageAt: z.string().nullable().optional(),
|
||||
}).parse(req.body);
|
||||
const t = now();
|
||||
db.prepare("UPDATE ai_sessions SET settings = ?, model = ?, updated_at = ? WHERE id = ?").run(settings, model, t, id);
|
||||
db.prepare(
|
||||
`UPDATE ai_sessions SET title = ?, kind = ?, messages = ?, suggestions = ?, notes = ?, last_message_at = ?, updated_at = ? WHERE id = ?`
|
||||
).run(
|
||||
body.title ?? row.title, body.kind ?? row.kind,
|
||||
JSON.stringify(body.messages ?? JSON.parse(row.messages)),
|
||||
JSON.stringify(body.suggestions ?? JSON.parse(row.suggestions)),
|
||||
JSON.stringify(body.notes ?? JSON.parse(row.notes)),
|
||||
body.lastMessageAt ?? row.last_message_at,
|
||||
t, id,
|
||||
);
|
||||
const updated = db.prepare("SELECT * FROM ai_sessions WHERE id = ?").get(id) as AISessionRow;
|
||||
return { session: toAISession(updated) };
|
||||
});
|
||||
@@ -617,7 +635,7 @@ export function registerRoutes(app: FastifyInstance): void {
|
||||
const messages = JSON.parse(row.messages) as any[];
|
||||
messages.push({ role, content, at: now() });
|
||||
const t = now();
|
||||
db.prepare("UPDATE ai_sessions SET messages = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(messages), t, id);
|
||||
db.prepare("UPDATE ai_sessions SET messages = ?, last_message_at = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(messages), t, t, id);
|
||||
const updated = db.prepare("SELECT * FROM ai_sessions WHERE id = ?").get(id) as AISessionRow;
|
||||
return { session: toAISession(updated) };
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user