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.
- package/.letta/settings.local.json +3 -0
- package/dist/cli/index.js +6 -4
- package/dist/cli/index.js.map +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/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +6 -3
- package/src/cli/index.ts +5 -5
- 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
- package/src/index.ts +1 -1
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL Database Adapter
|
|
3
|
+
*
|
|
4
|
+
* Adapter for PostgreSQL with connection pooling and pgvector support.
|
|
5
|
+
*/
|
|
6
|
+
import pg from 'pg';
|
|
7
|
+
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
8
|
+
import { BaseAdapter } from './base-adapter.js';
|
|
9
|
+
import { createLogger } from '../../utils/logger.js';
|
|
10
|
+
import { MemoryError } from '../../utils/errors.js';
|
|
11
|
+
import * as schema from '../drizzle/schema/index.js';
|
|
12
|
+
const { Pool } = pg;
|
|
13
|
+
const logger = createLogger('PostgresAdapter');
|
|
14
|
+
/**
|
|
15
|
+
* PostgreSQL database adapter with Drizzle ORM
|
|
16
|
+
*/
|
|
17
|
+
export class PostgresAdapter extends BaseAdapter {
|
|
18
|
+
type = 'postgresql';
|
|
19
|
+
pool = null;
|
|
20
|
+
drizzleInstance = null;
|
|
21
|
+
connectionString;
|
|
22
|
+
config;
|
|
23
|
+
constructor(connectionString, config) {
|
|
24
|
+
super();
|
|
25
|
+
this.connectionString = connectionString;
|
|
26
|
+
this.config = config;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get Drizzle ORM instance
|
|
30
|
+
*/
|
|
31
|
+
get drizzle() {
|
|
32
|
+
this.ensureInitialized();
|
|
33
|
+
return this.drizzleInstance;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get raw pool (for advanced operations)
|
|
37
|
+
*/
|
|
38
|
+
get rawPool() {
|
|
39
|
+
this.ensureInitialized();
|
|
40
|
+
return this.pool;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Initialize PostgreSQL connection pool
|
|
44
|
+
*/
|
|
45
|
+
async initialize() {
|
|
46
|
+
if (this._isInitialized)
|
|
47
|
+
return;
|
|
48
|
+
try {
|
|
49
|
+
this.pool = new Pool({
|
|
50
|
+
connectionString: this.connectionString,
|
|
51
|
+
max: this.config.postgresPoolMax,
|
|
52
|
+
idleTimeoutMillis: this.config.postgresIdleTimeoutMs,
|
|
53
|
+
connectionTimeoutMillis: this.config.postgresConnectionTimeoutMs,
|
|
54
|
+
});
|
|
55
|
+
// Set up event handlers
|
|
56
|
+
this.pool.on('error', (err) => {
|
|
57
|
+
logger.error('Pool error', { error: err.message });
|
|
58
|
+
});
|
|
59
|
+
this.pool.on('connect', () => {
|
|
60
|
+
logger.debug('New client connected to pool');
|
|
61
|
+
});
|
|
62
|
+
// Create Drizzle instance
|
|
63
|
+
this.drizzleInstance = drizzle(this.pool, {
|
|
64
|
+
schema,
|
|
65
|
+
logger: process.env.NODE_ENV === 'development',
|
|
66
|
+
});
|
|
67
|
+
// Test connection and enable pgvector
|
|
68
|
+
await this.testConnection();
|
|
69
|
+
await this.enablePgVector();
|
|
70
|
+
this._isInitialized = true;
|
|
71
|
+
logger.info('PostgreSQL adapter initialized', {
|
|
72
|
+
host: this.config.postgresHost,
|
|
73
|
+
database: this.config.postgresDatabase,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
78
|
+
logger.error('Failed to initialize PostgreSQL', { error: message });
|
|
79
|
+
throw new MemoryError(`PostgreSQL initialization failed: ${message}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Test database connection
|
|
84
|
+
*/
|
|
85
|
+
async testConnection() {
|
|
86
|
+
const client = await this.pool.connect();
|
|
87
|
+
try {
|
|
88
|
+
await client.query('SELECT 1');
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
client.release();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Enable pgvector extension if not already enabled
|
|
96
|
+
*/
|
|
97
|
+
async enablePgVector() {
|
|
98
|
+
try {
|
|
99
|
+
await this.pool.query('CREATE EXTENSION IF NOT EXISTS vector');
|
|
100
|
+
logger.debug('pgvector extension enabled');
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
logger.warn('Could not enable pgvector extension', {
|
|
104
|
+
error: error instanceof Error ? error.message : 'Unknown'
|
|
105
|
+
});
|
|
106
|
+
// Don't fail - extension might already exist or user might not have permissions
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Execute a raw SQL query
|
|
111
|
+
*/
|
|
112
|
+
async query(sqlText, params) {
|
|
113
|
+
this.ensureInitialized();
|
|
114
|
+
const start = Date.now();
|
|
115
|
+
try {
|
|
116
|
+
const result = await this.pool.query(sqlText, params);
|
|
117
|
+
const duration = Date.now() - start;
|
|
118
|
+
this.logQuery(sqlText, duration, result.rowCount);
|
|
119
|
+
return {
|
|
120
|
+
rows: result.rows,
|
|
121
|
+
rowCount: result.rowCount,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
this.logError(sqlText, error);
|
|
126
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
127
|
+
throw new MemoryError(`Query failed: ${message}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Execute a transaction
|
|
132
|
+
*/
|
|
133
|
+
async transaction(callback) {
|
|
134
|
+
this.ensureInitialized();
|
|
135
|
+
const client = await this.pool.connect();
|
|
136
|
+
try {
|
|
137
|
+
await client.query('BEGIN');
|
|
138
|
+
const transactionClient = {
|
|
139
|
+
query: async (sqlText, params) => {
|
|
140
|
+
const result = await client.query(sqlText, params);
|
|
141
|
+
return {
|
|
142
|
+
rows: result.rows,
|
|
143
|
+
rowCount: result.rowCount,
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
const result = await callback(transactionClient);
|
|
148
|
+
await client.query('COMMIT');
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
await client.query('ROLLBACK');
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
client.release();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Check database health
|
|
161
|
+
*/
|
|
162
|
+
async healthCheck() {
|
|
163
|
+
try {
|
|
164
|
+
const result = await this.query('SELECT 1 as ok');
|
|
165
|
+
return result.rows.length > 0 && result.rows[0].ok === 1;
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get connection pool statistics
|
|
173
|
+
*/
|
|
174
|
+
getPoolStats() {
|
|
175
|
+
if (!this.pool) {
|
|
176
|
+
return { total: 0, idle: 0, waiting: 0 };
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
total: this.pool.totalCount,
|
|
180
|
+
idle: this.pool.idleCount,
|
|
181
|
+
waiting: this.pool.waitingCount,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Close all connections
|
|
186
|
+
*/
|
|
187
|
+
async close() {
|
|
188
|
+
if (this.pool) {
|
|
189
|
+
await this.pool.end();
|
|
190
|
+
this.pool = null;
|
|
191
|
+
this.drizzleInstance = null;
|
|
192
|
+
this._isInitialized = false;
|
|
193
|
+
logger.info('PostgreSQL pool closed');
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Execute vector similarity search
|
|
198
|
+
*/
|
|
199
|
+
async vectorSearch(table, embeddingColumn, queryEmbedding, options = {}) {
|
|
200
|
+
const { limit = 5, minSimilarity = 0.7, filters = {}, selectColumns = ['*'], } = options;
|
|
201
|
+
const embeddingStr = `[${queryEmbedding.join(',')}]`;
|
|
202
|
+
// Build WHERE clause
|
|
203
|
+
const whereConditions = [`1 - (${embeddingColumn} <=> $1::vector) >= $2`];
|
|
204
|
+
const params = [embeddingStr, minSimilarity];
|
|
205
|
+
let paramIndex = 3;
|
|
206
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
207
|
+
whereConditions.push(`${key} = $${paramIndex}`);
|
|
208
|
+
params.push(value);
|
|
209
|
+
paramIndex++;
|
|
210
|
+
}
|
|
211
|
+
params.push(limit);
|
|
212
|
+
const columns = selectColumns.join(', ');
|
|
213
|
+
const sql = `
|
|
214
|
+
SELECT ${columns}, 1 - (${embeddingColumn} <=> $1::vector) as similarity
|
|
215
|
+
FROM ${table}
|
|
216
|
+
WHERE ${whereConditions.join(' AND ')}
|
|
217
|
+
ORDER BY similarity DESC
|
|
218
|
+
LIMIT $${paramIndex}
|
|
219
|
+
`;
|
|
220
|
+
const result = await this.query(sql, params);
|
|
221
|
+
return result.rows;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
export default PostgresAdapter;
|
|
225
|
+
//# sourceMappingURL=postgres-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-adapter.js","sourceRoot":"","sources":["../../../src/database/adapters/postgres-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Database Adapter
|
|
3
|
+
*
|
|
4
|
+
* Adapter for SQLite using better-sqlite3 for embedded database support.
|
|
5
|
+
* Provides zero-config database that works out of the box.
|
|
6
|
+
*/
|
|
7
|
+
import Database from 'better-sqlite3';
|
|
8
|
+
import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
9
|
+
import { BaseAdapter } from './base-adapter.js';
|
|
10
|
+
import type { QueryResult, TransactionClient, DatabaseConfig } from '../types.js';
|
|
11
|
+
import * as schema from '../drizzle/schema/index.js';
|
|
12
|
+
/**
|
|
13
|
+
* SQLite database adapter with Drizzle ORM
|
|
14
|
+
*/
|
|
15
|
+
export declare class SQLiteAdapter extends BaseAdapter {
|
|
16
|
+
readonly type: "sqlite";
|
|
17
|
+
private db;
|
|
18
|
+
private drizzleInstance;
|
|
19
|
+
private dbPath;
|
|
20
|
+
private config;
|
|
21
|
+
constructor(dbPath: string, config: DatabaseConfig);
|
|
22
|
+
/**
|
|
23
|
+
* Get Drizzle ORM instance
|
|
24
|
+
*/
|
|
25
|
+
get drizzle(): BetterSQLite3Database<typeof schema>;
|
|
26
|
+
/**
|
|
27
|
+
* Get raw database (for advanced operations)
|
|
28
|
+
*/
|
|
29
|
+
get rawDb(): Database.Database;
|
|
30
|
+
/**
|
|
31
|
+
* Initialize SQLite database
|
|
32
|
+
*/
|
|
33
|
+
initialize(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Initialize database schema
|
|
36
|
+
*/
|
|
37
|
+
private initializeSchema;
|
|
38
|
+
/**
|
|
39
|
+
* Execute a raw SQL query
|
|
40
|
+
*/
|
|
41
|
+
query<T extends Record<string, any> = Record<string, any>>(sqlText: string, params?: unknown[]): Promise<QueryResult<T>>;
|
|
42
|
+
/**
|
|
43
|
+
* Execute a transaction
|
|
44
|
+
*/
|
|
45
|
+
transaction<T>(callback: (client: TransactionClient) => Promise<T>): Promise<T>;
|
|
46
|
+
/**
|
|
47
|
+
* Check database health
|
|
48
|
+
*/
|
|
49
|
+
healthCheck(): Promise<boolean>;
|
|
50
|
+
/**
|
|
51
|
+
* Close database connection
|
|
52
|
+
*/
|
|
53
|
+
close(): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Get database file path
|
|
56
|
+
*/
|
|
57
|
+
getPath(): string;
|
|
58
|
+
/**
|
|
59
|
+
* Get database file size in bytes
|
|
60
|
+
*/
|
|
61
|
+
getFileSize(): number;
|
|
62
|
+
/**
|
|
63
|
+
* Vacuum database to reclaim space
|
|
64
|
+
*/
|
|
65
|
+
vacuum(): void;
|
|
66
|
+
/**
|
|
67
|
+
* Checkpoint WAL to main database
|
|
68
|
+
*/
|
|
69
|
+
checkpoint(): void;
|
|
70
|
+
}
|
|
71
|
+
export default SQLiteAdapter;
|
|
72
|
+
//# sourceMappingURL=sqlite-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-adapter.d.ts","sourceRoot":"","sources":["../../../src/database/adapters/sqlite-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAIxE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EACjB,cAAc,EACf,MAAM,aAAa,CAAC;AAIrB,OAAO,KAAK,MAAM,MAAM,4BAA4B,CAAC;AAIrD;;GAEG;AACH,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAElC,OAAO,CAAC,EAAE,CAAkC;IAC5C,OAAO,CAAC,eAAe,CAAqD;IAC5E,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAiB;gBAEnB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc;IAMlD;;OAEG;IACH,IAAI,OAAO,IAAI,qBAAqB,CAAC,OAAO,MAAM,CAAC,CAGlD;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAG7B;IAED;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuCjC;;OAEG;YACW,gBAAgB;IA+J9B;;OAEG;IACG,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC7D,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAyD1B;;OAEG;IACG,WAAW,CAAC,CAAC,EACjB,QAAQ,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC,GAClD,OAAO,CAAC,CAAC,CAAC;IAuBb;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IASrC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5B;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACH,WAAW,IAAI,MAAM;IAWrB;;OAEG;IACH,MAAM,IAAI,IAAI;IAMd;;OAEG;IACH,UAAU,IAAI,IAAI;CAKnB;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Database Adapter
|
|
3
|
+
*
|
|
4
|
+
* Adapter for SQLite using better-sqlite3 for embedded database support.
|
|
5
|
+
* Provides zero-config database that works out of the box.
|
|
6
|
+
*/
|
|
7
|
+
import Database from 'better-sqlite3';
|
|
8
|
+
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
9
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
10
|
+
import { dirname } from 'path';
|
|
11
|
+
import { BaseAdapter } from './base-adapter.js';
|
|
12
|
+
import { createLogger } from '../../utils/logger.js';
|
|
13
|
+
import { MemoryError } from '../../utils/errors.js';
|
|
14
|
+
import * as schema from '../drizzle/schema/index.js';
|
|
15
|
+
const logger = createLogger('SQLiteAdapter');
|
|
16
|
+
/**
|
|
17
|
+
* SQLite database adapter with Drizzle ORM
|
|
18
|
+
*/
|
|
19
|
+
export class SQLiteAdapter extends BaseAdapter {
|
|
20
|
+
type = 'sqlite';
|
|
21
|
+
db = null;
|
|
22
|
+
drizzleInstance = null;
|
|
23
|
+
dbPath;
|
|
24
|
+
config;
|
|
25
|
+
constructor(dbPath, config) {
|
|
26
|
+
super();
|
|
27
|
+
this.dbPath = dbPath;
|
|
28
|
+
this.config = config;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get Drizzle ORM instance
|
|
32
|
+
*/
|
|
33
|
+
get drizzle() {
|
|
34
|
+
this.ensureInitialized();
|
|
35
|
+
return this.drizzleInstance;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get raw database (for advanced operations)
|
|
39
|
+
*/
|
|
40
|
+
get rawDb() {
|
|
41
|
+
this.ensureInitialized();
|
|
42
|
+
return this.db;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Initialize SQLite database
|
|
46
|
+
*/
|
|
47
|
+
async initialize() {
|
|
48
|
+
if (this._isInitialized)
|
|
49
|
+
return;
|
|
50
|
+
try {
|
|
51
|
+
// Ensure directory exists
|
|
52
|
+
const dir = dirname(this.dbPath);
|
|
53
|
+
if (!existsSync(dir)) {
|
|
54
|
+
mkdirSync(dir, { recursive: true });
|
|
55
|
+
logger.debug('Created database directory', { path: dir });
|
|
56
|
+
}
|
|
57
|
+
// Open database
|
|
58
|
+
this.db = new Database(this.dbPath);
|
|
59
|
+
// Configure for better performance
|
|
60
|
+
this.db.pragma('journal_mode = WAL');
|
|
61
|
+
this.db.pragma('synchronous = NORMAL');
|
|
62
|
+
this.db.pragma('cache_size = -64000'); // 64MB cache
|
|
63
|
+
this.db.pragma('foreign_keys = ON');
|
|
64
|
+
this.db.pragma('temp_store = MEMORY');
|
|
65
|
+
// Create Drizzle instance
|
|
66
|
+
this.drizzleInstance = drizzle(this.db, {
|
|
67
|
+
schema,
|
|
68
|
+
logger: process.env.NODE_ENV === 'development',
|
|
69
|
+
});
|
|
70
|
+
// Initialize schema
|
|
71
|
+
await this.initializeSchema();
|
|
72
|
+
this._isInitialized = true;
|
|
73
|
+
logger.info('SQLite adapter initialized', { path: this.dbPath });
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
77
|
+
logger.error('Failed to initialize SQLite', { error: message });
|
|
78
|
+
throw new MemoryError(`SQLite initialization failed: ${message}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Initialize database schema
|
|
83
|
+
*/
|
|
84
|
+
async initializeSchema() {
|
|
85
|
+
const statements = [
|
|
86
|
+
// Conversations
|
|
87
|
+
`CREATE TABLE IF NOT EXISTS conversations (
|
|
88
|
+
id TEXT PRIMARY KEY,
|
|
89
|
+
thread_id TEXT NOT NULL,
|
|
90
|
+
user_id TEXT,
|
|
91
|
+
created_at INTEGER NOT NULL,
|
|
92
|
+
updated_at INTEGER NOT NULL
|
|
93
|
+
)`,
|
|
94
|
+
`CREATE INDEX IF NOT EXISTS idx_conversations_thread ON conversations(thread_id)`,
|
|
95
|
+
`CREATE INDEX IF NOT EXISTS idx_conversations_user ON conversations(user_id)`,
|
|
96
|
+
// Messages
|
|
97
|
+
`CREATE TABLE IF NOT EXISTS messages (
|
|
98
|
+
id TEXT PRIMARY KEY,
|
|
99
|
+
conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
|
|
100
|
+
role TEXT NOT NULL,
|
|
101
|
+
content TEXT NOT NULL,
|
|
102
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
103
|
+
created_at INTEGER NOT NULL
|
|
104
|
+
)`,
|
|
105
|
+
`CREATE INDEX IF NOT EXISTS idx_messages_conversation ON messages(conversation_id)`,
|
|
106
|
+
// Long-term memories
|
|
107
|
+
`CREATE TABLE IF NOT EXISTS long_term_memories (
|
|
108
|
+
id TEXT PRIMARY KEY,
|
|
109
|
+
user_id TEXT,
|
|
110
|
+
memory_type TEXT NOT NULL,
|
|
111
|
+
content TEXT NOT NULL,
|
|
112
|
+
embedding TEXT NOT NULL,
|
|
113
|
+
importance REAL NOT NULL DEFAULT 0.5,
|
|
114
|
+
access_count INTEGER NOT NULL DEFAULT 0,
|
|
115
|
+
last_accessed INTEGER,
|
|
116
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
117
|
+
created_at INTEGER NOT NULL,
|
|
118
|
+
updated_at INTEGER NOT NULL
|
|
119
|
+
)`,
|
|
120
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_user ON long_term_memories(user_id)`,
|
|
121
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_type ON long_term_memories(memory_type)`,
|
|
122
|
+
// Documents
|
|
123
|
+
`CREATE TABLE IF NOT EXISTS documents (
|
|
124
|
+
id TEXT PRIMARY KEY,
|
|
125
|
+
user_id TEXT,
|
|
126
|
+
filename TEXT NOT NULL,
|
|
127
|
+
file_type TEXT,
|
|
128
|
+
file_size INTEGER,
|
|
129
|
+
content TEXT,
|
|
130
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
131
|
+
created_at INTEGER NOT NULL
|
|
132
|
+
)`,
|
|
133
|
+
`CREATE INDEX IF NOT EXISTS idx_documents_user ON documents(user_id)`,
|
|
134
|
+
// Document chunks
|
|
135
|
+
`CREATE TABLE IF NOT EXISTS document_chunks (
|
|
136
|
+
id TEXT PRIMARY KEY,
|
|
137
|
+
document_id TEXT NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
|
|
138
|
+
chunk_index INTEGER NOT NULL,
|
|
139
|
+
content TEXT NOT NULL,
|
|
140
|
+
embedding TEXT NOT NULL,
|
|
141
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
142
|
+
created_at INTEGER NOT NULL
|
|
143
|
+
)`,
|
|
144
|
+
`CREATE INDEX IF NOT EXISTS idx_chunks_document ON document_chunks(document_id)`,
|
|
145
|
+
// Checkpoints
|
|
146
|
+
`CREATE TABLE IF NOT EXISTS checkpoints (
|
|
147
|
+
thread_id TEXT NOT NULL,
|
|
148
|
+
checkpoint_ns TEXT NOT NULL DEFAULT '',
|
|
149
|
+
checkpoint_id TEXT NOT NULL,
|
|
150
|
+
parent_checkpoint_id TEXT,
|
|
151
|
+
type TEXT,
|
|
152
|
+
checkpoint TEXT NOT NULL,
|
|
153
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
154
|
+
created_at INTEGER NOT NULL,
|
|
155
|
+
PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id)
|
|
156
|
+
)`,
|
|
157
|
+
// Checkpoint writes
|
|
158
|
+
`CREATE TABLE IF NOT EXISTS checkpoint_writes (
|
|
159
|
+
thread_id TEXT NOT NULL,
|
|
160
|
+
checkpoint_ns TEXT NOT NULL DEFAULT '',
|
|
161
|
+
checkpoint_id TEXT NOT NULL,
|
|
162
|
+
task_id TEXT NOT NULL,
|
|
163
|
+
idx INTEGER NOT NULL,
|
|
164
|
+
channel TEXT NOT NULL,
|
|
165
|
+
type TEXT,
|
|
166
|
+
value TEXT,
|
|
167
|
+
created_at INTEGER NOT NULL,
|
|
168
|
+
PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id, task_id, idx)
|
|
169
|
+
)`,
|
|
170
|
+
// Audit logs
|
|
171
|
+
`CREATE TABLE IF NOT EXISTS audit_logs (
|
|
172
|
+
id TEXT PRIMARY KEY,
|
|
173
|
+
user_id TEXT,
|
|
174
|
+
agent_id TEXT,
|
|
175
|
+
action_type TEXT NOT NULL,
|
|
176
|
+
action_details TEXT NOT NULL DEFAULT '{}',
|
|
177
|
+
input_hash TEXT,
|
|
178
|
+
output_hash TEXT,
|
|
179
|
+
status TEXT NOT NULL DEFAULT 'success',
|
|
180
|
+
error_message TEXT,
|
|
181
|
+
execution_time_ms INTEGER,
|
|
182
|
+
ip_address TEXT,
|
|
183
|
+
user_agent TEXT,
|
|
184
|
+
success INTEGER NOT NULL DEFAULT 1,
|
|
185
|
+
created_at INTEGER NOT NULL
|
|
186
|
+
)`,
|
|
187
|
+
`CREATE INDEX IF NOT EXISTS idx_audit_user ON audit_logs(user_id)`,
|
|
188
|
+
`CREATE INDEX IF NOT EXISTS idx_audit_action ON audit_logs(action_type)`,
|
|
189
|
+
`CREATE INDEX IF NOT EXISTS idx_audit_created ON audit_logs(created_at)`,
|
|
190
|
+
// Tasks
|
|
191
|
+
`CREATE TABLE IF NOT EXISTS tasks (
|
|
192
|
+
id TEXT PRIMARY KEY,
|
|
193
|
+
user_id TEXT,
|
|
194
|
+
task_type TEXT NOT NULL,
|
|
195
|
+
priority INTEGER NOT NULL DEFAULT 0,
|
|
196
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
197
|
+
payload TEXT NOT NULL DEFAULT '{}',
|
|
198
|
+
result TEXT,
|
|
199
|
+
error_message TEXT,
|
|
200
|
+
scheduled_at INTEGER,
|
|
201
|
+
started_at INTEGER,
|
|
202
|
+
completed_at INTEGER,
|
|
203
|
+
retry_count INTEGER NOT NULL DEFAULT 0,
|
|
204
|
+
max_retries INTEGER NOT NULL DEFAULT 3,
|
|
205
|
+
created_at INTEGER NOT NULL,
|
|
206
|
+
updated_at INTEGER NOT NULL
|
|
207
|
+
)`,
|
|
208
|
+
`CREATE INDEX IF NOT EXISTS idx_tasks_user ON tasks(user_id)`,
|
|
209
|
+
`CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status)`,
|
|
210
|
+
// Schema version tracking
|
|
211
|
+
`CREATE TABLE IF NOT EXISTS schema_versions (
|
|
212
|
+
version INTEGER PRIMARY KEY,
|
|
213
|
+
name TEXT NOT NULL,
|
|
214
|
+
applied_at INTEGER NOT NULL,
|
|
215
|
+
checksum TEXT
|
|
216
|
+
)`,
|
|
217
|
+
];
|
|
218
|
+
for (const statement of statements) {
|
|
219
|
+
try {
|
|
220
|
+
this.db.exec(statement);
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
// Ignore errors for existing objects
|
|
224
|
+
const message = error instanceof Error ? error.message : '';
|
|
225
|
+
if (!message.includes('already exists')) {
|
|
226
|
+
throw error;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
logger.debug('SQLite schema initialized');
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Execute a raw SQL query
|
|
234
|
+
*/
|
|
235
|
+
async query(sqlText, params) {
|
|
236
|
+
this.ensureInitialized();
|
|
237
|
+
const start = Date.now();
|
|
238
|
+
try {
|
|
239
|
+
// Convert PostgreSQL placeholders to SQLite
|
|
240
|
+
const sqliteSql = this.convertToSqlite(sqlText);
|
|
241
|
+
const sqliteParams = params ?? [];
|
|
242
|
+
const isSelect = this.isSelectQuery(sqlText);
|
|
243
|
+
const hasReturning = this.hasReturning(sqlText);
|
|
244
|
+
let rows = [];
|
|
245
|
+
let rowCount = 0;
|
|
246
|
+
if (isSelect) {
|
|
247
|
+
const stmt = this.db.prepare(sqliteSql);
|
|
248
|
+
rows = stmt.all(...sqliteParams);
|
|
249
|
+
rowCount = rows.length;
|
|
250
|
+
}
|
|
251
|
+
else if (hasReturning) {
|
|
252
|
+
// Handle INSERT/UPDATE/DELETE with RETURNING
|
|
253
|
+
const returning = this.extractReturning(sqlText);
|
|
254
|
+
const tableName = this.extractTableName(sqlText);
|
|
255
|
+
// Remove RETURNING clause for SQLite
|
|
256
|
+
const sqlWithoutReturning = sqliteSql.replace(/\s+RETURNING\s+.+$/i, '');
|
|
257
|
+
const stmt = this.db.prepare(sqlWithoutReturning);
|
|
258
|
+
const info = stmt.run(...sqliteParams);
|
|
259
|
+
rowCount = info.changes;
|
|
260
|
+
if (returning && tableName && info.lastInsertRowid) {
|
|
261
|
+
// Fetch the inserted/updated row
|
|
262
|
+
const selectStmt = this.db.prepare(`SELECT ${returning} FROM ${tableName} WHERE rowid = ?`);
|
|
263
|
+
const row = selectStmt.get(info.lastInsertRowid);
|
|
264
|
+
if (row) {
|
|
265
|
+
rows = [row];
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
const stmt = this.db.prepare(sqliteSql);
|
|
271
|
+
const info = stmt.run(...sqliteParams);
|
|
272
|
+
rowCount = info.changes;
|
|
273
|
+
}
|
|
274
|
+
const duration = Date.now() - start;
|
|
275
|
+
this.logQuery(sqlText, duration, rowCount);
|
|
276
|
+
return { rows, rowCount };
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
this.logError(sqlText, error);
|
|
280
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
281
|
+
throw new MemoryError(`Query failed: ${message}`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Execute a transaction
|
|
286
|
+
*/
|
|
287
|
+
async transaction(callback) {
|
|
288
|
+
this.ensureInitialized();
|
|
289
|
+
const transactionClient = {
|
|
290
|
+
query: async (sqlText, params) => {
|
|
291
|
+
return this.query(sqlText, params);
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
try {
|
|
295
|
+
this.db.exec('BEGIN');
|
|
296
|
+
const result = await callback(transactionClient);
|
|
297
|
+
this.db.exec('COMMIT');
|
|
298
|
+
return result;
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
this.db.exec('ROLLBACK');
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Check database health
|
|
307
|
+
*/
|
|
308
|
+
async healthCheck() {
|
|
309
|
+
try {
|
|
310
|
+
const result = await this.query('SELECT 1 as ok');
|
|
311
|
+
return result.rows.length > 0 && result.rows[0].ok === 1;
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Close database connection
|
|
319
|
+
*/
|
|
320
|
+
async close() {
|
|
321
|
+
if (this.db) {
|
|
322
|
+
this.db.close();
|
|
323
|
+
this.db = null;
|
|
324
|
+
this.drizzleInstance = null;
|
|
325
|
+
this._isInitialized = false;
|
|
326
|
+
logger.info('SQLite database closed');
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Get database file path
|
|
331
|
+
*/
|
|
332
|
+
getPath() {
|
|
333
|
+
return this.dbPath;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Get database file size in bytes
|
|
337
|
+
*/
|
|
338
|
+
getFileSize() {
|
|
339
|
+
if (!this.db)
|
|
340
|
+
return 0;
|
|
341
|
+
try {
|
|
342
|
+
const stats = this.db.pragma('page_count');
|
|
343
|
+
const pageSize = this.db.pragma('page_size');
|
|
344
|
+
return (stats[0]?.page_count ?? 0) * (pageSize[0]?.page_size ?? 4096);
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
return 0;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Vacuum database to reclaim space
|
|
352
|
+
*/
|
|
353
|
+
vacuum() {
|
|
354
|
+
this.ensureInitialized();
|
|
355
|
+
this.db.exec('VACUUM');
|
|
356
|
+
logger.debug('Database vacuumed');
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Checkpoint WAL to main database
|
|
360
|
+
*/
|
|
361
|
+
checkpoint() {
|
|
362
|
+
this.ensureInitialized();
|
|
363
|
+
this.db.pragma('wal_checkpoint(TRUNCATE)');
|
|
364
|
+
logger.debug('WAL checkpoint completed');
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
export default SQLiteAdapter;
|
|
368
|
+
//# sourceMappingURL=sqlite-adapter.js.map
|