@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,193 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Security Constants
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
/** Maximum content size in characters (50KB) */
|
|
8
|
+
const MAX_CONTENT_CHARS = 50000
|
|
9
|
+
|
|
10
|
+
/** Maximum query size in characters (10KB) */
|
|
11
|
+
const MAX_QUERY_CHARS = 10000
|
|
12
|
+
|
|
13
|
+
/** Maximum metadata size in bytes (10KB) */
|
|
14
|
+
const MAX_METADATA_BYTES = 10240
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Base Response Types
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
export interface SuccessResponse<T> {
|
|
21
|
+
data: T
|
|
22
|
+
timing: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ErrorResponse {
|
|
26
|
+
error: {
|
|
27
|
+
code: string
|
|
28
|
+
message: string
|
|
29
|
+
}
|
|
30
|
+
status: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type ApiResponse<T> = SuccessResponse<T> | ErrorResponse
|
|
34
|
+
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// Document Types
|
|
37
|
+
// ============================================================================
|
|
38
|
+
|
|
39
|
+
export const DocumentMetadataSchema = z
|
|
40
|
+
.record(z.unknown())
|
|
41
|
+
.optional()
|
|
42
|
+
.refine(
|
|
43
|
+
(metadata) => {
|
|
44
|
+
if (!metadata) return true
|
|
45
|
+
try {
|
|
46
|
+
const jsonSize = new TextEncoder().encode(JSON.stringify(metadata)).length
|
|
47
|
+
return jsonSize <= MAX_METADATA_BYTES
|
|
48
|
+
} catch {
|
|
49
|
+
return false
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{ message: `Metadata must be at most ${MAX_METADATA_BYTES} bytes (10KB)` }
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
export const CreateDocumentSchema = z.object({
|
|
56
|
+
content: z
|
|
57
|
+
.string()
|
|
58
|
+
.min(1, 'Content is required')
|
|
59
|
+
.max(MAX_CONTENT_CHARS, `Content must be at most ${MAX_CONTENT_CHARS} characters`),
|
|
60
|
+
containerTag: z.string().min(1).max(100).optional(),
|
|
61
|
+
metadata: DocumentMetadataSchema,
|
|
62
|
+
customId: z.string().min(1).max(255).optional(),
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
export const UpdateDocumentSchema = z.object({
|
|
66
|
+
content: z
|
|
67
|
+
.string()
|
|
68
|
+
.min(1)
|
|
69
|
+
.max(MAX_CONTENT_CHARS, `Content must be at most ${MAX_CONTENT_CHARS} characters`)
|
|
70
|
+
.optional(),
|
|
71
|
+
containerTag: z.string().min(1).max(100).optional(),
|
|
72
|
+
metadata: DocumentMetadataSchema,
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
export const ListDocumentsQuerySchema = z.object({
|
|
76
|
+
containerTag: z.string().optional(),
|
|
77
|
+
limit: z.coerce.number().int().min(1).max(100).default(20),
|
|
78
|
+
offset: z.coerce.number().int().min(0).default(0),
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
export const BulkDeleteSchema = z
|
|
82
|
+
.object({
|
|
83
|
+
ids: z.array(z.string()).optional(),
|
|
84
|
+
containerTags: z.array(z.string()).optional(),
|
|
85
|
+
})
|
|
86
|
+
.refine((data) => data.ids?.length || data.containerTags?.length, {
|
|
87
|
+
message: 'Either ids or containerTags must be provided',
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
export interface ApiDocument {
|
|
91
|
+
id: string
|
|
92
|
+
content: string
|
|
93
|
+
containerTag?: string
|
|
94
|
+
metadata?: Record<string, unknown>
|
|
95
|
+
customId?: string
|
|
96
|
+
createdAt: string
|
|
97
|
+
updatedAt: string
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export type CreateDocumentInput = z.infer<typeof CreateDocumentSchema>
|
|
101
|
+
export type UpdateDocumentInput = z.infer<typeof UpdateDocumentSchema>
|
|
102
|
+
export type ListDocumentsQuery = z.infer<typeof ListDocumentsQuerySchema>
|
|
103
|
+
export type BulkDeleteInput = z.infer<typeof BulkDeleteSchema>
|
|
104
|
+
|
|
105
|
+
// ============================================================================
|
|
106
|
+
// Search Types
|
|
107
|
+
// ============================================================================
|
|
108
|
+
|
|
109
|
+
export const SearchModeSchema = z.enum(['vector', 'fulltext', 'hybrid'])
|
|
110
|
+
|
|
111
|
+
export const SearchFiltersSchema = z.object({
|
|
112
|
+
createdAfter: z.string().datetime().optional(),
|
|
113
|
+
createdBefore: z.string().datetime().optional(),
|
|
114
|
+
metadata: z.record(z.unknown()).optional(),
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
export const SearchRequestSchema = z.object({
|
|
118
|
+
q: z.string().min(1, 'Query is required').max(MAX_QUERY_CHARS, `Query must be at most ${MAX_QUERY_CHARS} characters`),
|
|
119
|
+
containerTag: z.string().max(100).optional(),
|
|
120
|
+
searchMode: SearchModeSchema.default('hybrid'),
|
|
121
|
+
limit: z.coerce.number().int().min(1).max(100).default(10),
|
|
122
|
+
threshold: z.coerce.number().min(0).max(1).default(0.7),
|
|
123
|
+
rerank: z.boolean().default(false),
|
|
124
|
+
filters: SearchFiltersSchema.optional(),
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
export interface SearchResult {
|
|
128
|
+
id: string
|
|
129
|
+
content: string
|
|
130
|
+
score: number
|
|
131
|
+
containerTag?: string
|
|
132
|
+
metadata?: Record<string, unknown>
|
|
133
|
+
highlights?: string[]
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface SearchResponse {
|
|
137
|
+
results: SearchResult[]
|
|
138
|
+
total: number
|
|
139
|
+
query: string
|
|
140
|
+
searchMode: string
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export type SearchRequest = z.infer<typeof SearchRequestSchema>
|
|
144
|
+
export type SearchFilters = z.infer<typeof SearchFiltersSchema>
|
|
145
|
+
|
|
146
|
+
// ============================================================================
|
|
147
|
+
// Profile Types
|
|
148
|
+
// ============================================================================
|
|
149
|
+
|
|
150
|
+
export const UpdateProfileSchema = z.object({
|
|
151
|
+
name: z.string().min(1).max(255).optional(),
|
|
152
|
+
description: z.string().max(1000).optional(),
|
|
153
|
+
settings: z.record(z.unknown()).optional(),
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
export interface ApiProfile {
|
|
157
|
+
containerTag: string
|
|
158
|
+
name?: string
|
|
159
|
+
description?: string
|
|
160
|
+
settings?: Record<string, unknown>
|
|
161
|
+
documentCount: number
|
|
162
|
+
createdAt: string
|
|
163
|
+
updatedAt: string
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export type UpdateProfileInput = z.infer<typeof UpdateProfileSchema>
|
|
167
|
+
|
|
168
|
+
// ============================================================================
|
|
169
|
+
// Authentication Types
|
|
170
|
+
// ============================================================================
|
|
171
|
+
|
|
172
|
+
export interface AuthContext {
|
|
173
|
+
userId: string
|
|
174
|
+
apiKey: string
|
|
175
|
+
scopes: string[]
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ============================================================================
|
|
179
|
+
// Error Codes
|
|
180
|
+
// ============================================================================
|
|
181
|
+
|
|
182
|
+
export const ErrorCodes = {
|
|
183
|
+
VALIDATION_ERROR: 'VALIDATION_ERROR',
|
|
184
|
+
UNAUTHORIZED: 'UNAUTHORIZED',
|
|
185
|
+
FORBIDDEN: 'FORBIDDEN',
|
|
186
|
+
NOT_FOUND: 'NOT_FOUND',
|
|
187
|
+
CONFLICT: 'CONFLICT',
|
|
188
|
+
RATE_LIMITED: 'RATE_LIMITED',
|
|
189
|
+
INTERNAL_ERROR: 'INTERNAL_ERROR',
|
|
190
|
+
BAD_REQUEST: 'BAD_REQUEST',
|
|
191
|
+
} as const
|
|
192
|
+
|
|
193
|
+
export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes]
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document and extraction types for supermemory content pipeline
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type ContentType = 'text' | 'url' | 'pdf' | 'markdown' | 'code' | 'unknown'
|
|
6
|
+
|
|
7
|
+
export type DocumentStatus = 'queued' | 'extracting' | 'chunking' | 'embedding' | 'indexing' | 'done' | 'error'
|
|
8
|
+
|
|
9
|
+
export interface Document {
|
|
10
|
+
id: string
|
|
11
|
+
content: string
|
|
12
|
+
contentType?: ContentType
|
|
13
|
+
sourceUrl?: string
|
|
14
|
+
fileName?: string
|
|
15
|
+
language?: string
|
|
16
|
+
status: DocumentStatus
|
|
17
|
+
metadata: DocumentMetadata
|
|
18
|
+
createdAt: Date
|
|
19
|
+
updatedAt: Date
|
|
20
|
+
errorMessage?: string
|
|
21
|
+
retryCount: number
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface DocumentMetadata {
|
|
25
|
+
title?: string
|
|
26
|
+
author?: string
|
|
27
|
+
description?: string
|
|
28
|
+
tags?: string[]
|
|
29
|
+
source?: string
|
|
30
|
+
mimeType?: string
|
|
31
|
+
wordCount?: number
|
|
32
|
+
charCount?: number
|
|
33
|
+
[key: string]: unknown
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface Chunk {
|
|
37
|
+
id: string
|
|
38
|
+
documentId: string
|
|
39
|
+
content: string
|
|
40
|
+
type: ChunkType
|
|
41
|
+
position: ChunkPosition
|
|
42
|
+
metadata: ChunkMetadata
|
|
43
|
+
embedding?: number[]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type ChunkType =
|
|
47
|
+
| 'paragraph'
|
|
48
|
+
| 'heading'
|
|
49
|
+
| 'code_block'
|
|
50
|
+
| 'function'
|
|
51
|
+
| 'class'
|
|
52
|
+
| 'list'
|
|
53
|
+
| 'table'
|
|
54
|
+
| 'quote'
|
|
55
|
+
| 'section'
|
|
56
|
+
| 'raw'
|
|
57
|
+
|
|
58
|
+
export interface ChunkPosition {
|
|
59
|
+
index: number
|
|
60
|
+
start: number
|
|
61
|
+
end: number
|
|
62
|
+
lineStart?: number
|
|
63
|
+
lineEnd?: number
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface ChunkMetadata {
|
|
67
|
+
headingLevel?: number
|
|
68
|
+
headingText?: string
|
|
69
|
+
language?: string
|
|
70
|
+
functionName?: string
|
|
71
|
+
className?: string
|
|
72
|
+
parentChunkId?: string
|
|
73
|
+
wordCount: number
|
|
74
|
+
charCount: number
|
|
75
|
+
[key: string]: unknown
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface ExtractionResult {
|
|
79
|
+
content: string
|
|
80
|
+
contentType: ContentType
|
|
81
|
+
metadata: DocumentMetadata
|
|
82
|
+
rawContent?: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface ChunkingOptions {
|
|
86
|
+
maxChunkSize?: number
|
|
87
|
+
minChunkSize?: number
|
|
88
|
+
overlap?: number
|
|
89
|
+
preserveStructure?: boolean
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface PipelineResult {
|
|
93
|
+
documentId: string
|
|
94
|
+
status: DocumentStatus
|
|
95
|
+
chunks: Chunk[]
|
|
96
|
+
processingTimeMs: number
|
|
97
|
+
error?: string
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface ExtractorInterface {
|
|
101
|
+
extract(content: string | Buffer, options?: Record<string, unknown>): Promise<ExtractionResult>
|
|
102
|
+
canHandle(content: string | Buffer): boolean
|
|
103
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Memory Types
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
export const MemoryTypeSchema = z.enum(['fact', 'event', 'preference', 'skill', 'relationship', 'context', 'note'])
|
|
8
|
+
|
|
9
|
+
export type MemoryType = z.infer<typeof MemoryTypeSchema>
|
|
10
|
+
|
|
11
|
+
export const RelationshipTypeSchema = z.enum(['updates', 'extends', 'derives', 'contradicts', 'related', 'supersedes'])
|
|
12
|
+
|
|
13
|
+
export type RelationshipType = z.infer<typeof RelationshipTypeSchema>
|
|
14
|
+
|
|
15
|
+
export interface MemoryRelationship {
|
|
16
|
+
type: RelationshipType
|
|
17
|
+
targetId: string
|
|
18
|
+
confidence: number
|
|
19
|
+
metadata?: Record<string, unknown>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface Memory {
|
|
23
|
+
id: string
|
|
24
|
+
content: string
|
|
25
|
+
type: MemoryType
|
|
26
|
+
embedding?: number[]
|
|
27
|
+
relationships: MemoryRelationship[]
|
|
28
|
+
isLatest: boolean
|
|
29
|
+
supersededBy?: string
|
|
30
|
+
containerTag?: string
|
|
31
|
+
metadata: MemoryMetadata
|
|
32
|
+
createdAt: Date
|
|
33
|
+
updatedAt: Date
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface MemoryMetadata {
|
|
37
|
+
source?: string
|
|
38
|
+
confidence?: number
|
|
39
|
+
extractedFrom?: string
|
|
40
|
+
keywords?: string[]
|
|
41
|
+
entities?: Entity[]
|
|
42
|
+
[key: string]: unknown
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface Entity {
|
|
46
|
+
name: string
|
|
47
|
+
type: 'person' | 'place' | 'organization' | 'date' | 'concept' | 'other'
|
|
48
|
+
mentions: number
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// Search Types
|
|
53
|
+
// ============================================================================
|
|
54
|
+
|
|
55
|
+
export const SearchModeSchema = z.enum(['vector', 'keyword', 'hybrid'])
|
|
56
|
+
export type SearchMode = z.infer<typeof SearchModeSchema>
|
|
57
|
+
|
|
58
|
+
export interface SearchQuery {
|
|
59
|
+
query: string
|
|
60
|
+
mode?: SearchMode
|
|
61
|
+
containerTag?: string
|
|
62
|
+
filters?: SearchFilters
|
|
63
|
+
limit?: number
|
|
64
|
+
offset?: number
|
|
65
|
+
rerank?: boolean
|
|
66
|
+
minScore?: number
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface SearchFilters {
|
|
70
|
+
types?: MemoryType[]
|
|
71
|
+
dateRange?: {
|
|
72
|
+
start?: Date
|
|
73
|
+
end?: Date
|
|
74
|
+
}
|
|
75
|
+
metadata?: Record<string, unknown>
|
|
76
|
+
isLatest?: boolean
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface SearchResult {
|
|
80
|
+
memory: Memory
|
|
81
|
+
score: number
|
|
82
|
+
highlights?: string[]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface SearchResponse {
|
|
86
|
+
results: SearchResult[]
|
|
87
|
+
total: number
|
|
88
|
+
query: string
|
|
89
|
+
mode: SearchMode
|
|
90
|
+
took: number
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ============================================================================
|
|
94
|
+
// Profile Types
|
|
95
|
+
// ============================================================================
|
|
96
|
+
|
|
97
|
+
import { FactLifecycleCategorySchema, FactLifecycleCategory, BaseProfileFact } from './profile.base.js'
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Fact lifecycle category - determines expiration behavior
|
|
101
|
+
* Re-exported from profile.base for convenience
|
|
102
|
+
*/
|
|
103
|
+
export const FactCategorySchema = FactLifecycleCategorySchema
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Fact lifecycle category type
|
|
107
|
+
* Note: This represents the fact's lifecycle (static/dynamic/inferred),
|
|
108
|
+
* not its semantic category. For semantic categories (identity, skill, etc.),
|
|
109
|
+
* see FactSemanticCategory in profile.base.ts
|
|
110
|
+
*/
|
|
111
|
+
export type FactCategory = FactLifecycleCategory
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* API-level ProfileFact - simplified version for API contracts
|
|
115
|
+
* Extends BaseProfileFact with key-value structure for API compatibility
|
|
116
|
+
*/
|
|
117
|
+
export interface ProfileFact extends BaseProfileFact {
|
|
118
|
+
/** Key for the fact (for key-value style access) */
|
|
119
|
+
key: string
|
|
120
|
+
/** Value of the fact */
|
|
121
|
+
value: string
|
|
122
|
+
/** Lifecycle category */
|
|
123
|
+
category: FactCategory
|
|
124
|
+
/** Source identifier */
|
|
125
|
+
source?: string
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface Profile {
|
|
129
|
+
id: string
|
|
130
|
+
name?: string
|
|
131
|
+
facts: ProfileFact[]
|
|
132
|
+
memories: string[]
|
|
133
|
+
containerTags: string[]
|
|
134
|
+
createdAt: Date
|
|
135
|
+
updatedAt: Date
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ============================================================================
|
|
139
|
+
// Extraction Types
|
|
140
|
+
// ============================================================================
|
|
141
|
+
|
|
142
|
+
export const ContentTypeSchema = z.enum(['text', 'url', 'markdown', 'html', 'json', 'pdf', 'image', 'unknown'])
|
|
143
|
+
|
|
144
|
+
export type ContentType = z.infer<typeof ContentTypeSchema>
|
|
145
|
+
|
|
146
|
+
export const ChunkingStrategySchema = z.enum(['sentence', 'paragraph', 'fixed', 'semantic', 'sliding_window'])
|
|
147
|
+
|
|
148
|
+
export type ChunkingStrategy = z.infer<typeof ChunkingStrategySchema>
|
|
149
|
+
|
|
150
|
+
export interface ExtractionResult {
|
|
151
|
+
content: string
|
|
152
|
+
contentType: ContentType
|
|
153
|
+
chunks: ContentChunk[]
|
|
154
|
+
metadata: ExtractionMetadata
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface ContentChunk {
|
|
158
|
+
id: string
|
|
159
|
+
content: string
|
|
160
|
+
index: number
|
|
161
|
+
startOffset: number
|
|
162
|
+
endOffset: number
|
|
163
|
+
metadata?: Record<string, unknown>
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface ExtractionMetadata {
|
|
167
|
+
originalLength: number
|
|
168
|
+
chunkCount: number
|
|
169
|
+
processingTime: number
|
|
170
|
+
strategy: ChunkingStrategy
|
|
171
|
+
sourceUrl?: string
|
|
172
|
+
title?: string
|
|
173
|
+
author?: string
|
|
174
|
+
publishedAt?: Date
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ============================================================================
|
|
178
|
+
// Document Types
|
|
179
|
+
// ============================================================================
|
|
180
|
+
|
|
181
|
+
export const DocumentSchema = z.object({
|
|
182
|
+
id: z.string().optional(),
|
|
183
|
+
content: z.string().min(1, 'Content is required'),
|
|
184
|
+
containerTag: z.string().optional(),
|
|
185
|
+
metadata: z.record(z.unknown()).optional(),
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
export type DocumentInput = z.infer<typeof DocumentSchema>
|
|
189
|
+
|
|
190
|
+
export interface Document {
|
|
191
|
+
id: string
|
|
192
|
+
content: string
|
|
193
|
+
containerTag?: string
|
|
194
|
+
memories: Memory[]
|
|
195
|
+
metadata: Record<string, unknown>
|
|
196
|
+
createdAt: Date
|
|
197
|
+
updatedAt: Date
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// API Types
|
|
202
|
+
// ============================================================================
|
|
203
|
+
|
|
204
|
+
export interface APIError {
|
|
205
|
+
code: string
|
|
206
|
+
message: string
|
|
207
|
+
details?: unknown
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export interface APIResponse<T> {
|
|
211
|
+
success: boolean
|
|
212
|
+
data?: T
|
|
213
|
+
error?: APIError
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface PaginatedResponse<T> extends APIResponse<T[]> {
|
|
217
|
+
pagination: {
|
|
218
|
+
total: number
|
|
219
|
+
limit: number
|
|
220
|
+
offset: number
|
|
221
|
+
hasMore: boolean
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ============================================================================
|
|
226
|
+
// SDK Types
|
|
227
|
+
// ============================================================================
|
|
228
|
+
|
|
229
|
+
export interface SDKConfig {
|
|
230
|
+
apiKey: string
|
|
231
|
+
baseUrl?: string
|
|
232
|
+
timeout?: number
|
|
233
|
+
retries?: number
|
|
234
|
+
retryDelay?: number
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export interface RateLimitInfo {
|
|
238
|
+
limit: number
|
|
239
|
+
remaining: number
|
|
240
|
+
reset: Date
|
|
241
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Profile Types for Supermemory Clone
|
|
3
|
+
*
|
|
4
|
+
* Shared base interfaces for profile-related types to prevent duplication
|
|
5
|
+
* across profile.types.ts and types/index.ts
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { z } from 'zod'
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Base Schemas
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Fact lifecycle category - determines expiration behavior
|
|
16
|
+
* Used in types/index.ts Profile system
|
|
17
|
+
*/
|
|
18
|
+
export const FactLifecycleCategorySchema = z.enum([
|
|
19
|
+
'static', // Long-term, rarely changes
|
|
20
|
+
'dynamic', // Temporary, expires over time
|
|
21
|
+
'inferred', // Derived from other facts
|
|
22
|
+
])
|
|
23
|
+
|
|
24
|
+
export type FactLifecycleCategory = z.infer<typeof FactLifecycleCategorySchema>
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Fact semantic category - describes what the fact is about
|
|
28
|
+
* Used in services/profile.types.ts ProfileFact
|
|
29
|
+
*/
|
|
30
|
+
export const FactSemanticCategorySchema = z.enum([
|
|
31
|
+
'identity', // Name, role, company
|
|
32
|
+
'preference', // Likes, dislikes, preferences
|
|
33
|
+
'skill', // Technical skills, expertise
|
|
34
|
+
'background', // Education, history
|
|
35
|
+
'relationship', // Connections, team members
|
|
36
|
+
'project', // Current/past projects
|
|
37
|
+
'goal', // Objectives, aspirations
|
|
38
|
+
'context', // Current situation, temporary context
|
|
39
|
+
'other', // Uncategorized
|
|
40
|
+
])
|
|
41
|
+
|
|
42
|
+
export type FactSemanticCategory = z.infer<typeof FactSemanticCategorySchema>
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Fact type - static or dynamic lifecycle
|
|
46
|
+
*/
|
|
47
|
+
export const FactTypeSchema = z.enum(['static', 'dynamic'])
|
|
48
|
+
|
|
49
|
+
export type FactType = z.infer<typeof FactTypeSchema>
|
|
50
|
+
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// Base ProfileFact Schema
|
|
53
|
+
// ============================================================================
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Base schema for ProfileFact - shared between service and type layers
|
|
57
|
+
* Contains the common fields that all ProfileFact implementations must have
|
|
58
|
+
*/
|
|
59
|
+
export const BaseProfileFactSchema = z.object({
|
|
60
|
+
/** Unique identifier for the fact */
|
|
61
|
+
id: z.string(),
|
|
62
|
+
|
|
63
|
+
/** The actual fact content */
|
|
64
|
+
content: z.string().min(1),
|
|
65
|
+
|
|
66
|
+
/** Confidence score of the extraction (0-1) */
|
|
67
|
+
confidence: z.number().min(0).max(1),
|
|
68
|
+
|
|
69
|
+
/** When this fact was created/extracted */
|
|
70
|
+
createdAt: z.date(),
|
|
71
|
+
|
|
72
|
+
/** When this fact was last updated */
|
|
73
|
+
updatedAt: z.date(),
|
|
74
|
+
|
|
75
|
+
/** Source content or document this was extracted from */
|
|
76
|
+
sourceId: z.string().optional(),
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
export type BaseProfileFact = z.infer<typeof BaseProfileFactSchema>
|
|
80
|
+
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// Service Layer ProfileFact (extended version)
|
|
83
|
+
// ============================================================================
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Service layer ProfileFact schema - used in profile.service.ts
|
|
87
|
+
* Extends base with service-specific fields
|
|
88
|
+
*/
|
|
89
|
+
export const ServiceProfileFactSchema = BaseProfileFactSchema.extend({
|
|
90
|
+
/** Whether this is a static (long-term) or dynamic (temporary) fact */
|
|
91
|
+
type: FactTypeSchema,
|
|
92
|
+
|
|
93
|
+
/** When this fact was extracted */
|
|
94
|
+
extractedAt: z.date(),
|
|
95
|
+
|
|
96
|
+
/** When this fact expires (only for dynamic facts) */
|
|
97
|
+
expiresAt: z.date().optional(),
|
|
98
|
+
|
|
99
|
+
/** Category of the fact for organization */
|
|
100
|
+
category: FactSemanticCategorySchema.optional(),
|
|
101
|
+
|
|
102
|
+
/** Number of times this fact has been reinforced */
|
|
103
|
+
reinforcementCount: z.number().int().min(0),
|
|
104
|
+
|
|
105
|
+
/** Last time this fact was accessed or reinforced */
|
|
106
|
+
lastAccessedAt: z.date(),
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
export type ServiceProfileFact = z.infer<typeof ServiceProfileFactSchema>
|
|
110
|
+
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// Type Layer ProfileFact (API version)
|
|
113
|
+
// ============================================================================
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Type layer ProfileFact schema - used in types/index.ts
|
|
117
|
+
* Simpler version for API contracts
|
|
118
|
+
*/
|
|
119
|
+
export const TypeProfileFactSchema = BaseProfileFactSchema.extend({
|
|
120
|
+
/** Key-value style fact key */
|
|
121
|
+
key: z.string(),
|
|
122
|
+
|
|
123
|
+
/** Fact value */
|
|
124
|
+
value: z.string(),
|
|
125
|
+
|
|
126
|
+
/** Lifecycle category */
|
|
127
|
+
category: FactLifecycleCategorySchema,
|
|
128
|
+
|
|
129
|
+
/** Source identifier */
|
|
130
|
+
source: z.string().optional(),
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
export type TypeProfileFact = z.infer<typeof TypeProfileFactSchema>
|