diff --git a/apps/broker/src/broker.ts b/apps/broker/src/broker.ts index cf50251..a08b186 100644 --- a/apps/broker/src/broker.ts +++ b/apps/broker/src/broker.ts @@ -352,6 +352,53 @@ export async function heartbeat(presenceId: string): Promise { .where(eq(presence.id, presenceId)); } +// --- Peer discovery --- + +/** Return all active (connected) presences in a mesh, joined with member info. */ +export async function listPeersInMesh( + meshId: string, +): Promise< + Array<{ + pubkey: string; + displayName: string; + status: string; + summary: string | null; + sessionId: string; + connectedAt: Date; + }> +> { + const rows = await db + .select({ + pubkey: memberTable.peerPubkey, + displayName: memberTable.displayName, + status: presence.status, + summary: presence.summary, + sessionId: presence.sessionId, + connectedAt: presence.connectedAt, + }) + .from(presence) + .innerJoin(memberTable, eq(presence.memberId, memberTable.id)) + .where( + and( + eq(memberTable.meshId, meshId), + isNull(presence.disconnectedAt), + ), + ) + .orderBy(asc(presence.connectedAt)); + return rows; +} + +/** Update the summary text on a presence row. */ +export async function setSummary( + presenceId: string, + summary: string, +): Promise { + await db + .update(presence) + .set({ summary }) + .where(eq(presence.id, presenceId)); +} + // --- Message queueing + delivery --- export interface QueueParams { diff --git a/apps/broker/src/index.ts b/apps/broker/src/index.ts index f1729d6..f21f11e 100644 --- a/apps/broker/src/index.ts +++ b/apps/broker/src/index.ts @@ -24,9 +24,11 @@ import { handleHookSetStatus, heartbeat, joinMesh, + listPeersInMesh, queueMessage, refreshQueueDepth, refreshStatusFromJsonl, + setSummary, startSweepers, stopSweepers, writeStatus, @@ -494,6 +496,36 @@ function handleConnection(ws: WebSocket): void { status: msg.status, }); break; + case "list_peers": { + const peers = await listPeersInMesh(conn.meshId); + const resp: WSServerMessage = { + type: "peers_list", + peers: peers.map((p) => ({ + pubkey: p.pubkey, + displayName: p.displayName, + status: p.status as "idle" | "working" | "dnd", + summary: p.summary, + sessionId: p.sessionId, + connectedAt: p.connectedAt.toISOString(), + })), + }; + conn.ws.send(JSON.stringify(resp)); + log.info("ws list_peers", { + presence_id: presenceId, + mesh_id: conn.meshId, + count: peers.length, + }); + break; + } + case "set_summary": { + const summary = (msg as { summary?: string }).summary ?? ""; + await setSummary(presenceId, summary); + log.info("ws set_summary", { + presence_id: presenceId, + summary: summary.slice(0, 80), + }); + break; + } } } catch (e) { metrics.messagesRejectedTotal.inc({ reason: "parse_or_handler" }); diff --git a/apps/broker/src/types.ts b/apps/broker/src/types.ts index b5f32de..3bb557c 100644 --- a/apps/broker/src/types.ts +++ b/apps/broker/src/types.ts @@ -90,6 +90,17 @@ export interface WSSetStatusMessage { status: PeerStatus; } +/** Client → broker: request list of connected peers in the same mesh. */ +export interface WSListPeersMessage { + type: "list_peers"; +} + +/** Client → broker: update the session's human-readable summary. */ +export interface WSSetSummaryMessage { + type: "set_summary"; + summary: string; +} + /** Broker → client: acknowledgement for a send. */ export interface WSAckMessage { type: "ack"; @@ -105,6 +116,19 @@ export interface WSHelloAckMessage { memberDisplayName: string; } +/** Broker → client: list of connected peers in the same mesh. */ +export interface WSPeersListMessage { + type: "peers_list"; + peers: Array<{ + pubkey: string; + displayName: string; + status: PeerStatus; + summary: string | null; + sessionId: string; + connectedAt: string; + }>; +} + /** Broker → client: structured error. */ export interface WSErrorMessage { type: "error"; @@ -116,10 +140,13 @@ export interface WSErrorMessage { export type WSClientMessage = | WSHelloMessage | WSSendMessage - | WSSetStatusMessage; + | WSSetStatusMessage + | WSListPeersMessage + | WSSetSummaryMessage; export type WSServerMessage = | WSHelloAckMessage | WSPushMessage | WSAckMessage + | WSPeersListMessage | WSErrorMessage; diff --git a/apps/cli/src/mcp/server.ts b/apps/cli/src/mcp/server.ts index f16d5cb..eb76525 100644 --- a/apps/cli/src/mcp/server.ts +++ b/apps/cli/src/mcp/server.ts @@ -3,10 +3,6 @@ * * Starts BrokerClient connections for every mesh in config on boot, * then routes the 5 MCP tools through them. - * - * list_peers is stubbed at the CLI level — the broker's WS protocol - * does not yet carry a list-peers request type (Step 16). Until then, - * it returns a note. */ import { Server } from "@modelcontextprotocol/sdk/server/index.js"; @@ -163,13 +159,21 @@ If you have multiple joined meshes, prefix the \`to\` argument of send_message w : "list_peers: no joined meshes", true, ); - const lines = clients.map( - (c) => - `- ${c!.meshSlug} (${c!.status}, mesh ${c!.meshId.slice(0, 8)}…)`, - ); - return text( - `Connected meshes:\n${lines.join("\n")}\n\n(list_peers WS protocol lands in Step 16; only mesh status is shown for now.)`, - ); + const sections: string[] = []; + for (const c of clients) { + const peers = await c!.listPeers(); + const header = `## ${c!.meshSlug} (${c!.status}, mesh ${c!.meshId.slice(0, 8)}…)`; + if (peers.length === 0) { + sections.push(`${header}\nNo peers connected.`); + } else { + const peerLines = peers.map((p) => { + const summary = p.summary ? ` — "${p.summary}"` : ""; + return `- **${p.displayName}** [${p.status}] (${p.pubkey.slice(0, 12)}…)${summary}`; + }); + sections.push(`${header}\n${peerLines.join("\n")}`); + } + } + return text(sections.join("\n\n")); } case "check_messages": { @@ -187,8 +191,9 @@ If you have multiple joined meshes, prefix the \`to\` argument of send_message w case "set_summary": { const { summary } = (args ?? {}) as SetSummaryArgs; if (!summary) return text("set_summary: `summary` required", true); + for (const c of allClients()) await c.setSummary(summary); return text( - `set_summary: summary recorded locally ("${summary}"). (Broker WS protocol for summaries lands in Step 16.)`, + `Summary set: "${summary}" (visible to ${allClients().length} mesh(es)).`, ); } diff --git a/apps/cli/src/ws/client.ts b/apps/cli/src/ws/client.ts index d1c5a94..877d843 100644 --- a/apps/cli/src/ws/client.ts +++ b/apps/cli/src/ws/client.ts @@ -25,6 +25,15 @@ import { signHello } from "../crypto/hello-sig"; export type Priority = "now" | "next" | "low"; export type ConnStatus = "connecting" | "open" | "closed" | "reconnecting"; +export interface PeerInfo { + pubkey: string; + displayName: string; + status: string; + summary: string | null; + sessionId: string; + connectedAt: string; +} + export interface InboundPush { messageId: string; meshId: string; @@ -64,6 +73,7 @@ export class BrokerClient { private outbound: Array<() => void> = []; // closures that send once ws is open private pushHandlers = new Set(); private pushBuffer: InboundPush[] = []; + private listPeersResolvers: Array<(peers: PeerInfo[]) => void> = []; private closed = false; private reconnectAttempt = 0; private helloTimer: NodeJS.Timeout | null = null; @@ -266,6 +276,29 @@ export class BrokerClient { this.ws.send(JSON.stringify({ type: "set_status", status })); } + /** Request the list of connected peers from the broker. */ + async listPeers(): Promise { + if (!this.ws || this.ws.readyState !== this.ws.OPEN) return []; + return new Promise((resolve) => { + this.listPeersResolvers.push(resolve); + this.ws!.send(JSON.stringify({ type: "list_peers" })); + // Timeout after 5s — return empty list rather than hang. + setTimeout(() => { + const idx = this.listPeersResolvers.indexOf(resolve); + if (idx !== -1) { + this.listPeersResolvers.splice(idx, 1); + resolve([]); + } + }, 5_000); + }); + } + + /** Update this session's summary visible to other peers. */ + async setSummary(summary: string): Promise { + if (!this.ws || this.ws.readyState !== this.ws.OPEN) return; + this.ws.send(JSON.stringify({ type: "set_summary", summary })); + } + close(): void { this.closed = true; if (this.helloTimer) clearTimeout(this.helloTimer); @@ -294,6 +327,12 @@ export class BrokerClient { } return; } + if (msg.type === "peers_list") { + const peers = (msg.peers as PeerInfo[]) ?? []; + const resolver = this.listPeersResolvers.shift(); + if (resolver) resolver(peers); + return; + } if (msg.type === "push") { const nonce = String(msg.nonce ?? ""); const ciphertext = String(msg.ciphertext ?? ""); diff --git a/apps/web/next.config.ts b/apps/web/next.config.ts index a1c12e4..63e05c2 100644 --- a/apps/web/next.config.ts +++ b/apps/web/next.config.ts @@ -1,8 +1,5 @@ import type { NextConfig } from "next"; -// eslint-disable-next-line @typescript-eslint/no-require-imports -const { withPayload } = require("@payloadcms/next/withPayload"); - import env from "./env.config"; const INTERNAL_PACKAGES = [ @@ -124,4 +121,4 @@ const withBundleAnalyzer = require("@next/bundle-analyzer")({ enabled: env.ANALYZE, }); -export default withPayload(withBundleAnalyzer(config)); +export default withBundleAnalyzer(config); diff --git a/apps/web/src/app/(payload)/layout.tsx b/apps/web/src/app/(payload)/layout.tsx deleted file mode 100644 index bdcfe53..0000000 --- a/apps/web/src/app/(payload)/layout.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import "@payloadcms/next/css"; -import type { ReactNode } from "react"; - -export const metadata = { - title: "CMS — claudemesh", -}; - -export default function PayloadLayout({ children }: { children: ReactNode }) { - return ( - - {children} - - ); -} diff --git a/apps/web/src/app/(payload)/payload/[[...segments]]/page.tsx b/apps/web/src/app/(payload)/payload/[[...segments]]/page.tsx deleted file mode 100644 index fb963c6..0000000 --- a/apps/web/src/app/(payload)/payload/[[...segments]]/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { redirect } from "next/navigation"; - -// Payload admin disabled in production standalone output. -// Use local dev server for CMS admin. -export default function PayloadAdminRedirect() { - redirect("/"); -} diff --git a/apps/web/src/app/(payload)/payload/importMap.js b/apps/web/src/app/(payload)/payload/importMap.js deleted file mode 100644 index 73849ab..0000000 --- a/apps/web/src/app/(payload)/payload/importMap.js +++ /dev/null @@ -1 +0,0 @@ -export const importMap = {}; diff --git a/apps/web/src/app/[locale]/(marketing)/blog/[slug]/page.tsx b/apps/web/src/app/[locale]/(marketing)/blog/[slug]/page.tsx deleted file mode 100644 index b62c8b0..0000000 --- a/apps/web/src/app/[locale]/(marketing)/blog/[slug]/page.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { notFound } from "next/navigation"; - -export const dynamic = "force-dynamic"; - -type Props = { params: Promise<{ slug: string }> }; - -async function getPost(slug: string) { - try { - const { getPayload } = await import("payload"); - const config = (await import("@payload-config")).default; - const payload = await getPayload({ config }); - const { docs } = await payload.find({ - collection: "posts", - where: { slug: { equals: slug }, status: { equals: "published" } }, - limit: 1, - depth: 2, - }); - return docs[0] ?? null; - } catch { - return null; - } -} - -export async function generateMetadata({ params }: Props) { - const { slug } = await params; - const post = await getPost(slug); - if (!post) return { title: "Not found — claudemesh" }; - return { - title: `${(post as any).title} — claudemesh`, - description: (post as any).excerpt || undefined, - }; -} - -export default async function BlogPost({ params }: Props) { - const { slug } = await params; - const post = await getPost(slug) as any; - if (!post) notFound(); - - const author = typeof post.author === "object" ? post.author : null; - - return ( -
-
- -

