batch3 T1: session_panes schema + Pane/UserStreamFrame types + sidebar project_id

Adds the session_panes table, Pane/PaneState/PaneCreate/PaneUpdate types,
UserStreamFrame discriminated union, and extends SidebarSession with
project_id (also added to the sidebar SELECT).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-15 14:46:57 +00:00
parent 842cf146ec
commit 08ee57d6a1
3 changed files with 78 additions and 1 deletions

View File

@@ -18,7 +18,7 @@ export function registerSidebarRoutes(app: FastifyInstance, sql: Sql): void {
projects.map(async (p) => {
const [recent_sessions, countRows] = await Promise.all([
sql<SidebarSession[]>`
SELECT id, name, model, updated_at
SELECT id, project_id, name, model, updated_at
FROM sessions
WHERE project_id = ${p.id}
ORDER BY updated_at DESC

View File

@@ -46,3 +46,14 @@ CREATE TABLE IF NOT EXISTS settings (
);
INSERT INTO settings (key, value) VALUES ('default_model', '"qwen3.6-35b-a3b-mxfp4"') ON CONFLICT (key) DO NOTHING;
CREATE TABLE IF NOT EXISTS session_panes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
position INTEGER NOT NULL,
kind TEXT NOT NULL CHECK (kind IN ('chat', 'file_browser')),
state JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT clock_timestamp(),
UNIQUE (session_id, position)
);
CREATE INDEX IF NOT EXISTS session_panes_session_idx ON session_panes (session_id);

View File

@@ -61,6 +61,7 @@ export interface ModelInfo {
export interface SidebarSession {
id: string;
project_id: string;
name: string;
model: string;
updated_at: string;
@@ -76,3 +77,68 @@ export interface SidebarProject {
export interface SidebarResponse {
projects: SidebarProject[];
}
export type PaneKind = 'chat' | 'file_browser';
export interface FileBrowserPaneState {
open_file?: string | null;
filter?: string;
expanded_dirs?: string[];
}
// chat panes have no state for now
export type ChatPaneState = Record<string, never>;
export type PaneState = ChatPaneState | FileBrowserPaneState;
export interface Pane {
id: string;
session_id: string;
position: number;
kind: PaneKind;
state: PaneState;
created_at: string;
}
export interface PaneCreateRequest {
kind: PaneKind;
position?: number; // optional; if omitted, append at end
}
export interface PaneUpdateRequest {
state?: PaneState;
position?: number;
}
// User-stream frames (broadcast on /ws/user channel)
export interface ProjectCreatedFrame {
type: 'project_created';
project: Project;
}
export interface ProjectDeletedFrame {
type: 'project_deleted';
project_id: string;
}
export interface SessionCreatedFrame {
type: 'session_created';
session: Session;
project_id: string;
}
export interface SessionDeletedFrame {
type: 'session_deleted';
session_id: string;
project_id: string;
}
export interface SessionUpdatedFrame {
type: 'session_updated';
session_id: string;
project_id: string;
name: string;
updated_at: string;
}
export type UserStreamFrame =
| ProjectCreatedFrame
| ProjectDeletedFrame
| SessionCreatedFrame
| SessionDeletedFrame
| SessionUpdatedFrame;