audrey 0.16.1 → 0.20.0
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/LICENSE +21 -21
- package/README.md +146 -724
- package/dist/mcp-server/config.d.ts +20 -0
- package/dist/mcp-server/config.d.ts.map +1 -0
- package/dist/mcp-server/config.js +125 -0
- package/dist/mcp-server/config.js.map +1 -0
- package/dist/mcp-server/index.d.ts +100 -0
- package/dist/mcp-server/index.d.ts.map +1 -0
- package/dist/mcp-server/index.js +1113 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/src/adaptive.d.ts +7 -0
- package/dist/src/adaptive.d.ts.map +1 -0
- package/dist/src/adaptive.js +49 -0
- package/dist/src/adaptive.js.map +1 -0
- package/dist/src/affect.d.ts +19 -0
- package/dist/src/affect.d.ts.map +1 -0
- package/dist/src/affect.js +72 -0
- package/dist/src/affect.js.map +1 -0
- package/dist/src/audrey.d.ts +140 -0
- package/dist/src/audrey.d.ts.map +1 -0
- package/dist/src/audrey.js +564 -0
- package/dist/src/audrey.js.map +1 -0
- package/dist/src/capsule.d.ts +68 -0
- package/dist/src/capsule.d.ts.map +1 -0
- package/dist/src/capsule.js +311 -0
- package/dist/src/capsule.js.map +1 -0
- package/dist/src/causal.d.ts +28 -0
- package/dist/src/causal.d.ts.map +1 -0
- package/dist/src/causal.js +65 -0
- package/dist/src/causal.js.map +1 -0
- package/dist/src/confidence.d.ts +12 -0
- package/dist/src/confidence.d.ts.map +1 -0
- package/dist/src/confidence.js +63 -0
- package/dist/src/confidence.js.map +1 -0
- package/dist/src/consolidate.d.ts +8 -0
- package/dist/src/consolidate.d.ts.map +1 -0
- package/dist/src/consolidate.js +218 -0
- package/dist/src/consolidate.js.map +1 -0
- package/dist/src/context.d.ts +3 -0
- package/dist/src/context.d.ts.map +1 -0
- package/dist/src/context.js +19 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/db.d.ts +12 -0
- package/dist/src/db.d.ts.map +1 -0
- package/dist/src/db.js +380 -0
- package/dist/src/db.js.map +1 -0
- package/dist/src/decay.d.ts +7 -0
- package/dist/src/decay.d.ts.map +1 -0
- package/dist/src/decay.js +68 -0
- package/dist/src/decay.js.map +1 -0
- package/dist/src/embedding.d.ts +57 -0
- package/dist/src/embedding.d.ts.map +1 -0
- package/dist/src/embedding.js +254 -0
- package/dist/src/embedding.js.map +1 -0
- package/dist/src/encode.d.ts +15 -0
- package/dist/src/encode.d.ts.map +1 -0
- package/dist/src/encode.js +36 -0
- package/dist/src/encode.js.map +1 -0
- package/dist/src/events.d.ts +69 -0
- package/dist/src/events.d.ts.map +1 -0
- package/dist/src/events.js +149 -0
- package/dist/src/events.js.map +1 -0
- package/dist/src/export.d.ts +3 -0
- package/dist/src/export.d.ts.map +1 -0
- package/dist/src/export.js +46 -0
- package/dist/src/export.js.map +1 -0
- package/dist/src/forget.d.ts +11 -0
- package/dist/src/forget.d.ts.map +1 -0
- package/dist/src/forget.js +105 -0
- package/dist/src/forget.js.map +1 -0
- package/dist/src/fts.d.ts +34 -0
- package/dist/src/fts.d.ts.map +1 -0
- package/dist/src/fts.js +117 -0
- package/dist/src/fts.js.map +1 -0
- package/dist/src/hybrid-recall.d.ts +37 -0
- package/dist/src/hybrid-recall.d.ts.map +1 -0
- package/dist/src/hybrid-recall.js +213 -0
- package/dist/src/hybrid-recall.js.map +1 -0
- package/dist/src/import.d.ts +4 -0
- package/dist/src/import.d.ts.map +1 -0
- package/dist/src/import.js +127 -0
- package/dist/src/import.js.map +1 -0
- package/dist/src/index.d.ts +22 -0
- package/dist/src/index.d.ts.map +1 -0
- package/{src → dist/src}/index.js +5 -13
- package/dist/src/index.js.map +1 -0
- package/dist/src/interference.d.ts +13 -0
- package/dist/src/interference.d.ts.map +1 -0
- package/dist/src/interference.js +45 -0
- package/dist/src/interference.js.map +1 -0
- package/dist/src/introspect.d.ts +4 -0
- package/dist/src/introspect.d.ts.map +1 -0
- package/dist/src/introspect.js +40 -0
- package/dist/src/introspect.js.map +1 -0
- package/dist/src/llm.d.ts +38 -0
- package/dist/src/llm.d.ts.map +1 -0
- package/dist/src/llm.js +167 -0
- package/dist/src/llm.js.map +1 -0
- package/dist/src/migrate.d.ts +6 -0
- package/dist/src/migrate.d.ts.map +1 -0
- package/dist/src/migrate.js +51 -0
- package/dist/src/migrate.js.map +1 -0
- package/dist/src/promote.d.ts +40 -0
- package/dist/src/promote.d.ts.map +1 -0
- package/dist/src/promote.js +200 -0
- package/dist/src/promote.js.map +1 -0
- package/dist/src/prompts.d.ts +16 -0
- package/dist/src/prompts.d.ts.map +1 -0
- package/{src → dist/src}/prompts.js +172 -203
- package/dist/src/prompts.js.map +1 -0
- package/dist/src/recall.d.ts +9 -0
- package/dist/src/recall.d.ts.map +1 -0
- package/dist/src/recall.js +432 -0
- package/dist/src/recall.js.map +1 -0
- package/dist/src/redact.d.ts +27 -0
- package/dist/src/redact.d.ts.map +1 -0
- package/dist/src/redact.js +228 -0
- package/dist/src/redact.js.map +1 -0
- package/dist/src/rollback.d.ts +8 -0
- package/dist/src/rollback.d.ts.map +1 -0
- package/dist/src/rollback.js +33 -0
- package/dist/src/rollback.js.map +1 -0
- package/dist/src/routes.d.ts +7 -0
- package/dist/src/routes.d.ts.map +1 -0
- package/dist/src/routes.js +226 -0
- package/dist/src/routes.js.map +1 -0
- package/dist/src/rules-compiler.d.ts +20 -0
- package/dist/src/rules-compiler.d.ts.map +1 -0
- package/dist/src/rules-compiler.js +143 -0
- package/dist/src/rules-compiler.js.map +1 -0
- package/dist/src/server.d.ts +12 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/server.js +22 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/tool-trace.d.ts +37 -0
- package/dist/src/tool-trace.d.ts.map +1 -0
- package/dist/src/tool-trace.js +142 -0
- package/dist/src/tool-trace.js.map +1 -0
- package/dist/src/types.d.ts +446 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +6 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/ulid.d.ts +3 -0
- package/dist/src/ulid.d.ts.map +1 -0
- package/dist/src/ulid.js +11 -0
- package/dist/src/ulid.js.map +1 -0
- package/dist/src/utils.d.ts +10 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +41 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/src/validate.d.ts +22 -0
- package/dist/src/validate.d.ts.map +1 -0
- package/dist/src/validate.js +109 -0
- package/dist/src/validate.js.map +1 -0
- package/docs/assets/benchmarks/local-benchmark.svg +45 -0
- package/docs/assets/benchmarks/operations-benchmark.svg +45 -0
- package/docs/assets/benchmarks/published-memory-standards.svg +50 -0
- package/docs/benchmarking.md +151 -0
- package/docs/production-readiness.md +124 -0
- package/examples/fintech-ops-demo.js +67 -0
- package/examples/healthcare-ops-demo.js +67 -0
- package/examples/stripe-demo.js +105 -0
- package/package.json +53 -13
- package/mcp-server/config.js +0 -80
- package/mcp-server/index.js +0 -729
- package/src/adaptive.js +0 -53
- package/src/affect.js +0 -64
- package/src/audrey.js +0 -604
- package/src/causal.js +0 -95
- package/src/confidence.js +0 -120
- package/src/consolidate.js +0 -265
- package/src/context.js +0 -15
- package/src/db.js +0 -370
- package/src/decay.js +0 -84
- package/src/embedding.js +0 -256
- package/src/encode.js +0 -63
- package/src/export.js +0 -67
- package/src/forget.js +0 -111
- package/src/import.js +0 -245
- package/src/interference.js +0 -51
- package/src/introspect.js +0 -48
- package/src/llm.js +0 -246
- package/src/migrate.js +0 -58
- package/src/recall.js +0 -352
- package/src/rollback.js +0 -42
- package/src/ulid.js +0 -18
- package/src/utils.js +0 -38
- package/src/validate.js +0 -172
package/src/db.js
DELETED
|
@@ -1,370 +0,0 @@
|
|
|
1
|
-
import Database from 'better-sqlite3';
|
|
2
|
-
import * as sqliteVec from 'sqlite-vec';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { mkdirSync, existsSync } from 'node:fs';
|
|
5
|
-
|
|
6
|
-
const SCHEMA = `
|
|
7
|
-
CREATE TABLE IF NOT EXISTS episodes (
|
|
8
|
-
id TEXT PRIMARY KEY,
|
|
9
|
-
content TEXT NOT NULL,
|
|
10
|
-
embedding BLOB,
|
|
11
|
-
source TEXT NOT NULL CHECK(source IN ('direct-observation','told-by-user','tool-result','inference','model-generated')),
|
|
12
|
-
source_reliability REAL NOT NULL,
|
|
13
|
-
salience REAL DEFAULT 0.5,
|
|
14
|
-
context TEXT DEFAULT '{}',
|
|
15
|
-
affect TEXT DEFAULT '{}',
|
|
16
|
-
tags TEXT,
|
|
17
|
-
causal_trigger TEXT,
|
|
18
|
-
causal_consequence TEXT,
|
|
19
|
-
created_at TEXT NOT NULL,
|
|
20
|
-
embedding_model TEXT,
|
|
21
|
-
embedding_version TEXT,
|
|
22
|
-
supersedes TEXT,
|
|
23
|
-
superseded_by TEXT,
|
|
24
|
-
consolidated INTEGER DEFAULT 0,
|
|
25
|
-
private INTEGER DEFAULT 0,
|
|
26
|
-
FOREIGN KEY (supersedes) REFERENCES episodes(id)
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
CREATE TABLE IF NOT EXISTS semantics (
|
|
30
|
-
id TEXT PRIMARY KEY,
|
|
31
|
-
content TEXT NOT NULL,
|
|
32
|
-
embedding BLOB,
|
|
33
|
-
state TEXT DEFAULT 'active' CHECK(state IN ('active','disputed','superseded','context_dependent','dormant','rolled_back')),
|
|
34
|
-
conditions TEXT,
|
|
35
|
-
evidence_episode_ids TEXT,
|
|
36
|
-
evidence_count INTEGER DEFAULT 0,
|
|
37
|
-
supporting_count INTEGER DEFAULT 0,
|
|
38
|
-
contradicting_count INTEGER DEFAULT 0,
|
|
39
|
-
source_type_diversity INTEGER DEFAULT 0,
|
|
40
|
-
consolidation_checkpoint TEXT,
|
|
41
|
-
embedding_model TEXT,
|
|
42
|
-
embedding_version TEXT,
|
|
43
|
-
consolidation_model TEXT,
|
|
44
|
-
consolidation_prompt_hash TEXT,
|
|
45
|
-
created_at TEXT NOT NULL,
|
|
46
|
-
last_reinforced_at TEXT,
|
|
47
|
-
retrieval_count INTEGER DEFAULT 0,
|
|
48
|
-
challenge_count INTEGER DEFAULT 0,
|
|
49
|
-
interference_count INTEGER DEFAULT 0,
|
|
50
|
-
salience REAL DEFAULT 0.5
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
CREATE TABLE IF NOT EXISTS procedures (
|
|
54
|
-
id TEXT PRIMARY KEY,
|
|
55
|
-
content TEXT NOT NULL,
|
|
56
|
-
embedding BLOB,
|
|
57
|
-
state TEXT DEFAULT 'active' CHECK(state IN ('active','disputed','superseded','context_dependent','dormant','rolled_back')),
|
|
58
|
-
trigger_conditions TEXT,
|
|
59
|
-
evidence_episode_ids TEXT,
|
|
60
|
-
success_count INTEGER DEFAULT 0,
|
|
61
|
-
failure_count INTEGER DEFAULT 0,
|
|
62
|
-
embedding_model TEXT,
|
|
63
|
-
embedding_version TEXT,
|
|
64
|
-
created_at TEXT NOT NULL,
|
|
65
|
-
last_reinforced_at TEXT,
|
|
66
|
-
retrieval_count INTEGER DEFAULT 0,
|
|
67
|
-
interference_count INTEGER DEFAULT 0,
|
|
68
|
-
salience REAL DEFAULT 0.5
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
CREATE TABLE IF NOT EXISTS causal_links (
|
|
72
|
-
id TEXT PRIMARY KEY,
|
|
73
|
-
cause_id TEXT NOT NULL,
|
|
74
|
-
effect_id TEXT NOT NULL,
|
|
75
|
-
link_type TEXT DEFAULT 'causal' CHECK(link_type IN ('causal','correlational','temporal')),
|
|
76
|
-
mechanism TEXT,
|
|
77
|
-
confidence REAL,
|
|
78
|
-
evidence_count INTEGER DEFAULT 1,
|
|
79
|
-
created_at TEXT NOT NULL
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
CREATE TABLE IF NOT EXISTS contradictions (
|
|
83
|
-
id TEXT PRIMARY KEY,
|
|
84
|
-
claim_a_id TEXT NOT NULL,
|
|
85
|
-
claim_b_id TEXT NOT NULL,
|
|
86
|
-
claim_a_type TEXT NOT NULL,
|
|
87
|
-
claim_b_type TEXT NOT NULL,
|
|
88
|
-
state TEXT DEFAULT 'open' CHECK(state IN ('open','resolved','context_dependent','reopened')),
|
|
89
|
-
resolution TEXT,
|
|
90
|
-
resolved_at TEXT,
|
|
91
|
-
reopened_at TEXT,
|
|
92
|
-
reopen_evidence_id TEXT,
|
|
93
|
-
created_at TEXT NOT NULL
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
CREATE TABLE IF NOT EXISTS consolidation_runs (
|
|
97
|
-
id TEXT PRIMARY KEY,
|
|
98
|
-
checkpoint_cursor TEXT,
|
|
99
|
-
input_episode_ids TEXT,
|
|
100
|
-
output_memory_ids TEXT,
|
|
101
|
-
confidence_deltas TEXT,
|
|
102
|
-
consolidation_model TEXT,
|
|
103
|
-
consolidation_prompt_hash TEXT,
|
|
104
|
-
started_at TEXT,
|
|
105
|
-
completed_at TEXT,
|
|
106
|
-
status TEXT DEFAULT 'running' CHECK(status IN ('running','completed','failed','rolled_back'))
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
CREATE TABLE IF NOT EXISTS audrey_config (
|
|
110
|
-
key TEXT PRIMARY KEY,
|
|
111
|
-
value TEXT NOT NULL
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
CREATE TABLE IF NOT EXISTS consolidation_metrics (
|
|
115
|
-
id TEXT PRIMARY KEY,
|
|
116
|
-
run_id TEXT NOT NULL,
|
|
117
|
-
min_cluster_size INTEGER NOT NULL,
|
|
118
|
-
similarity_threshold REAL NOT NULL,
|
|
119
|
-
episodes_evaluated INTEGER NOT NULL,
|
|
120
|
-
clusters_found INTEGER NOT NULL,
|
|
121
|
-
principles_extracted INTEGER NOT NULL,
|
|
122
|
-
created_at TEXT NOT NULL,
|
|
123
|
-
FOREIGN KEY (run_id) REFERENCES consolidation_runs(id)
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
CREATE INDEX IF NOT EXISTS idx_episodes_created ON episodes(created_at);
|
|
127
|
-
CREATE INDEX IF NOT EXISTS idx_episodes_consolidated ON episodes(consolidated);
|
|
128
|
-
CREATE INDEX IF NOT EXISTS idx_episodes_source ON episodes(source);
|
|
129
|
-
CREATE INDEX IF NOT EXISTS idx_semantics_state ON semantics(state);
|
|
130
|
-
CREATE INDEX IF NOT EXISTS idx_procedures_state ON procedures(state);
|
|
131
|
-
CREATE INDEX IF NOT EXISTS idx_contradictions_state ON contradictions(state);
|
|
132
|
-
CREATE INDEX IF NOT EXISTS idx_consolidation_status ON consolidation_runs(status);
|
|
133
|
-
`;
|
|
134
|
-
|
|
135
|
-
export function createVec0Tables(db, dimensions) {
|
|
136
|
-
db.exec(`
|
|
137
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS vec_episodes USING vec0(
|
|
138
|
-
id text primary key,
|
|
139
|
-
embedding float[${dimensions}] distance_metric=cosine,
|
|
140
|
-
source text,
|
|
141
|
-
consolidated integer
|
|
142
|
-
);
|
|
143
|
-
`);
|
|
144
|
-
db.exec(`
|
|
145
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS vec_semantics USING vec0(
|
|
146
|
-
id text primary key,
|
|
147
|
-
embedding float[${dimensions}] distance_metric=cosine,
|
|
148
|
-
state text
|
|
149
|
-
);
|
|
150
|
-
`);
|
|
151
|
-
db.exec(`
|
|
152
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS vec_procedures USING vec0(
|
|
153
|
-
id text primary key,
|
|
154
|
-
embedding float[${dimensions}] distance_metric=cosine,
|
|
155
|
-
state text
|
|
156
|
-
);
|
|
157
|
-
`);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export function dropVec0Tables(db) {
|
|
161
|
-
db.exec('DROP TABLE IF EXISTS vec_episodes');
|
|
162
|
-
db.exec('DROP TABLE IF EXISTS vec_semantics');
|
|
163
|
-
db.exec('DROP TABLE IF EXISTS vec_procedures');
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function migrateTable(db, { source, target, selectCols, insertCols, placeholders, transform, dimensions }) {
|
|
167
|
-
const count = db.prepare(`SELECT COUNT(*) as c FROM ${target}`).get().c;
|
|
168
|
-
if (count > 0) return;
|
|
169
|
-
|
|
170
|
-
const rows = db.prepare(`SELECT ${selectCols} FROM ${source} WHERE embedding IS NOT NULL`).all();
|
|
171
|
-
if (rows.length === 0) return;
|
|
172
|
-
|
|
173
|
-
const expectedBytes = dimensions ? dimensions * 4 : null;
|
|
174
|
-
const insert = db.prepare(`INSERT INTO ${target}(${insertCols}) VALUES (${placeholders})`);
|
|
175
|
-
const tx = db.transaction(() => {
|
|
176
|
-
for (const row of rows) {
|
|
177
|
-
if (expectedBytes && row.embedding.byteLength !== expectedBytes) continue;
|
|
178
|
-
insert.run(...transform(row));
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
tx();
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function migrateEmbeddingsToVec0(db, dimensions) {
|
|
185
|
-
migrateTable(db, {
|
|
186
|
-
source: 'episodes',
|
|
187
|
-
target: 'vec_episodes',
|
|
188
|
-
selectCols: 'id, embedding, source, consolidated',
|
|
189
|
-
insertCols: 'id, embedding, source, consolidated',
|
|
190
|
-
placeholders: '?, ?, ?, ?',
|
|
191
|
-
transform: (row) => [row.id, row.embedding, row.source, BigInt(row.consolidated ?? 0)],
|
|
192
|
-
dimensions,
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
migrateTable(db, {
|
|
196
|
-
source: 'semantics',
|
|
197
|
-
target: 'vec_semantics',
|
|
198
|
-
selectCols: 'id, embedding, state',
|
|
199
|
-
insertCols: 'id, embedding, state',
|
|
200
|
-
placeholders: '?, ?, ?',
|
|
201
|
-
transform: (row) => [row.id, row.embedding, row.state],
|
|
202
|
-
dimensions,
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
migrateTable(db, {
|
|
206
|
-
source: 'procedures',
|
|
207
|
-
target: 'vec_procedures',
|
|
208
|
-
selectCols: 'id, embedding, state',
|
|
209
|
-
insertCols: 'id, embedding, state',
|
|
210
|
-
placeholders: '?, ?, ?',
|
|
211
|
-
transform: (row) => [row.id, row.embedding, row.state],
|
|
212
|
-
dimensions,
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function getEmbeddingSyncCounts(db) {
|
|
217
|
-
let vecEpisodes = 0;
|
|
218
|
-
let vecSemantics = 0;
|
|
219
|
-
let vecProcedures = 0;
|
|
220
|
-
|
|
221
|
-
try {
|
|
222
|
-
vecEpisodes = db.prepare('SELECT COUNT(*) as c FROM vec_episodes').get().c;
|
|
223
|
-
vecSemantics = db.prepare('SELECT COUNT(*) as c FROM vec_semantics').get().c;
|
|
224
|
-
vecProcedures = db.prepare('SELECT COUNT(*) as c FROM vec_procedures').get().c;
|
|
225
|
-
} catch {
|
|
226
|
-
// vec tables may not exist yet
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const episodes = db.prepare('SELECT COUNT(*) as c FROM episodes WHERE embedding IS NOT NULL').get().c;
|
|
230
|
-
const semantics = db.prepare('SELECT COUNT(*) as c FROM semantics WHERE embedding IS NOT NULL').get().c;
|
|
231
|
-
const procedures = db.prepare('SELECT COUNT(*) as c FROM procedures WHERE embedding IS NOT NULL').get().c;
|
|
232
|
-
|
|
233
|
-
return {
|
|
234
|
-
episodes,
|
|
235
|
-
vecEpisodes,
|
|
236
|
-
semantics,
|
|
237
|
-
vecSemantics,
|
|
238
|
-
procedures,
|
|
239
|
-
vecProcedures,
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
function addColumnIfMissing(db, table, column, definition) {
|
|
244
|
-
const columns = db.pragma(`table_info(${table})`);
|
|
245
|
-
const exists = columns.some(col => col.name === column);
|
|
246
|
-
if (!exists) {
|
|
247
|
-
db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const SCHEMA_VERSION = 7;
|
|
252
|
-
|
|
253
|
-
const MIGRATIONS = [
|
|
254
|
-
{ version: 1, up(db) { addColumnIfMissing(db, 'episodes', 'context', "TEXT DEFAULT '{}'"); } },
|
|
255
|
-
{ version: 2, up(db) { addColumnIfMissing(db, 'episodes', 'affect', "TEXT DEFAULT '{}'"); } },
|
|
256
|
-
{ version: 3, up(db) { addColumnIfMissing(db, 'semantics', 'interference_count', 'INTEGER DEFAULT 0'); } },
|
|
257
|
-
{ version: 4, up(db) { addColumnIfMissing(db, 'semantics', 'salience', 'REAL DEFAULT 0.5'); } },
|
|
258
|
-
{ version: 5, up(db) { addColumnIfMissing(db, 'procedures', 'interference_count', 'INTEGER DEFAULT 0'); } },
|
|
259
|
-
{ version: 6, up(db) { addColumnIfMissing(db, 'procedures', 'salience', 'REAL DEFAULT 0.5'); } },
|
|
260
|
-
{ version: 7, up(db) { addColumnIfMissing(db, 'episodes', 'private', 'INTEGER DEFAULT 0'); } },
|
|
261
|
-
];
|
|
262
|
-
|
|
263
|
-
function runMigrations(db) {
|
|
264
|
-
const row = db.prepare("SELECT value FROM audrey_config WHERE key = 'schema_version'").get();
|
|
265
|
-
const currentVersion = row ? Number(row.value) : 0;
|
|
266
|
-
|
|
267
|
-
if (currentVersion >= SCHEMA_VERSION) return;
|
|
268
|
-
|
|
269
|
-
const pending = MIGRATIONS.filter(m => m.version > currentVersion);
|
|
270
|
-
for (const migration of pending) {
|
|
271
|
-
migration.up(db);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
db.prepare(
|
|
275
|
-
`INSERT INTO audrey_config (key, value) VALUES ('schema_version', ?)
|
|
276
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value`
|
|
277
|
-
).run(String(SCHEMA_VERSION));
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* @param {string} dataDir
|
|
282
|
-
* @param {{ dimensions?: number }} [options]
|
|
283
|
-
* @returns {{ db: import('better-sqlite3').Database, migrated: boolean }}
|
|
284
|
-
*/
|
|
285
|
-
export function createDatabase(dataDir, options = {}) {
|
|
286
|
-
let { dimensions } = options;
|
|
287
|
-
let migrated = false;
|
|
288
|
-
|
|
289
|
-
mkdirSync(dataDir, { recursive: true });
|
|
290
|
-
const dbPath = join(dataDir, 'audrey.db');
|
|
291
|
-
const db = new Database(dbPath);
|
|
292
|
-
db.pragma('journal_mode = WAL');
|
|
293
|
-
db.pragma('foreign_keys = ON');
|
|
294
|
-
db.pragma('busy_timeout = 5000');
|
|
295
|
-
db.exec(SCHEMA);
|
|
296
|
-
runMigrations(db);
|
|
297
|
-
|
|
298
|
-
if (dimensions == null) {
|
|
299
|
-
const stored = db.prepare("SELECT value FROM audrey_config WHERE key = 'dimensions'").get();
|
|
300
|
-
if (stored) {
|
|
301
|
-
dimensions = parseInt(stored.value, 10);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
if (dimensions != null) {
|
|
306
|
-
if (!Number.isInteger(dimensions) || dimensions <= 0) {
|
|
307
|
-
throw new Error(`dimensions must be a positive integer, got: ${dimensions}`);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
sqliteVec.load(db);
|
|
311
|
-
|
|
312
|
-
const existing = db.prepare(
|
|
313
|
-
"SELECT value FROM audrey_config WHERE key = 'dimensions'"
|
|
314
|
-
).get();
|
|
315
|
-
|
|
316
|
-
if (existing) {
|
|
317
|
-
const storedDims = parseInt(existing.value, 10);
|
|
318
|
-
if (storedDims !== dimensions) {
|
|
319
|
-
dropVec0Tables(db);
|
|
320
|
-
db.prepare(
|
|
321
|
-
"UPDATE audrey_config SET value = ? WHERE key = 'dimensions'"
|
|
322
|
-
).run(String(dimensions));
|
|
323
|
-
migrated = true;
|
|
324
|
-
}
|
|
325
|
-
} else {
|
|
326
|
-
db.prepare(
|
|
327
|
-
"INSERT INTO audrey_config (key, value) VALUES ('dimensions', ?)"
|
|
328
|
-
).run(String(dimensions));
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
createVec0Tables(db, dimensions);
|
|
332
|
-
|
|
333
|
-
if (!migrated) {
|
|
334
|
-
migrateEmbeddingsToVec0(db, dimensions);
|
|
335
|
-
const sync = getEmbeddingSyncCounts(db);
|
|
336
|
-
if (
|
|
337
|
-
sync.episodes !== sync.vecEpisodes
|
|
338
|
-
|| sync.semantics !== sync.vecSemantics
|
|
339
|
-
|| sync.procedures !== sync.vecProcedures
|
|
340
|
-
) {
|
|
341
|
-
// Legacy blobs exist but could not be copied cleanly into vec0.
|
|
342
|
-
// Mark the store for lazy re-embedding so the next encode/recall repairs it.
|
|
343
|
-
migrated = true;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
return { db, migrated };
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
export function readStoredDimensions(dataDir) {
|
|
352
|
-
const dbPath = join(dataDir, 'audrey.db');
|
|
353
|
-
if (!existsSync(dbPath)) return null;
|
|
354
|
-
const db = new Database(dbPath, { readonly: true });
|
|
355
|
-
try {
|
|
356
|
-
const row = db.prepare("SELECT value FROM audrey_config WHERE key = 'dimensions'").get();
|
|
357
|
-
return row ? parseInt(row.value, 10) : null;
|
|
358
|
-
} catch (err) {
|
|
359
|
-
if (err.message?.includes('no such table')) return null;
|
|
360
|
-
throw err;
|
|
361
|
-
} finally {
|
|
362
|
-
db.close();
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
export function closeDatabase(db) {
|
|
367
|
-
if (db && db.open) {
|
|
368
|
-
db.close();
|
|
369
|
-
}
|
|
370
|
-
}
|
package/src/decay.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { computeConfidence, DEFAULT_HALF_LIVES, salienceModifier } from './confidence.js';
|
|
2
|
-
import { interferenceModifier } from './interference.js';
|
|
3
|
-
import { daysBetween } from './utils.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @param {import('better-sqlite3').Database} db
|
|
7
|
-
* @param {{ dormantThreshold?: number }} [options]
|
|
8
|
-
* @returns {{ totalEvaluated: number, transitionedToDormant: number, timestamp: string }}
|
|
9
|
-
*/
|
|
10
|
-
export function applyDecay(db, { dormantThreshold = 0.1, halfLives } = {}) {
|
|
11
|
-
const now = new Date();
|
|
12
|
-
let totalEvaluated = 0;
|
|
13
|
-
let transitionedToDormant = 0;
|
|
14
|
-
|
|
15
|
-
const semantics = db.prepare(`
|
|
16
|
-
SELECT id, supporting_count, contradicting_count, created_at,
|
|
17
|
-
last_reinforced_at, retrieval_count, interference_count, salience
|
|
18
|
-
FROM semantics WHERE state = 'active'
|
|
19
|
-
`).all();
|
|
20
|
-
|
|
21
|
-
const markDormantSem = db.prepare('UPDATE semantics SET state = ? WHERE id = ?');
|
|
22
|
-
|
|
23
|
-
for (const sem of semantics) {
|
|
24
|
-
totalEvaluated++;
|
|
25
|
-
const ageDays = daysBetween(sem.created_at, now);
|
|
26
|
-
const daysSinceRetrieval = sem.last_reinforced_at
|
|
27
|
-
? daysBetween(sem.last_reinforced_at, now)
|
|
28
|
-
: ageDays;
|
|
29
|
-
|
|
30
|
-
let confidence = computeConfidence({
|
|
31
|
-
sourceType: 'tool-result',
|
|
32
|
-
supportingCount: sem.supporting_count || 0,
|
|
33
|
-
contradictingCount: sem.contradicting_count || 0,
|
|
34
|
-
ageDays,
|
|
35
|
-
halfLifeDays: halfLives?.semantic ?? DEFAULT_HALF_LIVES.semantic,
|
|
36
|
-
retrievalCount: sem.retrieval_count || 0,
|
|
37
|
-
daysSinceRetrieval,
|
|
38
|
-
});
|
|
39
|
-
confidence *= interferenceModifier(sem.interference_count || 0);
|
|
40
|
-
confidence *= salienceModifier(sem.salience ?? 0.5);
|
|
41
|
-
confidence = Math.max(0, Math.min(1, confidence));
|
|
42
|
-
|
|
43
|
-
if (confidence < dormantThreshold) {
|
|
44
|
-
markDormantSem.run('dormant', sem.id);
|
|
45
|
-
transitionedToDormant++;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const procedures = db.prepare(`
|
|
50
|
-
SELECT id, success_count, failure_count, created_at,
|
|
51
|
-
last_reinforced_at, retrieval_count, interference_count, salience
|
|
52
|
-
FROM procedures WHERE state = 'active'
|
|
53
|
-
`).all();
|
|
54
|
-
|
|
55
|
-
const markDormantProc = db.prepare('UPDATE procedures SET state = ? WHERE id = ?');
|
|
56
|
-
|
|
57
|
-
for (const proc of procedures) {
|
|
58
|
-
totalEvaluated++;
|
|
59
|
-
const ageDays = daysBetween(proc.created_at, now);
|
|
60
|
-
const daysSinceRetrieval = proc.last_reinforced_at
|
|
61
|
-
? daysBetween(proc.last_reinforced_at, now)
|
|
62
|
-
: ageDays;
|
|
63
|
-
|
|
64
|
-
let confidence = computeConfidence({
|
|
65
|
-
sourceType: 'tool-result',
|
|
66
|
-
supportingCount: proc.success_count || 0,
|
|
67
|
-
contradictingCount: proc.failure_count || 0,
|
|
68
|
-
ageDays,
|
|
69
|
-
halfLifeDays: halfLives?.procedural ?? DEFAULT_HALF_LIVES.procedural,
|
|
70
|
-
retrievalCount: proc.retrieval_count || 0,
|
|
71
|
-
daysSinceRetrieval,
|
|
72
|
-
});
|
|
73
|
-
confidence *= interferenceModifier(proc.interference_count || 0);
|
|
74
|
-
confidence *= salienceModifier(proc.salience ?? 0.5);
|
|
75
|
-
confidence = Math.max(0, Math.min(1, confidence));
|
|
76
|
-
|
|
77
|
-
if (confidence < dormantThreshold) {
|
|
78
|
-
markDormantProc.run('dormant', proc.id);
|
|
79
|
-
transitionedToDormant++;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return { totalEvaluated, transitionedToDormant, timestamp: now.toISOString() };
|
|
84
|
-
}
|
package/src/embedding.js
DELETED
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {Object} EmbeddingProvider
|
|
5
|
-
* @property {number} dimensions
|
|
6
|
-
* @property {string} modelName
|
|
7
|
-
* @property {string} modelVersion
|
|
8
|
-
* @property {(text: string) => Promise<number[]>} embed
|
|
9
|
-
* @property {(texts: string[]) => Promise<number[][]>} embedBatch
|
|
10
|
-
* @property {(vector: number[]) => Buffer} vectorToBuffer
|
|
11
|
-
* @property {(buffer: Buffer) => number[]} bufferToVector
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
/** @implements {EmbeddingProvider} */
|
|
15
|
-
export class MockEmbeddingProvider {
|
|
16
|
-
constructor({ dimensions = 64 } = {}) {
|
|
17
|
-
this.dimensions = dimensions;
|
|
18
|
-
this.modelName = 'mock-embedding';
|
|
19
|
-
this.modelVersion = '1.0.0';
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async embed(text) {
|
|
23
|
-
const hash = createHash('sha256').update(text).digest();
|
|
24
|
-
const vector = new Array(this.dimensions);
|
|
25
|
-
for (let i = 0; i < this.dimensions; i++) {
|
|
26
|
-
vector[i] = (hash[i % hash.length] / 255) * 2 - 1;
|
|
27
|
-
}
|
|
28
|
-
const magnitude = Math.sqrt(vector.reduce((sum, v) => sum + v * v, 0));
|
|
29
|
-
return vector.map(v => v / magnitude);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async embedBatch(texts) {
|
|
33
|
-
return Promise.all(texts.map(t => this.embed(t)));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
vectorToBuffer(vector) {
|
|
37
|
-
return Buffer.from(new Float32Array(vector).buffer);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
bufferToVector(buffer) {
|
|
41
|
-
return Array.from(new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / 4));
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** @implements {EmbeddingProvider} */
|
|
46
|
-
export class OpenAIEmbeddingProvider {
|
|
47
|
-
constructor({ apiKey, model = 'text-embedding-3-small', dimensions = 1536, timeout = 30000 } = {}) {
|
|
48
|
-
this.apiKey = apiKey || process.env.OPENAI_API_KEY;
|
|
49
|
-
this.model = model;
|
|
50
|
-
this.dimensions = dimensions;
|
|
51
|
-
this.timeout = timeout;
|
|
52
|
-
this.modelName = model;
|
|
53
|
-
this.modelVersion = 'latest';
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async embed(text) {
|
|
57
|
-
const controller = new AbortController();
|
|
58
|
-
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
59
|
-
try {
|
|
60
|
-
const response = await fetch('https://api.openai.com/v1/embeddings', {
|
|
61
|
-
method: 'POST',
|
|
62
|
-
headers: {
|
|
63
|
-
'Authorization': `Bearer ${this.apiKey}`,
|
|
64
|
-
'Content-Type': 'application/json',
|
|
65
|
-
},
|
|
66
|
-
body: JSON.stringify({ input: text, model: this.model, dimensions: this.dimensions }),
|
|
67
|
-
signal: controller.signal,
|
|
68
|
-
});
|
|
69
|
-
if (!response.ok) throw new Error(`OpenAI embedding failed: ${response.status}`);
|
|
70
|
-
const data = await response.json();
|
|
71
|
-
return data.data[0].embedding;
|
|
72
|
-
} finally {
|
|
73
|
-
clearTimeout(timer);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async embedBatch(texts) {
|
|
78
|
-
const controller = new AbortController();
|
|
79
|
-
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
80
|
-
try {
|
|
81
|
-
const response = await fetch('https://api.openai.com/v1/embeddings', {
|
|
82
|
-
method: 'POST',
|
|
83
|
-
headers: {
|
|
84
|
-
'Authorization': `Bearer ${this.apiKey}`,
|
|
85
|
-
'Content-Type': 'application/json',
|
|
86
|
-
},
|
|
87
|
-
body: JSON.stringify({ input: texts, model: this.model, dimensions: this.dimensions }),
|
|
88
|
-
signal: controller.signal,
|
|
89
|
-
});
|
|
90
|
-
if (!response.ok) throw new Error(`OpenAI embedding failed: ${response.status}`);
|
|
91
|
-
const data = await response.json();
|
|
92
|
-
return data.data.map(d => d.embedding);
|
|
93
|
-
} finally {
|
|
94
|
-
clearTimeout(timer);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
vectorToBuffer(vector) {
|
|
99
|
-
return Buffer.from(new Float32Array(vector).buffer);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
bufferToVector(buffer) {
|
|
103
|
-
return Array.from(new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / 4));
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** @implements {EmbeddingProvider} */
|
|
108
|
-
export class LocalEmbeddingProvider {
|
|
109
|
-
constructor({ model = 'Xenova/all-MiniLM-L6-v2', device = 'gpu', batchSize = 64 } = {}) {
|
|
110
|
-
this.model = model;
|
|
111
|
-
this.dimensions = 384;
|
|
112
|
-
this.modelName = model;
|
|
113
|
-
this.modelVersion = '1.0.0';
|
|
114
|
-
this.device = device;
|
|
115
|
-
this.batchSize = batchSize;
|
|
116
|
-
this._pipeline = null;
|
|
117
|
-
this._readyPromise = null;
|
|
118
|
-
this._actualDevice = null;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
ready() {
|
|
122
|
-
if (!this._readyPromise) {
|
|
123
|
-
this._readyPromise = (async () => {
|
|
124
|
-
const { pipeline } = await import('@huggingface/transformers');
|
|
125
|
-
try {
|
|
126
|
-
this._pipeline = await pipeline('feature-extraction', this.model, {
|
|
127
|
-
dtype: 'fp32', device: this.device,
|
|
128
|
-
});
|
|
129
|
-
this._actualDevice = this.device;
|
|
130
|
-
} catch {
|
|
131
|
-
this._pipeline = await pipeline('feature-extraction', this.model, {
|
|
132
|
-
dtype: 'fp32', device: 'cpu',
|
|
133
|
-
});
|
|
134
|
-
this._actualDevice = 'cpu';
|
|
135
|
-
}
|
|
136
|
-
})();
|
|
137
|
-
}
|
|
138
|
-
return this._readyPromise;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async embed(text) {
|
|
142
|
-
await this.ready();
|
|
143
|
-
const output = await this._pipeline(text, { pooling: 'mean', normalize: true });
|
|
144
|
-
return Array.from(output.data);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async embedBatch(texts) {
|
|
148
|
-
if (texts.length === 0) return [];
|
|
149
|
-
await this.ready();
|
|
150
|
-
const results = [];
|
|
151
|
-
for (let i = 0; i < texts.length; i += this.batchSize) {
|
|
152
|
-
const chunk = texts.slice(i, i + this.batchSize);
|
|
153
|
-
const output = await this._pipeline(chunk, { pooling: 'mean', normalize: true });
|
|
154
|
-
results.push(...output.tolist());
|
|
155
|
-
}
|
|
156
|
-
return results;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
vectorToBuffer(vector) {
|
|
160
|
-
return Buffer.from(new Float32Array(vector).buffer);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
bufferToVector(buffer) {
|
|
164
|
-
return Array.from(new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / 4));
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/** @implements {EmbeddingProvider} */
|
|
169
|
-
export class GeminiEmbeddingProvider {
|
|
170
|
-
constructor({ apiKey, model = 'gemini-embedding-001', timeout = 30000 } = {}) {
|
|
171
|
-
this.apiKey = apiKey || process.env.GOOGLE_API_KEY;
|
|
172
|
-
this.model = model;
|
|
173
|
-
this.dimensions = 3072;
|
|
174
|
-
this.timeout = timeout;
|
|
175
|
-
this.modelName = model;
|
|
176
|
-
this.modelVersion = 'latest';
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
async embed(text) {
|
|
180
|
-
if (!this.apiKey) throw new Error('Gemini embedding requires GOOGLE_API_KEY');
|
|
181
|
-
const controller = new AbortController();
|
|
182
|
-
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
183
|
-
try {
|
|
184
|
-
const response = await fetch(
|
|
185
|
-
`https://generativelanguage.googleapis.com/v1beta/models/${this.model}:embedContent?key=${this.apiKey}`,
|
|
186
|
-
{
|
|
187
|
-
method: 'POST',
|
|
188
|
-
headers: { 'Content-Type': 'application/json' },
|
|
189
|
-
body: JSON.stringify({ model: `models/${this.model}`, content: { parts: [{ text }] } }),
|
|
190
|
-
signal: controller.signal,
|
|
191
|
-
}
|
|
192
|
-
);
|
|
193
|
-
if (!response.ok) throw new Error(`Gemini embedding failed: ${response.status}`);
|
|
194
|
-
const data = await response.json();
|
|
195
|
-
return data.embedding.values;
|
|
196
|
-
} finally {
|
|
197
|
-
clearTimeout(timer);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
async embedBatch(texts) {
|
|
202
|
-
if (texts.length === 0) return [];
|
|
203
|
-
if (!this.apiKey) throw new Error('Gemini embedding requires GOOGLE_API_KEY');
|
|
204
|
-
const results = [];
|
|
205
|
-
for (let i = 0; i < texts.length; i += 100) {
|
|
206
|
-
const chunk = texts.slice(i, i + 100);
|
|
207
|
-
const controller = new AbortController();
|
|
208
|
-
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
209
|
-
try {
|
|
210
|
-
const response = await fetch(
|
|
211
|
-
`https://generativelanguage.googleapis.com/v1beta/models/${this.model}:batchEmbedContents?key=${this.apiKey}`,
|
|
212
|
-
{
|
|
213
|
-
method: 'POST',
|
|
214
|
-
headers: { 'Content-Type': 'application/json' },
|
|
215
|
-
body: JSON.stringify({
|
|
216
|
-
requests: chunk.map(text => ({
|
|
217
|
-
model: `models/${this.model}`,
|
|
218
|
-
content: { parts: [{ text }] },
|
|
219
|
-
})),
|
|
220
|
-
}),
|
|
221
|
-
signal: controller.signal,
|
|
222
|
-
}
|
|
223
|
-
);
|
|
224
|
-
if (!response.ok) throw new Error(`Gemini batch embedding failed: ${response.status}`);
|
|
225
|
-
const data = await response.json();
|
|
226
|
-
results.push(...data.embeddings.map(e => e.values));
|
|
227
|
-
} finally {
|
|
228
|
-
clearTimeout(timer);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return results;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
vectorToBuffer(vector) {
|
|
235
|
-
return Buffer.from(new Float32Array(vector).buffer);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
bufferToVector(buffer) {
|
|
239
|
-
return Array.from(new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / 4));
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export function createEmbeddingProvider(config) {
|
|
244
|
-
switch (config.provider) {
|
|
245
|
-
case 'mock':
|
|
246
|
-
return new MockEmbeddingProvider(config);
|
|
247
|
-
case 'openai':
|
|
248
|
-
return new OpenAIEmbeddingProvider(config);
|
|
249
|
-
case 'local':
|
|
250
|
-
return new LocalEmbeddingProvider(config);
|
|
251
|
-
case 'gemini':
|
|
252
|
-
return new GeminiEmbeddingProvider(config);
|
|
253
|
-
default:
|
|
254
|
-
throw new Error(`Unknown embedding provider: ${config.provider}. Valid: mock, openai, local, gemini`);
|
|
255
|
-
}
|
|
256
|
-
}
|