obedding 1.0.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.
@@ -0,0 +1,82 @@
1
+ export interface NoteEmbedding {
2
+ path: string;
3
+ vault_path: string;
4
+ embedding: number[];
5
+ metadata: {
6
+ type?: string;
7
+ repo?: string;
8
+ context?: string;
9
+ modified?: string;
10
+ tags?: string[];
11
+ title?: string;
12
+ };
13
+ excerpt: string;
14
+ indexed_at: string;
15
+ hash: string;
16
+ }
17
+ export interface EmbeddingStore {
18
+ version: string;
19
+ model: string;
20
+ dimensions: number;
21
+ indexed_at: string;
22
+ notes: NoteEmbedding[];
23
+ }
24
+ /**
25
+ * Storage manager for embeddings
26
+ */
27
+ export declare class StorageManager {
28
+ private storagePath;
29
+ private data;
30
+ constructor(storagePath: string);
31
+ /**
32
+ * Initialize storage (create directory and load existing data)
33
+ */
34
+ initialize(): Promise<void>;
35
+ /**
36
+ * Load existing embeddings from disk
37
+ */
38
+ load(): Promise<void>;
39
+ /**
40
+ * Save embeddings to disk
41
+ */
42
+ save(): Promise<void>;
43
+ /**
44
+ * Get all stored notes
45
+ */
46
+ getNotes(): NoteEmbedding[];
47
+ /**
48
+ * Add or update a note embedding
49
+ */
50
+ upsertNote(note: NoteEmbedding): Promise<void>;
51
+ /**
52
+ * Remove a note by path
53
+ */
54
+ removeNote(notePath: string): Promise<boolean>;
55
+ /**
56
+ * Check if a note needs updating based on content hash
57
+ */
58
+ needsUpdate(notePath: string, contentHash: string): boolean;
59
+ /**
60
+ * Get storage statistics
61
+ */
62
+ getStats(): {
63
+ noteCount: number;
64
+ totalSize: number;
65
+ model: string;
66
+ dimensions: number;
67
+ lastIndexed: string;
68
+ };
69
+ /**
70
+ * Clear all stored notes
71
+ */
72
+ clear(): Promise<void>;
73
+ /**
74
+ * Create empty store structure
75
+ */
76
+ private createEmptyStore;
77
+ /**
78
+ * Validate loaded data
79
+ */
80
+ private validate;
81
+ }
82
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAMD;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,IAAI,CAA+B;gBAE/B,WAAW,EAAE,MAAM;IAI/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAYjC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB3B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B;;OAEG;IACH,QAAQ,IAAI,aAAa,EAAE;IAO3B;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBpD;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBpD;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO;IAc3D;;OAEG;IACH,QAAQ,IAAI;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;KACrB;IAwBD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;OAEG;IACH,OAAO,CAAC,QAAQ;CAoBjB"}
@@ -0,0 +1,183 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as fsSync from 'fs';
3
+ import * as path from 'path';
4
+ const STORAGE_VERSION = '1.0';
5
+ const DEFAULT_MODEL = 'mlx-community/Qwen3-Embedding-0.6B-4bit-DWQ';
6
+ const DEFAULT_DIMENSIONS = 2048;
7
+ /**
8
+ * Storage manager for embeddings
9
+ */
10
+ export class StorageManager {
11
+ storagePath;
12
+ data = null;
13
+ constructor(storagePath) {
14
+ this.storagePath = path.resolve(storagePath);
15
+ }
16
+ /**
17
+ * Initialize storage (create directory and load existing data)
18
+ */
19
+ async initialize() {
20
+ const dir = path.dirname(this.storagePath);
21
+ try {
22
+ await fs.mkdir(dir, { recursive: true });
23
+ }
24
+ catch (error) {
25
+ throw new Error(`Failed to create storage directory: ${error.message}`);
26
+ }
27
+ await this.load();
28
+ }
29
+ /**
30
+ * Load existing embeddings from disk
31
+ */
32
+ async load() {
33
+ try {
34
+ const content = await fs.readFile(this.storagePath, 'utf-8');
35
+ this.data = JSON.parse(content);
36
+ }
37
+ catch (error) {
38
+ if (error.code === 'ENOENT') {
39
+ // File doesn't exist, create new store
40
+ this.data = this.createEmptyStore();
41
+ }
42
+ else {
43
+ throw new Error(`Failed to load storage: ${error.message}`);
44
+ }
45
+ }
46
+ // Validate data structure
47
+ this.validate();
48
+ }
49
+ /**
50
+ * Save embeddings to disk
51
+ */
52
+ async save() {
53
+ if (!this.data) {
54
+ throw new Error('No data to save');
55
+ }
56
+ try {
57
+ const json = JSON.stringify(this.data);
58
+ fsSync.writeFileSync(this.storagePath, json, 'utf-8');
59
+ }
60
+ catch (error) {
61
+ throw new Error(`Failed to save storage: ${error.message}`);
62
+ }
63
+ }
64
+ /**
65
+ * Get all stored notes
66
+ */
67
+ getNotes() {
68
+ if (!this.data) {
69
+ return [];
70
+ }
71
+ return this.data.notes;
72
+ }
73
+ /**
74
+ * Add or update a note embedding
75
+ */
76
+ async upsertNote(note) {
77
+ if (!this.data) {
78
+ await this.initialize();
79
+ }
80
+ const existingIndex = this.data.notes.findIndex(n => n.path === note.path);
81
+ if (existingIndex >= 0) {
82
+ // Update existing note
83
+ this.data.notes[existingIndex] = note;
84
+ }
85
+ else {
86
+ // Add new note
87
+ this.data.notes.push(note);
88
+ }
89
+ this.data.indexed_at = new Date().toISOString();
90
+ }
91
+ /**
92
+ * Remove a note by path
93
+ */
94
+ async removeNote(notePath) {
95
+ if (!this.data) {
96
+ return false;
97
+ }
98
+ const initialLength = this.data.notes.length;
99
+ this.data.notes = this.data.notes.filter(n => n.path !== notePath);
100
+ if (this.data.notes.length < initialLength) {
101
+ this.data.indexed_at = new Date().toISOString();
102
+ return true;
103
+ }
104
+ return false;
105
+ }
106
+ /**
107
+ * Check if a note needs updating based on content hash
108
+ */
109
+ needsUpdate(notePath, contentHash) {
110
+ if (!this.data) {
111
+ return true;
112
+ }
113
+ const existing = this.data.notes.find(n => n.path === notePath);
114
+ if (!existing) {
115
+ return true; // Note doesn't exist
116
+ }
117
+ return existing.hash !== contentHash; // Content changed
118
+ }
119
+ /**
120
+ * Get storage statistics
121
+ */
122
+ getStats() {
123
+ if (!this.data) {
124
+ return {
125
+ noteCount: 0,
126
+ totalSize: 0,
127
+ model: DEFAULT_MODEL,
128
+ dimensions: DEFAULT_DIMENSIONS,
129
+ lastIndexed: 'never'
130
+ };
131
+ }
132
+ const totalSize = this.data.notes.reduce((sum, note) => {
133
+ return sum + note.embedding.length * 4; // 4 bytes per float32
134
+ }, 0);
135
+ return {
136
+ noteCount: this.data.notes.length,
137
+ totalSize,
138
+ model: this.data.model,
139
+ dimensions: this.data.dimensions,
140
+ lastIndexed: this.data.indexed_at
141
+ };
142
+ }
143
+ /**
144
+ * Clear all stored notes
145
+ */
146
+ async clear() {
147
+ this.data = this.createEmptyStore();
148
+ await this.save();
149
+ }
150
+ /**
151
+ * Create empty store structure
152
+ */
153
+ createEmptyStore() {
154
+ return {
155
+ version: STORAGE_VERSION,
156
+ model: DEFAULT_MODEL,
157
+ dimensions: DEFAULT_DIMENSIONS,
158
+ indexed_at: new Date().toISOString(),
159
+ notes: []
160
+ };
161
+ }
162
+ /**
163
+ * Validate loaded data
164
+ */
165
+ validate() {
166
+ if (!this.data) {
167
+ throw new Error('No data loaded');
168
+ }
169
+ if (this.data.version !== STORAGE_VERSION) {
170
+ console.warn(`Warning: Storage version mismatch. Expected ${STORAGE_VERSION}, got ${this.data.version}`);
171
+ }
172
+ if (!this.data.notes || !Array.isArray(this.data.notes)) {
173
+ throw new Error('Invalid storage structure: missing notes array');
174
+ }
175
+ // Validate each note
176
+ for (const note of this.data.notes) {
177
+ if (!note.path || !note.embedding || !Array.isArray(note.embedding)) {
178
+ throw new Error('Invalid note structure in storage');
179
+ }
180
+ }
181
+ }
182
+ }
183
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Calculate cosine similarity between two vectors
3
+ */
4
+ export declare function cosineSimilarity(a: number[], b: number[]): number;
5
+ /**
6
+ * Generate SHA256 hash of content
7
+ */
8
+ export declare function hashContent(content: string): string;
9
+ /**
10
+ * Truncate text to approximately maxTokens (rough estimate)
11
+ */
12
+ export declare function truncateToTokens(text: string, maxTokens?: number): string;
13
+ /**
14
+ * Generate excerpt from content
15
+ */
16
+ export declare function generateExcerpt(content: string, maxLength?: number): string;
17
+ /**
18
+ * Format file size for display
19
+ */
20
+ export declare function formatFileSize(bytes: number): string;
21
+ /**
22
+ * Format duration in seconds
23
+ */
24
+ export declare function formatDuration(seconds: number): string;
25
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAcjE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAa,GAAG,MAAM,CAO/E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,MAAY,GAAG,MAAM,CAYhF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWpD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKtD"}
package/dist/utils.js ADDED
@@ -0,0 +1,69 @@
1
+ import { createHash } from 'crypto';
2
+ /**
3
+ * Calculate cosine similarity between two vectors
4
+ */
5
+ export function cosineSimilarity(a, b) {
6
+ if (a.length !== b.length) {
7
+ throw new Error('Vectors must have the same length');
8
+ }
9
+ const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
10
+ const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
11
+ const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
12
+ if (magnitudeA === 0 || magnitudeB === 0) {
13
+ return 0;
14
+ }
15
+ return dotProduct / (magnitudeA * magnitudeB);
16
+ }
17
+ /**
18
+ * Generate SHA256 hash of content
19
+ */
20
+ export function hashContent(content) {
21
+ return createHash('sha256').update(content).digest('hex');
22
+ }
23
+ /**
24
+ * Truncate text to approximately maxTokens (rough estimate)
25
+ */
26
+ export function truncateToTokens(text, maxTokens = 8000) {
27
+ // Rough estimate: 1 token ≈ 4 characters
28
+ const maxChars = maxTokens * 4;
29
+ if (text.length <= maxChars) {
30
+ return text;
31
+ }
32
+ return text.substring(0, maxChars);
33
+ }
34
+ /**
35
+ * Generate excerpt from content
36
+ */
37
+ export function generateExcerpt(content, maxLength = 200) {
38
+ // Remove YAML frontmatter
39
+ const withoutFrontmatter = content.replace(/^---\n.*?\n---\n/s, '');
40
+ // Get first paragraph or section
41
+ const firstParagraph = withoutFrontmatter.split('\n\n')[0].replace(/\n/g, ' ').trim();
42
+ if (firstParagraph.length <= maxLength) {
43
+ return firstParagraph;
44
+ }
45
+ return firstParagraph.substring(0, maxLength) + '...';
46
+ }
47
+ /**
48
+ * Format file size for display
49
+ */
50
+ export function formatFileSize(bytes) {
51
+ const units = ['B', 'KB', 'MB', 'GB'];
52
+ let size = bytes;
53
+ let unitIndex = 0;
54
+ while (size >= 1024 && unitIndex < units.length - 1) {
55
+ size /= 1024;
56
+ unitIndex++;
57
+ }
58
+ return `${size.toFixed(2)} ${units[unitIndex]}`;
59
+ }
60
+ /**
61
+ * Format duration in seconds
62
+ */
63
+ export function formatDuration(seconds) {
64
+ if (seconds < 1) {
65
+ return `${(seconds * 1000).toFixed(0)}ms`;
66
+ }
67
+ return `${seconds.toFixed(2)}s`;
68
+ }
69
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAW,EAAE,CAAW;IACvD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IAEzE,IAAI,UAAU,KAAK,CAAC,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;QACzC,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,UAAU,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,YAAoB,IAAI;IACrE,yCAAyC;IACzC,MAAM,QAAQ,GAAG,SAAS,GAAG,CAAC,CAAC;IAC/B,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,YAAoB,GAAG;IACtE,0BAA0B;IAC1B,MAAM,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IAEpE,iCAAiC;IACjC,MAAM,cAAc,GAAG,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAEtF,IAAI,cAAc,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QACvC,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,OAAO,cAAc,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,OAAO,IAAI,IAAI,IAAI,IAAI,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,IAAI,IAAI,IAAI,CAAC;QACb,SAAS,EAAE,CAAC;IACd,CAAC;IAED,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,OAAO,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,CAAC;IACD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAClC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "obedding",
3
+ "version": "1.0.0",
4
+ "description": "Semantic search for Obsidian notes using local MLX embeddings",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "bin": {
8
+ "obedding": "./dist/cli.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "prepublishOnly": "npm run build",
14
+ "start": "node dist/cli.js"
15
+ },
16
+ "keywords": [
17
+ "obsidian",
18
+ "semantic-search",
19
+ "embeddings",
20
+ "mlx",
21
+ "local",
22
+ "privacy",
23
+ "note-taking",
24
+ "knowledge-base",
25
+ "vector-search"
26
+ ],
27
+ "author": "tuannvm <tuannvm@users.noreply.github.com>",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/tuannvm/obedding.git"
32
+ },
33
+ "homepage": "https://github.com/tuannvm/obedding#readme",
34
+ "bugs": {
35
+ "url": "https://github.com/tuannvm/obedding/issues"
36
+ },
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "README.md",
43
+ "LICENSE"
44
+ ],
45
+ "dependencies": {
46
+ "commander": "^12.0.0",
47
+ "chalk": "^5.3.0",
48
+ "gray-matter": "^4.0.3",
49
+ "glob": "^10.3.10",
50
+ "node-fetch": "^3.3.2"
51
+ },
52
+ "devDependencies": {
53
+ "@types/glob": "^8.1.0",
54
+ "@types/node": "^20.11.0",
55
+ "typescript": "^5.3.3"
56
+ }
57
+ }