- {post.title} -

- {author && ( -

- by {author.name}{author.role ? ` · ${author.role}` : ""} -

- )} -
- -
- {post.content && typeof post.content === "string" ? ( -
- ) : ( -

Content not available.

- )} -
-
- ); -} diff --git a/apps/web/src/app/[locale]/(marketing)/blog/page.tsx b/apps/web/src/app/[locale]/(marketing)/blog/page.tsx index 4b2e514..7a70824 100644 --- a/apps/web/src/app/[locale]/(marketing)/blog/page.tsx +++ b/apps/web/src/app/[locale]/(marketing)/blog/page.tsx @@ -1,33 +1,21 @@ import Link from "next/link"; -export const dynamic = "force-dynamic"; - export const metadata = { title: "Blog — claudemesh", description: "Engineering notes on peer messaging, protocol design, and multi-agent security.", }; -async function getPosts() { - try { - const { getPayload } = await import("payload"); - const config = (await import("@payload-config")).default; - const payload = await getPayload({ config }); - const { docs } = await payload.find({ - collection: "posts", - where: { status: { equals: "published" } }, - sort: "-publishedAt", - limit: 20, - depth: 1, - }); - return docs; - } catch { - return []; - } -} - -export default async function BlogIndex() { - const posts = await getPosts(); +const POSTS = [ + { + slug: "peer-messaging-claude-code", + title: "Peer messaging for Claude Code: protocol, security, UX", + excerpt: + "How claudemesh connects Claude Code sessions over an encrypted mesh, using MCP dev-channels for real-time message injection.", + date: "2026-04-06", + }, +]; +export default function BlogIndex() { return (

- {posts.length === 0 && ( -

- No posts yet. First one ships soon. -

- )} - {posts.map((post: any) => ( -
+ {POSTS.map((post) => ( +

- {post.excerpt && ( -

- {post.excerpt} -

- )} +

+ {post.excerpt} +

))}
diff --git a/apps/web/src/app/[locale]/(marketing)/changelog/page.tsx b/apps/web/src/app/[locale]/(marketing)/changelog/page.tsx index 2610dae..02dc874 100644 --- a/apps/web/src/app/[locale]/(marketing)/changelog/page.tsx +++ b/apps/web/src/app/[locale]/(marketing)/changelog/page.tsx @@ -1,43 +1,18 @@ -export const dynamic = "force-dynamic"; - export const metadata = { title: "Changelog — claudemesh", description: "Release history for claudemesh-cli.", }; -const TYPE_LABELS: Record = { - feat: "Feature", - fix: "Fix", - docs: "Docs", - breaking: "Breaking", -}; +const ENTRIES = [ + { version: "0.1.4", date: "2026-04-06", type: "feat", summary: "Stateful welcome screen, PROTOCOL.md, THREAT_MODEL.md, Windows CI matrix" }, + { version: "0.1.3", date: "2026-04-05", type: "feat", summary: "claudemesh --version, status, doctor commands" }, + { version: "0.1.2", date: "2026-04-05", type: "feat", summary: "claudemesh launch command, transparency banner, decrypt fix, Windows support" }, +]; -const TYPE_COLORS: Record = { - feat: "bg-[var(--cm-clay)]", - fix: "bg-[var(--cm-cactus)]", - docs: "bg-[var(--cm-oat)]", - breaking: "bg-red-500", -}; - -async function getChangelog() { - try { - const { getPayload } = await import("payload"); - const config = (await import("@payload-config")).default; - const payload = await getPayload({ config }); - const { docs } = await payload.find({ - collection: "changelog", - sort: "-date", - limit: 50, - }); - return docs; - } catch { - return []; - } -} - -export default async function ChangelogPage() { - const entries = await getChangelog(); +const TYPE_LABELS: Record = { feat: "Feature", fix: "Fix", docs: "Docs" }; +const TYPE_COLORS: Record = { feat: "bg-[var(--cm-clay)]", fix: "bg-[var(--cm-cactus)]", docs: "bg-[var(--cm-oat)]" }; +export default function ChangelogPage() { return (

Every shipped version of claudemesh-cli.

-
- {entries.length === 0 && ( -

- No entries yet. -

- )} - {entries.map((entry: any) => ( -
+ {ENTRIES.map((entry) => ( +
{TYPE_LABELS[entry.type] || entry.type} - + v{entry.version} -
-

+

{entry.summary}

- {(entry.npmUrl || entry.githubUrl) && ( -
- {entry.npmUrl && ( - - npm → - - )} - {entry.githubUrl && ( - - github → - - )} -
- )}
))}
diff --git a/packages/db/migrations/0003_add-presence-summary.sql b/packages/db/migrations/0003_add-presence-summary.sql new file mode 100644 index 0000000..5301b16 --- /dev/null +++ b/packages/db/migrations/0003_add-presence-summary.sql @@ -0,0 +1 @@ +ALTER TABLE "mesh"."presence" ADD COLUMN "summary" text; \ No newline at end of file diff --git a/packages/db/migrations/meta/0003_snapshot.json b/packages/db/migrations/meta/0003_snapshot.json new file mode 100644 index 0000000..197b415 --- /dev/null +++ b/packages/db/migrations/meta/0003_snapshot.json @@ -0,0 +1,2839 @@ +{ + "id": "850dbb6a-6bec-415b-a364-66c637bb5207", + "prevId": "e288fab9-4732-43d6-938e-3cda71417932", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "invitation_organizationId_idx": { + "name": "invitation_organizationId_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitation_email_idx": { + "name": "invitation_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "invitation_organization_id_organization_id_fk": { + "name": "invitation_organization_id_organization_id_fk", + "tableFrom": "invitation", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitation_inviter_id_user_id_fk": { + "name": "invitation_inviter_id_user_id_fk", + "tableFrom": "invitation", + "tableTo": "user", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.member": { + "name": "member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "member_organizationId_idx": { + "name": "member_organizationId_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "member_userId_idx": { + "name": "member_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "member_organization_id_organization_id_fk": { + "name": "member_organization_id_organization_id_fk", + "tableFrom": "member", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_user_id_user_id_fk": { + "name": "member_user_id_user_id_fk", + "tableFrom": "member", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization": { + "name": "organization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "organization_slug_unique": { + "name": "organization_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.passkey": { + "name": "passkey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "counter": { + "name": "counter", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "backed_up": { + "name": "backed_up", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "transports": { + "name": "transports", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "aaguid": { + "name": "aaguid", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "passkey_userId_idx": { + "name": "passkey_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "passkey_credentialID_idx": { + "name": "passkey_credentialID_idx", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "passkey_user_id_user_id_fk": { + "name": "passkey_user_id_user_id_fk", + "tableFrom": "passkey", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "impersonated_by": { + "name": "impersonated_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.two_factor": { + "name": "two_factor", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "backup_codes": { + "name": "backup_codes", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "twoFactor_secret_idx": { + "name": "twoFactor_secret_idx", + "columns": [ + { + "expression": "secret", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "twoFactor_userId_idx": { + "name": "twoFactor_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "two_factor_user_id_user_id_fk": { + "name": "two_factor_user_id_user_id_fk", + "tableFrom": "two_factor", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "two_factor_enabled": { + "name": "two_factor_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "is_anonymous": { + "name": "is_anonymous", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.credit_transaction": { + "name": "credit_transaction", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "customer_id": { + "name": "customer_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "amount": { + "name": "amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "credit_transaction_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "balance_after": { + "name": "balance_after", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "credit_transaction_customer_id_customer_id_fk": { + "name": "credit_transaction_customer_id_customer_id_fk", + "tableFrom": "credit_transaction", + "tableTo": "customer", + "columnsFrom": [ + "customer_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.customer": { + "name": "customer", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "customer_id": { + "name": "customer_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "status", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "plan": { + "name": "plan", + "type": "plan", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "credits": { + "name": "credits", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 100 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "customer_user_id_user_id_fk": { + "name": "customer_user_id_user_id_fk", + "tableFrom": "customer", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "customer_userId_unique": { + "name": "customer_userId_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + }, + "customer_customerId_unique": { + "name": "customer_customerId_unique", + "nullsNotDistinct": false, + "columns": [ + "customer_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "chat.chat": { + "name": "chat", + "schema": "chat", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "chat_user_id_user_id_fk": { + "name": "chat_user_id_user_id_fk", + "tableFrom": "chat", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "chat.message": { + "name": "message", + "schema": "chat", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "role", + "typeSchema": "chat", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "message_chat_id_chat_id_fk": { + "name": "message_chat_id_chat_id_fk", + "tableFrom": "message", + "tableTo": "chat", + "schemaTo": "chat", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "chat.part": { + "name": "part", + "schema": "chat", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "details": { + "name": "details", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "part_message_id_message_id_fk": { + "name": "part_message_id_message_id_fk", + "tableFrom": "part", + "tableTo": "message", + "schemaTo": "chat", + "columnsFrom": [ + "message_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "pdf.chat": { + "name": "chat", + "schema": "pdf", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "chat_user_id_user_id_fk": { + "name": "chat_user_id_user_id_fk", + "tableFrom": "chat", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "pdf.citation_unit": { + "name": "citation_unit", + "schema": "pdf", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "retrieval_chunk_id": { + "name": "retrieval_chunk_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "page_number": { + "name": "page_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "paragraph_index": { + "name": "paragraph_index", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "char_start": { + "name": "char_start", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "char_end": { + "name": "char_end", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "bbox_x": { + "name": "bbox_x", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "bbox_y": { + "name": "bbox_y", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "bbox_width": { + "name": "bbox_width", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "bbox_height": { + "name": "bbox_height", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "section_title": { + "name": "section_title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "unit_type": { + "name": "unit_type", + "type": "unit_type", + "typeSchema": "pdf", + "primaryKey": false, + "notNull": false, + "default": "'prose'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "idx_cu_document": { + "name": "idx_cu_document", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_cu_retrieval": { + "name": "idx_cu_retrieval", + "columns": [ + { + "expression": "retrieval_chunk_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_cu_page": { + "name": "idx_cu_page", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "page_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_cu_unique": { + "name": "idx_cu_unique", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "page_number", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "paragraph_index", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "citation_unit_document_id_document_id_fk": { + "name": "citation_unit_document_id_document_id_fk", + "tableFrom": "citation_unit", + "tableTo": "document", + "schemaTo": "pdf", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "citation_unit_retrieval_chunk_id_retrieval_chunk_id_fk": { + "name": "citation_unit_retrieval_chunk_id_retrieval_chunk_id_fk", + "tableFrom": "citation_unit", + "tableTo": "retrieval_chunk", + "schemaTo": "pdf", + "columnsFrom": [ + "retrieval_chunk_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "pdf.document": { + "name": "document", + "schema": "pdf", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "processing_status": { + "name": "processing_status", + "type": "processing_status", + "typeSchema": "pdf", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "processing_error": { + "name": "processing_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "document_chat_id_chat_id_fk": { + "name": "document_chat_id_chat_id_fk", + "tableFrom": "document", + "tableTo": "chat", + "schemaTo": "pdf", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "pdf.embedding": { + "name": "embedding", + "schema": "pdf", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": true + }, + "page_number": { + "name": "page_number", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "char_start": { + "name": "char_start", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "char_end": { + "name": "char_end", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "section_title": { + "name": "section_title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "pdf_embeddingIndex": { + "name": "pdf_embeddingIndex", + "columns": [ + { + "expression": "embedding", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": {} + } + }, + "foreignKeys": { + "embedding_document_id_document_id_fk": { + "name": "embedding_document_id_document_id_fk", + "tableFrom": "embedding", + "tableTo": "document", + "schemaTo": "pdf", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "pdf.message": { + "name": "message", + "schema": "pdf", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "role", + "typeSchema": "pdf", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "message_chat_id_chat_id_fk": { + "name": "message_chat_id_chat_id_fk", + "tableFrom": "message", + "tableTo": "chat", + "schemaTo": "pdf", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "pdf.retrieval_chunk": { + "name": "retrieval_chunk", + "schema": "pdf", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": false + }, + "page_start": { + "name": "page_start", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "page_end": { + "name": "page_end", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "section_hierarchy": { + "name": "section_hierarchy", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "chunk_type": { + "name": "chunk_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'prose'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "idx_rc_document": { + "name": "idx_rc_document", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_rc_embedding": { + "name": "idx_rc_embedding", + "columns": [ + { + "expression": "embedding", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": {} + } + }, + "foreignKeys": { + "retrieval_chunk_document_id_document_id_fk": { + "name": "retrieval_chunk_document_id_document_id_fk", + "tableFrom": "retrieval_chunk", + "tableTo": "document", + "schemaTo": "pdf", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "image.generation": { + "name": "generation", + "schema": "image", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "prompt": { + "name": "prompt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "aspect_ratio": { + "name": "aspect_ratio", + "type": "aspect_ratio", + "typeSchema": "image", + "primaryKey": false, + "notNull": true, + "default": "'square'" + }, + "count": { + "name": "count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "generation_user_id_user_id_fk": { + "name": "generation_user_id_user_id_fk", + "tableFrom": "generation", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "image.image": { + "name": "image", + "schema": "image", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "generation_id": { + "name": "generation_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "image_generation_id_generation_id_fk": { + "name": "image_generation_id_generation_id_fk", + "tableFrom": "image", + "tableTo": "generation", + "schemaTo": "image", + "columnsFrom": [ + "generation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mesh.audit_log": { + "name": "audit_log", + "schema": "mesh", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "mesh_id": { + "name": "mesh_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "event_type": { + "name": "event_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "actor_peer_id": { + "name": "actor_peer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "target_peer_id": { + "name": "target_peer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "audit_log_mesh_id_mesh_id_fk": { + "name": "audit_log_mesh_id_mesh_id_fk", + "tableFrom": "audit_log", + "tableTo": "mesh", + "schemaTo": "mesh", + "columnsFrom": [ + "mesh_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mesh.invite": { + "name": "invite", + "schema": "mesh", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "mesh_id": { + "name": "mesh_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token_bytes": { + "name": "token_bytes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "max_uses": { + "name": "max_uses", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "used_count": { + "name": "used_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "role": { + "name": "role", + "type": "role", + "typeSchema": "mesh", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "invite_mesh_id_mesh_id_fk": { + "name": "invite_mesh_id_mesh_id_fk", + "tableFrom": "invite", + "tableTo": "mesh", + "schemaTo": "mesh", + "columnsFrom": [ + "mesh_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "invite_created_by_user_id_fk": { + "name": "invite_created_by_user_id_fk", + "tableFrom": "invite", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "invite_token_unique": { + "name": "invite_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mesh.mesh": { + "name": "mesh", + "schema": "mesh", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "visibility": { + "name": "visibility", + "type": "visibility", + "typeSchema": "mesh", + "primaryKey": false, + "notNull": true, + "default": "'private'" + }, + "transport": { + "name": "transport", + "type": "transport", + "typeSchema": "mesh", + "primaryKey": false, + "notNull": true, + "default": "'managed'" + }, + "max_peers": { + "name": "max_peers", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "tier": { + "name": "tier", + "type": "tier", + "typeSchema": "mesh", + "primaryKey": false, + "notNull": true, + "default": "'free'" + }, + "owner_pubkey": { + "name": "owner_pubkey", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner_secret_key": { + "name": "owner_secret_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "root_key": { + "name": "root_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "mesh_owner_user_id_user_id_fk": { + "name": "mesh_owner_user_id_user_id_fk", + "tableFrom": "mesh", + "tableTo": "user", + "columnsFrom": [ + "owner_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mesh_slug_unique": { + "name": "mesh_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mesh.member": { + "name": "member", + "schema": "mesh", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "mesh_id": { + "name": "mesh_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "peer_pubkey": { + "name": "peer_pubkey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "role", + "typeSchema": "mesh", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "member_mesh_id_mesh_id_fk": { + "name": "member_mesh_id_mesh_id_fk", + "tableFrom": "member", + "tableTo": "mesh", + "schemaTo": "mesh", + "columnsFrom": [ + "mesh_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "member_user_id_user_id_fk": { + "name": "member_user_id_user_id_fk", + "tableFrom": "member", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mesh.message_queue": { + "name": "message_queue", + "schema": "mesh", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "mesh_id": { + "name": "mesh_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sender_member_id": { + "name": "sender_member_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_spec": { + "name": "target_spec", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "priority": { + "name": "priority", + "type": "message_priority", + "typeSchema": "mesh", + "primaryKey": false, + "notNull": true, + "default": "'next'" + }, + "nonce": { + "name": "nonce", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "ciphertext": { + "name": "ciphertext", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "delivered_at": { + "name": "delivered_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "message_queue_mesh_id_mesh_id_fk": { + "name": "message_queue_mesh_id_mesh_id_fk", + "tableFrom": "message_queue", + "tableTo": "mesh", + "schemaTo": "mesh", + "columnsFrom": [ + "mesh_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "message_queue_sender_member_id_member_id_fk": { + "name": "message_queue_sender_member_id_member_id_fk", + "tableFrom": "message_queue", + "tableTo": "member", + "schemaTo": "mesh", + "columnsFrom": [ + "sender_member_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mesh.pending_status": { + "name": "pending_status", + "schema": "mesh", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pid": { + "name": "pid", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "cwd": { + "name": "cwd", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status_source": { + "name": "status_source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "applied_at": { + "name": "applied_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mesh.presence": { + "name": "presence", + "schema": "mesh", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "member_id": { + "name": "member_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pid": { + "name": "pid", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "cwd": { + "name": "cwd", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "presence_status", + "typeSchema": "mesh", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "status_source": { + "name": "status_source", + "type": "presence_status_source", + "typeSchema": "mesh", + "primaryKey": false, + "notNull": true, + "default": "'jsonl'" + }, + "status_updated_at": { + "name": "status_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "summary": { + "name": "summary", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connected_at": { + "name": "connected_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_ping_at": { + "name": "last_ping_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "disconnected_at": { + "name": "disconnected_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "presence_member_id_member_id_fk": { + "name": "presence_member_id_member_id_fk", + "tableFrom": "presence", + "tableTo": "member", + "schemaTo": "mesh", + "columnsFrom": [ + "member_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.credit_transaction_type": { + "name": "credit_transaction_type", + "schema": "public", + "values": [ + "signup", + "purchase", + "usage", + "admin_grant", + "admin_deduct", + "refund", + "promo", + "referral", + "expiry" + ] + }, + "public.status": { + "name": "status", + "schema": "public", + "values": [ + "active", + "canceled", + "incomplete", + "incomplete_expired", + "past_due", + "paused", + "trialing", + "unpaid" + ] + }, + "public.plan": { + "name": "plan", + "schema": "public", + "values": [ + "free", + "premium", + "enterprise" + ] + }, + "chat.role": { + "name": "role", + "schema": "chat", + "values": [ + "system", + "assistant", + "user" + ] + }, + "pdf.role": { + "name": "role", + "schema": "pdf", + "values": [ + "user", + "assistant", + "system" + ] + }, + "pdf.processing_status": { + "name": "processing_status", + "schema": "pdf", + "values": [ + "pending", + "processing", + "ready", + "failed" + ] + }, + "pdf.unit_type": { + "name": "unit_type", + "schema": "pdf", + "values": [ + "prose", + "heading", + "list", + "table", + "code" + ] + }, + "image.aspect_ratio": { + "name": "aspect_ratio", + "schema": "image", + "values": [ + "square", + "standard", + "landscape", + "portrait" + ] + }, + "mesh.role": { + "name": "role", + "schema": "mesh", + "values": [ + "admin", + "member" + ] + }, + "mesh.tier": { + "name": "tier", + "schema": "mesh", + "values": [ + "free", + "pro", + "team", + "enterprise" + ] + }, + "mesh.transport": { + "name": "transport", + "schema": "mesh", + "values": [ + "managed", + "tailscale", + "self_hosted" + ] + }, + "mesh.visibility": { + "name": "visibility", + "schema": "mesh", + "values": [ + "private", + "public" + ] + }, + "mesh.message_priority": { + "name": "message_priority", + "schema": "mesh", + "values": [ + "now", + "next", + "low" + ] + }, + "mesh.presence_status": { + "name": "presence_status", + "schema": "mesh", + "values": [ + "idle", + "working", + "dnd" + ] + }, + "mesh.presence_status_source": { + "name": "presence_status_source", + "schema": "mesh", + "values": [ + "hook", + "manual", + "jsonl" + ] + } + }, + "schemas": { + "chat": "chat", + "pdf": "pdf", + "image": "image", + "mesh": "mesh" + }, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json index ce95d18..c75c713 100644 --- a/packages/db/migrations/meta/_journal.json +++ b/packages/db/migrations/meta/_journal.json @@ -22,6 +22,13 @@ "when": 1775340519054, "tag": "0002_vengeful_enchantress", "breakpoints": true + }, + { + "idx": 3, + "version": "7", + "when": 1775463897329, + "tag": "0003_add-presence-summary", + "breakpoints": true } ] } \ No newline at end of file diff --git a/packages/db/src/schema/mesh.ts b/packages/db/src/schema/mesh.ts index e8592e6..a6ab83e 100644 --- a/packages/db/src/schema/mesh.ts +++ b/packages/db/src/schema/mesh.ts @@ -197,6 +197,7 @@ export const presence = meshSchema.table("presence", { status: presenceStatusEnum().notNull().default("idle"), statusSource: presenceStatusSourceEnum().notNull().default("jsonl"), statusUpdatedAt: timestamp().defaultNow().notNull(), + summary: text(), connectedAt: timestamp().defaultNow().notNull(), lastPingAt: timestamp().defaultNow().notNull(), disconnectedAt: timestamp(),