@twelvehart/supermemory-runtime 1.0.0-next.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 (156) hide show
  1. package/.env.example +57 -0
  2. package/README.md +374 -0
  3. package/dist/index.js +189 -0
  4. package/dist/mcp/index.js +1132 -0
  5. package/docker-compose.prod.yml +91 -0
  6. package/docker-compose.yml +358 -0
  7. package/drizzle/0000_dapper_the_professor.sql +159 -0
  8. package/drizzle/0001_api_keys.sql +51 -0
  9. package/drizzle/meta/0000_snapshot.json +1532 -0
  10. package/drizzle/meta/_journal.json +13 -0
  11. package/drizzle.config.ts +20 -0
  12. package/package.json +114 -0
  13. package/scripts/add-extraction-job.ts +122 -0
  14. package/scripts/benchmark-pgvector.ts +122 -0
  15. package/scripts/bootstrap.sh +209 -0
  16. package/scripts/check-runtime-pack.ts +111 -0
  17. package/scripts/claude-mcp-config.ts +336 -0
  18. package/scripts/docker-entrypoint.sh +183 -0
  19. package/scripts/doctor.ts +377 -0
  20. package/scripts/init-db.sql +33 -0
  21. package/scripts/install.sh +1110 -0
  22. package/scripts/mcp-setup.ts +271 -0
  23. package/scripts/migrations/001_create_pgvector_extension.sql +31 -0
  24. package/scripts/migrations/002_create_memory_embeddings_table.sql +75 -0
  25. package/scripts/migrations/003_create_hnsw_index.sql +94 -0
  26. package/scripts/migrations/004_create_memory_embeddings_standalone.sql +70 -0
  27. package/scripts/migrations/005_create_chunks_table.sql +95 -0
  28. package/scripts/migrations/006_create_processing_queue.sql +45 -0
  29. package/scripts/migrations/generate_test_data.sql +42 -0
  30. package/scripts/migrations/phase1_comprehensive_test.sql +204 -0
  31. package/scripts/migrations/run_migrations.sh +286 -0
  32. package/scripts/migrations/test_hnsw_index.sql +255 -0
  33. package/scripts/pre-commit-secrets +282 -0
  34. package/scripts/run-extraction-worker.ts +46 -0
  35. package/scripts/run-phase1-tests.sh +291 -0
  36. package/scripts/setup.ts +222 -0
  37. package/scripts/smoke-install.sh +12 -0
  38. package/scripts/test-health-endpoint.sh +328 -0
  39. package/src/api/index.ts +2 -0
  40. package/src/api/middleware/auth.ts +80 -0
  41. package/src/api/middleware/csrf.ts +308 -0
  42. package/src/api/middleware/errorHandler.ts +166 -0
  43. package/src/api/middleware/rateLimit.ts +360 -0
  44. package/src/api/middleware/validation.ts +514 -0
  45. package/src/api/routes/documents.ts +286 -0
  46. package/src/api/routes/profiles.ts +237 -0
  47. package/src/api/routes/search.ts +71 -0
  48. package/src/api/stores/index.ts +58 -0
  49. package/src/config/bootstrap-env.ts +3 -0
  50. package/src/config/env.ts +71 -0
  51. package/src/config/feature-flags.ts +25 -0
  52. package/src/config/index.ts +140 -0
  53. package/src/config/secrets.config.ts +291 -0
  54. package/src/db/client.ts +92 -0
  55. package/src/db/index.ts +73 -0
  56. package/src/db/postgres.ts +72 -0
  57. package/src/db/schema/chunks.schema.ts +31 -0
  58. package/src/db/schema/containers.schema.ts +46 -0
  59. package/src/db/schema/documents.schema.ts +49 -0
  60. package/src/db/schema/embeddings.schema.ts +32 -0
  61. package/src/db/schema/index.ts +11 -0
  62. package/src/db/schema/memories.schema.ts +72 -0
  63. package/src/db/schema/profiles.schema.ts +34 -0
  64. package/src/db/schema/queue.schema.ts +59 -0
  65. package/src/db/schema/relationships.schema.ts +42 -0
  66. package/src/db/schema.ts +223 -0
  67. package/src/db/worker-connection.ts +47 -0
  68. package/src/index.ts +235 -0
  69. package/src/mcp/CLAUDE.md +1 -0
  70. package/src/mcp/index.ts +1380 -0
  71. package/src/mcp/legacyState.ts +22 -0
  72. package/src/mcp/rateLimit.ts +358 -0
  73. package/src/mcp/resources.ts +309 -0
  74. package/src/mcp/results.ts +104 -0
  75. package/src/mcp/tools.ts +401 -0
  76. package/src/queues/config.ts +119 -0
  77. package/src/queues/index.ts +289 -0
  78. package/src/sdk/client.ts +225 -0
  79. package/src/sdk/errors.ts +266 -0
  80. package/src/sdk/http.ts +560 -0
  81. package/src/sdk/index.ts +244 -0
  82. package/src/sdk/resources/base.ts +65 -0
  83. package/src/sdk/resources/connections.ts +204 -0
  84. package/src/sdk/resources/documents.ts +163 -0
  85. package/src/sdk/resources/index.ts +10 -0
  86. package/src/sdk/resources/memories.ts +150 -0
  87. package/src/sdk/resources/search.ts +60 -0
  88. package/src/sdk/resources/settings.ts +36 -0
  89. package/src/sdk/types.ts +674 -0
  90. package/src/services/chunking/index.ts +451 -0
  91. package/src/services/chunking.service.ts +650 -0
  92. package/src/services/csrf.service.ts +252 -0
  93. package/src/services/documents.repository.ts +219 -0
  94. package/src/services/documents.service.ts +191 -0
  95. package/src/services/embedding.service.ts +404 -0
  96. package/src/services/extraction.service.ts +300 -0
  97. package/src/services/extractors/code.extractor.ts +451 -0
  98. package/src/services/extractors/index.ts +9 -0
  99. package/src/services/extractors/markdown.extractor.ts +461 -0
  100. package/src/services/extractors/pdf.extractor.ts +315 -0
  101. package/src/services/extractors/text.extractor.ts +118 -0
  102. package/src/services/extractors/url.extractor.ts +243 -0
  103. package/src/services/index.ts +235 -0
  104. package/src/services/ingestion.service.ts +177 -0
  105. package/src/services/llm/anthropic.ts +400 -0
  106. package/src/services/llm/base.ts +460 -0
  107. package/src/services/llm/contradiction-detector.service.ts +526 -0
  108. package/src/services/llm/heuristics.ts +148 -0
  109. package/src/services/llm/index.ts +309 -0
  110. package/src/services/llm/memory-classifier.service.ts +383 -0
  111. package/src/services/llm/memory-extension-detector.service.ts +523 -0
  112. package/src/services/llm/mock.ts +470 -0
  113. package/src/services/llm/openai.ts +398 -0
  114. package/src/services/llm/prompts.ts +438 -0
  115. package/src/services/llm/types.ts +373 -0
  116. package/src/services/memory.repository.ts +1769 -0
  117. package/src/services/memory.service.ts +1338 -0
  118. package/src/services/memory.types.ts +234 -0
  119. package/src/services/persistence/index.ts +295 -0
  120. package/src/services/pipeline.service.ts +509 -0
  121. package/src/services/profile.repository.ts +436 -0
  122. package/src/services/profile.service.ts +560 -0
  123. package/src/services/profile.types.ts +270 -0
  124. package/src/services/relationships/detector.ts +1128 -0
  125. package/src/services/relationships/index.ts +268 -0
  126. package/src/services/relationships/memory-integration.ts +459 -0
  127. package/src/services/relationships/strategies.ts +132 -0
  128. package/src/services/relationships/types.ts +370 -0
  129. package/src/services/search.service.ts +761 -0
  130. package/src/services/search.types.ts +220 -0
  131. package/src/services/secrets.service.ts +384 -0
  132. package/src/services/vectorstore/base.ts +327 -0
  133. package/src/services/vectorstore/index.ts +444 -0
  134. package/src/services/vectorstore/memory.ts +286 -0
  135. package/src/services/vectorstore/migration.ts +295 -0
  136. package/src/services/vectorstore/mock.ts +403 -0
  137. package/src/services/vectorstore/pgvector.ts +695 -0
  138. package/src/services/vectorstore/types.ts +247 -0
  139. package/src/startup.ts +389 -0
  140. package/src/types/api.types.ts +193 -0
  141. package/src/types/document.types.ts +103 -0
  142. package/src/types/index.ts +241 -0
  143. package/src/types/profile.base.ts +133 -0
  144. package/src/utils/errors.ts +447 -0
  145. package/src/utils/id.ts +15 -0
  146. package/src/utils/index.ts +101 -0
  147. package/src/utils/logger.ts +313 -0
  148. package/src/utils/sanitization.ts +501 -0
  149. package/src/utils/secret-validation.ts +273 -0
  150. package/src/utils/synonyms.ts +188 -0
  151. package/src/utils/validation.ts +581 -0
  152. package/src/workers/chunking.worker.ts +242 -0
  153. package/src/workers/embedding.worker.ts +358 -0
  154. package/src/workers/extraction.worker.ts +346 -0
  155. package/src/workers/indexing.worker.ts +505 -0
  156. package/tsconfig.json +38 -0
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Services Index
3
+ *
4
+ * Export all services for the Supermemory Clone
5
+ */
6
+
7
+ // Memory System
8
+ export * from './memory.types.js'
9
+ export * from './memory.repository.js'
10
+ export {
11
+ MemoryService,
12
+ getMemoryService,
13
+ resetMemoryService,
14
+ createMemoryService,
15
+ memoryService,
16
+ } from './memory.service.js'
17
+
18
+ // Profile System
19
+ export * from './profile.types.js'
20
+ export * from './profile.repository.js'
21
+ export * from './profile.service.js'
22
+
23
+ // Document System
24
+ export * from './documents.repository.js'
25
+ export * from './documents.service.js'
26
+
27
+ // Search & Embedding System
28
+ export * from './search.types.js'
29
+ export {
30
+ EmbeddingService,
31
+ cosineSimilarity,
32
+ createEmbeddingService,
33
+ getEmbeddingService,
34
+ resetEmbeddingService,
35
+ embeddingService,
36
+ } from './embedding.service.js'
37
+ export {
38
+ SearchService,
39
+ createSearchService,
40
+ createSearchServiceWithVectorStore,
41
+ getSearchService,
42
+ resetSearchService,
43
+ searchService,
44
+ } from './search.service.js'
45
+
46
+ // Vector Store System
47
+ // Using explicit exports to avoid name collisions with search.types.js
48
+ export {
49
+ // Types
50
+ type VectorStoreProvider,
51
+ type IndexType,
52
+ type FilterOperator,
53
+ type MetadataFilter as VectorMetadataFilter,
54
+ type VectorEntry as VectorStoreEntry,
55
+ type SearchOptions as VectorSearchOptions,
56
+ type VectorSearchResult as VectorStoreSearchResult,
57
+ type AddOptions as VectorAddOptions,
58
+ type DeleteOptions as VectorDeleteOptions,
59
+ type VectorStoreConfig,
60
+ type HNSWConfig,
61
+ type VectorStoreStats,
62
+ type BatchResult,
63
+ type MigrationOptions,
64
+ type MigrationProgress,
65
+ type VectorStoreEvent,
66
+ type VectorStoreEventListener,
67
+
68
+ // Constants
69
+ DEFAULT_SEARCH_OPTIONS as VECTOR_DEFAULT_SEARCH_OPTIONS,
70
+ DEFAULT_HNSW_CONFIG,
71
+
72
+ // Base class and utilities
73
+ BaseVectorStore,
74
+ cosineSimilarity as vectorCosineSimilarity,
75
+ euclideanDistance,
76
+ dotProduct,
77
+ normalizeVector,
78
+ validateVector,
79
+
80
+ // Implementations
81
+ InMemoryVectorStore,
82
+ createInMemoryVectorStore,
83
+ MockVectorStore,
84
+ createMockVectorStore,
85
+
86
+ // Factory functions
87
+ createVectorStore,
88
+ createAndInitializeVectorStore,
89
+ configureVectorStore,
90
+ getVectorStore,
91
+ getInitializedVectorStore,
92
+ resetVectorStore,
93
+ getAvailableProviders as getAvailableVectorProviders,
94
+ getBestProvider as getBestVectorProvider,
95
+
96
+ // Migration
97
+ migrateVectorStore,
98
+ reindexVectorStore,
99
+ getDefaultVectorStoreConfig,
100
+ } from './vectorstore/index.js'
101
+
102
+ // Re-export singleton instances for convenience
103
+ export { profileRepository } from './profile.repository.js'
104
+ export { profileService } from './profile.service.js'
105
+
106
+ // Relationship Detection System
107
+ // Note: Using explicit exports to avoid name collisions with memory.types.js and search.types.js
108
+ export {
109
+ // Types
110
+ type RelationshipConfig,
111
+ type RelationshipThresholds,
112
+ type RelationshipCandidate,
113
+ type DetectedRelationship,
114
+ type RelationshipDetectionResult as EmbeddingRelationshipDetectionResult,
115
+ type RelationshipDetectionStats,
116
+ type Contradiction,
117
+ type ContradictionType,
118
+ type ContradictionResolution,
119
+ type DetectionStrategyType,
120
+ type VectorStore as RelationshipVectorStore,
121
+ type VectorSearchResult as RelationshipVectorSearchResult,
122
+ type LLMProvider,
123
+ type LLMVerificationRequest,
124
+ type LLMVerificationResponse,
125
+ type CachedRelationshipScore,
126
+
127
+ // Constants
128
+ DEFAULT_RELATIONSHIP_CONFIG,
129
+ DEFAULT_RELATIONSHIP_THRESHOLDS,
130
+ generateCacheKey,
131
+
132
+ // Detector
133
+ EmbeddingRelationshipDetector,
134
+ InMemoryVectorStoreAdapter,
135
+ createEmbeddingRelationshipDetector,
136
+
137
+ // Factory Functions
138
+ getSharedVectorStore,
139
+ getRelationshipDetector,
140
+ resetRelationshipDetector,
141
+ createRelationshipDetector,
142
+ detectRelationshipsQuick,
143
+ batchDetectRelationshipsQuick,
144
+ detectContradictionsQuick,
145
+
146
+ // Integration Helpers
147
+ indexMemoryForRelationships,
148
+ removeMemoryFromRelationshipIndex,
149
+ clearRelationshipIndex,
150
+
151
+ // Enhanced Memory Service
152
+ EnhancedMemoryService,
153
+ createEnhancedMemoryService,
154
+ getEnhancedMemoryService,
155
+ resetEnhancedMemoryService,
156
+ enhancedMemoryService,
157
+ type EnhancedMemoryServiceConfig,
158
+ DEFAULT_ENHANCED_CONFIG,
159
+ } from './relationships/index.js'
160
+
161
+ // Content Extraction Pipeline
162
+ export { ExtractionService } from './extraction.service.js'
163
+ export { ChunkingService } from './chunking.service.js'
164
+ export { PipelineService } from './pipeline.service.js'
165
+
166
+ // Extractors
167
+ export { TextExtractor } from './extractors/text.extractor.js'
168
+ export { UrlExtractor } from './extractors/url.extractor.js'
169
+ export { PdfExtractor } from './extractors/pdf.extractor.js'
170
+ export { MarkdownExtractor, type MarkdownSection } from './extractors/markdown.extractor.js'
171
+ export { CodeExtractor, type CodeBlock } from './extractors/code.extractor.js'
172
+
173
+ // Secrets Management
174
+ export {
175
+ SecretsService,
176
+ getSecretsService,
177
+ initializeSecretsService,
178
+ type EncryptedSecret,
179
+ type SecretMetadata,
180
+ type SecretValidationResult,
181
+ } from './secrets.service.js'
182
+
183
+ // LLM Providers for Memory Extraction
184
+ export {
185
+ // Types
186
+ type LLMProvider as LLMExtractionProvider,
187
+ type LLMProviderType,
188
+ type LLMConfig,
189
+ type OpenAILLMConfig,
190
+ type AnthropicLLMConfig,
191
+ type MockLLMConfig,
192
+ type ExtractedMemory,
193
+ type LLMExtractionResult,
194
+ type LLMRelationshipResult,
195
+ type DetectedRelationship as LLMDetectedRelationship,
196
+ type ExtractionOptions,
197
+ type RelationshipDetectionOptions as LLMRelationshipDetectionOptions,
198
+ type ProviderHealthStatus,
199
+ type CacheConfig as LLMCacheConfig,
200
+ LLMErrorCode,
201
+
202
+ // Base
203
+ BaseLLMProvider,
204
+ LLMError,
205
+ DEFAULT_LLM_CONFIG,
206
+ DEFAULT_CACHE_CONFIG as DEFAULT_LLM_CACHE_CONFIG,
207
+
208
+ // Providers
209
+ OpenAILLMProvider,
210
+ createOpenAIProvider,
211
+ AnthropicLLMProvider,
212
+ createAnthropicProvider,
213
+ MockLLMProvider,
214
+ createMockProvider,
215
+
216
+ // Factory
217
+ createLLMProvider,
218
+ getLLMProvider,
219
+ resetLLMProvider,
220
+ setLLMProvider,
221
+ llmProvider,
222
+ getDefaultProviderType,
223
+ isLLMAvailable,
224
+ getAvailableProviders,
225
+
226
+ // Prompts (for testing/customization)
227
+ MEMORY_EXTRACTION_SYSTEM_PROMPT,
228
+ MEMORY_EXTRACTION_EXAMPLES,
229
+ RELATIONSHIP_DETECTION_SYSTEM_PROMPT,
230
+ RELATIONSHIP_DETECTION_EXAMPLES,
231
+ generateExtractionPrompt,
232
+ generateRelationshipPrompt,
233
+ parseExtractionResponse,
234
+ parseRelationshipResponse,
235
+ } from './llm/index.js'
@@ -0,0 +1,177 @@
1
+ import { eq } from 'drizzle-orm'
2
+ import { getDatabaseUrl, isPostgresUrl } from '../db/client.js'
3
+ import { getPostgresDatabase } from '../db/postgres.js'
4
+ import { documents, processingQueue } from '../db/schema/index.js'
5
+ import { extractionQueue } from '../queues/index.js'
6
+ import { createMemoryService } from './memory.service.js'
7
+ import { createSearchService } from './search.service.js'
8
+ import { ProfileService } from './profile.service.js'
9
+ import { getLogger } from '../utils/logger.js'
10
+
11
+ const logger = getLogger('ingestion-service')
12
+
13
+ export interface EnqueueDocumentInput {
14
+ documentId: string
15
+ content: string
16
+ containerTag: string
17
+ sourceType: 'text' | 'url' | 'file'
18
+ sourceUrl?: string
19
+ filePath?: string
20
+ }
21
+
22
+ export interface EnqueueDocumentResult {
23
+ mode: 'queue' | 'inline'
24
+ queued: boolean
25
+ queueJobId?: string
26
+ queueRecordId?: string
27
+ memoriesIndexed?: number
28
+ error?: string
29
+ }
30
+
31
+ function getPostgresDbOrNull() {
32
+ const url = getDatabaseUrl()
33
+ if (!isPostgresUrl(url)) {
34
+ return null
35
+ }
36
+ return getPostgresDatabase(url)
37
+ }
38
+
39
+ async function processInline(input: EnqueueDocumentInput): Promise<EnqueueDocumentResult> {
40
+ const db = getPostgresDbOrNull()
41
+
42
+ try {
43
+ const memoryService = createMemoryService()
44
+ const searchService = createSearchService()
45
+ const profileService = new ProfileService()
46
+
47
+ const processed = await memoryService.processAndStoreMemories(input.content, {
48
+ containerTag: input.containerTag,
49
+ sourceId: input.documentId,
50
+ })
51
+
52
+ for (const memory of processed.memories) {
53
+ await searchService.indexMemory(memory)
54
+ }
55
+
56
+ await profileService.ingestContent(input.containerTag, input.content, input.documentId)
57
+
58
+ if (db) {
59
+ await db
60
+ .update(documents)
61
+ .set({ status: 'processed', updatedAt: new Date() })
62
+ .where(eq(documents.id, input.documentId))
63
+ }
64
+
65
+ return {
66
+ mode: 'inline',
67
+ queued: false,
68
+ memoriesIndexed: processed.memories.length,
69
+ }
70
+ } catch (error) {
71
+ if (db) {
72
+ try {
73
+ await db
74
+ .update(documents)
75
+ .set({ status: 'failed', updatedAt: new Date() })
76
+ .where(eq(documents.id, input.documentId))
77
+ } catch (updateError) {
78
+ logger.warn(
79
+ 'Failed to update document status after inline ingestion failure',
80
+ { documentId: input.documentId },
81
+ updateError instanceof Error ? updateError : undefined
82
+ )
83
+ }
84
+ }
85
+
86
+ const message = error instanceof Error ? error.message : 'Unknown ingestion error'
87
+ return {
88
+ mode: 'inline',
89
+ queued: false,
90
+ error: message,
91
+ }
92
+ }
93
+ }
94
+
95
+ export async function enqueueDocumentForProcessing(input: EnqueueDocumentInput): Promise<EnqueueDocumentResult> {
96
+ const db = getPostgresDbOrNull()
97
+
98
+ if (process.env.NODE_ENV === 'test' || !db) {
99
+ return processInline(input)
100
+ }
101
+
102
+ let queueRecordId: string | undefined
103
+
104
+ try {
105
+ const queueRecords = await db
106
+ .insert(processingQueue)
107
+ .values({
108
+ documentId: input.documentId,
109
+ stage: 'extraction',
110
+ status: 'pending',
111
+ priority: 0,
112
+ metadata: {
113
+ sourceType: input.sourceType,
114
+ sourceUrl: input.sourceUrl,
115
+ filePath: input.filePath,
116
+ },
117
+ })
118
+ .returning({ id: processingQueue.id })
119
+
120
+ queueRecordId = queueRecords[0]?.id
121
+
122
+ const queueJob = await extractionQueue.add(
123
+ 'extract-document',
124
+ {
125
+ documentId: input.documentId,
126
+ containerTag: input.containerTag,
127
+ sourceType: input.sourceType,
128
+ sourceUrl: input.sourceUrl,
129
+ filePath: input.filePath,
130
+ },
131
+ {
132
+ attempts: 3,
133
+ backoff: {
134
+ type: 'exponential',
135
+ delay: 2000,
136
+ },
137
+ }
138
+ )
139
+
140
+ await db
141
+ .update(documents)
142
+ .set({ status: 'processing', updatedAt: new Date() })
143
+ .where(eq(documents.id, input.documentId))
144
+
145
+ return {
146
+ mode: 'queue',
147
+ queued: true,
148
+ queueJobId: queueJob.id?.toString(),
149
+ queueRecordId,
150
+ }
151
+ } catch (error) {
152
+ const message = error instanceof Error ? error.message : 'Unknown queue ingestion error'
153
+
154
+ logger.warn(
155
+ 'Queue ingestion unavailable, falling back to inline ingestion',
156
+ { documentId: input.documentId, error: message },
157
+ error instanceof Error ? error : undefined
158
+ )
159
+
160
+ if (queueRecordId) {
161
+ try {
162
+ await db
163
+ .update(processingQueue)
164
+ .set({
165
+ status: 'failed',
166
+ error: message,
167
+ completedAt: new Date(),
168
+ })
169
+ .where(eq(processingQueue.id, queueRecordId))
170
+ } catch {
171
+ // Best effort only.
172
+ }
173
+ }
174
+
175
+ return processInline(input)
176
+ }
177
+ }