family-ai-agent 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/.letta/settings.local.json +3 -0
  2. package/dist/cli/index.js +6 -4
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/database/adapters/base-adapter.d.ts +81 -0
  5. package/dist/database/adapters/base-adapter.d.ts.map +1 -0
  6. package/dist/database/adapters/base-adapter.js +105 -0
  7. package/dist/database/adapters/base-adapter.js.map +1 -0
  8. package/dist/database/adapters/index.d.ts +49 -0
  9. package/dist/database/adapters/index.d.ts.map +1 -0
  10. package/dist/database/adapters/index.js +200 -0
  11. package/dist/database/adapters/index.js.map +1 -0
  12. package/dist/database/adapters/postgres-adapter.d.ts +75 -0
  13. package/dist/database/adapters/postgres-adapter.d.ts.map +1 -0
  14. package/dist/database/adapters/postgres-adapter.js +225 -0
  15. package/dist/database/adapters/postgres-adapter.js.map +1 -0
  16. package/dist/database/adapters/sqlite-adapter.d.ts +72 -0
  17. package/dist/database/adapters/sqlite-adapter.d.ts.map +1 -0
  18. package/dist/database/adapters/sqlite-adapter.js +368 -0
  19. package/dist/database/adapters/sqlite-adapter.js.map +1 -0
  20. package/dist/database/cache/cache-keys.d.ts +180 -0
  21. package/dist/database/cache/cache-keys.d.ts.map +1 -0
  22. package/dist/database/cache/cache-keys.js +107 -0
  23. package/dist/database/cache/cache-keys.js.map +1 -0
  24. package/dist/database/cache/index.d.ts +24 -0
  25. package/dist/database/cache/index.d.ts.map +1 -0
  26. package/dist/database/cache/index.js +34 -0
  27. package/dist/database/cache/index.js.map +1 -0
  28. package/dist/database/cache/query-cache.d.ts +67 -0
  29. package/dist/database/cache/query-cache.d.ts.map +1 -0
  30. package/dist/database/cache/query-cache.js +177 -0
  31. package/dist/database/cache/query-cache.js.map +1 -0
  32. package/dist/database/client.d.ts +63 -4
  33. package/dist/database/client.d.ts.map +1 -1
  34. package/dist/database/client.js +147 -59
  35. package/dist/database/client.js.map +1 -1
  36. package/dist/database/db-config.d.ts +104 -0
  37. package/dist/database/db-config.d.ts.map +1 -0
  38. package/dist/database/db-config.js +167 -0
  39. package/dist/database/db-config.js.map +1 -0
  40. package/dist/database/drizzle/index.d.ts +42 -0
  41. package/dist/database/drizzle/index.d.ts.map +1 -0
  42. package/dist/database/drizzle/index.js +48 -0
  43. package/dist/database/drizzle/index.js.map +1 -0
  44. package/dist/database/drizzle/schema/audit.d.ts +533 -0
  45. package/dist/database/drizzle/schema/audit.d.ts.map +1 -0
  46. package/dist/database/drizzle/schema/audit.js +71 -0
  47. package/dist/database/drizzle/schema/audit.js.map +1 -0
  48. package/dist/database/drizzle/schema/checkpoints.d.ts +665 -0
  49. package/dist/database/drizzle/schema/checkpoints.d.ts.map +1 -0
  50. package/dist/database/drizzle/schema/checkpoints.js +110 -0
  51. package/dist/database/drizzle/schema/checkpoints.js.map +1 -0
  52. package/dist/database/drizzle/schema/conversations.d.ts +449 -0
  53. package/dist/database/drizzle/schema/conversations.d.ts.map +1 -0
  54. package/dist/database/drizzle/schema/conversations.js +91 -0
  55. package/dist/database/drizzle/schema/conversations.js.map +1 -0
  56. package/dist/database/drizzle/schema/documents.d.ts +600 -0
  57. package/dist/database/drizzle/schema/documents.d.ts.map +1 -0
  58. package/dist/database/drizzle/schema/documents.js +100 -0
  59. package/dist/database/drizzle/schema/documents.js.map +1 -0
  60. package/dist/database/drizzle/schema/index.d.ts +3084 -0
  61. package/dist/database/drizzle/schema/index.d.ts.map +1 -0
  62. package/dist/database/drizzle/schema/index.js +46 -0
  63. package/dist/database/drizzle/schema/index.js.map +1 -0
  64. package/dist/database/drizzle/schema/memories.d.ts +435 -0
  65. package/dist/database/drizzle/schema/memories.d.ts.map +1 -0
  66. package/dist/database/drizzle/schema/memories.js +73 -0
  67. package/dist/database/drizzle/schema/memories.js.map +1 -0
  68. package/dist/database/drizzle/schema/tasks.d.ts +565 -0
  69. package/dist/database/drizzle/schema/tasks.d.ts.map +1 -0
  70. package/dist/database/drizzle/schema/tasks.js +84 -0
  71. package/dist/database/drizzle/schema/tasks.js.map +1 -0
  72. package/dist/database/health/circuit-breaker.d.ts +81 -0
  73. package/dist/database/health/circuit-breaker.d.ts.map +1 -0
  74. package/dist/database/health/circuit-breaker.js +184 -0
  75. package/dist/database/health/circuit-breaker.js.map +1 -0
  76. package/dist/database/health/health-monitor.d.ts +69 -0
  77. package/dist/database/health/health-monitor.d.ts.map +1 -0
  78. package/dist/database/health/health-monitor.js +174 -0
  79. package/dist/database/health/health-monitor.js.map +1 -0
  80. package/dist/database/health/index.d.ts +27 -0
  81. package/dist/database/health/index.d.ts.map +1 -0
  82. package/dist/database/health/index.js +23 -0
  83. package/dist/database/health/index.js.map +1 -0
  84. package/dist/database/index.d.ts +16 -0
  85. package/dist/database/index.d.ts.map +1 -0
  86. package/dist/database/index.js +41 -0
  87. package/dist/database/index.js.map +1 -0
  88. package/dist/database/migrations/index.d.ts +34 -0
  89. package/dist/database/migrations/index.d.ts.map +1 -0
  90. package/dist/database/migrations/index.js +45 -0
  91. package/dist/database/migrations/index.js.map +1 -0
  92. package/dist/database/migrations/migrator.d.ts +77 -0
  93. package/dist/database/migrations/migrator.d.ts.map +1 -0
  94. package/dist/database/migrations/migrator.js +258 -0
  95. package/dist/database/migrations/migrator.js.map +1 -0
  96. package/dist/database/migrations/versions/001_initial.d.ts +9 -0
  97. package/dist/database/migrations/versions/001_initial.d.ts.map +1 -0
  98. package/dist/database/migrations/versions/001_initial.js +183 -0
  99. package/dist/database/migrations/versions/001_initial.js.map +1 -0
  100. package/dist/database/types.d.ts +255 -0
  101. package/dist/database/types.d.ts.map +1 -0
  102. package/dist/database/types.js +8 -0
  103. package/dist/database/types.js.map +1 -0
  104. package/dist/database/vector/embedding-cache.d.ts +92 -0
  105. package/dist/database/vector/embedding-cache.d.ts.map +1 -0
  106. package/dist/database/vector/embedding-cache.js +185 -0
  107. package/dist/database/vector/embedding-cache.js.map +1 -0
  108. package/dist/database/vector/hnsw-index.d.ts +111 -0
  109. package/dist/database/vector/hnsw-index.d.ts.map +1 -0
  110. package/dist/database/vector/hnsw-index.js +337 -0
  111. package/dist/database/vector/hnsw-index.js.map +1 -0
  112. package/dist/database/vector/index.d.ts +75 -0
  113. package/dist/database/vector/index.d.ts.map +1 -0
  114. package/dist/database/vector/index.js +213 -0
  115. package/dist/database/vector/index.js.map +1 -0
  116. package/dist/database/vector/similarity.d.ts +67 -0
  117. package/dist/database/vector/similarity.d.ts.map +1 -0
  118. package/dist/database/vector/similarity.js +176 -0
  119. package/dist/database/vector/similarity.js.map +1 -0
  120. package/dist/index.d.ts +1 -1
  121. package/dist/index.js +1 -1
  122. package/package.json +6 -3
  123. package/src/cli/index.ts +5 -5
  124. package/src/database/adapters/base-adapter.ts +171 -0
  125. package/src/database/adapters/index.ts +224 -0
  126. package/src/database/adapters/postgres-adapter.ts +285 -0
  127. package/src/database/adapters/sqlite-adapter.ts +420 -0
  128. package/src/database/cache/cache-keys.ts +150 -0
  129. package/src/database/cache/index.ts +44 -0
  130. package/src/database/cache/query-cache.ts +213 -0
  131. package/src/database/client.ts +166 -64
  132. package/src/database/db-config.ts +194 -0
  133. package/src/database/drizzle/index.ts +66 -0
  134. package/src/database/drizzle/schema/audit.ts +127 -0
  135. package/src/database/drizzle/schema/checkpoints.ts +164 -0
  136. package/src/database/drizzle/schema/conversations.ts +138 -0
  137. package/src/database/drizzle/schema/documents.ts +157 -0
  138. package/src/database/drizzle/schema/index.ts +139 -0
  139. package/src/database/drizzle/schema/memories.ts +127 -0
  140. package/src/database/drizzle/schema/tasks.ts +129 -0
  141. package/src/database/health/circuit-breaker.ts +214 -0
  142. package/src/database/health/health-monitor.ts +224 -0
  143. package/src/database/health/index.ts +41 -0
  144. package/src/database/index.ts +157 -0
  145. package/src/database/migrations/index.ts +52 -0
  146. package/src/database/migrations/migrator.ts +325 -0
  147. package/src/database/migrations/versions/001_initial.ts +198 -0
  148. package/src/database/types.ts +324 -0
  149. package/src/database/vector/embedding-cache.ts +234 -0
  150. package/src/database/vector/hnsw-index.ts +452 -0
  151. package/src/database/vector/index.ts +292 -0
  152. package/src/database/vector/similarity.ts +198 -0
  153. package/src/index.ts +1 -1
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Drizzle ORM Instance Factory
3
+ *
4
+ * Creates and manages Drizzle ORM instances for both PostgreSQL and SQLite.
5
+ */
6
+
7
+ import { drizzle as drizzlePg } from 'drizzle-orm/node-postgres';
8
+ import { drizzle as drizzleSqlite } from 'drizzle-orm/better-sqlite3';
9
+ import type { NodePgDatabase } from 'drizzle-orm/node-postgres';
10
+ import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
11
+ import type { Pool } from 'pg';
12
+ import type Database from 'better-sqlite3';
13
+
14
+ import * as pgSchema from './schema/conversations.js';
15
+ import * as sqliteSchema from './schema/conversations.js';
16
+
17
+ // Re-export schema
18
+ export * from './schema/index.js';
19
+
20
+ /**
21
+ * Drizzle instance types
22
+ */
23
+ export type DrizzlePgInstance = NodePgDatabase<typeof pgSchema>;
24
+ export type DrizzleSqliteInstance = BetterSQLite3Database<typeof sqliteSchema>;
25
+ export type DrizzleInstance = DrizzlePgInstance | DrizzleSqliteInstance;
26
+
27
+ /**
28
+ * Create Drizzle instance for PostgreSQL
29
+ */
30
+ export function createPgDrizzle(pool: Pool): DrizzlePgInstance {
31
+ return drizzlePg(pool, {
32
+ schema: pgSchema,
33
+ logger: process.env.NODE_ENV === 'development',
34
+ });
35
+ }
36
+
37
+ /**
38
+ * Create Drizzle instance for SQLite
39
+ */
40
+ export function createSqliteDrizzle(database: Database.Database): DrizzleSqliteInstance {
41
+ return drizzleSqlite(database, {
42
+ schema: sqliteSchema,
43
+ logger: process.env.NODE_ENV === 'development',
44
+ });
45
+ }
46
+
47
+ /**
48
+ * Database type guard for PostgreSQL
49
+ */
50
+ export function isPgDrizzle(db: DrizzleInstance): db is DrizzlePgInstance {
51
+ return 'dialect' in db && (db as unknown as { dialect: { name: string } }).dialect?.name === 'pg';
52
+ }
53
+
54
+ /**
55
+ * Database type guard for SQLite
56
+ */
57
+ export function isSqliteDrizzle(db: DrizzleInstance): db is DrizzleSqliteInstance {
58
+ return 'dialect' in db && (db as unknown as { dialect: { name: string } }).dialect?.name === 'sqlite';
59
+ }
60
+
61
+ export default {
62
+ createPgDrizzle,
63
+ createSqliteDrizzle,
64
+ isPgDrizzle,
65
+ isSqliteDrizzle,
66
+ };
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Audit Logs Schema
3
+ *
4
+ * Drizzle ORM schema for safety and compliance audit logging.
5
+ * Tracks all significant actions in the system.
6
+ */
7
+
8
+ import {
9
+ pgTable,
10
+ uuid,
11
+ text,
12
+ integer,
13
+ timestamp,
14
+ jsonb,
15
+ boolean,
16
+ index,
17
+ } from 'drizzle-orm/pg-core';
18
+ import {
19
+ sqliteTable,
20
+ text as sqliteText,
21
+ integer as sqliteInteger,
22
+ } from 'drizzle-orm/sqlite-core';
23
+ import { sql } from 'drizzle-orm';
24
+
25
+ // =============================================================================
26
+ // PostgreSQL Schema
27
+ // =============================================================================
28
+
29
+ /**
30
+ * Audit logs table (PostgreSQL)
31
+ */
32
+ export const auditLogsPg = pgTable(
33
+ 'audit_logs',
34
+ {
35
+ id: uuid('id')
36
+ .primaryKey()
37
+ .default(sql`gen_random_uuid()`),
38
+ userId: text('user_id'),
39
+ agentId: text('agent_id'),
40
+ actionType: text('action_type').notNull(),
41
+ actionDetails: jsonb('action_details').default({}).notNull(),
42
+ inputHash: text('input_hash'),
43
+ outputHash: text('output_hash'),
44
+ status: text('status').default('success').notNull(),
45
+ errorMessage: text('error_message'),
46
+ executionTimeMs: integer('execution_time_ms'),
47
+ ipAddress: text('ip_address'),
48
+ userAgent: text('user_agent'),
49
+ success: boolean('success').default(true).notNull(),
50
+ createdAt: timestamp('created_at', { withTimezone: true })
51
+ .defaultNow()
52
+ .notNull(),
53
+ },
54
+ (table) => ({
55
+ userIdIdx: index('audit_user_id_idx').on(table.userId),
56
+ agentIdIdx: index('audit_agent_id_idx').on(table.agentId),
57
+ actionTypeIdx: index('audit_action_type_idx').on(table.actionType),
58
+ createdAtIdx: index('audit_created_at_idx').on(table.createdAt),
59
+ statusIdx: index('audit_status_idx').on(table.status),
60
+ })
61
+ );
62
+
63
+ // =============================================================================
64
+ // SQLite Schema
65
+ // =============================================================================
66
+
67
+ /**
68
+ * Audit logs table (SQLite)
69
+ */
70
+ export const auditLogsSqlite = sqliteTable('audit_logs', {
71
+ id: sqliteText('id')
72
+ .primaryKey()
73
+ .$defaultFn(() => crypto.randomUUID()),
74
+ userId: sqliteText('user_id'),
75
+ agentId: sqliteText('agent_id'),
76
+ actionType: sqliteText('action_type').notNull(),
77
+ actionDetails: sqliteText('action_details', { mode: 'json' })
78
+ .notNull()
79
+ .$type<Record<string, unknown>>()
80
+ .default({}),
81
+ inputHash: sqliteText('input_hash'),
82
+ outputHash: sqliteText('output_hash'),
83
+ status: sqliteText('status').default('success').notNull(),
84
+ errorMessage: sqliteText('error_message'),
85
+ executionTimeMs: sqliteInteger('execution_time_ms'),
86
+ ipAddress: sqliteText('ip_address'),
87
+ userAgent: sqliteText('user_agent'),
88
+ success: sqliteInteger('success', { mode: 'boolean' }).default(true).notNull(),
89
+ createdAt: sqliteInteger('created_at', { mode: 'timestamp' })
90
+ .notNull()
91
+ .$defaultFn(() => new Date()),
92
+ });
93
+
94
+ // =============================================================================
95
+ // TypeScript Types
96
+ // =============================================================================
97
+
98
+ export type AuditLogPg = typeof auditLogsPg.$inferSelect;
99
+ export type NewAuditLogPg = typeof auditLogsPg.$inferInsert;
100
+
101
+ export type AuditLogSqlite = typeof auditLogsSqlite.$inferSelect;
102
+ export type NewAuditLogSqlite = typeof auditLogsSqlite.$inferInsert;
103
+
104
+ // Unified types
105
+ export type AuditLog = AuditLogPg | AuditLogSqlite;
106
+ export type NewAuditLog = NewAuditLogPg | NewAuditLogSqlite;
107
+
108
+ // Action types enum
109
+ export type AuditActionType =
110
+ | 'chat_message'
111
+ | 'memory_store'
112
+ | 'memory_search'
113
+ | 'memory_delete'
114
+ | 'document_upload'
115
+ | 'document_search'
116
+ | 'document_delete'
117
+ | 'agent_invocation'
118
+ | 'tool_execution'
119
+ | 'safety_block'
120
+ | 'safety_warning'
121
+ | 'authentication'
122
+ | 'authorization'
123
+ | 'config_change'
124
+ | 'system_event';
125
+
126
+ // Status types
127
+ export type AuditStatus = 'success' | 'failure' | 'blocked' | 'warning';
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Checkpoints Schema
3
+ *
4
+ * Drizzle ORM schema for LangGraph checkpointing.
5
+ * Stores execution state for resumable workflows.
6
+ */
7
+
8
+ import {
9
+ pgTable,
10
+ text,
11
+ timestamp,
12
+ jsonb,
13
+ primaryKey,
14
+ integer,
15
+ } from 'drizzle-orm/pg-core';
16
+ import {
17
+ sqliteTable,
18
+ text as sqliteText,
19
+ integer as sqliteInteger,
20
+ primaryKey as sqlitePrimaryKey,
21
+ } from 'drizzle-orm/sqlite-core';
22
+
23
+ // =============================================================================
24
+ // PostgreSQL Schema
25
+ // =============================================================================
26
+
27
+ /**
28
+ * Checkpoints table (PostgreSQL)
29
+ */
30
+ export const checkpointsPg = pgTable(
31
+ 'checkpoints',
32
+ {
33
+ threadId: text('thread_id').notNull(),
34
+ checkpointNs: text('checkpoint_ns').default('').notNull(),
35
+ checkpointId: text('checkpoint_id').notNull(),
36
+ parentCheckpointId: text('parent_checkpoint_id'),
37
+ type: text('type'),
38
+ checkpoint: jsonb('checkpoint').notNull(),
39
+ metadata: jsonb('metadata').default({}).notNull(),
40
+ createdAt: timestamp('created_at', { withTimezone: true })
41
+ .defaultNow()
42
+ .notNull(),
43
+ },
44
+ (table) => ({
45
+ pk: primaryKey({
46
+ columns: [table.threadId, table.checkpointNs, table.checkpointId],
47
+ }),
48
+ })
49
+ );
50
+
51
+ /**
52
+ * Checkpoint writes table (PostgreSQL)
53
+ */
54
+ export const checkpointWritesPg = pgTable(
55
+ 'checkpoint_writes',
56
+ {
57
+ threadId: text('thread_id').notNull(),
58
+ checkpointNs: text('checkpoint_ns').default('').notNull(),
59
+ checkpointId: text('checkpoint_id').notNull(),
60
+ taskId: text('task_id').notNull(),
61
+ idx: integer('idx').notNull(),
62
+ channel: text('channel').notNull(),
63
+ type: text('type'),
64
+ value: jsonb('value'),
65
+ createdAt: timestamp('created_at', { withTimezone: true })
66
+ .defaultNow()
67
+ .notNull(),
68
+ },
69
+ (table) => ({
70
+ pk: primaryKey({
71
+ columns: [
72
+ table.threadId,
73
+ table.checkpointNs,
74
+ table.checkpointId,
75
+ table.taskId,
76
+ table.idx,
77
+ ],
78
+ }),
79
+ })
80
+ );
81
+
82
+ // =============================================================================
83
+ // SQLite Schema
84
+ // =============================================================================
85
+
86
+ /**
87
+ * Checkpoints table (SQLite)
88
+ */
89
+ export const checkpointsSqlite = sqliteTable(
90
+ 'checkpoints',
91
+ {
92
+ threadId: sqliteText('thread_id').notNull(),
93
+ checkpointNs: sqliteText('checkpoint_ns').default('').notNull(),
94
+ checkpointId: sqliteText('checkpoint_id').notNull(),
95
+ parentCheckpointId: sqliteText('parent_checkpoint_id'),
96
+ type: sqliteText('type'),
97
+ checkpoint: sqliteText('checkpoint', { mode: 'json' })
98
+ .notNull()
99
+ .$type<Record<string, unknown>>(),
100
+ metadata: sqliteText('metadata', { mode: 'json' })
101
+ .notNull()
102
+ .$type<Record<string, unknown>>()
103
+ .default({}),
104
+ createdAt: sqliteInteger('created_at', { mode: 'timestamp' })
105
+ .notNull()
106
+ .$defaultFn(() => new Date()),
107
+ },
108
+ (table) => ({
109
+ pk: sqlitePrimaryKey({
110
+ columns: [table.threadId, table.checkpointNs, table.checkpointId],
111
+ }),
112
+ })
113
+ );
114
+
115
+ /**
116
+ * Checkpoint writes table (SQLite)
117
+ */
118
+ export const checkpointWritesSqlite = sqliteTable(
119
+ 'checkpoint_writes',
120
+ {
121
+ threadId: sqliteText('thread_id').notNull(),
122
+ checkpointNs: sqliteText('checkpoint_ns').default('').notNull(),
123
+ checkpointId: sqliteText('checkpoint_id').notNull(),
124
+ taskId: sqliteText('task_id').notNull(),
125
+ idx: sqliteInteger('idx').notNull(),
126
+ channel: sqliteText('channel').notNull(),
127
+ type: sqliteText('type'),
128
+ value: sqliteText('value', { mode: 'json' }).$type<unknown>(),
129
+ createdAt: sqliteInteger('created_at', { mode: 'timestamp' })
130
+ .notNull()
131
+ .$defaultFn(() => new Date()),
132
+ },
133
+ (table) => ({
134
+ pk: sqlitePrimaryKey({
135
+ columns: [
136
+ table.threadId,
137
+ table.checkpointNs,
138
+ table.checkpointId,
139
+ table.taskId,
140
+ table.idx,
141
+ ],
142
+ }),
143
+ })
144
+ );
145
+
146
+ // =============================================================================
147
+ // TypeScript Types
148
+ // =============================================================================
149
+
150
+ export type CheckpointPg = typeof checkpointsPg.$inferSelect;
151
+ export type NewCheckpointPg = typeof checkpointsPg.$inferInsert;
152
+ export type CheckpointWritePg = typeof checkpointWritesPg.$inferSelect;
153
+ export type NewCheckpointWritePg = typeof checkpointWritesPg.$inferInsert;
154
+
155
+ export type CheckpointSqlite = typeof checkpointsSqlite.$inferSelect;
156
+ export type NewCheckpointSqlite = typeof checkpointsSqlite.$inferInsert;
157
+ export type CheckpointWriteSqlite = typeof checkpointWritesSqlite.$inferSelect;
158
+ export type NewCheckpointWriteSqlite = typeof checkpointWritesSqlite.$inferInsert;
159
+
160
+ // Unified types
161
+ export type Checkpoint = CheckpointPg | CheckpointSqlite;
162
+ export type NewCheckpoint = NewCheckpointPg | NewCheckpointSqlite;
163
+ export type CheckpointWrite = CheckpointWritePg | CheckpointWriteSqlite;
164
+ export type NewCheckpointWrite = NewCheckpointWritePg | NewCheckpointWriteSqlite;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Conversations Schema
3
+ *
4
+ * Drizzle ORM schema for conversations and messages tables.
5
+ * Supports both PostgreSQL and SQLite.
6
+ */
7
+
8
+ import {
9
+ pgTable,
10
+ uuid,
11
+ text,
12
+ timestamp,
13
+ jsonb,
14
+ index,
15
+ } from 'drizzle-orm/pg-core';
16
+ import {
17
+ sqliteTable,
18
+ text as sqliteText,
19
+ integer,
20
+ } from 'drizzle-orm/sqlite-core';
21
+ import { sql } from 'drizzle-orm';
22
+
23
+ // =============================================================================
24
+ // PostgreSQL Schema
25
+ // =============================================================================
26
+
27
+ /**
28
+ * Conversations table (PostgreSQL)
29
+ */
30
+ export const conversationsPg = pgTable(
31
+ 'conversations',
32
+ {
33
+ id: uuid('id')
34
+ .primaryKey()
35
+ .default(sql`gen_random_uuid()`),
36
+ threadId: text('thread_id').notNull(),
37
+ userId: text('user_id'),
38
+ createdAt: timestamp('created_at', { withTimezone: true })
39
+ .defaultNow()
40
+ .notNull(),
41
+ updatedAt: timestamp('updated_at', { withTimezone: true })
42
+ .defaultNow()
43
+ .notNull(),
44
+ },
45
+ (table) => ({
46
+ threadIdIdx: index('conversations_thread_id_idx').on(table.threadId),
47
+ userIdIdx: index('conversations_user_id_idx').on(table.userId),
48
+ })
49
+ );
50
+
51
+ /**
52
+ * Messages table (PostgreSQL)
53
+ */
54
+ export const messagesPg = pgTable(
55
+ 'messages',
56
+ {
57
+ id: uuid('id')
58
+ .primaryKey()
59
+ .default(sql`gen_random_uuid()`),
60
+ conversationId: uuid('conversation_id')
61
+ .notNull()
62
+ .references(() => conversationsPg.id, { onDelete: 'cascade' }),
63
+ role: text('role').notNull(), // 'user' | 'assistant' | 'system'
64
+ content: text('content').notNull(),
65
+ metadata: jsonb('metadata').default({}).notNull(),
66
+ createdAt: timestamp('created_at', { withTimezone: true })
67
+ .defaultNow()
68
+ .notNull(),
69
+ },
70
+ (table) => ({
71
+ conversationIdIdx: index('messages_conversation_id_idx').on(
72
+ table.conversationId
73
+ ),
74
+ createdAtIdx: index('messages_created_at_idx').on(table.createdAt),
75
+ })
76
+ );
77
+
78
+ // =============================================================================
79
+ // SQLite Schema
80
+ // =============================================================================
81
+
82
+ /**
83
+ * Conversations table (SQLite)
84
+ */
85
+ export const conversationsSqlite = sqliteTable('conversations', {
86
+ id: sqliteText('id')
87
+ .primaryKey()
88
+ .$defaultFn(() => crypto.randomUUID()),
89
+ threadId: sqliteText('thread_id').notNull(),
90
+ userId: sqliteText('user_id'),
91
+ createdAt: integer('created_at', { mode: 'timestamp' })
92
+ .notNull()
93
+ .$defaultFn(() => new Date()),
94
+ updatedAt: integer('updated_at', { mode: 'timestamp' })
95
+ .notNull()
96
+ .$defaultFn(() => new Date()),
97
+ });
98
+
99
+ /**
100
+ * Messages table (SQLite)
101
+ */
102
+ export const messagesSqlite = sqliteTable('messages', {
103
+ id: sqliteText('id')
104
+ .primaryKey()
105
+ .$defaultFn(() => crypto.randomUUID()),
106
+ conversationId: sqliteText('conversation_id')
107
+ .notNull()
108
+ .references(() => conversationsSqlite.id, { onDelete: 'cascade' }),
109
+ role: sqliteText('role').notNull(),
110
+ content: sqliteText('content').notNull(),
111
+ metadata: sqliteText('metadata', { mode: 'json' })
112
+ .notNull()
113
+ .$type<Record<string, unknown>>()
114
+ .default({}),
115
+ createdAt: integer('created_at', { mode: 'timestamp' })
116
+ .notNull()
117
+ .$defaultFn(() => new Date()),
118
+ });
119
+
120
+ // =============================================================================
121
+ // TypeScript Types
122
+ // =============================================================================
123
+
124
+ export type ConversationPg = typeof conversationsPg.$inferSelect;
125
+ export type NewConversationPg = typeof conversationsPg.$inferInsert;
126
+ export type MessagePg = typeof messagesPg.$inferSelect;
127
+ export type NewMessagePg = typeof messagesPg.$inferInsert;
128
+
129
+ export type ConversationSqlite = typeof conversationsSqlite.$inferSelect;
130
+ export type NewConversationSqlite = typeof conversationsSqlite.$inferInsert;
131
+ export type MessageSqlite = typeof messagesSqlite.$inferSelect;
132
+ export type NewMessageSqlite = typeof messagesSqlite.$inferInsert;
133
+
134
+ // Unified types
135
+ export type Conversation = ConversationPg | ConversationSqlite;
136
+ export type NewConversation = NewConversationPg | NewConversationSqlite;
137
+ export type Message = MessagePg | MessageSqlite;
138
+ export type NewMessage = NewMessagePg | NewMessageSqlite;
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Documents Schema
3
+ *
4
+ * Drizzle ORM schema for knowledge base documents and chunks.
5
+ * Supports vector embeddings for RAG (Retrieval Augmented Generation).
6
+ */
7
+
8
+ import {
9
+ pgTable,
10
+ uuid,
11
+ text,
12
+ integer,
13
+ timestamp,
14
+ jsonb,
15
+ index,
16
+ } from 'drizzle-orm/pg-core';
17
+ import {
18
+ sqliteTable,
19
+ text as sqliteText,
20
+ integer as sqliteInteger,
21
+ } from 'drizzle-orm/sqlite-core';
22
+ import { sql } from 'drizzle-orm';
23
+
24
+ // =============================================================================
25
+ // PostgreSQL Schema
26
+ // =============================================================================
27
+
28
+ /**
29
+ * Documents table (PostgreSQL)
30
+ */
31
+ export const documentsPg = pgTable(
32
+ 'documents',
33
+ {
34
+ id: uuid('id')
35
+ .primaryKey()
36
+ .default(sql`gen_random_uuid()`),
37
+ userId: text('user_id'),
38
+ filename: text('filename').notNull(),
39
+ fileType: text('file_type'),
40
+ fileSize: integer('file_size'),
41
+ content: text('content'),
42
+ metadata: jsonb('metadata').default({}).notNull(),
43
+ createdAt: timestamp('created_at', { withTimezone: true })
44
+ .defaultNow()
45
+ .notNull(),
46
+ },
47
+ (table) => ({
48
+ userIdIdx: index('documents_user_id_idx').on(table.userId),
49
+ filenameIdx: index('documents_filename_idx').on(table.filename),
50
+ createdAtIdx: index('documents_created_at_idx').on(table.createdAt),
51
+ })
52
+ );
53
+
54
+ /**
55
+ * Document chunks table (PostgreSQL)
56
+ */
57
+ export const documentChunksPg = pgTable(
58
+ 'document_chunks',
59
+ {
60
+ id: uuid('id')
61
+ .primaryKey()
62
+ .default(sql`gen_random_uuid()`),
63
+ documentId: uuid('document_id')
64
+ .notNull()
65
+ .references(() => documentsPg.id, { onDelete: 'cascade' }),
66
+ chunkIndex: integer('chunk_index').notNull(),
67
+ content: text('content').notNull(),
68
+ // pgvector embedding
69
+ embedding: text('embedding').notNull(),
70
+ metadata: jsonb('metadata').default({}).notNull(),
71
+ createdAt: timestamp('created_at', { withTimezone: true })
72
+ .defaultNow()
73
+ .notNull(),
74
+ },
75
+ (table) => ({
76
+ documentIdIdx: index('chunks_document_id_idx').on(table.documentId),
77
+ chunkIndexIdx: index('chunks_chunk_index_idx').on(table.chunkIndex),
78
+ })
79
+ );
80
+
81
+ // =============================================================================
82
+ // SQLite Schema
83
+ // =============================================================================
84
+
85
+ /**
86
+ * Documents table (SQLite)
87
+ */
88
+ export const documentsSqlite = sqliteTable('documents', {
89
+ id: sqliteText('id')
90
+ .primaryKey()
91
+ .$defaultFn(() => crypto.randomUUID()),
92
+ userId: sqliteText('user_id'),
93
+ filename: sqliteText('filename').notNull(),
94
+ fileType: sqliteText('file_type'),
95
+ fileSize: sqliteInteger('file_size'),
96
+ content: sqliteText('content'),
97
+ metadata: sqliteText('metadata', { mode: 'json' })
98
+ .notNull()
99
+ .$type<Record<string, unknown>>()
100
+ .default({}),
101
+ createdAt: sqliteInteger('created_at', { mode: 'timestamp' })
102
+ .notNull()
103
+ .$defaultFn(() => new Date()),
104
+ });
105
+
106
+ /**
107
+ * Document chunks table (SQLite)
108
+ */
109
+ export const documentChunksSqlite = sqliteTable('document_chunks', {
110
+ id: sqliteText('id')
111
+ .primaryKey()
112
+ .$defaultFn(() => crypto.randomUUID()),
113
+ documentId: sqliteText('document_id')
114
+ .notNull()
115
+ .references(() => documentsSqlite.id, { onDelete: 'cascade' }),
116
+ chunkIndex: sqliteInteger('chunk_index').notNull(),
117
+ content: sqliteText('content').notNull(),
118
+ embedding: sqliteText('embedding').notNull(),
119
+ metadata: sqliteText('metadata', { mode: 'json' })
120
+ .notNull()
121
+ .$type<Record<string, unknown>>()
122
+ .default({}),
123
+ createdAt: sqliteInteger('created_at', { mode: 'timestamp' })
124
+ .notNull()
125
+ .$defaultFn(() => new Date()),
126
+ });
127
+
128
+ // =============================================================================
129
+ // TypeScript Types
130
+ // =============================================================================
131
+
132
+ export type DocumentPg = typeof documentsPg.$inferSelect;
133
+ export type NewDocumentPg = typeof documentsPg.$inferInsert;
134
+ export type DocumentChunkPg = typeof documentChunksPg.$inferSelect;
135
+ export type NewDocumentChunkPg = typeof documentChunksPg.$inferInsert;
136
+
137
+ export type DocumentSqlite = typeof documentsSqlite.$inferSelect;
138
+ export type NewDocumentSqlite = typeof documentsSqlite.$inferInsert;
139
+ export type DocumentChunkSqlite = typeof documentChunksSqlite.$inferSelect;
140
+ export type NewDocumentChunkSqlite = typeof documentChunksSqlite.$inferInsert;
141
+
142
+ // Unified types
143
+ export type Document = DocumentPg | DocumentSqlite;
144
+ export type NewDocument = NewDocumentPg | NewDocumentSqlite;
145
+ export type DocumentChunk = DocumentChunkPg | DocumentChunkSqlite;
146
+ export type NewDocumentChunk = NewDocumentChunkPg | NewDocumentChunkSqlite;
147
+
148
+ // Parsed chunk with embedding array
149
+ export interface ParsedDocumentChunk {
150
+ id: string;
151
+ documentId: string;
152
+ chunkIndex: number;
153
+ content: string;
154
+ embedding: number[];
155
+ metadata: Record<string, unknown>;
156
+ createdAt: Date;
157
+ }