@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,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
+ }
@@ -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'