62 lines
2.4 KiB
TypeScript
62 lines
2.4 KiB
TypeScript
import { sqliteTable, text, index, primaryKey } from "drizzle-orm/sqlite-core";
|
|
import { sql } from "drizzle-orm";
|
|
import { user } from "./better-auth-schema";
|
|
import { projects } from "./app.schema";
|
|
|
|
// One row per SAM chat session. The conversation history itself lives in the
|
|
// SamChatAgent Durable Object's SQLite (keyed by this id); this table is the
|
|
// listable registry the session side-panel reads from, and the project/user
|
|
// scoping the Worker authorizes a connection against before it reaches the DO.
|
|
// Normalized on purpose: org and user email are derived from the project and
|
|
// user rows at read time, never snapshotted here.
|
|
export const samSessions = sqliteTable(
|
|
"sam_sessions",
|
|
{
|
|
id: text("id").primaryKey(),
|
|
projectId: text("project_id")
|
|
.notNull()
|
|
.references(() => projects.id, { onDelete: "cascade" }),
|
|
userId: text("user_id")
|
|
.notNull()
|
|
.references(() => user.id, { onDelete: "cascade" }),
|
|
title: text("title").notNull().default("New chat"),
|
|
createdAt: text("created_at")
|
|
.notNull()
|
|
.default(sql`(current_timestamp)`),
|
|
updatedAt: text("updated_at")
|
|
.notNull()
|
|
.default(sql`(current_timestamp)`),
|
|
// Soft-delete marker: null = active. Archived sessions disappear from the
|
|
// list but keep their registry row and DO transcript for a future unarchive.
|
|
archivedAt: text("archived_at"),
|
|
},
|
|
(table) => [
|
|
// The side-panel lists a project's sessions newest-first.
|
|
index("sam_sessions_project_updated_idx").on(
|
|
table.projectId,
|
|
table.updatedAt,
|
|
),
|
|
],
|
|
);
|
|
|
|
// SAM's persistent project memory: one row per (project, context-block label).
|
|
// The SamChatAgent DO surfaces these rows to the model as writable context
|
|
// blocks ("memory", "research_log"), so every chat session in a project reads
|
|
// and writes the same memory. Lives in the app DB rather than DO storage so it
|
|
// is shared across the per-session DOs and stays queryable by the Worker (for
|
|
// a future settings/inspection UI).
|
|
export const samProjectMemory = sqliteTable(
|
|
"sam_project_memory",
|
|
{
|
|
projectId: text("project_id")
|
|
.notNull()
|
|
.references(() => projects.id, { onDelete: "cascade" }),
|
|
label: text("label").notNull(),
|
|
content: text("content").notNull(),
|
|
updatedAt: text("updated_at")
|
|
.notNull()
|
|
.default(sql`(current_timestamp)`),
|
|
},
|
|
(table) => [primaryKey({ columns: [table.projectId, table.label] })],
|
|
);
|