@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.
- package/.env.example +57 -0
- package/README.md +374 -0
- package/dist/index.js +189 -0
- package/dist/mcp/index.js +1132 -0
- package/docker-compose.prod.yml +91 -0
- package/docker-compose.yml +358 -0
- package/drizzle/0000_dapper_the_professor.sql +159 -0
- package/drizzle/0001_api_keys.sql +51 -0
- package/drizzle/meta/0000_snapshot.json +1532 -0
- package/drizzle/meta/_journal.json +13 -0
- package/drizzle.config.ts +20 -0
- package/package.json +114 -0
- package/scripts/add-extraction-job.ts +122 -0
- package/scripts/benchmark-pgvector.ts +122 -0
- package/scripts/bootstrap.sh +209 -0
- package/scripts/check-runtime-pack.ts +111 -0
- package/scripts/claude-mcp-config.ts +336 -0
- package/scripts/docker-entrypoint.sh +183 -0
- package/scripts/doctor.ts +377 -0
- package/scripts/init-db.sql +33 -0
- package/scripts/install.sh +1110 -0
- package/scripts/mcp-setup.ts +271 -0
- package/scripts/migrations/001_create_pgvector_extension.sql +31 -0
- package/scripts/migrations/002_create_memory_embeddings_table.sql +75 -0
- package/scripts/migrations/003_create_hnsw_index.sql +94 -0
- package/scripts/migrations/004_create_memory_embeddings_standalone.sql +70 -0
- package/scripts/migrations/005_create_chunks_table.sql +95 -0
- package/scripts/migrations/006_create_processing_queue.sql +45 -0
- package/scripts/migrations/generate_test_data.sql +42 -0
- package/scripts/migrations/phase1_comprehensive_test.sql +204 -0
- package/scripts/migrations/run_migrations.sh +286 -0
- package/scripts/migrations/test_hnsw_index.sql +255 -0
- package/scripts/pre-commit-secrets +282 -0
- package/scripts/run-extraction-worker.ts +46 -0
- package/scripts/run-phase1-tests.sh +291 -0
- package/scripts/setup.ts +222 -0
- package/scripts/smoke-install.sh +12 -0
- package/scripts/test-health-endpoint.sh +328 -0
- package/src/api/index.ts +2 -0
- package/src/api/middleware/auth.ts +80 -0
- package/src/api/middleware/csrf.ts +308 -0
- package/src/api/middleware/errorHandler.ts +166 -0
- package/src/api/middleware/rateLimit.ts +360 -0
- package/src/api/middleware/validation.ts +514 -0
- package/src/api/routes/documents.ts +286 -0
- package/src/api/routes/profiles.ts +237 -0
- package/src/api/routes/search.ts +71 -0
- package/src/api/stores/index.ts +58 -0
- package/src/config/bootstrap-env.ts +3 -0
- package/src/config/env.ts +71 -0
- package/src/config/feature-flags.ts +25 -0
- package/src/config/index.ts +140 -0
- package/src/config/secrets.config.ts +291 -0
- package/src/db/client.ts +92 -0
- package/src/db/index.ts +73 -0
- package/src/db/postgres.ts +72 -0
- package/src/db/schema/chunks.schema.ts +31 -0
- package/src/db/schema/containers.schema.ts +46 -0
- package/src/db/schema/documents.schema.ts +49 -0
- package/src/db/schema/embeddings.schema.ts +32 -0
- package/src/db/schema/index.ts +11 -0
- package/src/db/schema/memories.schema.ts +72 -0
- package/src/db/schema/profiles.schema.ts +34 -0
- package/src/db/schema/queue.schema.ts +59 -0
- package/src/db/schema/relationships.schema.ts +42 -0
- package/src/db/schema.ts +223 -0
- package/src/db/worker-connection.ts +47 -0
- package/src/index.ts +235 -0
- package/src/mcp/CLAUDE.md +1 -0
- package/src/mcp/index.ts +1380 -0
- package/src/mcp/legacyState.ts +22 -0
- package/src/mcp/rateLimit.ts +358 -0
- package/src/mcp/resources.ts +309 -0
- package/src/mcp/results.ts +104 -0
- package/src/mcp/tools.ts +401 -0
- package/src/queues/config.ts +119 -0
- package/src/queues/index.ts +289 -0
- package/src/sdk/client.ts +225 -0
- package/src/sdk/errors.ts +266 -0
- package/src/sdk/http.ts +560 -0
- package/src/sdk/index.ts +244 -0
- package/src/sdk/resources/base.ts +65 -0
- package/src/sdk/resources/connections.ts +204 -0
- package/src/sdk/resources/documents.ts +163 -0
- package/src/sdk/resources/index.ts +10 -0
- package/src/sdk/resources/memories.ts +150 -0
- package/src/sdk/resources/search.ts +60 -0
- package/src/sdk/resources/settings.ts +36 -0
- package/src/sdk/types.ts +674 -0
- package/src/services/chunking/index.ts +451 -0
- package/src/services/chunking.service.ts +650 -0
- package/src/services/csrf.service.ts +252 -0
- package/src/services/documents.repository.ts +219 -0
- package/src/services/documents.service.ts +191 -0
- package/src/services/embedding.service.ts +404 -0
- package/src/services/extraction.service.ts +300 -0
- package/src/services/extractors/code.extractor.ts +451 -0
- package/src/services/extractors/index.ts +9 -0
- package/src/services/extractors/markdown.extractor.ts +461 -0
- package/src/services/extractors/pdf.extractor.ts +315 -0
- package/src/services/extractors/text.extractor.ts +118 -0
- package/src/services/extractors/url.extractor.ts +243 -0
- package/src/services/index.ts +235 -0
- package/src/services/ingestion.service.ts +177 -0
- package/src/services/llm/anthropic.ts +400 -0
- package/src/services/llm/base.ts +460 -0
- package/src/services/llm/contradiction-detector.service.ts +526 -0
- package/src/services/llm/heuristics.ts +148 -0
- package/src/services/llm/index.ts +309 -0
- package/src/services/llm/memory-classifier.service.ts +383 -0
- package/src/services/llm/memory-extension-detector.service.ts +523 -0
- package/src/services/llm/mock.ts +470 -0
- package/src/services/llm/openai.ts +398 -0
- package/src/services/llm/prompts.ts +438 -0
- package/src/services/llm/types.ts +373 -0
- package/src/services/memory.repository.ts +1769 -0
- package/src/services/memory.service.ts +1338 -0
- package/src/services/memory.types.ts +234 -0
- package/src/services/persistence/index.ts +295 -0
- package/src/services/pipeline.service.ts +509 -0
- package/src/services/profile.repository.ts +436 -0
- package/src/services/profile.service.ts +560 -0
- package/src/services/profile.types.ts +270 -0
- package/src/services/relationships/detector.ts +1128 -0
- package/src/services/relationships/index.ts +268 -0
- package/src/services/relationships/memory-integration.ts +459 -0
- package/src/services/relationships/strategies.ts +132 -0
- package/src/services/relationships/types.ts +370 -0
- package/src/services/search.service.ts +761 -0
- package/src/services/search.types.ts +220 -0
- package/src/services/secrets.service.ts +384 -0
- package/src/services/vectorstore/base.ts +327 -0
- package/src/services/vectorstore/index.ts +444 -0
- package/src/services/vectorstore/memory.ts +286 -0
- package/src/services/vectorstore/migration.ts +295 -0
- package/src/services/vectorstore/mock.ts +403 -0
- package/src/services/vectorstore/pgvector.ts +695 -0
- package/src/services/vectorstore/types.ts +247 -0
- package/src/startup.ts +389 -0
- package/src/types/api.types.ts +193 -0
- package/src/types/document.types.ts +103 -0
- package/src/types/index.ts +241 -0
- package/src/types/profile.base.ts +133 -0
- package/src/utils/errors.ts +447 -0
- package/src/utils/id.ts +15 -0
- package/src/utils/index.ts +101 -0
- package/src/utils/logger.ts +313 -0
- package/src/utils/sanitization.ts +501 -0
- package/src/utils/secret-validation.ts +273 -0
- package/src/utils/synonyms.ts +188 -0
- package/src/utils/validation.ts +581 -0
- package/src/workers/chunking.worker.ts +242 -0
- package/src/workers/embedding.worker.ts +358 -0
- package/src/workers/extraction.worker.ts +346 -0
- package/src/workers/indexing.worker.ts +505 -0
- 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
|
+
}
|