@cccarv82/freya 2.14.1 → 2.16.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cccarv82/freya",
3
- "version": "2.14.1",
3
+ "version": "2.16.0",
4
4
  "description": "Personal AI Assistant with local-first persistence",
5
5
  "scripts": {
6
6
  "health": "node scripts/validate-data.js && node scripts/validate-structure.js",
@@ -31,7 +31,7 @@
31
31
  ],
32
32
  "preferGlobal": true,
33
33
  "dependencies": {
34
- "@xenova/transformers": "^2.17.2",
34
+ "@huggingface/transformers": "^3.8.1",
35
35
  "pdf-lib": "^1.17.1",
36
36
  "sql.js": "^1.12.0"
37
37
  }
@@ -319,13 +319,22 @@ class DataLayer {
319
319
  CREATE TABLE IF NOT EXISTS document_embeddings (
320
320
  id INTEGER PRIMARY KEY AUTOINCREMENT,
321
321
  reference_type TEXT NOT NULL, /* 'daily_log', 'task', 'blocker' */
322
- reference_id TEXT NOT NULL,
322
+ reference_id TEXT NOT NULL,
323
323
  chunk_index INTEGER DEFAULT 0,
324
324
  text_chunk TEXT NOT NULL,
325
325
  embedding BLOB NOT NULL, /* Stored as Buffer of Float32Array */
326
326
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
327
327
  );
328
328
  `);
329
+
330
+ // --- Migrations for existing databases ---
331
+ // Add due_date column to tasks (safe to run multiple times)
332
+ try {
333
+ const cols = this.db.prepare("PRAGMA table_info(tasks)").all();
334
+ if (!cols.some(c => c.name === 'due_date')) {
335
+ this.db.exec("ALTER TABLE tasks ADD COLUMN due_date TEXT");
336
+ }
337
+ } catch { /* ignore if PRAGMA not supported */ }
329
338
  }
330
339
 
331
340
  // Helper close method
@@ -40,6 +40,7 @@ class DataManager {
40
40
  status: t.status,
41
41
  createdAt: t.created_at,
42
42
  completedAt: t.completed_at,
43
+ dueDate: t.due_date || null,
43
44
  priority: meta.priority,
44
45
  streamSlug: meta.streamSlug
45
46
  };
@@ -1,5 +1,6 @@
1
1
  class Embedder {
2
2
  constructor() {
3
+ // V3: use the official HuggingFace model name (same weights, new namespace)
3
4
  this.modelName = 'Xenova/all-MiniLM-L6-v2';
4
5
  this.extractorInfo = null;
5
6
  this.initPromise = null;
@@ -9,7 +10,9 @@ class Embedder {
9
10
  if (this.extractorInfo) return;
10
11
  if (!this.initPromise) {
11
12
  this.initPromise = (async () => {
12
- const { pipeline } = await import('@xenova/transformers');
13
+ // V3: @huggingface/transformers replaces @xenova/transformers
14
+ // sharp 0.34+ uses prebuilt platform binaries (no node-gyp needed)
15
+ const { pipeline } = await import('@huggingface/transformers');
13
16
  this.extractorInfo = await pipeline('feature-extraction', this.modelName, { quantized: true });
14
17
  })().catch((err) => {
15
18
  this.initPromise = null;
@@ -25,6 +28,7 @@ class Embedder {
25
28
  if (!cleanText) return new Float32Array(384); // Empty zero vector for model
26
29
 
27
30
  const output = await this.extractorInfo(cleanText, { pooling: 'mean', normalize: true });
31
+ // V3: output.data may be a typed array or need .tolist()
28
32
  return new Float32Array(output.data);
29
33
  }
30
34
 
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * DataLayer.js (V2.1 - sql.js powered, no native compilation needed)
3
- *
3
+ *
4
4
  * Drop-in replacement for better-sqlite3 using sql.js (WebAssembly SQLite).
5
5
  * Exposes the same API surface: .prepare().all(), .prepare().get(), .prepare().run(),
6
6
  * .exec(), .pragma(), .transaction(), .close()
7
- *
7
+ *
8
8
  * Auto-persists to disk after every write operation.
9
9
  */
10
10
 
@@ -326,6 +326,15 @@ class DataLayer {
326
326
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
327
327
  );
328
328
  `);
329
+
330
+ // --- Migrations for existing databases ---
331
+ // Add due_date column to tasks (safe to run multiple times)
332
+ try {
333
+ const cols = this.db.prepare("PRAGMA table_info(tasks)").all();
334
+ if (!cols.some(c => c.name === 'due_date')) {
335
+ this.db.exec("ALTER TABLE tasks ADD COLUMN due_date TEXT");
336
+ }
337
+ } catch { /* ignore if PRAGMA not supported */ }
329
338
  }
330
339
 
331
340
  // Helper close method
