@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,447 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Hierarchy for Supermemory Clone
|
|
3
|
+
*
|
|
4
|
+
* Provides a consistent error taxonomy and handling patterns.
|
|
5
|
+
* All service-level errors should extend AppError.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ZodError, ZodIssue } from 'zod'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Error codes for categorization and handling
|
|
12
|
+
*/
|
|
13
|
+
export const ErrorCode = {
|
|
14
|
+
// Validation errors (400)
|
|
15
|
+
VALIDATION_ERROR: 'VALIDATION_ERROR',
|
|
16
|
+
INVALID_INPUT: 'INVALID_INPUT',
|
|
17
|
+
MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',
|
|
18
|
+
INVALID_FORMAT: 'INVALID_FORMAT',
|
|
19
|
+
|
|
20
|
+
// Authentication/Authorization errors (401, 403)
|
|
21
|
+
AUTHENTICATION_ERROR: 'AUTHENTICATION_ERROR',
|
|
22
|
+
AUTHORIZATION_ERROR: 'AUTHORIZATION_ERROR',
|
|
23
|
+
INVALID_API_KEY: 'INVALID_API_KEY',
|
|
24
|
+
EXPIRED_TOKEN: 'EXPIRED_TOKEN',
|
|
25
|
+
|
|
26
|
+
// Not found errors (404)
|
|
27
|
+
NOT_FOUND: 'NOT_FOUND',
|
|
28
|
+
MEMORY_NOT_FOUND: 'MEMORY_NOT_FOUND',
|
|
29
|
+
PROFILE_NOT_FOUND: 'PROFILE_NOT_FOUND',
|
|
30
|
+
DOCUMENT_NOT_FOUND: 'DOCUMENT_NOT_FOUND',
|
|
31
|
+
|
|
32
|
+
// Conflict errors (409)
|
|
33
|
+
CONFLICT: 'CONFLICT',
|
|
34
|
+
DUPLICATE_ENTRY: 'DUPLICATE_ENTRY',
|
|
35
|
+
VERSION_CONFLICT: 'VERSION_CONFLICT',
|
|
36
|
+
|
|
37
|
+
// Rate limit errors (429)
|
|
38
|
+
RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',
|
|
39
|
+
|
|
40
|
+
// Server errors (500)
|
|
41
|
+
INTERNAL_ERROR: 'INTERNAL_ERROR',
|
|
42
|
+
DATABASE_ERROR: 'DATABASE_ERROR',
|
|
43
|
+
EMBEDDING_ERROR: 'EMBEDDING_ERROR',
|
|
44
|
+
EXTRACTION_ERROR: 'EXTRACTION_ERROR',
|
|
45
|
+
EXTERNAL_SERVICE_ERROR: 'EXTERNAL_SERVICE_ERROR',
|
|
46
|
+
CRYPTO_ERROR: 'CRYPTO_ERROR',
|
|
47
|
+
CONFIGURATION_ERROR: 'CONFIGURATION_ERROR',
|
|
48
|
+
DEPENDENCY_ERROR: 'DEPENDENCY_ERROR',
|
|
49
|
+
DATABASE_NOT_INITIALIZED: 'DATABASE_NOT_INITIALIZED',
|
|
50
|
+
VECTOR_DIMENSION_MISMATCH: 'VECTOR_DIMENSION_MISMATCH',
|
|
51
|
+
EMPTY_TEXT: 'EMPTY_TEXT',
|
|
52
|
+
|
|
53
|
+
// Service unavailable (503)
|
|
54
|
+
SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE',
|
|
55
|
+
} as const
|
|
56
|
+
|
|
57
|
+
export type ErrorCodeType = (typeof ErrorCode)[keyof typeof ErrorCode]
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* HTTP status codes mapped to error types
|
|
61
|
+
*/
|
|
62
|
+
export const ErrorStatusCode: Record<string, number> = {
|
|
63
|
+
VALIDATION_ERROR: 400,
|
|
64
|
+
INVALID_INPUT: 400,
|
|
65
|
+
MISSING_REQUIRED_FIELD: 400,
|
|
66
|
+
INVALID_FORMAT: 400,
|
|
67
|
+
AUTHENTICATION_ERROR: 401,
|
|
68
|
+
INVALID_API_KEY: 401,
|
|
69
|
+
EXPIRED_TOKEN: 401,
|
|
70
|
+
AUTHORIZATION_ERROR: 403,
|
|
71
|
+
NOT_FOUND: 404,
|
|
72
|
+
MEMORY_NOT_FOUND: 404,
|
|
73
|
+
PROFILE_NOT_FOUND: 404,
|
|
74
|
+
DOCUMENT_NOT_FOUND: 404,
|
|
75
|
+
CONFLICT: 409,
|
|
76
|
+
DUPLICATE_ENTRY: 409,
|
|
77
|
+
VERSION_CONFLICT: 409,
|
|
78
|
+
RATE_LIMIT_EXCEEDED: 429,
|
|
79
|
+
INTERNAL_ERROR: 500,
|
|
80
|
+
DATABASE_ERROR: 500,
|
|
81
|
+
EMBEDDING_ERROR: 500,
|
|
82
|
+
EXTRACTION_ERROR: 500,
|
|
83
|
+
EXTERNAL_SERVICE_ERROR: 502,
|
|
84
|
+
CRYPTO_ERROR: 500,
|
|
85
|
+
CONFIGURATION_ERROR: 500,
|
|
86
|
+
DEPENDENCY_ERROR: 500,
|
|
87
|
+
DATABASE_NOT_INITIALIZED: 500,
|
|
88
|
+
VECTOR_DIMENSION_MISMATCH: 400,
|
|
89
|
+
EMPTY_TEXT: 400,
|
|
90
|
+
SERVICE_UNAVAILABLE: 503,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Base application error class
|
|
95
|
+
* All custom errors should extend this class
|
|
96
|
+
*/
|
|
97
|
+
export class AppError extends Error {
|
|
98
|
+
readonly code: ErrorCodeType
|
|
99
|
+
readonly statusCode: number
|
|
100
|
+
readonly details?: unknown
|
|
101
|
+
readonly isOperational: boolean
|
|
102
|
+
readonly timestamp: Date
|
|
103
|
+
|
|
104
|
+
constructor(
|
|
105
|
+
message: string,
|
|
106
|
+
code: ErrorCodeType = ErrorCode.INTERNAL_ERROR,
|
|
107
|
+
details?: unknown,
|
|
108
|
+
isOperational: boolean = true
|
|
109
|
+
) {
|
|
110
|
+
super(message)
|
|
111
|
+
this.name = 'AppError'
|
|
112
|
+
this.code = code
|
|
113
|
+
this.statusCode = ErrorStatusCode[code] ?? 500
|
|
114
|
+
this.details = details
|
|
115
|
+
this.isOperational = isOperational
|
|
116
|
+
this.timestamp = new Date()
|
|
117
|
+
|
|
118
|
+
// Maintains proper stack trace
|
|
119
|
+
Error.captureStackTrace(this, this.constructor)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Convert error to JSON representation
|
|
124
|
+
*/
|
|
125
|
+
toJSON(): Record<string, unknown> {
|
|
126
|
+
return {
|
|
127
|
+
name: this.name,
|
|
128
|
+
code: this.code,
|
|
129
|
+
message: this.message,
|
|
130
|
+
statusCode: this.statusCode,
|
|
131
|
+
details: this.details,
|
|
132
|
+
timestamp: this.timestamp.toISOString(),
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Create error from unknown value
|
|
138
|
+
*/
|
|
139
|
+
static from(err: unknown, defaultCode?: ErrorCodeType): AppError {
|
|
140
|
+
if (err instanceof AppError) {
|
|
141
|
+
return err
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (err instanceof ZodError) {
|
|
145
|
+
return ValidationError.fromZodError(err)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (err instanceof Error) {
|
|
149
|
+
return new AppError(err.message, defaultCode ?? ErrorCode.INTERNAL_ERROR, { originalError: err.name }, true)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return new AppError(String(err), defaultCode ?? ErrorCode.INTERNAL_ERROR, undefined, true)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ============================================================================
|
|
157
|
+
// Specific Error Types
|
|
158
|
+
// ============================================================================
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Validation error for invalid input data
|
|
162
|
+
*/
|
|
163
|
+
export class ValidationError extends AppError {
|
|
164
|
+
readonly fieldErrors: Record<string, string[]>
|
|
165
|
+
|
|
166
|
+
constructor(message: string, fieldErrors: Record<string, string[]> = {}, details?: unknown) {
|
|
167
|
+
super(message, ErrorCode.VALIDATION_ERROR, details)
|
|
168
|
+
this.name = 'ValidationError'
|
|
169
|
+
this.fieldErrors = fieldErrors
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Create from Zod validation error
|
|
174
|
+
*/
|
|
175
|
+
static fromZodError(error: ZodError): ValidationError {
|
|
176
|
+
const fieldErrors: Record<string, string[]> = {}
|
|
177
|
+
|
|
178
|
+
for (const issue of error.issues) {
|
|
179
|
+
const path = issue.path.join('.')
|
|
180
|
+
const key = path || '_root'
|
|
181
|
+
if (!fieldErrors[key]) {
|
|
182
|
+
fieldErrors[key] = []
|
|
183
|
+
}
|
|
184
|
+
fieldErrors[key].push(issue.message)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const message = error.issues
|
|
188
|
+
.map((issue: ZodIssue) => {
|
|
189
|
+
const path = issue.path.join('.')
|
|
190
|
+
return path ? `${path}: ${issue.message}` : issue.message
|
|
191
|
+
})
|
|
192
|
+
.join('; ')
|
|
193
|
+
|
|
194
|
+
return new ValidationError(`Validation failed: ${message}`, fieldErrors, {
|
|
195
|
+
zodErrors: error.issues,
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
override toJSON(): Record<string, unknown> {
|
|
200
|
+
return {
|
|
201
|
+
...super.toJSON(),
|
|
202
|
+
fieldErrors: this.fieldErrors,
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Not found error for missing resources
|
|
209
|
+
*/
|
|
210
|
+
export class NotFoundError extends AppError {
|
|
211
|
+
readonly resourceType: string
|
|
212
|
+
readonly resourceId?: string
|
|
213
|
+
|
|
214
|
+
constructor(resourceType: string, resourceId?: string, code: ErrorCodeType = ErrorCode.NOT_FOUND) {
|
|
215
|
+
const message = resourceId ? `${resourceType} with ID '${resourceId}' not found` : `${resourceType} not found`
|
|
216
|
+
super(message, code)
|
|
217
|
+
this.name = 'NotFoundError'
|
|
218
|
+
this.resourceType = resourceType
|
|
219
|
+
this.resourceId = resourceId
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
override toJSON(): Record<string, unknown> {
|
|
223
|
+
return {
|
|
224
|
+
...super.toJSON(),
|
|
225
|
+
resourceType: this.resourceType,
|
|
226
|
+
resourceId: this.resourceId,
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Authentication error
|
|
233
|
+
*/
|
|
234
|
+
export class AuthenticationError extends AppError {
|
|
235
|
+
constructor(message: string = 'Authentication required', code: ErrorCodeType = ErrorCode.AUTHENTICATION_ERROR) {
|
|
236
|
+
super(message, code)
|
|
237
|
+
this.name = 'AuthenticationError'
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Authorization error
|
|
243
|
+
*/
|
|
244
|
+
export class AuthorizationError extends AppError {
|
|
245
|
+
readonly requiredPermission?: string
|
|
246
|
+
|
|
247
|
+
constructor(message: string = 'Permission denied', requiredPermission?: string) {
|
|
248
|
+
super(message, ErrorCode.AUTHORIZATION_ERROR)
|
|
249
|
+
this.name = 'AuthorizationError'
|
|
250
|
+
this.requiredPermission = requiredPermission
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
override toJSON(): Record<string, unknown> {
|
|
254
|
+
return {
|
|
255
|
+
...super.toJSON(),
|
|
256
|
+
requiredPermission: this.requiredPermission,
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Conflict error for duplicate entries or version conflicts
|
|
263
|
+
*/
|
|
264
|
+
export class ConflictError extends AppError {
|
|
265
|
+
readonly conflictType: 'duplicate' | 'version' | 'other'
|
|
266
|
+
|
|
267
|
+
constructor(message: string, conflictType: 'duplicate' | 'version' | 'other' = 'other', details?: unknown) {
|
|
268
|
+
const code =
|
|
269
|
+
conflictType === 'duplicate'
|
|
270
|
+
? ErrorCode.DUPLICATE_ENTRY
|
|
271
|
+
: conflictType === 'version'
|
|
272
|
+
? ErrorCode.VERSION_CONFLICT
|
|
273
|
+
: ErrorCode.CONFLICT
|
|
274
|
+
super(message, code, details)
|
|
275
|
+
this.name = 'ConflictError'
|
|
276
|
+
this.conflictType = conflictType
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Rate limit error
|
|
282
|
+
*/
|
|
283
|
+
export class RateLimitError extends AppError {
|
|
284
|
+
readonly retryAfterMs?: number
|
|
285
|
+
|
|
286
|
+
constructor(message: string = 'Rate limit exceeded', retryAfterMs?: number) {
|
|
287
|
+
super(message, ErrorCode.RATE_LIMIT_EXCEEDED)
|
|
288
|
+
this.name = 'RateLimitError'
|
|
289
|
+
this.retryAfterMs = retryAfterMs
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
override toJSON(): Record<string, unknown> {
|
|
293
|
+
return {
|
|
294
|
+
...super.toJSON(),
|
|
295
|
+
retryAfterMs: this.retryAfterMs,
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Database error
|
|
302
|
+
*/
|
|
303
|
+
export class DatabaseError extends AppError {
|
|
304
|
+
readonly operation?: string
|
|
305
|
+
|
|
306
|
+
constructor(message: string, operation?: string, details?: unknown) {
|
|
307
|
+
super(message, ErrorCode.DATABASE_ERROR, details)
|
|
308
|
+
this.name = 'DatabaseError'
|
|
309
|
+
this.operation = operation
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Embedding service error
|
|
315
|
+
*/
|
|
316
|
+
export class EmbeddingError extends AppError {
|
|
317
|
+
readonly provider?: string
|
|
318
|
+
|
|
319
|
+
constructor(message: string, provider?: string, details?: unknown) {
|
|
320
|
+
super(message, ErrorCode.EMBEDDING_ERROR, details)
|
|
321
|
+
this.name = 'EmbeddingError'
|
|
322
|
+
this.provider = provider
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Extraction error
|
|
328
|
+
*/
|
|
329
|
+
export class ExtractionError extends AppError {
|
|
330
|
+
readonly contentType?: string
|
|
331
|
+
|
|
332
|
+
constructor(message: string, contentType?: string, details?: unknown) {
|
|
333
|
+
super(message, ErrorCode.EXTRACTION_ERROR, details)
|
|
334
|
+
this.name = 'ExtractionError'
|
|
335
|
+
this.contentType = contentType
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* External service error
|
|
341
|
+
*/
|
|
342
|
+
export class ExternalServiceError extends AppError {
|
|
343
|
+
readonly serviceName: string
|
|
344
|
+
readonly serviceStatus?: number
|
|
345
|
+
|
|
346
|
+
constructor(serviceName: string, message: string, serviceStatus?: number, details?: unknown) {
|
|
347
|
+
super(message, ErrorCode.EXTERNAL_SERVICE_ERROR, details)
|
|
348
|
+
this.name = 'ExternalServiceError'
|
|
349
|
+
this.serviceName = serviceName
|
|
350
|
+
this.serviceStatus = serviceStatus
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Crypto/encryption error
|
|
356
|
+
*/
|
|
357
|
+
export class CryptoError extends AppError {
|
|
358
|
+
readonly operation?: string
|
|
359
|
+
|
|
360
|
+
constructor(message: string, operation?: string, details?: unknown) {
|
|
361
|
+
super(message, ErrorCode.CRYPTO_ERROR, details)
|
|
362
|
+
this.name = 'CryptoError'
|
|
363
|
+
this.operation = operation
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Configuration error
|
|
369
|
+
*/
|
|
370
|
+
export class ConfigurationError extends AppError {
|
|
371
|
+
readonly configKey?: string
|
|
372
|
+
|
|
373
|
+
constructor(message: string, configKey?: string, details?: unknown) {
|
|
374
|
+
super(message, ErrorCode.CONFIGURATION_ERROR, details)
|
|
375
|
+
this.name = 'ConfigurationError'
|
|
376
|
+
this.configKey = configKey
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Dependency error for missing required dependencies
|
|
382
|
+
*/
|
|
383
|
+
export class DependencyError extends AppError {
|
|
384
|
+
readonly dependency: string
|
|
385
|
+
readonly installCommand?: string
|
|
386
|
+
|
|
387
|
+
constructor(dependency: string, installCommand?: string, details?: unknown) {
|
|
388
|
+
const message = installCommand
|
|
389
|
+
? `Missing dependency '${dependency}'. Run: ${installCommand}`
|
|
390
|
+
: `Missing dependency '${dependency}'`
|
|
391
|
+
super(message, ErrorCode.DEPENDENCY_ERROR, details)
|
|
392
|
+
this.name = 'DependencyError'
|
|
393
|
+
this.dependency = dependency
|
|
394
|
+
this.installCommand = installCommand
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// ============================================================================
|
|
399
|
+
// Type Guards
|
|
400
|
+
// ============================================================================
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Check if error is an AppError
|
|
404
|
+
*/
|
|
405
|
+
export function isAppError(error: unknown): error is AppError {
|
|
406
|
+
return error instanceof AppError
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Check if error is a validation error
|
|
411
|
+
*/
|
|
412
|
+
export function isValidationError(error: unknown): error is ValidationError {
|
|
413
|
+
return error instanceof ValidationError
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Check if error is a not found error
|
|
418
|
+
*/
|
|
419
|
+
export function isNotFoundError(error: unknown): error is NotFoundError {
|
|
420
|
+
return error instanceof NotFoundError
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Check if error is retryable
|
|
425
|
+
*/
|
|
426
|
+
export function isRetryableError(error: unknown): boolean {
|
|
427
|
+
if (error instanceof RateLimitError) {
|
|
428
|
+
return true
|
|
429
|
+
}
|
|
430
|
+
if (error instanceof ExternalServiceError) {
|
|
431
|
+
return true
|
|
432
|
+
}
|
|
433
|
+
if (error instanceof AppError) {
|
|
434
|
+
return error.code === ErrorCode.SERVICE_UNAVAILABLE
|
|
435
|
+
}
|
|
436
|
+
return false
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Check if error is operational (expected) vs programming error
|
|
441
|
+
*/
|
|
442
|
+
export function isOperationalError(error: unknown): boolean {
|
|
443
|
+
if (error instanceof AppError) {
|
|
444
|
+
return error.isOperational
|
|
445
|
+
}
|
|
446
|
+
return false
|
|
447
|
+
}
|
package/src/utils/id.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generate a unique ID using crypto for better randomness
|
|
5
|
+
*/
|
|
6
|
+
export function generateId(): string {
|
|
7
|
+
return randomUUID()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate a UUID v4 using Node.js crypto module
|
|
12
|
+
*/
|
|
13
|
+
export function generateUUID(): string {
|
|
14
|
+
return randomUUID()
|
|
15
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities Index
|
|
3
|
+
*
|
|
4
|
+
* Export all utility functions and classes
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// ID Generation
|
|
8
|
+
export { generateId, generateUUID } from './id.js'
|
|
9
|
+
|
|
10
|
+
// Logging
|
|
11
|
+
export {
|
|
12
|
+
Logger,
|
|
13
|
+
LogLevel,
|
|
14
|
+
type LogLevelName,
|
|
15
|
+
type LogLevelValue,
|
|
16
|
+
type LogEntry,
|
|
17
|
+
type LoggerConfig,
|
|
18
|
+
createLogger,
|
|
19
|
+
getLogger,
|
|
20
|
+
resetLoggers,
|
|
21
|
+
logger,
|
|
22
|
+
} from './logger.js'
|
|
23
|
+
|
|
24
|
+
// Error Handling
|
|
25
|
+
export {
|
|
26
|
+
ErrorCode,
|
|
27
|
+
type ErrorCodeType,
|
|
28
|
+
ErrorStatusCode,
|
|
29
|
+
AppError,
|
|
30
|
+
ValidationError,
|
|
31
|
+
NotFoundError,
|
|
32
|
+
AuthenticationError,
|
|
33
|
+
AuthorizationError,
|
|
34
|
+
ConflictError,
|
|
35
|
+
RateLimitError,
|
|
36
|
+
DatabaseError,
|
|
37
|
+
EmbeddingError,
|
|
38
|
+
ExtractionError,
|
|
39
|
+
ExternalServiceError,
|
|
40
|
+
isAppError,
|
|
41
|
+
isValidationError,
|
|
42
|
+
isNotFoundError,
|
|
43
|
+
isRetryableError,
|
|
44
|
+
isOperationalError,
|
|
45
|
+
} from './errors.js'
|
|
46
|
+
|
|
47
|
+
// Validation
|
|
48
|
+
export {
|
|
49
|
+
// Common schemas
|
|
50
|
+
nonEmptyString,
|
|
51
|
+
uuidSchema,
|
|
52
|
+
positiveInt,
|
|
53
|
+
nonNegativeInt,
|
|
54
|
+
confidenceScore,
|
|
55
|
+
containerTagSchema,
|
|
56
|
+
paginationSchema,
|
|
57
|
+
dateRangeSchema,
|
|
58
|
+
// Memory schemas
|
|
59
|
+
memoryTypeSchema,
|
|
60
|
+
relationshipTypeSchema,
|
|
61
|
+
createMemoryInputSchema,
|
|
62
|
+
memoryQueryOptionsSchema,
|
|
63
|
+
// Profile schemas
|
|
64
|
+
factTypeSchema,
|
|
65
|
+
factCategorySchema,
|
|
66
|
+
profileFactInputSchema,
|
|
67
|
+
// Search schemas
|
|
68
|
+
searchModeSchema,
|
|
69
|
+
filterOperatorSchema,
|
|
70
|
+
metadataFilterSchema,
|
|
71
|
+
searchOptionsSchema,
|
|
72
|
+
// Extraction schemas
|
|
73
|
+
contentTypeSchema,
|
|
74
|
+
chunkingStrategySchema,
|
|
75
|
+
documentInputSchema,
|
|
76
|
+
// Validation functions
|
|
77
|
+
validate,
|
|
78
|
+
validateSafe,
|
|
79
|
+
validateWithDefaults,
|
|
80
|
+
createValidator,
|
|
81
|
+
assertDefined,
|
|
82
|
+
assertNonEmpty,
|
|
83
|
+
validateMemoryContent,
|
|
84
|
+
validateSearchQuery,
|
|
85
|
+
validateContainerTag,
|
|
86
|
+
} from './validation.js'
|
|
87
|
+
|
|
88
|
+
// Secret Validation
|
|
89
|
+
export {
|
|
90
|
+
validateApiKey,
|
|
91
|
+
validateDatabaseUrl,
|
|
92
|
+
checkSecretStrength,
|
|
93
|
+
generateSecret,
|
|
94
|
+
validateJwtFormat,
|
|
95
|
+
sanitizeDatabaseUrl,
|
|
96
|
+
looksLikeSecret,
|
|
97
|
+
SECRET_FORMAT_PATTERNS,
|
|
98
|
+
type ApiKeyValidation,
|
|
99
|
+
type DatabaseUrlComponents,
|
|
100
|
+
type SecretStrength,
|
|
101
|
+
} from './secret-validation.js'
|