import type { IncomingMessage, ServerResponse } from "node:http"; import { appendSessionName, buildSessionListResponse, deleteSessionFile, pinSession, readSessionMessages, readSessionSummary, resolveSessionFile, } from "../services/sessions.ts"; import type { WebUiContext } from "../types/context.ts"; import { isSameResolvedPath } from "../utils/paths.ts"; import { json, readBody } from "../http/request.ts"; export function handleSessionsRoute( req: IncomingMessage, res: ServerResponse, ctx: WebUiContext, pathname: string, ): boolean { const { paths } = ctx.config; const { sendCmd } = ctx.rpc; if (req.method === "POST" && pathname === "/api/new-session") { void sendCmd({ type: "new_session" }) .then(async (r: any) => { if (!r.success) return json(res, { error: r.error }, 500); if (r.data?.cancelled) return json(res, r.data); const state = await sendCmd({ type: "get_state" }); const sessionFile = state.success ? state.data?.sessionFile : undefined; return json(res, { ...r.data, sessionFile }); }) .catch((err) => json(res, { error: err.message }, 500)); return true; } if (req.method === "GET" && pathname === "/api/sessions") { json(res, buildSessionListResponse(paths)); return true; } if (req.method === "POST" && pathname === "/api/sessions/history") { void readBody(req) .then(({ path: sp }) => { const messages = readSessionMessages(sp as string); const summary = readSessionSummary(paths, sp as string); json(res, { messages, session: summary }); }) .catch((err) => json(res, { error: err.message }, 500)); return true; } if (req.method === "POST" && pathname === "/api/sessions/delete") { void readBody(req) .then(({ path: sp }) => { deleteSessionFile(paths, sp as string); json(res, { ok: true }); }) .catch((err) => json(res, { error: err.message }, 500)); return true; } if (req.method === "POST" && pathname === "/api/sessions/pin") { void readBody(req) .then(({ path: sp, pinned }) => { const result = pinSession(paths, sp as string, Boolean(pinned)); json(res, { ok: true, ...result }); }) .catch((err) => json(res, { error: err.message }, 500)); return true; } if (req.method === "POST" && pathname === "/api/sessions/load") { void readBody(req) .then(async ({ path: sp }) => { const sw = await sendCmd({ type: "switch_session", sessionPath: sp, cwdOverride: paths.repoRoot }); if (!sw.success) throw new Error(sw.error); const mr = await sendCmd({ type: "get_messages" }); if (!mr.success) throw new Error(mr.error); const summary = readSessionSummary(paths, sp as string); json(res, { messages: mr.data.messages, session: summary }); }) .catch((err) => json(res, { error: err.message }, 500)); return true; } if (req.method === "POST" && pathname === "/api/sessions/activate") { void readBody(req) .then(async ({ path: sp }) => { const sw = await sendCmd({ type: "switch_session", sessionPath: sp, cwdOverride: paths.repoRoot }); if (!sw.success) throw new Error(sw.error); const state = await sendCmd({ type: "get_state" }); if (!state.success) throw new Error(state.error); json(res, { ok: true, state: state.data }); }) .catch((err) => json(res, { error: err.message }, 500)); return true; } if (req.method === "POST" && pathname === "/api/sessions/name") { void readBody(req) .then(async ({ path: sp, name }) => { if (typeof sp !== "string" || !sp.trim()) throw new Error("无效会话路径"); const savedName = appendSessionName(paths, sp, typeof name === "string" ? name : ""); const sessionPath = resolveSessionFile(paths, sp); const state = await sendCmd({ type: "get_state" }); if ( state.success && state.data?.sessionFile && isSameResolvedPath(String(state.data.sessionFile), sessionPath) ) { const rename = await sendCmd({ type: "set_session_name", name: savedName }); if (!rename.success) throw new Error(rename.error || "同步当前会话名称失败"); } json(res, { ok: true, name: savedName }); }) .catch((err) => json(res, { error: err.message }, 500)); return true; } if (req.method === "GET" && pathname === "/api/session-state") { void sendCmd({ type: "get_state" }) .then((r: any) => (r.success ? json(res, r.data) : json(res, { error: r.error }, 500))) .catch((err) => json(res, { error: err.message }, 500)); return true; } return false; }