@@ -40,6 +40,7 @@ class DataManager {
40
40
  status: t.status,
41
41
  createdAt: t.created_at,
42
42
  completedAt: t.completed_at,
43
+ dueDate: t.due_date || null,
43
44
  priority: meta.priority,
44
45
  streamSlug: meta.streamSlug
45
46
  };
@@ -54,13 +55,13 @@ class DataManager {
54
55
 
55
56
  const tasks = this.getTasksRaw();
56
57
  const completed = dl.db.prepare(`
57
- SELECT * FROM tasks
58
- WHERE status = 'COMPLETED'
58
+ SELECT * FROM tasks
59
+ WHERE status = 'COMPLETED'
59
60
  AND completed_at >= ? AND completed_at <= ?
60
61
  `).all(startIso, endIso).map(t => ({ ...t, completedAt: t.completed_at, createdAt: t.created_at }));
61
62
 
62
63
  const pending = dl.db.prepare(`
63
- SELECT * FROM tasks
64
+ SELECT * FROM tasks
64
65
  WHERE status = 'PENDING' AND category = 'DO_NOW'
65
66
  `).all().map(t => ({ ...t, createdAt: t.created_at }));
66
67
 
@@ -100,27 +101,27 @@ class DataManager {
100
101
  const blockers = this.getBlockersRaw();
101
102
 
102
103
  const open = dl.db.prepare(`
103
- SELECT * FROM blockers
104
+ SELECT * FROM blockers
104
105
  WHERE status NOT IN ('RESOLVED', 'CLOSED', 'DONE', 'FIXED')
105
106
  AND resolved_at IS NULL
106
- ORDER BY
107
- CASE severity
108
- WHEN 'CRITICAL' THEN 0
109
- WHEN 'HIGH' THEN 1
110
- WHEN 'MEDIUM' THEN 2
111
- WHEN 'LOW' THEN 3
112
- ELSE 99
107
+ ORDER BY
108
+ CASE severity
109
+ WHEN 'CRITICAL' THEN 0
110
+ WHEN 'HIGH' THEN 1
111
+ WHEN 'MEDIUM' THEN 2
112
+ WHEN 'LOW' THEN 3
113
+ ELSE 99
113
114
  END ASC,
114
115
  created_at ASC
115
116
  `).all().map(b => ({ ...b, projectSlug: b.project_slug, createdAt: b.created_at }));
116
117
 
117
118
  const openedRecent = dl.db.prepare(`
118
- SELECT * FROM blockers
119
+ SELECT * FROM blockers
119
120
  WHERE created_at >= ? AND created_at <= ?
120
121
  `).all(startIso, endIso).map(b => ({ ...b, projectSlug: b.project_slug, createdAt: b.created_at }));
121
122
 
122
123
  const resolvedRecent = dl.db.prepare(`
123
- SELECT * FROM blockers
124
+ SELECT * FROM blockers
124
125
  WHERE resolved_at >= ? AND resolved_at <= ?
125
126
  `).all(startIso, endIso).map(b => ({ ...b, projectSlug: b.project_slug, resolvedAt: b.resolved_at }));
126
127
 
@@ -234,7 +235,7 @@ class DataManager {
234
235
 
235
236
  // Fetch all stored embeddings. For a local personal tool with < 100k chunks, in-memory cosine sim is perfectly fast.
236
237
  const rows = dl.db.prepare(`
237
- SELECT reference_type, reference_id, chunk_index, text_chunk, embedding
238
+ SELECT reference_type, reference_id, chunk_index, text_chunk, embedding
238
239
  FROM document_embeddings
239
240
  `).all();
240
241
 
@@ -1,5 +1,6 @@
1
1
  class Embedder {
2
2
  constructor() {
3
+ // V3: use the official HuggingFace model name (same weights, new namespace)
3
4
  this.modelName = 'Xenova/all-MiniLM-L6-v2';
4
5
  this.extractorInfo = null;
5
6
  this.initPromise = null;
@@ -9,7 +10,9 @@ class Embedder {
9
10
  if (this.extractorInfo) return;
10
11
  if (!this.initPromise) {
11
12
  this.initPromise = (async () => {
12
- const { pipeline } = await import('@xenova/transformers');
13
+ // V3: @huggingface/transformers replaces @xenova/transformers
14
+ // sharp 0.34+ uses prebuilt platform binaries (no node-gyp needed)
15
+ const { pipeline } = await import('@huggingface/transformers');
13
16
  this.extractorInfo = await pipeline('feature-extraction', this.modelName, { quantized: true });
14
17
  })().catch((err) => {
15
18
  this.initPromise = null;
@@ -25,6 +28,7 @@ class Embedder {
25
28
  if (!cleanText) return new Float32Array(384); // Empty zero vector for model
26
29
 
27
30
  const output = await this.extractorInfo(cleanText, { pooling: 'mean', normalize: true });
31
+ // V3: output.data may be a typed array or need .tolist()
28
32
  return new Float32Array(output.data);
29
33
  }
30
34