audrey 0.5.0 → 0.5.1

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/README.md CHANGED
@@ -398,6 +398,7 @@ brain.on('contradiction', ({ episodeId, contradictionId, semanticId, resolution
398
398
  brain.on('consolidation', ({ runId, principlesExtracted }) => { ... });
399
399
  brain.on('decay', ({ totalEvaluated, transitionedToDormant }) => { ... });
400
400
  brain.on('rollback', ({ runId, rolledBackMemories }) => { ... });
401
+ brain.on('migration', ({ episodes, semantics, procedures }) => { ... });
401
402
  brain.on('error', (err) => { ... });
402
403
  ```
403
404
 
@@ -429,10 +430,14 @@ src/
429
430
  rollback.js Undo consolidation runs.
430
431
  utils.js Date math, safe JSON parse.
431
432
  validate.js KNN validation + LLM contradiction detection.
433
+ migrate.js Dimension migration re-embedding.
434
+ adaptive.js Adaptive consolidation parameter suggestions.
435
+ export.js Memory export (JSON snapshots).
436
+ import.js Memory import with re-embedding.
432
437
  index.js Barrel export.
433
438
 
434
439
  mcp-server/
435
- index.js MCP tool server (5 tools, stdio transport) + CLI subcommands.
440
+ index.js MCP tool server (7 tools, stdio transport) + CLI subcommands.
436
441
  config.js Shared config (env var parsing, install arg builder).
437
442
  ```
438
443
 
@@ -456,7 +461,7 @@ All mutations use SQLite transactions. CHECK constraints enforce valid states an
456
461
  ## Running Tests
457
462
 
458
463
  ```bash
459
- npm test # 208 tests across 17 files
464
+ npm test # 243 tests across 22 files
460
465
  npm run test:watch
461
466
  ```
462
467
 
@@ -544,7 +549,7 @@ Demonstrates the full pipeline: encode 3 rate-limit observations → consolidate
544
549
  - [x] Auto-consolidation scheduling (`startAutoConsolidate` / `stopAutoConsolidate`)
545
550
  - [x] Consolidation metrics tracking (per-run params and results)
546
551
  - [x] Adaptive consolidation parameter suggestions based on historical yield
547
- - [x] 220+ tests across 20 test files
552
+ - [x] 243 tests across 22 test files
548
553
 
549
554
  ### v0.4.0 — Type Safety & Developer Experience
550
555
 
@@ -1,7 +1,7 @@
1
1
  import { homedir } from 'node:os';
2
2
  import { join } from 'node:path';
3
3
 
4
- export const VERSION = '0.5.0';
4
+ export const VERSION = '0.5.1';
5
5
  export const SERVER_NAME = 'audrey-memory';
6
6
  export const DEFAULT_DATA_DIR = join(homedir(), '.audrey', 'data');
7
7
 
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { z } from 'zod';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "audrey",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Biological memory architecture for AI agents — encode, consolidate, and recall memories with confidence decay, contradiction detection, and causal graphs",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/audrey.js CHANGED
@@ -13,6 +13,7 @@ import { buildContextResolutionPrompt } from './prompts.js';
13
13
  import { exportMemories } from './export.js';
14
14
  import { importMemories } from './import.js';
15
15
  import { suggestConsolidationParams as suggestParamsFn } from './adaptive.js';
16
+ import { reembedAll } from './migrate.js';
16
17
 
17
18
  /**
18
19
  * @typedef {'direct-observation' | 'told-by-user' | 'tool-result' | 'inference' | 'model-generated'} SourceType
@@ -99,7 +100,9 @@ export class Audrey extends EventEmitter {
99
100
  this.agent = agent;
100
101
  this.dataDir = dataDir;
101
102
  this.embeddingProvider = createEmbeddingProvider(embedding);
102
- this.db = createDatabase(dataDir, { dimensions: this.embeddingProvider.dimensions });
103
+ const { db, migrated } = createDatabase(dataDir, { dimensions: this.embeddingProvider.dimensions });
104
+ this.db = db;
105
+ this._migrationPending = migrated;
103
106
  this.llmProvider = llm ? createLLMProvider(llm) : null;
104
107
  this.confidenceConfig = {
105
108
  weights: confidence.weights,
@@ -113,6 +116,13 @@ export class Audrey extends EventEmitter {
113
116
  this._autoConsolidateTimer = null;
114
117
  }
115
118
 
119
+ async _ensureMigrated() {
120
+ if (!this._migrationPending) return;
121
+ const counts = await reembedAll(this.db, this.embeddingProvider);
122
+ this._migrationPending = false;
123
+ this.emit('migration', counts);
124
+ }
125
+
116
126
  _emitValidation(id, params) {
117
127
  validateMemory(this.db, this.embeddingProvider, { id, ...params }, {
118
128
  llmProvider: this.llmProvider,
@@ -142,6 +152,7 @@ export class Audrey extends EventEmitter {
142
152
  * @returns {Promise<string>}
143
153
  */
144
154
  async encode(params) {
155
+ await this._ensureMigrated();
145
156
  const id = await encodeEpisode(this.db, this.embeddingProvider, params);
146
157
  this.emit('encode', { id, ...params });
147
158
  this._emitValidation(id, params);
@@ -153,6 +164,7 @@ export class Audrey extends EventEmitter {
153
164
  * @returns {Promise<string[]>}
154
165
  */
155
166
  async encodeBatch(paramsList) {
167
+ await this._ensureMigrated();
156
168
  const ids = [];
157
169
  for (const params of paramsList) {
158
170
  const id = await encodeEpisode(this.db, this.embeddingProvider, params);
@@ -172,7 +184,8 @@ export class Audrey extends EventEmitter {
172
184
  * @param {RecallOptions} [options]
173
185
  * @returns {Promise<RecallResult[]>}
174
186
  */
175
- recall(query, options = {}) {
187
+ async recall(query, options = {}) {
188
+ await this._ensureMigrated();
176
189
  return recallFn(this.db, this.embeddingProvider, query, {
177
190
  ...options,
178
191
  confidenceConfig: options.confidenceConfig ?? this.confidenceConfig,
@@ -185,6 +198,7 @@ export class Audrey extends EventEmitter {
185
198
  * @returns {AsyncGenerator<RecallResult>}
186
199
  */
187
200
  async *recallStream(query, options = {}) {
201
+ await this._ensureMigrated();
188
202
  yield* recallStreamFn(this.db, this.embeddingProvider, query, {
189
203
  ...options,
190
204
  confidenceConfig: options.confidenceConfig ?? this.confidenceConfig,
@@ -196,6 +210,7 @@ export class Audrey extends EventEmitter {
196
210
  * @returns {Promise<ConsolidationResult>}
197
211
  */
198
212
  async consolidate(options = {}) {
213
+ await this._ensureMigrated();
199
214
  const result = await runConsolidation(this.db, this.embeddingProvider, {
200
215
  minClusterSize: options.minClusterSize || this.consolidationConfig.minEpisodes,
201
216
  similarityThreshold: options.similarityThreshold || 0.80,
package/src/db.js CHANGED
@@ -150,6 +150,12 @@ function createVec0Tables(db, dimensions) {
150
150
  `);
151
151
  }
152
152
 
153
+ function dropVec0Tables(db) {
154
+ db.exec('DROP TABLE IF EXISTS vec_episodes');
155
+ db.exec('DROP TABLE IF EXISTS vec_semantics');
156
+ db.exec('DROP TABLE IF EXISTS vec_procedures');
157
+ }
158
+
153
159
  function migrateTable(db, { source, target, selectCols, insertCols, placeholders, transform }) {
154
160
  const count = db.prepare(`SELECT COUNT(*) as c FROM ${target}`).get().c;
155
161
  if (count > 0) return;
@@ -198,10 +204,11 @@ function migrateEmbeddingsToVec0(db) {
198
204
  /**
199
205
  * @param {string} dataDir
200
206
  * @param {{ dimensions?: number }} [options]
201
- * @returns {import('better-sqlite3').Database}
207
+ * @returns {{ db: import('better-sqlite3').Database, migrated: boolean }}
202
208
  */
203
209
  export function createDatabase(dataDir, options = {}) {
204
210
  const { dimensions } = options;
211
+ let migrated = false;
205
212
 
206
213
  mkdirSync(dataDir, { recursive: true });
207
214
  const dbPath = join(dataDir, 'audrey.db');
@@ -225,10 +232,11 @@ export function createDatabase(dataDir, options = {}) {
225
232
  if (existing) {
226
233
  const storedDims = parseInt(existing.value, 10);
227
234
  if (storedDims !== dimensions) {
228
- db.close();
229
- throw new Error(
230
- `Dimension mismatch: database was created with ${storedDims} dimensions, but ${dimensions} were requested`
231
- );
235
+ dropVec0Tables(db);
236
+ db.prepare(
237
+ "UPDATE audrey_config SET value = ? WHERE key = 'dimensions'"
238
+ ).run(String(dimensions));
239
+ migrated = true;
232
240
  }
233
241
  } else {
234
242
  db.prepare(
@@ -238,10 +246,12 @@ export function createDatabase(dataDir, options = {}) {
238
246
 
239
247
  createVec0Tables(db, dimensions);
240
248
 
241
- migrateEmbeddingsToVec0(db);
249
+ if (!migrated) {
250
+ migrateEmbeddingsToVec0(db);
251
+ }
242
252
  }
243
253
 
244
- return db;
254
+ return { db, migrated };
245
255
  }
246
256
 
247
257
  export function readStoredDimensions(dataDir) {
package/src/index.js CHANGED
@@ -13,3 +13,4 @@ export {
13
13
  export { exportMemories } from './export.js';
14
14
  export { importMemories } from './import.js';
15
15
  export { suggestConsolidationParams } from './adaptive.js';
16
+ export { reembedAll } from './migrate.js';
package/src/migrate.js ADDED
@@ -0,0 +1,32 @@
1
+ export async function reembedAll(db, embeddingProvider) {
2
+ const episodes = db.prepare('SELECT id, content, source FROM episodes').all();
3
+ const semantics = db.prepare('SELECT id, content, state FROM semantics').all();
4
+ const procedures = db.prepare('SELECT id, content, state FROM procedures').all();
5
+
6
+ for (const ep of episodes) {
7
+ const vector = await embeddingProvider.embed(ep.content);
8
+ const buffer = embeddingProvider.vectorToBuffer(vector);
9
+ db.prepare('UPDATE episodes SET embedding = ? WHERE id = ?').run(buffer, ep.id);
10
+ db.prepare('INSERT INTO vec_episodes(id, embedding, source, consolidated) VALUES (?, ?, ?, ?)').run(ep.id, buffer, ep.source, BigInt(0));
11
+ }
12
+
13
+ for (const sem of semantics) {
14
+ const vector = await embeddingProvider.embed(sem.content);
15
+ const buffer = embeddingProvider.vectorToBuffer(vector);
16
+ db.prepare('UPDATE semantics SET embedding = ? WHERE id = ?').run(buffer, sem.id);
17
+ db.prepare('INSERT INTO vec_semantics(id, embedding, state) VALUES (?, ?, ?)').run(sem.id, buffer, sem.state);
18
+ }
19
+
20
+ for (const proc of procedures) {
21
+ const vector = await embeddingProvider.embed(proc.content);
22
+ const buffer = embeddingProvider.vectorToBuffer(vector);
23
+ db.prepare('UPDATE procedures SET embedding = ? WHERE id = ?').run(buffer, proc.id);
24
+ db.prepare('INSERT INTO vec_procedures(id, embedding, state) VALUES (?, ?, ?)').run(proc.id, buffer, proc.state);
25
+ }
26
+
27
+ return {
28
+ episodes: episodes.length,
29
+ semantics: semantics.length,
30
+ procedures: procedures.length,
31
+ };
32
+ }