@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.
Files changed (121) hide show
  1. package/dist/library/errors.d.ts +48 -0
  2. package/dist/library/errors.js +80 -0
  3. package/dist/library/parsers/jsonl.d.ts +9 -4
  4. package/dist/library/parsers/jsonl.js +52 -20
  5. package/dist/library/schemas.d.ts +6 -6
  6. package/dist/library/storage.d.ts +2 -2
  7. package/dist/library/storage.js +2 -2
  8. package/dist/library 2/embeddings.d.ts +21 -0
  9. package/dist/library 2/embeddings.js +86 -0
  10. package/dist/library 2/manager.d.ts +42 -0
  11. package/dist/library 2/manager.js +218 -0
  12. package/dist/library 2/parsers/cursor.d.ts +15 -0
  13. package/dist/library 2/parsers/cursor.js +168 -0
  14. package/dist/library 2/parsers/index.d.ts +6 -0
  15. package/dist/library 2/parsers/index.js +5 -0
  16. package/dist/library 2/parsers/json.d.ts +11 -0
  17. package/dist/library 2/parsers/json.js +95 -0
  18. package/dist/library 2/parsers/jsonl.d.ts +14 -0
  19. package/dist/library 2/parsers/jsonl.js +85 -0
  20. package/dist/library 2/parsers/markdown.d.ts +15 -0
  21. package/dist/library 2/parsers/markdown.js +77 -0
  22. package/dist/library 2/parsers/sqlite.d.ts +8 -0
  23. package/dist/library 2/parsers/sqlite.js +123 -0
  24. package/dist/library 2/parsers/types.d.ts +21 -0
  25. package/dist/library 2/parsers/types.js +4 -0
  26. package/dist/library 2/query.d.ts +26 -0
  27. package/dist/library 2/query.js +104 -0
  28. package/dist/library 2/schemas.d.ts +324 -0
  29. package/dist/library 2/schemas.js +79 -0
  30. package/dist/library 2/storage.d.ts +22 -0
  31. package/dist/library 2/storage.js +36 -0
  32. package/dist/library 2/vector-index.d.ts +55 -0
  33. package/dist/library 2/vector-index.js +160 -0
  34. package/dist/server 2.js +199 -0
  35. package/dist/server.d 2.ts +2 -0
  36. package/dist/server.js +102 -54
  37. package/dist/tools/adopt.d.ts +1 -0
  38. package/dist/tools/adopt.js +37 -10
  39. package/dist/tools/auth.d.ts +69 -0
  40. package/dist/tools/auth.js +379 -0
  41. package/dist/tools/bounty-claim.d.ts +28 -0
  42. package/dist/tools/bounty-claim.js +92 -0
  43. package/dist/tools/bounty-create.d.ts +47 -0
  44. package/dist/tools/bounty-create.js +118 -0
  45. package/dist/tools/bounty-list.d.ts +50 -0
  46. package/dist/tools/bounty-list.js +116 -0
  47. package/dist/tools/bounty-submit.d.ts +34 -0
  48. package/dist/tools/bounty-submit.js +94 -0
  49. package/dist/tools/brief.d.ts +94 -0
  50. package/dist/tools/brief.js +234 -15
  51. package/dist/tools/delete.d.ts +87 -0
  52. package/dist/tools/delete.js +266 -0
  53. package/dist/tools/feedback.d.ts +27 -0
  54. package/dist/tools/feedback.js +98 -0
  55. package/dist/tools/help.d.ts +22 -0
  56. package/dist/tools/help.js +482 -0
  57. package/dist/tools/import-memories.d.ts +1 -0
  58. package/dist/tools/import-memories.js +18 -13
  59. package/dist/tools/index.d.ts +11 -0
  60. package/dist/tools/index.js +12 -0
  61. package/dist/tools/library-buy.d.ts +31 -0
  62. package/dist/tools/library-buy.js +104 -0
  63. package/dist/tools/library-download.d.ts +27 -0
  64. package/dist/tools/library-download.js +177 -0
  65. package/dist/tools/library-publish.d.ts +112 -0
  66. package/dist/tools/library-publish.js +387 -0
  67. package/dist/tools/library-search.d.ts +110 -0
  68. package/dist/tools/library-search.js +132 -0
  69. package/dist/tools/mark-hit.d.ts +1 -0
  70. package/dist/tools/mark-hit.js +83 -5
  71. package/dist/tools/my-books.d.ts +51 -0
  72. package/dist/tools/my-books.js +115 -0
  73. package/dist/tools/my-bounties.d.ts +43 -0
  74. package/dist/tools/my-bounties.js +126 -0
  75. package/dist/tools/rate-book.d.ts +40 -0
  76. package/dist/tools/rate-book.js +147 -0
  77. package/dist/tools/rebuild-index.d.ts +1 -0
  78. package/dist/tools/rebuild-index.js +40 -8
  79. package/dist/tools/record.d.ts +18 -0
  80. package/dist/tools/record.js +30 -26
  81. package/dist/tools/seller-analytics.d.ts +53 -0
  82. package/dist/tools/seller-analytics.js +180 -0
  83. package/dist/tools/sync.d.ts +55 -0
  84. package/dist/tools/sync.js +304 -0
  85. package/dist/tools/unsubscribe.d.ts +48 -0
  86. package/dist/tools/unsubscribe.js +120 -0
  87. package/dist/tools 2/adopt.d.ts +24 -0
  88. package/dist/tools 2/adopt.js +154 -0
  89. package/dist/tools 2/auth.d.ts +35 -0
  90. package/dist/tools 2/auth.js +229 -0
  91. package/dist/tools 2/brief.d.ts +56 -0
  92. package/dist/tools 2/brief.js +414 -0
  93. package/dist/tools 2/help.d.ts +21 -0
  94. package/dist/tools 2/help.js +267 -0
  95. package/dist/tools 2/import-memories.d.ts +32 -0
  96. package/dist/tools 2/import-memories.js +231 -0
  97. package/dist/tools 2/index.d.ts +12 -0
  98. package/dist/tools 2/index.js +12 -0
  99. package/dist/tools 2/mark-hit.d.ts +20 -0
  100. package/dist/tools 2/mark-hit.js +71 -0
  101. package/dist/tools 2/marketplace-buy.d.ts +30 -0
  102. package/dist/tools 2/marketplace-buy.js +97 -0
  103. package/dist/tools 2/marketplace-download.d.ts +26 -0
  104. package/dist/tools 2/marketplace-download.js +160 -0
  105. package/dist/tools 2/marketplace-publish.d.ts +111 -0
  106. package/dist/tools 2/marketplace-publish.js +377 -0
  107. package/dist/tools 2/marketplace-search.d.ts +57 -0
  108. package/dist/tools 2/marketplace-search.js +96 -0
  109. package/dist/tools 2/my-books.d.ts +50 -0
  110. package/dist/tools 2/my-books.js +107 -0
  111. package/dist/tools 2/rate-book.d.ts +39 -0
  112. package/dist/tools 2/rate-book.js +139 -0
  113. package/dist/tools 2/rebuild-index.d.ts +23 -0
  114. package/dist/tools 2/rebuild-index.js +107 -0
  115. package/dist/tools 2/record.d.ts +40 -0
  116. package/dist/tools 2/record.js +205 -0
  117. package/dist/tools 2/seller-analytics.d.ts +35 -0
  118. package/dist/tools 2/seller-analytics.js +102 -0
  119. package/dist/tools 2/sync.d.ts +54 -0
  120. package/dist/tools 2/sync.js +298 -0
  121. 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 (Anthropic MCP Memory / mcp-knowledge-graph format).
