family-ai-agent 1.0.6 → 1.0.8
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.
- package/.letta/settings.local.json +3 -0
- package/dist/cli/index.js +1 -1
- package/dist/database/adapters/base-adapter.d.ts +81 -0
- package/dist/database/adapters/base-adapter.d.ts.map +1 -0
- package/dist/database/adapters/base-adapter.js +105 -0
- package/dist/database/adapters/base-adapter.js.map +1 -0
- package/dist/database/adapters/index.d.ts +49 -0
- package/dist/database/adapters/index.d.ts.map +1 -0
- package/dist/database/adapters/index.js +200 -0
- package/dist/database/adapters/index.js.map +1 -0
- package/dist/database/adapters/postgres-adapter.d.ts +75 -0
- package/dist/database/adapters/postgres-adapter.d.ts.map +1 -0
- package/dist/database/adapters/postgres-adapter.js +225 -0
- package/dist/database/adapters/postgres-adapter.js.map +1 -0
- package/dist/database/adapters/sqlite-adapter.d.ts +72 -0
- package/dist/database/adapters/sqlite-adapter.d.ts.map +1 -0
- package/dist/database/adapters/sqlite-adapter.js +368 -0
- package/dist/database/adapters/sqlite-adapter.js.map +1 -0
- package/dist/database/cache/cache-keys.d.ts +180 -0
- package/dist/database/cache/cache-keys.d.ts.map +1 -0
- package/dist/database/cache/cache-keys.js +107 -0
- package/dist/database/cache/cache-keys.js.map +1 -0
- package/dist/database/cache/index.d.ts +24 -0
- package/dist/database/cache/index.d.ts.map +1 -0
- package/dist/database/cache/index.js +34 -0
- package/dist/database/cache/index.js.map +1 -0
- package/dist/database/cache/query-cache.d.ts +67 -0
- package/dist/database/cache/query-cache.d.ts.map +1 -0
- package/dist/database/cache/query-cache.js +177 -0
- package/dist/database/cache/query-cache.js.map +1 -0
- package/dist/database/client.d.ts +63 -4
- package/dist/database/client.d.ts.map +1 -1
- package/dist/database/client.js +147 -59
- package/dist/database/client.js.map +1 -1
- package/dist/database/db-config.d.ts +104 -0
- package/dist/database/db-config.d.ts.map +1 -0
- package/dist/database/db-config.js +167 -0
- package/dist/database/db-config.js.map +1 -0
- package/dist/database/drizzle/index.d.ts +42 -0
- package/dist/database/drizzle/index.d.ts.map +1 -0
- package/dist/database/drizzle/index.js +48 -0
- package/dist/database/drizzle/index.js.map +1 -0
- package/dist/database/drizzle/schema/audit.d.ts +533 -0
- package/dist/database/drizzle/schema/audit.d.ts.map +1 -0
- package/dist/database/drizzle/schema/audit.js +71 -0
- package/dist/database/drizzle/schema/audit.js.map +1 -0
- package/dist/database/drizzle/schema/checkpoints.d.ts +665 -0
- package/dist/database/drizzle/schema/checkpoints.d.ts.map +1 -0
- package/dist/database/drizzle/schema/checkpoints.js +110 -0
- package/dist/database/drizzle/schema/checkpoints.js.map +1 -0
- package/dist/database/drizzle/schema/conversations.d.ts +449 -0
- package/dist/database/drizzle/schema/conversations.d.ts.map +1 -0
- package/dist/database/drizzle/schema/conversations.js +91 -0
- package/dist/database/drizzle/schema/conversations.js.map +1 -0
- package/dist/database/drizzle/schema/documents.d.ts +600 -0
- package/dist/database/drizzle/schema/documents.d.ts.map +1 -0
- package/dist/database/drizzle/schema/documents.js +100 -0
- package/dist/database/drizzle/schema/documents.js.map +1 -0
- package/dist/database/drizzle/schema/index.d.ts +3084 -0
- package/dist/database/drizzle/schema/index.d.ts.map +1 -0
- package/dist/database/drizzle/schema/index.js +46 -0
- package/dist/database/drizzle/schema/index.js.map +1 -0
- package/dist/database/drizzle/schema/memories.d.ts +435 -0
- package/dist/database/drizzle/schema/memories.d.ts.map +1 -0
- package/dist/database/drizzle/schema/memories.js +73 -0
- package/dist/database/drizzle/schema/memories.js.map +1 -0
- package/dist/database/drizzle/schema/tasks.d.ts +565 -0
- package/dist/database/drizzle/schema/tasks.d.ts.map +1 -0
- package/dist/database/drizzle/schema/tasks.js +84 -0
- package/dist/database/drizzle/schema/tasks.js.map +1 -0
- package/dist/database/health/circuit-breaker.d.ts +81 -0
- package/dist/database/health/circuit-breaker.d.ts.map +1 -0
- package/dist/database/health/circuit-breaker.js +184 -0
- package/dist/database/health/circuit-breaker.js.map +1 -0
- package/dist/database/health/health-monitor.d.ts +69 -0
- package/dist/database/health/health-monitor.d.ts.map +1 -0
- package/dist/database/health/health-monitor.js +174 -0
- package/dist/database/health/health-monitor.js.map +1 -0
- package/dist/database/health/index.d.ts +27 -0
- package/dist/database/health/index.d.ts.map +1 -0
- package/dist/database/health/index.js +23 -0
- package/dist/database/health/index.js.map +1 -0
- package/dist/database/index.d.ts +16 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +41 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/migrations/index.d.ts +34 -0
- package/dist/database/migrations/index.d.ts.map +1 -0
- package/dist/database/migrations/index.js +45 -0
- package/dist/database/migrations/index.js.map +1 -0
- package/dist/database/migrations/migrator.d.ts +77 -0
- package/dist/database/migrations/migrator.d.ts.map +1 -0
- package/dist/database/migrations/migrator.js +258 -0
- package/dist/database/migrations/migrator.js.map +1 -0
- package/dist/database/migrations/versions/001_initial.d.ts +9 -0
- package/dist/database/migrations/versions/001_initial.d.ts.map +1 -0
- package/dist/database/migrations/versions/001_initial.js +183 -0
- package/dist/database/migrations/versions/001_initial.js.map +1 -0
- package/dist/database/types.d.ts +255 -0
- package/dist/database/types.d.ts.map +1 -0
- package/dist/database/types.js +8 -0
- package/dist/database/types.js.map +1 -0
- package/dist/database/vector/embedding-cache.d.ts +92 -0
- package/dist/database/vector/embedding-cache.d.ts.map +1 -0
- package/dist/database/vector/embedding-cache.js +185 -0
- package/dist/database/vector/embedding-cache.js.map +1 -0
- package/dist/database/vector/hnsw-index.d.ts +111 -0
- package/dist/database/vector/hnsw-index.d.ts.map +1 -0
- package/dist/database/vector/hnsw-index.js +337 -0
- package/dist/database/vector/hnsw-index.js.map +1 -0
- package/dist/database/vector/index.d.ts +75 -0
- package/dist/database/vector/index.d.ts.map +1 -0
- package/dist/database/vector/index.js +213 -0
- package/dist/database/vector/index.js.map +1 -0
- package/dist/database/vector/similarity.d.ts +67 -0
- package/dist/database/vector/similarity.d.ts.map +1 -0
- package/dist/database/vector/similarity.js +176 -0
- package/dist/database/vector/similarity.js.map +1 -0
- package/package.json +6 -3
- package/src/cli/index.ts +1 -1
- package/src/database/adapters/base-adapter.ts +171 -0
- package/src/database/adapters/index.ts +224 -0
- package/src/database/adapters/postgres-adapter.ts +285 -0
- package/src/database/adapters/sqlite-adapter.ts +420 -0
- package/src/database/cache/cache-keys.ts +150 -0
- package/src/database/cache/index.ts +44 -0
- package/src/database/cache/query-cache.ts +213 -0
- package/src/database/client.ts +166 -64
- package/src/database/db-config.ts +194 -0
- package/src/database/drizzle/index.ts +66 -0
- package/src/database/drizzle/schema/audit.ts +127 -0
- package/src/database/drizzle/schema/checkpoints.ts +164 -0
- package/src/database/drizzle/schema/conversations.ts +138 -0
- package/src/database/drizzle/schema/documents.ts +157 -0
- package/src/database/drizzle/schema/index.ts +139 -0
- package/src/database/drizzle/schema/memories.ts +127 -0
- package/src/database/drizzle/schema/tasks.ts +129 -0
- package/src/database/health/circuit-breaker.ts +214 -0
- package/src/database/health/health-monitor.ts +224 -0
- package/src/database/health/index.ts +41 -0
- package/src/database/index.ts +157 -0
- package/src/database/migrations/index.ts +52 -0
- package/src/database/migrations/migrator.ts +325 -0
- package/src/database/migrations/versions/001_initial.ts +198 -0
- package/src/database/types.ts +324 -0
- package/src/database/vector/embedding-cache.ts +234 -0
- package/src/database/vector/hnsw-index.ts +452 -0
- package/src/database/vector/index.ts +292 -0
- package/src/database/vector/similarity.ts +198 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Configuration
|
|
3
|
+
*
|
|
4
|
+
* Configuration management for the database layer.
|
|
5
|
+
* Supports both PostgreSQL and SQLite with validation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { homedir } from 'os';
|
|
10
|
+
import { join } from 'path';
|
|
11
|
+
import type { DatabaseConfig, DatabaseDetectionMode } from './types.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Database configuration schema with Zod validation
|
|
15
|
+
*/
|
|
16
|
+
export const databaseConfigSchema = z.object({
|
|
17
|
+
// Detection mode
|
|
18
|
+
DATABASE_TYPE: z
|
|
19
|
+
.enum(['auto', 'postgresql', 'sqlite'])
|
|
20
|
+
.default('auto')
|
|
21
|
+
.describe('Database type selection mode'),
|
|
22
|
+
|
|
23
|
+
// PostgreSQL settings
|
|
24
|
+
DATABASE_URL: z
|
|
25
|
+
.string()
|
|
26
|
+
.url()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Full PostgreSQL connection URL'),
|
|
29
|
+
DB_HOST: z.string().default('localhost').describe('PostgreSQL host'),
|
|
30
|
+
DB_PORT: z.coerce.number().default(5432).describe('PostgreSQL port'),
|
|
31
|
+
DB_USER: z.string().default('familyai').describe('PostgreSQL user'),
|
|
32
|
+
DB_PASSWORD: z.string().default('familyai123').describe('PostgreSQL password'),
|
|
33
|
+
DB_NAME: z.string().default('familyai').describe('PostgreSQL database name'),
|
|
34
|
+
DB_POOL_MAX: z.coerce.number().default(20).describe('Maximum pool connections'),
|
|
35
|
+
DB_POOL_IDLE_TIMEOUT_MS: z.coerce
|
|
36
|
+
.number()
|
|
37
|
+
.default(30000)
|
|
38
|
+
.describe('Pool idle timeout'),
|
|
39
|
+
DB_POOL_CONNECTION_TIMEOUT_MS: z.coerce
|
|
40
|
+
.number()
|
|
41
|
+
.default(5000)
|
|
42
|
+
.describe('Connection timeout'),
|
|
43
|
+
|
|
44
|
+
// SQLite settings
|
|
45
|
+
SQLITE_PATH: z
|
|
46
|
+
.string()
|
|
47
|
+
.optional()
|
|
48
|
+
.describe('SQLite database file path'),
|
|
49
|
+
|
|
50
|
+
// Health monitoring
|
|
51
|
+
DB_HEALTH_CHECK_INTERVAL_MS: z.coerce
|
|
52
|
+
.number()
|
|
53
|
+
.default(30000)
|
|
54
|
+
.describe('Health check interval'),
|
|
55
|
+
DB_CIRCUIT_BREAKER_THRESHOLD: z.coerce
|
|
56
|
+
.number()
|
|
57
|
+
.default(5)
|
|
58
|
+
.describe('Circuit breaker failure threshold'),
|
|
59
|
+
DB_CIRCUIT_BREAKER_TIMEOUT_MS: z.coerce
|
|
60
|
+
.number()
|
|
61
|
+
.default(60000)
|
|
62
|
+
.describe('Circuit breaker reset timeout'),
|
|
63
|
+
|
|
64
|
+
// Cache settings
|
|
65
|
+
DB_CACHE_MAX_SIZE: z.coerce
|
|
66
|
+
.number()
|
|
67
|
+
.default(1000)
|
|
68
|
+
.describe('Maximum cache entries'),
|
|
69
|
+
DB_CACHE_TTL_MS: z.coerce
|
|
70
|
+
.number()
|
|
71
|
+
.default(300000)
|
|
72
|
+
.describe('Cache TTL in milliseconds'),
|
|
73
|
+
|
|
74
|
+
// Vector settings
|
|
75
|
+
VECTOR_DIMENSION: z.coerce
|
|
76
|
+
.number()
|
|
77
|
+
.default(1536)
|
|
78
|
+
.describe('Embedding vector dimension'),
|
|
79
|
+
VECTOR_MIN_SIMILARITY: z.coerce
|
|
80
|
+
.number()
|
|
81
|
+
.default(0.7)
|
|
82
|
+
.describe('Minimum similarity threshold'),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export type RawDatabaseConfig = z.infer<typeof databaseConfigSchema>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Default SQLite database path
|
|
89
|
+
*/
|
|
90
|
+
export function getDefaultSqlitePath(): string {
|
|
91
|
+
return join(homedir(), '.family-ai-agent', 'data', 'family-ai.db');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Build PostgreSQL connection URL from config
|
|
96
|
+
*/
|
|
97
|
+
export function buildPostgresUrl(config: RawDatabaseConfig): string {
|
|
98
|
+
if (config.DATABASE_URL) {
|
|
99
|
+
return config.DATABASE_URL;
|
|
100
|
+
}
|
|
101
|
+
return `postgresql://${config.DB_USER}:${config.DB_PASSWORD}@${config.DB_HOST}:${config.DB_PORT}/${config.DB_NAME}`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Load and validate database configuration from environment
|
|
106
|
+
*/
|
|
107
|
+
export function loadDatabaseConfig(
|
|
108
|
+
env: Record<string, string | undefined> = process.env
|
|
109
|
+
): DatabaseConfig {
|
|
110
|
+
const parsed = databaseConfigSchema.safeParse(env);
|
|
111
|
+
|
|
112
|
+
if (!parsed.success) {
|
|
113
|
+
// Return defaults on validation failure
|
|
114
|
+
const defaults = databaseConfigSchema.parse({});
|
|
115
|
+
return convertToConfig(defaults);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return convertToConfig(parsed.data);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Convert raw config to DatabaseConfig interface
|
|
123
|
+
*/
|
|
124
|
+
function convertToConfig(raw: RawDatabaseConfig): DatabaseConfig {
|
|
125
|
+
return {
|
|
126
|
+
type: raw.DATABASE_TYPE as DatabaseDetectionMode,
|
|
127
|
+
|
|
128
|
+
// PostgreSQL
|
|
129
|
+
postgresUrl: raw.DATABASE_URL,
|
|
130
|
+
postgresHost: raw.DB_HOST,
|
|
131
|
+
postgresPort: raw.DB_PORT,
|
|
132
|
+
postgresUser: raw.DB_USER,
|
|
133
|
+
postgresPassword: raw.DB_PASSWORD,
|
|
134
|
+
postgresDatabase: raw.DB_NAME,
|
|
135
|
+
postgresPoolMax: raw.DB_POOL_MAX,
|
|
136
|
+
postgresIdleTimeoutMs: raw.DB_POOL_IDLE_TIMEOUT_MS,
|
|
137
|
+
postgresConnectionTimeoutMs: raw.DB_POOL_CONNECTION_TIMEOUT_MS,
|
|
138
|
+
|
|
139
|
+
// SQLite
|
|
140
|
+
sqlitePath: raw.SQLITE_PATH ?? getDefaultSqlitePath(),
|
|
141
|
+
|
|
142
|
+
// Health monitoring
|
|
143
|
+
healthCheckIntervalMs: raw.DB_HEALTH_CHECK_INTERVAL_MS,
|
|
144
|
+
circuitBreakerThreshold: raw.DB_CIRCUIT_BREAKER_THRESHOLD,
|
|
145
|
+
circuitBreakerTimeoutMs: raw.DB_CIRCUIT_BREAKER_TIMEOUT_MS,
|
|
146
|
+
|
|
147
|
+
// Cache
|
|
148
|
+
cacheMaxSize: raw.DB_CACHE_MAX_SIZE,
|
|
149
|
+
cacheTtlMs: raw.DB_CACHE_TTL_MS,
|
|
150
|
+
|
|
151
|
+
// Vector
|
|
152
|
+
vectorDimension: raw.VECTOR_DIMENSION,
|
|
153
|
+
vectorMinSimilarity: raw.VECTOR_MIN_SIMILARITY,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Global database configuration instance
|
|
159
|
+
*/
|
|
160
|
+
let dbConfig: DatabaseConfig | null = null;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Get database configuration
|
|
164
|
+
*/
|
|
165
|
+
export function getDatabaseConfig(): DatabaseConfig {
|
|
166
|
+
if (!dbConfig) {
|
|
167
|
+
dbConfig = loadDatabaseConfig();
|
|
168
|
+
}
|
|
169
|
+
return dbConfig;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Reset configuration (for testing)
|
|
174
|
+
*/
|
|
175
|
+
export function resetDatabaseConfig(): void {
|
|
176
|
+
dbConfig = null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Set custom configuration (for testing)
|
|
181
|
+
*/
|
|
182
|
+
export function setDatabaseConfig(config: Partial<DatabaseConfig>): void {
|
|
183
|
+
const defaults = loadDatabaseConfig();
|
|
184
|
+
dbConfig = { ...defaults, ...config };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export default {
|
|
188
|
+
loadDatabaseConfig,
|
|
189
|
+
getDatabaseConfig,
|
|
190
|
+
resetDatabaseConfig,
|
|
191
|
+
setDatabaseConfig,
|
|
192
|
+
getDefaultSqlitePath,
|
|
193
|
+
buildPostgresUrl,
|
|
194
|
+
};
|
|
@@ -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;
|