@telvok/librarian-mcp 1.5.3 → 2.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.
- package/dist/library/errors.d.ts +48 -0
- package/dist/library/errors.js +80 -0
- package/dist/library/parsers/jsonl.d.ts +9 -4
- package/dist/library/parsers/jsonl.js +52 -20
- package/dist/library/schemas.d.ts +6 -6
- package/dist/library/storage.d.ts +2 -2
- package/dist/library/storage.js +2 -2
- package/dist/library 2/embeddings.d.ts +21 -0
- package/dist/library 2/embeddings.js +86 -0
- package/dist/library 2/manager.d.ts +42 -0
- package/dist/library 2/manager.js +218 -0
- package/dist/library 2/parsers/cursor.d.ts +15 -0
- package/dist/library 2/parsers/cursor.js +168 -0
- package/dist/library 2/parsers/index.d.ts +6 -0
- package/dist/library 2/parsers/index.js +5 -0
- package/dist/library 2/parsers/json.d.ts +11 -0
- package/dist/library 2/parsers/json.js +95 -0
- package/dist/library 2/parsers/jsonl.d.ts +14 -0
- package/dist/library 2/parsers/jsonl.js +85 -0
- package/dist/library 2/parsers/markdown.d.ts +15 -0
- package/dist/library 2/parsers/markdown.js +77 -0
- package/dist/library 2/parsers/sqlite.d.ts +8 -0
- package/dist/library 2/parsers/sqlite.js +123 -0
- package/dist/library 2/parsers/types.d.ts +21 -0
- package/dist/library 2/parsers/types.js +4 -0
- package/dist/library 2/query.d.ts +26 -0
- package/dist/library 2/query.js +104 -0
- package/dist/library 2/schemas.d.ts +324 -0
- package/dist/library 2/schemas.js +79 -0
- package/dist/library 2/storage.d.ts +22 -0
- package/dist/library 2/storage.js +36 -0
- package/dist/library 2/vector-index.d.ts +55 -0
- package/dist/library 2/vector-index.js +160 -0
- package/dist/server 2.js +199 -0
- package/dist/server.d 2.ts +2 -0
- package/dist/server.js +102 -54
- package/dist/tools/adopt.d.ts +1 -0
- package/dist/tools/adopt.js +37 -10
- package/dist/tools/auth.d.ts +69 -0
- package/dist/tools/auth.js +379 -0
- package/dist/tools/bounty-claim.d.ts +28 -0
- package/dist/tools/bounty-claim.js +92 -0
- package/dist/tools/bounty-create.d.ts +47 -0
- package/dist/tools/bounty-create.js +118 -0
- package/dist/tools/bounty-list.d.ts +50 -0
- package/dist/tools/bounty-list.js +116 -0
- package/dist/tools/bounty-submit.d.ts +34 -0
- package/dist/tools/bounty-submit.js +94 -0
- package/dist/tools/brief.d.ts +94 -0
- package/dist/tools/brief.js +234 -15
- package/dist/tools/delete.d.ts +87 -0
- package/dist/tools/delete.js +266 -0
- package/dist/tools/feedback.d.ts +27 -0
- package/dist/tools/feedback.js +98 -0
- package/dist/tools/help.d.ts +22 -0
- package/dist/tools/help.js +482 -0
- package/dist/tools/import-memories.d.ts +1 -0
- package/dist/tools/import-memories.js +18 -13
- package/dist/tools/index.d.ts +11 -0
- package/dist/tools/index.js +12 -0
- package/dist/tools/library-buy.d.ts +31 -0
- package/dist/tools/library-buy.js +104 -0
- package/dist/tools/library-download.d.ts +27 -0
- package/dist/tools/library-download.js +177 -0
- package/dist/tools/library-publish.d.ts +112 -0
- package/dist/tools/library-publish.js +387 -0
- package/dist/tools/library-search.d.ts +110 -0
- package/dist/tools/library-search.js +132 -0
- package/dist/tools/mark-hit.d.ts +1 -0
- package/dist/tools/mark-hit.js +83 -5
- package/dist/tools/my-books.d.ts +51 -0
- package/dist/tools/my-books.js +115 -0
- package/dist/tools/my-bounties.d.ts +43 -0
- package/dist/tools/my-bounties.js +126 -0
- package/dist/tools/rate-book.d.ts +40 -0
- package/dist/tools/rate-book.js +147 -0
- package/dist/tools/rebuild-index.d.ts +1 -0
- package/dist/tools/rebuild-index.js +40 -8
- package/dist/tools/record.d.ts +18 -0
- package/dist/tools/record.js +30 -26
- package/dist/tools/seller-analytics.d.ts +53 -0
- package/dist/tools/seller-analytics.js +180 -0
- package/dist/tools/sync.d.ts +55 -0
- package/dist/tools/sync.js +304 -0
- package/dist/tools/unsubscribe.d.ts +48 -0
- package/dist/tools/unsubscribe.js +120 -0
- package/dist/tools 2/adopt.d.ts +24 -0
- package/dist/tools 2/adopt.js +154 -0
- package/dist/tools 2/auth.d.ts +35 -0
- package/dist/tools 2/auth.js +229 -0
- package/dist/tools 2/brief.d.ts +56 -0
- package/dist/tools 2/brief.js +414 -0
- package/dist/tools 2/help.d.ts +21 -0
- package/dist/tools 2/help.js +267 -0
- package/dist/tools 2/import-memories.d.ts +32 -0
- package/dist/tools 2/import-memories.js +231 -0
- package/dist/tools 2/index.d.ts +12 -0
- package/dist/tools 2/index.js +12 -0
- package/dist/tools 2/mark-hit.d.ts +20 -0
- package/dist/tools 2/mark-hit.js +71 -0
- package/dist/tools 2/marketplace-buy.d.ts +30 -0
- package/dist/tools 2/marketplace-buy.js +97 -0
- package/dist/tools 2/marketplace-download.d.ts +26 -0
- package/dist/tools 2/marketplace-download.js +160 -0
- package/dist/tools 2/marketplace-publish.d.ts +111 -0
- package/dist/tools 2/marketplace-publish.js +377 -0
- package/dist/tools 2/marketplace-search.d.ts +57 -0
- package/dist/tools 2/marketplace-search.js +96 -0
- package/dist/tools 2/my-books.d.ts +50 -0
- package/dist/tools 2/my-books.js +107 -0
- package/dist/tools 2/rate-book.d.ts +39 -0
- package/dist/tools 2/rate-book.js +139 -0
- package/dist/tools 2/rebuild-index.d.ts +23 -0
- package/dist/tools 2/rebuild-index.js +107 -0
- package/dist/tools 2/record.d.ts +40 -0
- package/dist/tools 2/record.js +205 -0
- package/dist/tools 2/seller-analytics.d.ts +35 -0
- package/dist/tools 2/seller-analytics.js +102 -0
- package/dist/tools 2/sync.d.ts +54 -0
- package/dist/tools 2/sync.js +298 -0
- package/package.json +1 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error codes following JSON-RPC 2.0 conventions
|
|
3
|
+
* -32xxx: Standard JSON-RPC errors
|
|
4
|
+
* -31xxx: Authentication errors
|
|
5
|
+
* -30xxx: Resource errors
|
|
6
|
+
* -29xxx: Network errors
|
|
7
|
+
*/
|
|
8
|
+
export declare const ErrorCodes: {
|
|
9
|
+
readonly AUTH_REQUIRED: -31001;
|
|
10
|
+
readonly AUTH_EXPIRED: -31002;
|
|
11
|
+
readonly AUTH_INVALID_SCOPE: -31003;
|
|
12
|
+
readonly AUTH_INVALID_KEY: -31004;
|
|
13
|
+
readonly ENTRY_NOT_FOUND: -30001;
|
|
14
|
+
readonly BOOK_NOT_FOUND: -30002;
|
|
15
|
+
readonly INDEX_STALE: -30003;
|
|
16
|
+
readonly FILE_NOT_FOUND: -30004;
|
|
17
|
+
readonly INVALID_PATH: -30005;
|
|
18
|
+
readonly INVALID_PARAMS: -32602;
|
|
19
|
+
readonly INVALID_REQUEST: -32600;
|
|
20
|
+
readonly API_UNAVAILABLE: -29001;
|
|
21
|
+
readonly NETWORK_TIMEOUT: -29002;
|
|
22
|
+
readonly API_ERROR: -29003;
|
|
23
|
+
};
|
|
24
|
+
export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
25
|
+
/**
|
|
26
|
+
* Custom error class for Librarian MCP
|
|
27
|
+
* Includes error code and retryable flag for AI agents
|
|
28
|
+
*/
|
|
29
|
+
export declare class LibrarianError extends Error {
|
|
30
|
+
readonly code: ErrorCode;
|
|
31
|
+
readonly retryable: boolean;
|
|
32
|
+
constructor(code: ErrorCode, message: string, retryable?: boolean);
|
|
33
|
+
/**
|
|
34
|
+
* Convert to JSON-RPC compatible error object
|
|
35
|
+
*/
|
|
36
|
+
toJSON(): {
|
|
37
|
+
error: string;
|
|
38
|
+
code: ErrorCode;
|
|
39
|
+
retryable: boolean;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export declare function authRequired(): LibrarianError;
|
|
43
|
+
export declare function authExpired(): LibrarianError;
|
|
44
|
+
export declare function entryNotFound(path: string): LibrarianError;
|
|
45
|
+
export declare function bookNotFound(slug: string): LibrarianError;
|
|
46
|
+
export declare function apiError(message: string): LibrarianError;
|
|
47
|
+
export declare function networkTimeout(): LibrarianError;
|
|
48
|
+
export declare function invalidParams(message: string): LibrarianError;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Error Code Definitions
|
|
3
|
+
// JSON-RPC compatible error codes for MCP
|
|
4
|
+
// ============================================================================
|
|
5
|
+
/**
|
|
6
|
+
* Error codes following JSON-RPC 2.0 conventions
|
|
7
|
+
* -32xxx: Standard JSON-RPC errors
|
|
8
|
+
* -31xxx: Authentication errors
|
|
9
|
+
* -30xxx: Resource errors
|
|
10
|
+
* -29xxx: Network errors
|
|
11
|
+
*/
|
|
12
|
+
export const ErrorCodes = {
|
|
13
|
+
// Auth errors (-31xxx)
|
|
14
|
+
AUTH_REQUIRED: -31001,
|
|
15
|
+
AUTH_EXPIRED: -31002,
|
|
16
|
+
AUTH_INVALID_SCOPE: -31003,
|
|
17
|
+
AUTH_INVALID_KEY: -31004,
|
|
18
|
+
// Resource errors (-30xxx)
|
|
19
|
+
ENTRY_NOT_FOUND: -30001,
|
|
20
|
+
BOOK_NOT_FOUND: -30002,
|
|
21
|
+
INDEX_STALE: -30003,
|
|
22
|
+
FILE_NOT_FOUND: -30004,
|
|
23
|
+
INVALID_PATH: -30005,
|
|
24
|
+
// Validation errors (-32xxx - JSON-RPC standard)
|
|
25
|
+
INVALID_PARAMS: -32602,
|
|
26
|
+
INVALID_REQUEST: -32600,
|
|
27
|
+
// Network errors (-29xxx)
|
|
28
|
+
API_UNAVAILABLE: -29001,
|
|
29
|
+
NETWORK_TIMEOUT: -29002,
|
|
30
|
+
API_ERROR: -29003,
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Custom error class for Librarian MCP
|
|
34
|
+
* Includes error code and retryable flag for AI agents
|
|
35
|
+
*/
|
|
36
|
+
export class LibrarianError extends Error {
|
|
37
|
+
code;
|
|
38
|
+
retryable;
|
|
39
|
+
constructor(code, message, retryable = false) {
|
|
40
|
+
super(message);
|
|
41
|
+
this.name = 'LibrarianError';
|
|
42
|
+
this.code = code;
|
|
43
|
+
this.retryable = retryable;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Convert to JSON-RPC compatible error object
|
|
47
|
+
*/
|
|
48
|
+
toJSON() {
|
|
49
|
+
return {
|
|
50
|
+
error: this.message,
|
|
51
|
+
code: this.code,
|
|
52
|
+
retryable: this.retryable,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// Helper Functions for Common Errors
|
|
58
|
+
// ============================================================================
|
|
59
|
+
export function authRequired() {
|
|
60
|
+
return new LibrarianError(ErrorCodes.AUTH_REQUIRED, 'Authentication required. Use auth({ action: "login" }) to connect.', false);
|
|
61
|
+
}
|
|
62
|
+
export function authExpired() {
|
|
63
|
+
return new LibrarianError(ErrorCodes.AUTH_EXPIRED, 'API key has expired. Use auth({ action: "login" }) to get a new key.', false);
|
|
64
|
+
}
|
|
65
|
+
export function entryNotFound(path) {
|
|
66
|
+
return new LibrarianError(ErrorCodes.ENTRY_NOT_FOUND, `Entry not found: ${path}`, false);
|
|
67
|
+
}
|
|
68
|
+
export function bookNotFound(slug) {
|
|
69
|
+
return new LibrarianError(ErrorCodes.BOOK_NOT_FOUND, `Book not found: ${slug}`, false);
|
|
70
|
+
}
|
|
71
|
+
export function apiError(message) {
|
|
72
|
+
return new LibrarianError(ErrorCodes.API_ERROR, message, true // Network errors are typically retryable
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
export function networkTimeout() {
|
|
76
|
+
return new LibrarianError(ErrorCodes.NETWORK_TIMEOUT, 'Request timed out. Please try again.', true);
|
|
77
|
+
}
|
|
78
|
+
export function invalidParams(message) {
|
|
79
|
+
return new LibrarianError(ErrorCodes.INVALID_PARAMS, message, false);
|
|
80
|
+
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import type { ParseResult } from './types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Parse a JSONL file
|
|
3
|
+
* Parse a JSONL file. Supports multiple formats:
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* {"type":"entity","name":"
|
|
7
|
-
*
|
|
5
|
+
* mcp-knowledge-graph:
|
|
6
|
+
* {"type":"entity","name":"Topic","observations":["fact 1","fact 2"]}
|
|
7
|
+
*
|
|
8
|
+
* Generic memory formats:
|
|
9
|
+
* {"title":"Topic","content":"..."}
|
|
10
|
+
* {"content":"...","timestamp":"..."}
|
|
11
|
+
* {"text":"...","metadata":{}}
|
|
12
|
+
* {"memory":"...","created_at":"..."}
|
|
8
13
|
*/
|
|
9
14
|
export declare function parseJSONL(filePath: string): Promise<ParseResult>;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import * as fs from 'fs/promises';
|
|
2
2
|
/**
|
|
3
|
-
* Parse a JSONL file
|
|
3
|
+
* Parse a JSONL file. Supports multiple formats:
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* {"type":"entity","name":"
|
|
7
|
-
*
|
|
5
|
+
* mcp-knowledge-graph:
|
|
6
|
+
* {"type":"entity","name":"Topic","observations":["fact 1","fact 2"]}
|
|
7
|
+
*
|
|
8
|
+
* Generic memory formats:
|
|
9
|
+
* {"title":"Topic","content":"..."}
|
|
10
|
+
* {"content":"...","timestamp":"..."}
|
|
11
|
+
* {"text":"...","metadata":{}}
|
|
12
|
+
* {"memory":"...","created_at":"..."}
|
|
8
13
|
*/
|
|
9
14
|
export async function parseJSONL(filePath) {
|
|
10
15
|
const entries = [];
|
|
@@ -17,28 +22,55 @@ export async function parseJSONL(filePath) {
|
|
|
17
22
|
const line = lines[i];
|
|
18
23
|
try {
|
|
19
24
|
const item = JSON.parse(line);
|
|
20
|
-
// Skip
|
|
25
|
+
// Skip internal markers and relations
|
|
21
26
|
if (item.type === '_aim' || item.type === 'relation') {
|
|
22
27
|
skipped++;
|
|
23
28
|
continue;
|
|
24
29
|
}
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
// Extract title (try multiple fields)
|
|
31
|
+
const title = item.name || item.title || item.key || `Entry ${i + 1}`;
|
|
32
|
+
// Extract content (try multiple fields)
|
|
33
|
+
let entryContent;
|
|
34
|
+
// Check observations array first (mcp-knowledge-graph)
|
|
35
|
+
if (item.observations && Array.isArray(item.observations) && item.observations.length > 0) {
|
|
36
|
+
entryContent = item.observations.join('\n\n');
|
|
37
|
+
}
|
|
38
|
+
// Fall back to common content fields
|
|
39
|
+
if (!entryContent) {
|
|
40
|
+
entryContent = item.content || item.text || item.description ||
|
|
41
|
+
item.value || item.memory || item.observation || item.body;
|
|
42
|
+
}
|
|
43
|
+
// Skip if no content found
|
|
44
|
+
if (!entryContent) {
|
|
40
45
|
skipped++;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
// Extract context
|
|
49
|
+
let context;
|
|
50
|
+
if (item.entityType) {
|
|
51
|
+
context = item.entityType;
|
|
52
|
+
}
|
|
53
|
+
else if (item.context) {
|
|
54
|
+
context = item.context;
|
|
55
|
+
}
|
|
56
|
+
else if (item.category) {
|
|
57
|
+
context = item.category;
|
|
58
|
+
}
|
|
59
|
+
else if (item.type && item.type !== 'entity' && item.type !== 'memory') {
|
|
60
|
+
context = item.type;
|
|
61
|
+
}
|
|
62
|
+
else if (item.tags && Array.isArray(item.tags)) {
|
|
63
|
+
context = item.tags.join(', ');
|
|
41
64
|
}
|
|
65
|
+
entries.push({
|
|
66
|
+
title: String(title),
|
|
67
|
+
content: String(entryContent),
|
|
68
|
+
context,
|
|
69
|
+
intent: item.intent ? String(item.intent) : undefined,
|
|
70
|
+
reasoning: item.reasoning ? String(item.reasoning) : undefined,
|
|
71
|
+
example: item.example ? String(item.example) : undefined,
|
|
72
|
+
source: 'jsonl',
|
|
73
|
+
});
|
|
42
74
|
}
|
|
43
75
|
catch (parseError) {
|
|
44
76
|
errors.push(`Line ${i + 1}: Invalid JSON - ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
@@ -146,14 +146,14 @@ export declare const ImportedLibrarySchema: z.ZodObject<{
|
|
|
146
146
|
name: string;
|
|
147
147
|
entry_count: number;
|
|
148
148
|
purchased_at: string;
|
|
149
|
-
sync_preference?: "manual" | "auto" | "pinned" | undefined;
|
|
150
149
|
last_synced?: string | undefined;
|
|
150
|
+
sync_preference?: "pinned" | "manual" | "auto" | undefined;
|
|
151
151
|
}, {
|
|
152
152
|
name: string;
|
|
153
153
|
entry_count: number;
|
|
154
154
|
purchased_at: string;
|
|
155
|
-
sync_preference?: "manual" | "auto" | "pinned" | undefined;
|
|
156
155
|
last_synced?: string | undefined;
|
|
156
|
+
sync_preference?: "pinned" | "manual" | "auto" | undefined;
|
|
157
157
|
}>;
|
|
158
158
|
export type ImportedLibrary = z.infer<typeof ImportedLibrarySchema>;
|
|
159
159
|
export declare const StateResultSchema: z.ZodObject<{
|
|
@@ -192,14 +192,14 @@ export declare const StateResultSchema: z.ZodObject<{
|
|
|
192
192
|
name: string;
|
|
193
193
|
entry_count: number;
|
|
194
194
|
purchased_at: string;
|
|
195
|
-
sync_preference?: "manual" | "auto" | "pinned" | undefined;
|
|
196
195
|
last_synced?: string | undefined;
|
|
196
|
+
sync_preference?: "pinned" | "manual" | "auto" | undefined;
|
|
197
197
|
}, {
|
|
198
198
|
name: string;
|
|
199
199
|
entry_count: number;
|
|
200
200
|
purchased_at: string;
|
|
201
|
-
sync_preference?: "manual" | "auto" | "pinned" | undefined;
|
|
202
201
|
last_synced?: string | undefined;
|
|
202
|
+
sync_preference?: "pinned" | "manual" | "auto" | undefined;
|
|
203
203
|
}>, "many">;
|
|
204
204
|
}, "strip", z.ZodTypeAny, {
|
|
205
205
|
entries: {
|
|
@@ -215,8 +215,8 @@ export declare const StateResultSchema: z.ZodObject<{
|
|
|
215
215
|
name: string;
|
|
216
216
|
entry_count: number;
|
|
217
217
|
purchased_at: string;
|
|
218
|
-
sync_preference?: "manual" | "auto" | "pinned" | undefined;
|
|
219
218
|
last_synced?: string | undefined;
|
|
219
|
+
sync_preference?: "pinned" | "manual" | "auto" | undefined;
|
|
220
220
|
}[];
|
|
221
221
|
}, {
|
|
222
222
|
entries: {
|
|
@@ -232,8 +232,8 @@ export declare const StateResultSchema: z.ZodObject<{
|
|
|
232
232
|
name: string;
|
|
233
233
|
entry_count: number;
|
|
234
234
|
purchased_at: string;
|
|
235
|
-
sync_preference?: "manual" | "auto" | "pinned" | undefined;
|
|
236
235
|
last_synced?: string | undefined;
|
|
236
|
+
sync_preference?: "pinned" | "manual" | "auto" | undefined;
|
|
237
237
|
}[];
|
|
238
238
|
}>;
|
|
239
239
|
export type StateResult = z.infer<typeof StateResultSchema>;
|
|
@@ -9,11 +9,11 @@ export declare function getLibraryPath(): string;
|
|
|
9
9
|
export declare function getLocalPath(libraryPath: string): string;
|
|
10
10
|
/**
|
|
11
11
|
* Get the imported entries path.
|
|
12
|
-
* @deprecated Use getPackagesPath for
|
|
12
|
+
* @deprecated Use getPackagesPath for library content
|
|
13
13
|
*/
|
|
14
14
|
export declare function getImportedPath(libraryPath: string): string;
|
|
15
15
|
/**
|
|
16
|
-
* Get the packages path (
|
|
16
|
+
* Get the packages path (library content from others).
|
|
17
17
|
*/
|
|
18
18
|
export declare function getPackagesPath(libraryPath: string): string;
|
|
19
19
|
/**
|
package/dist/library/storage.js
CHANGED
|
@@ -17,13 +17,13 @@ export function getLocalPath(libraryPath) {
|
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Get the imported entries path.
|
|
20
|
-
* @deprecated Use getPackagesPath for
|
|
20
|
+
* @deprecated Use getPackagesPath for library content
|
|
21
21
|
*/
|
|
22
22
|
export function getImportedPath(libraryPath) {
|
|
23
23
|
return path.join(libraryPath, 'imported');
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
* Get the packages path (
|
|
26
|
+
* Get the packages path (library content from others).
|
|
27
27
|
*/
|
|
28
28
|
export function getPackagesPath(libraryPath) {
|
|
29
29
|
return path.join(libraryPath, 'packages');
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get embedding for a text string.
|
|
3
|
+
* Returns a 384-dimensional normalized vector.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getEmbedding(text: string): Promise<number[]>;
|
|
6
|
+
/**
|
|
7
|
+
* Check if embeddings are available (model can load).
|
|
8
|
+
*/
|
|
9
|
+
export declare function isEmbeddingAvailable(): Promise<boolean>;
|
|
10
|
+
/**
|
|
11
|
+
* Calculate cosine similarity between two vectors.
|
|
12
|
+
* Since vectors are normalized, this is just the dot product.
|
|
13
|
+
*/
|
|
14
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
15
|
+
/**
|
|
16
|
+
* Split text into chunks at sentence boundaries.
|
|
17
|
+
* Aims for ~500 chars per chunk to preserve semantic meaning.
|
|
18
|
+
*/
|
|
19
|
+
export declare function chunkText(text: string, maxChars?: number): string[];
|
|
20
|
+
export declare const EMBEDDING_MODEL_ID = "Xenova/all-MiniLM-L6-v2";
|
|
21
|
+
export declare const EMBEDDING_DIMENSION = 384;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { pipeline, env } from '@huggingface/transformers';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { getLibraryPath } from './storage.js';
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Configuration
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Cache model in .librarian/models
|
|
8
|
+
env.allowRemoteModels = true;
|
|
9
|
+
const MODEL_ID = 'Xenova/all-MiniLM-L6-v2';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Embedding Generation
|
|
12
|
+
// ============================================================================
|
|
13
|
+
let embedder = null;
|
|
14
|
+
/**
|
|
15
|
+
* Get embedding for a text string.
|
|
16
|
+
* Returns a 384-dimensional normalized vector.
|
|
17
|
+
*/
|
|
18
|
+
export async function getEmbedding(text) {
|
|
19
|
+
if (!embedder) {
|
|
20
|
+
// Set local model path on first call
|
|
21
|
+
const libraryPath = getLibraryPath();
|
|
22
|
+
env.localModelPath = path.join(libraryPath, 'models');
|
|
23
|
+
embedder = await pipeline('feature-extraction', MODEL_ID);
|
|
24
|
+
}
|
|
25
|
+
const result = await embedder(text, { pooling: 'mean', normalize: true });
|
|
26
|
+
return Array.from(result.data);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if embeddings are available (model can load).
|
|
30
|
+
*/
|
|
31
|
+
export async function isEmbeddingAvailable() {
|
|
32
|
+
try {
|
|
33
|
+
await getEmbedding('test');
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// Similarity Calculation
|
|
42
|
+
// ============================================================================
|
|
43
|
+
/**
|
|
44
|
+
* Calculate cosine similarity between two vectors.
|
|
45
|
+
* Since vectors are normalized, this is just the dot product.
|
|
46
|
+
*/
|
|
47
|
+
export function cosineSimilarity(a, b) {
|
|
48
|
+
if (a.length !== b.length) {
|
|
49
|
+
throw new Error('Vectors must have same dimension');
|
|
50
|
+
}
|
|
51
|
+
return a.reduce((sum, val, i) => sum + val * b[i], 0);
|
|
52
|
+
}
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// Text Chunking
|
|
55
|
+
// ============================================================================
|
|
56
|
+
/**
|
|
57
|
+
* Split text into chunks at sentence boundaries.
|
|
58
|
+
* Aims for ~500 chars per chunk to preserve semantic meaning.
|
|
59
|
+
*/
|
|
60
|
+
export function chunkText(text, maxChars = 500) {
|
|
61
|
+
// Split at sentence boundaries (. ! ? followed by whitespace)
|
|
62
|
+
const sentences = text.split(/(?<=[.!?])\s+/);
|
|
63
|
+
const chunks = [];
|
|
64
|
+
let current = '';
|
|
65
|
+
for (const sentence of sentences) {
|
|
66
|
+
// If adding this sentence exceeds limit and we have content, start new chunk
|
|
67
|
+
if ((current + ' ' + sentence).length > maxChars && current.trim()) {
|
|
68
|
+
chunks.push(current.trim());
|
|
69
|
+
current = sentence;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
current = current ? current + ' ' + sentence : sentence;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Don't forget the last chunk
|
|
76
|
+
if (current.trim()) {
|
|
77
|
+
chunks.push(current.trim());
|
|
78
|
+
}
|
|
79
|
+
// If no chunks created (e.g., no sentence boundaries), return original text
|
|
80
|
+
return chunks.length > 0 ? chunks : [text];
|
|
81
|
+
}
|
|
82
|
+
// ============================================================================
|
|
83
|
+
// Constants
|
|
84
|
+
// ============================================================================
|
|
85
|
+
export const EMBEDDING_MODEL_ID = MODEL_ID;
|
|
86
|
+
export const EMBEDDING_DIMENSION = 384;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { LibraryEntry } from './schemas.js';
|
|
2
|
+
export declare class LibraryManager {
|
|
3
|
+
private libraryPath;
|
|
4
|
+
constructor();
|
|
5
|
+
/**
|
|
6
|
+
* Initialize the library directory structure.
|
|
7
|
+
*/
|
|
8
|
+
initialize(): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Get all entries from local library.
|
|
11
|
+
*/
|
|
12
|
+
getLocalEntries(): Promise<LibraryEntry[]>;
|
|
13
|
+
/**
|
|
14
|
+
* Get all entries from imported libraries.
|
|
15
|
+
*/
|
|
16
|
+
getImportedEntries(): Promise<LibraryEntry[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Get all archived entries.
|
|
19
|
+
*/
|
|
20
|
+
getArchivedEntries(): Promise<LibraryEntry[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Query entries by topic.
|
|
23
|
+
*/
|
|
24
|
+
queryByTopic(topic: string): Promise<LibraryEntry[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Record a new entry to local library.
|
|
27
|
+
*/
|
|
28
|
+
record(topics: string[], content: string): Promise<{
|
|
29
|
+
entry: LibraryEntry;
|
|
30
|
+
path: string;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Archive an entry (move to archived/).
|
|
34
|
+
*/
|
|
35
|
+
archive(entryId: string): Promise<{
|
|
36
|
+
success: boolean;
|
|
37
|
+
message: string;
|
|
38
|
+
}>;
|
|
39
|
+
private readEntriesFromPath;
|
|
40
|
+
private findEntryById;
|
|
41
|
+
private fileExists;
|
|
42
|
+
}
|