3
+ * Parse a JSONL file. Supports multiple formats:
4
4
  *
5
- * Input format:
6
- * {"type":"entity","name":"Stripe Webhooks","entityType":"concept","observations":["Need idempotency checks"]}
7
- * {"type":"relation","from":"Stripe Webhooks","to":"Payment Processing","relationType":"part_of"}
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 (Anthropic MCP Memory / mcp-knowledge-graph format).
3
+ * Parse a JSONL file. Supports multiple formats:
4
4
  *
5
- * Input format:
6
- * {"type":"entity","name":"Stripe Webhooks","entityType":"concept","observations":["Need idempotency checks"]}
7
- * {"type":"relation","from":"Stripe Webhooks","to":"Payment Processing","relationType":"part_of"}
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 safety markers and relations
25
+ // Skip internal markers and relations
21
26
  if (item.type === '_aim' || item.type === 'relation') {
22
27
  skipped++;
23
28
  continue;
24
29
  }
25
- // Only process entities
26
- if (item.type === 'entity' && item.name) {
27
- // Skip if no observations (empty content)
28
- if (!item.observations || item.observations.length === 0) {
29
- skipped++;
30
- continue;
31
- }
32
- entries.push({
33
- title: item.name,
34
- content: item.observations.join('\n\n'),
35
- context: item.entityType || undefined,
36
- source: 'jsonl',
37
- });
38
- }
39
- else {
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 marketplace content
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 (marketplace content from others).
16
+ * Get the packages path (library content from others).
17
17
  */
18
18
  export declare function getPackagesPath(libraryPath: string): string;
19
19
  /**
@@ -17,13 +17,13 @@ export function getLocalPath(libraryPath) {
17
17
  }
18
18
  /**
19
19
  * Get the imported entries path.
20
- * @deprecated Use getPackagesPath for marketplace content
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 (marketplace content from others).
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
+ }