@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
package/.env.example ADDED
@@ -0,0 +1,57 @@
1
+ # Supermemory Clone - Environment Configuration
2
+ # Copy to `.env` and adjust for your local setup.
3
+
4
+ # -----------------------------------------------------------------------------
5
+ # Core runtime (PostgreSQL required outside tests)
6
+ # -----------------------------------------------------------------------------
7
+ DATABASE_URL=postgresql://supermemory:supermemory_secret@localhost:15432/supermemory
8
+ API_HOST=localhost
9
+ API_PORT=13000
10
+ API_HOST_PORT=13000
11
+ LOG_LEVEL=info
12
+
13
+ # -----------------------------------------------------------------------------
14
+ # Optional REST API auth (disabled by default)
15
+ # -----------------------------------------------------------------------------
16
+ AUTH_ENABLED=false
17
+ AUTH_TOKEN=
18
+
19
+ # Optional CSRF hardening secret (recommended when auth is enabled)
20
+ CSRF_SECRET=
21
+ ALLOWED_ORIGINS=http://localhost:13000,http://localhost:15173
22
+
23
+ # -----------------------------------------------------------------------------
24
+ # Optional async pipeline (Redis/BullMQ)
25
+ # -----------------------------------------------------------------------------
26
+ REDIS_URL=redis://localhost:16379
27
+ POSTGRES_HOST_PORT=15432
28
+ REDIS_HOST_PORT=16379
29
+ BULLMQ_CONCURRENCY_EXTRACTION=5
30
+ BULLMQ_CONCURRENCY_CHUNKING=3
31
+ BULLMQ_CONCURRENCY_EMBEDDING=2
32
+ BULLMQ_CONCURRENCY_INDEXING=1
33
+
34
+ # -----------------------------------------------------------------------------
35
+ # Embeddings / LLM extraction (all optional)
36
+ # -----------------------------------------------------------------------------
37
+ OPENAI_API_KEY=
38
+ ANTHROPIC_API_KEY=
39
+
40
+ EMBEDDING_MODEL=text-embedding-3-small
41
+ EMBEDDING_DIMENSIONS=1536
42
+
43
+ # LLM provider: empty | openai | anthropic | mock
44
+ LLM_PROVIDER=
45
+ LLM_MODEL=
46
+ LLM_MAX_TOKENS=2000
47
+ LLM_TEMPERATURE=0.1
48
+ LLM_TIMEOUT_MS=30000
49
+ LLM_MAX_RETRIES=3
50
+ LLM_CACHE_ENABLED=true
51
+ LLM_CACHE_TTL_MS=900000
52
+
53
+ # -----------------------------------------------------------------------------
54
+ # API protections
55
+ # -----------------------------------------------------------------------------
56
+ RATE_LIMIT_REQUESTS=100
57
+ RATE_LIMIT_WINDOW_MS=60000
package/README.md ADDED
@@ -0,0 +1,374 @@
1
+ # Supermemory Clone
2
+
3
+ Local-first memory service for developers and coding agents.
4
+
5
+ It stores documents, extracts memories, indexes embeddings, and serves search/profile APIs plus an MCP server for agent workflows.
6
+
7
+ ## What It Does
8
+
9
+ - Ingests text and files into documents.
10
+ - Extracts memory units and profile facts.
11
+ - Supports semantic, memory, and hybrid search.
12
+ - Exposes REST API (`/api/v1/*`) and MCP tools (`supermemory_*`).
13
+ - Runs with PostgreSQL + pgvector; Redis is optional (queue path) because inline fallback is built in.
14
+
15
+ ## Architecture (High Level)
16
+
17
+ - `src/index.ts`: Hono API server, middleware stack, route mounting.
18
+ - `src/api/routes/*`: documents, search, profiles endpoints.
19
+ - `src/services/*`: document processing, memory extraction, search, profile logic.
20
+ - `src/mcp/*`: MCP server, tools, resources, rate limiting.
21
+ - `src/db/*`: database client routing (PostgreSQL in runtime; SQLite only for tests).
22
+ - `src/queues/*` + `src/workers/*`: BullMQ pipeline (`extraction -> chunking -> embedding -> indexing`).
23
+
24
+ ## Requirements
25
+
26
+ - Node.js >= 20
27
+ - Docker + Docker Compose
28
+ - PostgreSQL with pgvector
29
+ - Redis (optional but recommended for async workers)
30
+
31
+ ## Quick Start (Turnkey)
32
+
33
+ Primary path for first-time users:
34
+
35
+ ```bash
36
+ npx -y @twelvehart/supermemory@latest full --dir ./supermemory --mcp project
37
+ cd ./supermemory
38
+ claude
39
+ ```
40
+
41
+ That command unpacks the runtime into `./supermemory`, runs the canonical `scripts/install.sh` from the final directory, registers Claude MCP against that final path, and prints only the next steps a new user can actually take.
42
+
43
+ The npx installer supports:
44
+
45
+ ```bash
46
+ npx -y @twelvehart/supermemory@latest agent --dir ./supermemory-agent --mcp project
47
+ npx -y @twelvehart/supermemory@latest api --dir ./supermemory-api
48
+ npx -y @twelvehart/supermemory@latest full --dir ./supermemory --mcp project --skip-api-keys
49
+ npx -y @twelvehart/supermemory@latest full --dir ./supermemory --source-path "$(pwd)"
50
+ ```
51
+
52
+ Maintainer-only override for a non-empty target directory:
53
+
54
+ ```bash
55
+ npx -y @twelvehart/supermemory@latest full --dir ./supermemory --source-path "$(pwd)" --update
56
+ ```
57
+
58
+ Fallback transport for users who prefer reviewing remote scripts first:
59
+
60
+ ```bash
61
+ curl -fsSL https://raw.githubusercontent.com/ASRagab/supermemory-clone/main/scripts/bootstrap.sh | less
62
+ curl -fsSL https://raw.githubusercontent.com/ASRagab/supermemory-clone/main/scripts/bootstrap.sh | bash
63
+ ```
64
+
65
+ Local clone + canonical installer (fallback for contributors and maintainers):
66
+
67
+ ```bash
68
+ git clone https://github.com/ASRagab/supermemory-clone.git
69
+ cd supermemory-clone
70
+ ./scripts/install.sh full --scope project
71
+ ```
72
+
73
+ The in-repo shell installer remains canonical. `@twelvehart/supermemory` is the default transport and zero-knowledge entrypoint.
74
+
75
+ The canonical installer still supports explicit modes:
76
+
77
+ ```bash
78
+ ./scripts/install.sh # same as: install --mode agent
79
+ ./scripts/install.sh agent # agent-first MCP workflow
80
+ ./scripts/install.sh api # REST API workflow
81
+ ./scripts/install.sh full # both surfaces, explicit all-in path
82
+ ./scripts/install.sh update --mode api
83
+ ./scripts/install.sh agent --env-file /tmp/supermemory-agent.env
84
+ ```
85
+
86
+ Mode behavior:
87
+
88
+ - `agent`: installs dependencies, creates `.env`, starts PostgreSQL, builds the project, and prepares MCP usage without auto-starting the API.
89
+ - `api`: installs dependencies, creates `.env`, starts PostgreSQL + Redis + API, builds the project, and verifies API health.
90
+ - `full`: explicit all-surfaces install path. In the current implementation it shares the same container startup set as `api` but prints both API and MCP next steps.
91
+
92
+ The install/update flow handles:
93
+
94
+ - prerequisite checks (Node/Docker/Compose)
95
+ - `npm install`
96
+ - `.env` creation from `.env.example`
97
+ - optional API key prompts (or you can skip and configure later)
98
+ - mode-aware Docker startup + migrations
99
+ - non-conflicting local host ports by default (`13000`, `15432`, `16379`)
100
+ - build + optional Claude Code MCP registration
101
+ - connectivity check (`npm run doctor`)
102
+
103
+ Installer lifecycle commands:
104
+
105
+ ```bash
106
+ ./scripts/install.sh install # default if command is omitted; defaults to --mode agent
107
+ ./scripts/install.sh update # clean reinstall of app components; preserves postgres/redis data and attempts migrations
108
+ ./scripts/install.sh uninstall # removes generated artifacts and stops local services
109
+ ./scripts/install.sh uninstall --purge
110
+ ```
111
+
112
+ Optional flags:
113
+
114
+ ```bash
115
+ ./scripts/install.sh --skip-api-keys --skip-mcp
116
+ ./scripts/install.sh update --skip-docker
117
+ ./scripts/install.sh install --mode api --skip-api-start
118
+ ./scripts/install.sh --register-mcp --scope project
119
+ ./scripts/install.sh --non-interactive # does not register MCP unless --scope or --register-mcp is also passed
120
+ ./scripts/install.sh uninstall --purge # also removes env files, Claude MCP registrations, and docker volumes
121
+ ```
122
+
123
+ Manual path (if you skip parts of installer):
124
+
125
+ ```bash
126
+ cp .env.example .env
127
+ npm run stack:up
128
+ ./scripts/migrations/run_migrations.sh
129
+ npm run build
130
+ npm run doctor
131
+ ```
132
+
133
+ After a clone-based `./scripts/install.sh agent` install, the API is not running yet. To start the MCP server manually:
134
+
135
+ ```bash
136
+ npm run mcp
137
+ ```
138
+
139
+ If you want the REST API instead, use API mode:
140
+
141
+ ```bash
142
+ ./scripts/install.sh api
143
+ curl http://localhost:13000/health
144
+ ```
145
+
146
+ If you already installed in `api` or `full` mode, the API is running in Docker and ready to use:
147
+
148
+ ```bash
149
+ curl http://localhost:13000/health
150
+ ```
151
+
152
+ If you prefer local watch mode instead of Docker for API runtime:
153
+
154
+ ```bash
155
+ docker compose stop api
156
+ npm run dev
157
+ curl http://localhost:13000/health
158
+ ```
159
+
160
+ ## Configuration
161
+
162
+ Copy `.env.example` to `.env` and set values.
163
+
164
+ Env file precedence is:
165
+
166
+ 1. CLI `--env-file` for supported scripts
167
+ 2. `SUPERMEMORY_ENV_FILE`
168
+ 3. `.env.local`
169
+ 4. `.env`
170
+
171
+ The API and MCP runtime honor `SUPERMEMORY_ENV_FILE`, then fall back to `.env.local`, then `.env`.
172
+
173
+ Examples:
174
+
175
+ ```bash
176
+ SUPERMEMORY_ENV_FILE=~/.config/supermemory/config.env npm run doctor -- --mode agent
177
+ npm run mcp:setup -- --env-file /tmp/supermemory-agent.env
178
+ ./scripts/install.sh agent --env-file /tmp/supermemory-agent.env
179
+ ```
180
+
181
+ Required:
182
+
183
+ - `DATABASE_URL` (must be `postgres://` or `postgresql://` outside tests)
184
+
185
+ Optional:
186
+
187
+ - `AUTH_ENABLED`, `AUTH_TOKEN` (minimal bearer token auth)
188
+ - `REDIS_URL` (queues; if unavailable, ingestion falls back inline)
189
+ - `OPENAI_API_KEY` (embeddings)
190
+ - `LLM_PROVIDER`, `ANTHROPIC_API_KEY` (LLM extraction)
191
+ - `CSRF_SECRET`, `ALLOWED_ORIGINS` (hardening)
192
+
193
+ No external API keys are required for basic local operation.
194
+ Fresh installs leave provider keys and `LLM_PROVIDER` blank until you set real credentials.
195
+
196
+ ## Auth and CSRF
197
+
198
+ - API auth is optional.
199
+ - `AUTH_ENABLED=false` (default): pass-through auth context.
200
+ - `AUTH_ENABLED=true`: requires `Authorization: Bearer <AUTH_TOKEN>`.
201
+ - CSRF protection is applied to API state-changing routes; use `GET /api/v1/csrf-token` first for browser clients.
202
+
203
+ ## REST API Surface
204
+
205
+ Base path: `/api/v1`
206
+
207
+ - `POST /documents`
208
+ - `GET /documents`
209
+ - `GET /documents/:id`
210
+ - `PUT /documents/:id`
211
+ - `DELETE /documents/:id`
212
+ - `POST /documents/file`
213
+ - `POST /documents/bulk-delete`
214
+ - `POST /search`
215
+ - `GET /profiles`
216
+ - `GET /profiles/:tag`
217
+ - `PUT /profiles/:tag`
218
+ - `DELETE /profiles/:tag`
219
+
220
+ ## MCP for Coding Agents
221
+
222
+ ### Quick Setup
223
+
224
+ First-time user path:
225
+
226
+ ```bash
227
+ npx -y @twelvehart/supermemory@latest full --dir ./supermemory --mcp project
228
+ cd ./supermemory
229
+ claude
230
+ ```
231
+
232
+ Clone-based maintainer path:
233
+
234
+ ```bash
235
+ npm run mcp:setup
236
+ npm run mcp:setup -- --scope project --non-interactive --register-mcp
237
+ ```
238
+
239
+ ### Installation Options
240
+
241
+ **Option A — npx-first install**
242
+
243
+ ```bash
244
+ npx -y @twelvehart/supermemory@latest full --dir ./supermemory --mcp project
245
+ ```
246
+
247
+ **Option B — Manual registration with the setup helper**
248
+
249
+ ```bash
250
+ npm run mcp:setup
251
+ ```
252
+
253
+ **Option C — Project-scope registration**
254
+
255
+ ```bash
256
+ npm run build
257
+ npm run mcp:setup -- --scope project --non-interactive --register-mcp
258
+ ```
259
+
260
+ **Option D — Direct Claude CLI registration**
261
+
262
+ ```bash
263
+ npm run build
264
+ claude mcp add supermemory --scope user -- node "$(pwd)/dist/mcp/index.js"
265
+ ```
266
+
267
+ **Option E — Direct MCP package execution**
268
+
269
+ ```bash
270
+ claude mcp add supermemory -- npx supermemory-mcp
271
+ ```
272
+
273
+ ### Prerequisites
274
+
275
+ - Node.js >= 20
276
+ - PostgreSQL with pgvector running (`docker compose up -d postgres`)
277
+ - Project built (`npm run build`)
278
+
279
+ ### Environment Variables
280
+
281
+ | Variable | Required | Description |
282
+ |----------|----------|-------------|
283
+ | `DATABASE_URL` | Yes | PostgreSQL connection string |
284
+ | `OPENAI_API_KEY` | No | Enables embeddings and LLM features |
285
+ | `REDIS_URL` | No | Enables async queue workers |
286
+ | `LOG_LEVEL` | No | Logging verbosity (default: `info`) |
287
+
288
+ ### Verification
289
+
290
+ ```bash
291
+ npm run doctor -- --mode agent
292
+ npm run doctor -- --mode api
293
+ claude mcp get supermemory
294
+ ```
295
+
296
+ ### Troubleshooting
297
+
298
+ | Symptom | Fix |
299
+ |---------|-----|
300
+ | `dist/mcp/index.js` not found | Run `npm run build` |
301
+ | PostgreSQL connection refused | Start the container: `docker compose up -d postgres` |
302
+ | Port already in use | Check `API_PORT` in `.env` (default 13000) |
303
+ | MCP tools not appearing | Re-register: `npm run mcp:setup` |
304
+
305
+ ### MCP Tools
306
+
307
+ - `supermemory_add`
308
+ - `supermemory_search`
309
+ - `supermemory_profile`
310
+ - `supermemory_list`
311
+ - `supermemory_delete`
312
+ - `supermemory_remember`
313
+ - `supermemory_recall`
314
+
315
+ ## Development Commands
316
+
317
+ - `npm run dev` - API with watch mode
318
+ - `npm run build` - TypeScript build
319
+ - `npm run build:install` - Build `packages/install`
320
+ - `npm run start` - Run built API
321
+ - `npm run mcp:dev` - MCP with tsx
322
+ - `npm run mcp` - Run built MCP server
323
+ - `npm run stack:up` - Start API + Postgres + Redis containers
324
+ - `npm run stack:down` - Stop and remove stack containers
325
+ - `npm run stack:logs` - Tail API container logs
326
+ - `npm run test:run` - Full tests once
327
+ - `npm run test:install` - Installer-specific tests
328
+ - `npm run lint` - ESLint
329
+ - `npm run typecheck` - TS checks
330
+ - `npm run typecheck:install` - Installer package TS checks
331
+ - `npm run pack:check:runtime` - Verify the runtime npm tarball contents
332
+ - `npm run validate` - typecheck + lint + format + tests
333
+
334
+ ## Testing
335
+
336
+ - Unit/integration tests: `vitest`
337
+ - Typical focused run:
338
+
339
+ ```bash
340
+ npx vitest run tests/services/search.service.test.ts
341
+ ```
342
+
343
+ - Database regression flow:
344
+
345
+ ```bash
346
+ npm run db:test:phase1
347
+ ```
348
+
349
+ ## Publish and Smoke Release
350
+
351
+ Publish order:
352
+
353
+ 1. Publish `@twelvehart/supermemory-runtime` from the repo root after `npm run build` and `npm run pack:check:runtime`.
354
+ 2. Publish `@twelvehart/supermemory` from `packages/install` after `npm run build:install`, `npm run typecheck:install`, and `npm run test:install`.
355
+
356
+ Smoke-release procedure for the freshly published packages:
357
+
358
+ ```bash
359
+ bash scripts/smoke-install.sh ./supermemory-smoke
360
+ cd ./supermemory-smoke
361
+ curl http://localhost:13000/health
362
+ claude
363
+ ```
364
+
365
+ ## Project Policy
366
+
367
+ Repository documentation is intentionally consolidated into only:
368
+
369
+ - `README.md` (project/system/operator reference)
370
+ - `AGENTS.md` (agent/contributor implementation reference)
371
+
372
+ ## License
373
+
374
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,189 @@
1
+ import './config/bootstrap-env.js';
2
+ import { serve } from '@hono/node-server';
3
+ import { Hono } from 'hono';
4
+ import { cors } from 'hono/cors';
5
+ import { logger } from 'hono/logger';
6
+ import { prettyJSON } from 'hono/pretty-json';
7
+ import { timing } from 'hono/timing';
8
+ import pkg from 'pg';
9
+ import { config } from './config/index.js';
10
+ import { getDatabase } from './db/client.js';
11
+ // Import route modules
12
+ import { documentsRouter } from './api/routes/documents.js';
13
+ import { searchRouter } from './api/routes/search.js';
14
+ import { profilesRouter } from './api/routes/profiles.js';
15
+ import { authMiddleware } from './api/middleware/auth.js';
16
+ import { errorHandlerMiddleware } from './api/middleware/errorHandler.js';
17
+ import { standardRateLimit } from './api/middleware/rateLimit.js';
18
+ import { setCsrfCookie, csrfProtection } from './api/middleware/csrf.js';
19
+ import { initializeAndValidate } from './startup.js';
20
+ const { Pool } = pkg;
21
+ // Initialize database
22
+ const db = getDatabase();
23
+ let healthPool = null;
24
+ function getHealthPool() {
25
+ if (!healthPool) {
26
+ healthPool = new Pool({
27
+ connectionString: config.databaseUrl,
28
+ max: 1,
29
+ idleTimeoutMillis: 30000,
30
+ connectionTimeoutMillis: 2000,
31
+ });
32
+ }
33
+ return healthPool;
34
+ }
35
+ // Create Hono app
36
+ const app = new Hono();
37
+ // ============================================================================
38
+ // Global Middleware
39
+ // ============================================================================
40
+ // Error handler (must be first to catch all errors)
41
+ app.use('*', errorHandlerMiddleware);
42
+ // Request logging
43
+ app.use('*', logger());
44
+ // CORS configuration
45
+ app.use('*', cors({
46
+ origin: ['http://localhost:3000', 'http://localhost:5173'],
47
+ allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
48
+ allowHeaders: ['Content-Type', 'Authorization', 'X-Request-ID', 'X-CSRF-Token'],
49
+ exposeHeaders: ['X-RateLimit-Limit', 'X-RateLimit-Remaining', 'X-RateLimit-Reset'],
50
+ credentials: true,
51
+ maxAge: 86400,
52
+ }));
53
+ // Pretty JSON responses in development
54
+ if (process.env.NODE_ENV !== 'production') {
55
+ app.use('*', prettyJSON());
56
+ }
57
+ // Request timing
58
+ app.use('*', timing());
59
+ // ============================================================================
60
+ // Health Check (No Auth Required)
61
+ // ============================================================================
62
+ app.get('/health', async (c) => {
63
+ const checks = {
64
+ status: 'healthy',
65
+ version: '1.0.0',
66
+ timestamp: new Date().toISOString(),
67
+ };
68
+ try {
69
+ const pool = getHealthPool();
70
+ await pool.query('SELECT 1');
71
+ }
72
+ catch {
73
+ checks.status = 'unhealthy';
74
+ }
75
+ const statusCode = checks.status === 'healthy' ? 200 : 503;
76
+ return c.json(checks, statusCode);
77
+ });
78
+ app.get('/', (c) => {
79
+ return c.json({
80
+ name: 'Supermemory Clone API',
81
+ version: '1.0.0',
82
+ description: 'Personal AI memory assistant with semantic search',
83
+ endpoints: {
84
+ documents: '/api/v1/documents',
85
+ search: '/api/v1/search',
86
+ profiles: '/api/v1/profiles',
87
+ },
88
+ });
89
+ });
90
+ // CSRF token endpoint for SPA clients
91
+ // Apply CSRF cookie middleware to provide token
92
+ app.get('/api/v1/csrf-token', setCsrfCookie(), (c) => {
93
+ const csrfToken = c.get('csrfToken');
94
+ return c.json({
95
+ csrfToken,
96
+ expiresIn: 3600, // 1 hour in seconds
97
+ });
98
+ });
99
+ // ============================================================================
100
+ // API Routes (Auth Required)
101
+ // ============================================================================
102
+ const api = new Hono();
103
+ // Apply middleware stack to all API routes
104
+ // Order: auth → CSRF → rate limit → routes
105
+ api.use('*', authMiddleware);
106
+ api.use('*', setCsrfCookie());
107
+ api.use('*', csrfProtection({
108
+ allowedOrigins: process.env.ALLOWED_ORIGINS?.split(',') || ['http://localhost:3000', 'http://localhost:5173'],
109
+ }));
110
+ api.use('*', standardRateLimit);
111
+ // Mount route modules
112
+ api.route('/documents', documentsRouter);
113
+ api.route('/search', searchRouter);
114
+ api.route('/profiles', profilesRouter);
115
+ // Mount API under versioned path
116
+ app.route('/api/v1', api);
117
+ // ============================================================================
118
+ // 404 Handler
119
+ // ============================================================================
120
+ app.notFound((c) => {
121
+ return c.json({
122
+ error: {
123
+ code: 'NOT_FOUND',
124
+ message: `Route ${c.req.method} ${c.req.path} not found`,
125
+ },
126
+ status: 404,
127
+ }, 404);
128
+ });
129
+ // ============================================================================
130
+ // Error Handler
131
+ // ============================================================================
132
+ app.onError((err, c) => {
133
+ console.error('Unhandled error:', err);
134
+ return c.json({
135
+ error: {
136
+ code: 'INTERNAL_SERVER_ERROR',
137
+ message: process.env.NODE_ENV === 'development' ? err.message : 'An unexpected error occurred',
138
+ },
139
+ status: 500,
140
+ }, 500);
141
+ });
142
+ // ============================================================================
143
+ // Start Server
144
+ // ============================================================================
145
+ const port = config.apiPort;
146
+ const host = config.apiHost;
147
+ console.log(`
148
+ ================================================
149
+ Supermemory Clone API Server
150
+ ================================================
151
+ Version: 1.0.0
152
+ Port: ${port}
153
+ Host: ${host}
154
+ Environment: ${process.env.NODE_ENV ?? 'development'}
155
+ ================================================
156
+
157
+ Available endpoints:
158
+ GET / - API info
159
+ GET /health - Health check
160
+
161
+ POST /api/v1/documents - Create document
162
+ GET /api/v1/documents - List documents
163
+ GET /api/v1/documents/:id - Get document
164
+ PUT /api/v1/documents/:id - Update document
165
+ DELETE /api/v1/documents/:id - Delete document
166
+ POST /api/v1/documents/file - Upload file
167
+ POST /api/v1/documents/bulk-delete - Bulk delete
168
+
169
+ POST /api/v1/search - Search documents
170
+
171
+ GET /api/v1/profiles - List profiles
172
+ GET /api/v1/profiles/:tag - Get profile
173
+ PUT /api/v1/profiles/:tag - Update profile
174
+ DELETE /api/v1/profiles/:tag - Delete profile
175
+ `);
176
+ async function startServer() {
177
+ await initializeAndValidate();
178
+ serve({
179
+ fetch: app.fetch,
180
+ port,
181
+ hostname: host,
182
+ });
183
+ }
184
+ startServer().catch((error) => {
185
+ console.error('Failed to start API server:', error);
186
+ process.exit(1);
187
+ });
188
+ export { app, db };
189
+ //# sourceMappingURL=index.js.map