@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,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BullMQ Queue Factory and Exports
|
|
3
|
+
*
|
|
4
|
+
* Provides queue instances for document processing pipeline:
|
|
5
|
+
* - extraction: Document content extraction
|
|
6
|
+
* - chunking: Text chunking for embeddings
|
|
7
|
+
* - embedding: Generate vector embeddings
|
|
8
|
+
* - indexing: Index into vector store
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { Queue, QueueEvents } from 'bullmq'
|
|
12
|
+
import { Redis } from 'ioredis'
|
|
13
|
+
import { defaultQueueOptions, deadLetterQueueOptions, redisConfig, JobProgress } from './config.js'
|
|
14
|
+
import { ValidationError, NotFoundError, ErrorCode } from '../utils/errors.js'
|
|
15
|
+
import { getLogger } from '../utils/logger.js'
|
|
16
|
+
|
|
17
|
+
const logger = getLogger('queues')
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Queue names enum for type safety
|
|
21
|
+
*/
|
|
22
|
+
export enum QueueName {
|
|
23
|
+
EXTRACTION = 'extraction',
|
|
24
|
+
CHUNKING = 'chunking',
|
|
25
|
+
EMBEDDING = 'embedding',
|
|
26
|
+
INDEXING = 'indexing',
|
|
27
|
+
DEAD_LETTER = 'dead-letter',
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Queue metrics interface
|
|
32
|
+
*/
|
|
33
|
+
export interface QueueMetrics {
|
|
34
|
+
waiting: number
|
|
35
|
+
active: number
|
|
36
|
+
completed: number
|
|
37
|
+
failed: number
|
|
38
|
+
delayed: number
|
|
39
|
+
paused: boolean
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Redis connection singleton
|
|
44
|
+
*/
|
|
45
|
+
let redisConnection: Redis | null = null
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get or create Redis connection
|
|
49
|
+
*/
|
|
50
|
+
export function getRedisConnection(): Redis {
|
|
51
|
+
if (!redisConnection) {
|
|
52
|
+
redisConnection = new Redis(redisConfig.connection)
|
|
53
|
+
|
|
54
|
+
redisConnection.on('connect', () => {
|
|
55
|
+
logger.info('Redis connected successfully')
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
redisConnection.on('ready', () => {
|
|
59
|
+
logger.info('Redis ready to accept commands')
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
redisConnection.on('error', (err: Error) => {
|
|
63
|
+
logger.error('Redis connection error', {}, err)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
redisConnection.on('close', () => {
|
|
67
|
+
logger.info('Redis connection closed')
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
redisConnection.on('reconnecting', () => {
|
|
71
|
+
logger.info('Redis attempting to reconnect')
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return redisConnection
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Check Redis connection health
|
|
80
|
+
*/
|
|
81
|
+
export async function checkRedisHealth(): Promise<boolean> {
|
|
82
|
+
try {
|
|
83
|
+
const redis = getRedisConnection()
|
|
84
|
+
const result = await redis.ping()
|
|
85
|
+
return result === 'PONG'
|
|
86
|
+
} catch (error) {
|
|
87
|
+
logger.error('Redis health check failed', {}, error instanceof Error ? error : undefined)
|
|
88
|
+
return false
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Close Redis connection gracefully
|
|
94
|
+
*/
|
|
95
|
+
export async function closeRedisConnection(): Promise<void> {
|
|
96
|
+
if (redisConnection) {
|
|
97
|
+
await redisConnection.quit()
|
|
98
|
+
redisConnection = null
|
|
99
|
+
logger.info('Redis connection closed gracefully')
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Create a queue instance
|
|
105
|
+
*/
|
|
106
|
+
function createQueue(name: QueueName, isDLQ = false): Queue {
|
|
107
|
+
const options = isDLQ ? deadLetterQueueOptions : defaultQueueOptions
|
|
108
|
+
return new Queue(name, options)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Queue instances
|
|
113
|
+
*/
|
|
114
|
+
export const extractionQueue = createQueue(QueueName.EXTRACTION)
|
|
115
|
+
export const chunkingQueue = createQueue(QueueName.CHUNKING)
|
|
116
|
+
export const embeddingQueue = createQueue(QueueName.EMBEDDING)
|
|
117
|
+
export const indexingQueue = createQueue(QueueName.INDEXING)
|
|
118
|
+
export const deadLetterQueue = createQueue(QueueName.DEAD_LETTER, true)
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Queue events for monitoring
|
|
122
|
+
*/
|
|
123
|
+
export const extractionEvents = new QueueEvents(QueueName.EXTRACTION, {
|
|
124
|
+
connection: redisConfig.connection,
|
|
125
|
+
})
|
|
126
|
+
export const chunkingEvents = new QueueEvents(QueueName.CHUNKING, {
|
|
127
|
+
connection: redisConfig.connection,
|
|
128
|
+
})
|
|
129
|
+
export const embeddingEvents = new QueueEvents(QueueName.EMBEDDING, {
|
|
130
|
+
connection: redisConfig.connection,
|
|
131
|
+
})
|
|
132
|
+
export const indexingEvents = new QueueEvents(QueueName.INDEXING, {
|
|
133
|
+
connection: redisConfig.connection,
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get queue by name
|
|
138
|
+
*/
|
|
139
|
+
export function getQueue(name: QueueName): Queue {
|
|
140
|
+
switch (name) {
|
|
141
|
+
case QueueName.EXTRACTION:
|
|
142
|
+
return extractionQueue
|
|
143
|
+
case QueueName.CHUNKING:
|
|
144
|
+
return chunkingQueue
|
|
145
|
+
case QueueName.EMBEDDING:
|
|
146
|
+
return embeddingQueue
|
|
147
|
+
case QueueName.INDEXING:
|
|
148
|
+
return indexingQueue
|
|
149
|
+
case QueueName.DEAD_LETTER:
|
|
150
|
+
return deadLetterQueue
|
|
151
|
+
default:
|
|
152
|
+
throw new ValidationError(`Unknown queue: ${name}`, {
|
|
153
|
+
queue: [`Invalid queue '${name}'. Valid queues: ${Object.values(QueueName).join(', ')}`],
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get queue metrics for monitoring
|
|
160
|
+
*/
|
|
161
|
+
export async function getQueueMetrics(queueName: QueueName): Promise<QueueMetrics> {
|
|
162
|
+
const queue = getQueue(queueName)
|
|
163
|
+
|
|
164
|
+
const [waiting, active, completed, failed, delayed, isPaused] = await Promise.all([
|
|
165
|
+
queue.getWaitingCount(),
|
|
166
|
+
queue.getActiveCount(),
|
|
167
|
+
queue.getCompletedCount(),
|
|
168
|
+
queue.getFailedCount(),
|
|
169
|
+
queue.getDelayedCount(),
|
|
170
|
+
queue.isPaused(),
|
|
171
|
+
])
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
waiting,
|
|
175
|
+
active,
|
|
176
|
+
completed,
|
|
177
|
+
failed,
|
|
178
|
+
delayed,
|
|
179
|
+
paused: isPaused,
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Get metrics for all queues
|
|
185
|
+
*/
|
|
186
|
+
export async function getAllQueueMetrics(): Promise<Record<QueueName, QueueMetrics>> {
|
|
187
|
+
const queueNames = [
|
|
188
|
+
QueueName.EXTRACTION,
|
|
189
|
+
QueueName.CHUNKING,
|
|
190
|
+
QueueName.EMBEDDING,
|
|
191
|
+
QueueName.INDEXING,
|
|
192
|
+
QueueName.DEAD_LETTER,
|
|
193
|
+
]
|
|
194
|
+
|
|
195
|
+
const metricsPromises = queueNames.map(async (name) => ({
|
|
196
|
+
name,
|
|
197
|
+
metrics: await getQueueMetrics(name),
|
|
198
|
+
}))
|
|
199
|
+
|
|
200
|
+
const results = await Promise.all(metricsPromises)
|
|
201
|
+
|
|
202
|
+
return results.reduce(
|
|
203
|
+
(acc, { name, metrics }) => {
|
|
204
|
+
acc[name] = metrics
|
|
205
|
+
return acc
|
|
206
|
+
},
|
|
207
|
+
{} as Record<QueueName, QueueMetrics>
|
|
208
|
+
)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Move failed job to dead letter queue
|
|
213
|
+
*/
|
|
214
|
+
export async function moveToDeadLetterQueue(queueName: QueueName, jobId: string, reason: string): Promise<string> {
|
|
215
|
+
const sourceQueue = getQueue(queueName)
|
|
216
|
+
const job = await sourceQueue.getJob(jobId)
|
|
217
|
+
|
|
218
|
+
if (!job) {
|
|
219
|
+
throw new NotFoundError('Job', jobId, ErrorCode.NOT_FOUND)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Add to dead letter queue with original data plus metadata
|
|
223
|
+
const dlqJob = await deadLetterQueue.add(
|
|
224
|
+
'failed-job',
|
|
225
|
+
{
|
|
226
|
+
originalQueue: queueName,
|
|
227
|
+
originalJobId: jobId,
|
|
228
|
+
originalData: job.data,
|
|
229
|
+
failureReason: reason,
|
|
230
|
+
attemptsMade: job.attemptsMade,
|
|
231
|
+
timestamp: new Date().toISOString(),
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
priority: 1, // Low priority for manual review
|
|
235
|
+
}
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
// Remove from original queue
|
|
239
|
+
await job.remove()
|
|
240
|
+
logger.info('Moved job to dead letter queue', { jobId, queueName, reason })
|
|
241
|
+
|
|
242
|
+
return dlqJob.id!
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Update job progress
|
|
247
|
+
*/
|
|
248
|
+
export async function updateJobProgress(queueName: QueueName, jobId: string, progress: JobProgress): Promise<void> {
|
|
249
|
+
const queue = getQueue(queueName)
|
|
250
|
+
const job = await queue.getJob(jobId)
|
|
251
|
+
|
|
252
|
+
if (!job) {
|
|
253
|
+
throw new NotFoundError('Job', jobId, ErrorCode.NOT_FOUND)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
await job.updateProgress(progress)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Clean up old jobs across all queues
|
|
261
|
+
*/
|
|
262
|
+
export async function cleanupQueues(gracePeriodMs = 24 * 60 * 60 * 1000): Promise<void> {
|
|
263
|
+
const queues = [extractionQueue, chunkingQueue, embeddingQueue, indexingQueue]
|
|
264
|
+
|
|
265
|
+
for (const queue of queues) {
|
|
266
|
+
await queue.clean(gracePeriodMs, 1000, 'completed')
|
|
267
|
+
await queue.clean(gracePeriodMs * 7, 1000, 'failed') // Keep failed jobs longer
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
logger.info('Queue cleanup completed', { gracePeriodMs })
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Gracefully close all queues
|
|
275
|
+
*/
|
|
276
|
+
export async function closeAllQueues(): Promise<void> {
|
|
277
|
+
const queues = [extractionQueue, chunkingQueue, embeddingQueue, indexingQueue, deadLetterQueue]
|
|
278
|
+
|
|
279
|
+
const events = [extractionEvents, chunkingEvents, embeddingEvents, indexingEvents]
|
|
280
|
+
|
|
281
|
+
await Promise.all([...queues.map((q) => q.close()), ...events.map((e) => e.close()), closeRedisConnection()])
|
|
282
|
+
|
|
283
|
+
logger.info('All queues closed gracefully')
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Export types and enums
|
|
287
|
+
export type { JobProgress }
|
|
288
|
+
export { JobPriority } from './config.js'
|
|
289
|
+
export { concurrencySettings } from './config.js'
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supermemory Client
|
|
3
|
+
* Main entry point for the Supermemory SDK
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { HTTPClient, APIPromise, toFile } from './http.js'
|
|
7
|
+
import { Search, Documents, Memories, Connections, Settings } from './resources/index.js'
|
|
8
|
+
import type { ClientOptions, RequestOptions, AddParams, AddResponse, ProfileParams, ProfileResponse } from './types.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* API Client for interfacing with the Supermemory API
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import Supermemory from 'supermemory';
|
|
16
|
+
*
|
|
17
|
+
* const client = new Supermemory({
|
|
18
|
+
* apiKey: process.env.SUPERMEMORY_API_KEY,
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* const response = await client.add({ content: 'Hello, world!' });
|
|
22
|
+
* console.log(response.id);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export class Supermemory {
|
|
26
|
+
private _client: HTTPClient
|
|
27
|
+
private _options: ClientOptions
|
|
28
|
+
|
|
29
|
+
// Resource instances
|
|
30
|
+
readonly search: Search
|
|
31
|
+
readonly documents: Documents
|
|
32
|
+
readonly memories: Memories
|
|
33
|
+
readonly connections: Connections
|
|
34
|
+
readonly settings: Settings
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Create a new Supermemory client
|
|
38
|
+
*
|
|
39
|
+
* @param options - Client configuration options
|
|
40
|
+
*/
|
|
41
|
+
constructor(options: ClientOptions = {}) {
|
|
42
|
+
this._options = options
|
|
43
|
+
this._client = new HTTPClient(options)
|
|
44
|
+
|
|
45
|
+
// Initialize resources
|
|
46
|
+
this.search = new Search(this._client)
|
|
47
|
+
this.documents = new Documents(this._client)
|
|
48
|
+
this.memories = new Memories(this._client)
|
|
49
|
+
this.connections = new Connections(this._client)
|
|
50
|
+
this.settings = new Settings(this._client)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// Top-Level Methods
|
|
55
|
+
// ============================================================================
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Add content to Supermemory
|
|
59
|
+
*
|
|
60
|
+
* This is the primary method for ingesting content. The content can be:
|
|
61
|
+
* - A URL to a website, PDF, image, or video
|
|
62
|
+
* - Plain text content
|
|
63
|
+
* - Markdown content
|
|
64
|
+
*
|
|
65
|
+
* @param body - Content and metadata to add
|
|
66
|
+
* @param options - Request options
|
|
67
|
+
* @returns Document ID and status
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* // Add a URL
|
|
72
|
+
* const response = await client.add({
|
|
73
|
+
* content: 'https://example.com/article',
|
|
74
|
+
* containerTag: 'my-project',
|
|
75
|
+
* });
|
|
76
|
+
*
|
|
77
|
+
* // Add text content
|
|
78
|
+
* const response = await client.add({
|
|
79
|
+
* content: 'This is important information to remember.',
|
|
80
|
+
* metadata: { source: 'notes', priority: 'high' },
|
|
81
|
+
* });
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
add(body: AddParams, options?: RequestOptions): APIPromise<AddResponse> {
|
|
85
|
+
return this._client.post<AddResponse>('/v3/add', {
|
|
86
|
+
body,
|
|
87
|
+
requestOptions: options,
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get user profile with optional search context
|
|
93
|
+
*
|
|
94
|
+
* Returns both dynamic (recent) and static (long-term) memory profile
|
|
95
|
+
* for a given container tag. Optionally includes search results.
|
|
96
|
+
*
|
|
97
|
+
* @param body - Profile parameters including container tag
|
|
98
|
+
* @param options - Request options
|
|
99
|
+
* @returns Profile data and optional search results
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const profile = await client.profile({
|
|
104
|
+
* containerTag: 'user-123',
|
|
105
|
+
* q: 'preferences', // Optional search query
|
|
106
|
+
* });
|
|
107
|
+
*
|
|
108
|
+
* console.log('Dynamic memories:', profile.profile.dynamic);
|
|
109
|
+
* console.log('Static memories:', profile.profile.static);
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
profile(body: ProfileParams, options?: RequestOptions): APIPromise<ProfileResponse> {
|
|
113
|
+
return this._client.post<ProfileResponse>('/v3/profile', {
|
|
114
|
+
body,
|
|
115
|
+
requestOptions: options,
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ============================================================================
|
|
120
|
+
// Low-Level HTTP Methods
|
|
121
|
+
// ============================================================================
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Make a raw GET request
|
|
125
|
+
*
|
|
126
|
+
* @param path - API path
|
|
127
|
+
* @param options - Request options
|
|
128
|
+
*/
|
|
129
|
+
get<T>(path: string, options?: { query?: Record<string, unknown>; requestOptions?: RequestOptions }): APIPromise<T> {
|
|
130
|
+
return this._client.get<T>(path, options)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Make a raw POST request
|
|
135
|
+
*
|
|
136
|
+
* @param path - API path
|
|
137
|
+
* @param options - Request options
|
|
138
|
+
*/
|
|
139
|
+
post<T>(
|
|
140
|
+
path: string,
|
|
141
|
+
options?: {
|
|
142
|
+
body?: unknown
|
|
143
|
+
query?: Record<string, unknown>
|
|
144
|
+
requestOptions?: RequestOptions
|
|
145
|
+
}
|
|
146
|
+
): APIPromise<T> {
|
|
147
|
+
return this._client.post<T>(path, options)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Make a raw PUT request
|
|
152
|
+
*
|
|
153
|
+
* @param path - API path
|
|
154
|
+
* @param options - Request options
|
|
155
|
+
*/
|
|
156
|
+
put<T>(
|
|
157
|
+
path: string,
|
|
158
|
+
options?: {
|
|
159
|
+
body?: unknown
|
|
160
|
+
query?: Record<string, unknown>
|
|
161
|
+
requestOptions?: RequestOptions
|
|
162
|
+
}
|
|
163
|
+
): APIPromise<T> {
|
|
164
|
+
return this._client.put<T>(path, options)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Make a raw PATCH request
|
|
169
|
+
*
|
|
170
|
+
* @param path - API path
|
|
171
|
+
* @param options - Request options
|
|
172
|
+
*/
|
|
173
|
+
patch<T>(
|
|
174
|
+
path: string,
|
|
175
|
+
options?: {
|
|
176
|
+
body?: unknown
|
|
177
|
+
query?: Record<string, unknown>
|
|
178
|
+
requestOptions?: RequestOptions
|
|
179
|
+
}
|
|
180
|
+
): APIPromise<T> {
|
|
181
|
+
return this._client.patch<T>(path, options)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Make a raw DELETE request
|
|
186
|
+
*
|
|
187
|
+
* @param path - API path
|
|
188
|
+
* @param options - Request options
|
|
189
|
+
*/
|
|
190
|
+
delete<T>(
|
|
191
|
+
path: string,
|
|
192
|
+
options?: {
|
|
193
|
+
body?: unknown
|
|
194
|
+
query?: Record<string, unknown>
|
|
195
|
+
requestOptions?: RequestOptions
|
|
196
|
+
}
|
|
197
|
+
): APIPromise<T> {
|
|
198
|
+
return this._client.delete<T>(path, options)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ============================================================================
|
|
202
|
+
// Configuration Methods
|
|
203
|
+
// ============================================================================
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Create a new client with modified options
|
|
207
|
+
*
|
|
208
|
+
* @param options - Options to override
|
|
209
|
+
* @returns New client instance with merged options
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```typescript
|
|
213
|
+
* const clientWithTimeout = client.withOptions({ timeout: 30000 });
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
216
|
+
withOptions(options: Partial<ClientOptions>): Supermemory {
|
|
217
|
+
return new Supermemory({
|
|
218
|
+
...this._options,
|
|
219
|
+
...options,
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Re-export for convenience
|
|
225
|
+
export { toFile }
|