cursor-supermemory 1.0.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/dist/cli.js ADDED
@@ -0,0 +1,1767 @@
1
+ // src/config.ts
2
+ import path2 from "node:path";
3
+ import os2 from "node:os";
4
+ import fs2 from "node:fs";
5
+
6
+ // src/auth.ts
7
+ import path from "node:path";
8
+ import os from "node:os";
9
+ import fs from "node:fs";
10
+ var CREDENTIALS_DIR = path.join(os.homedir(), ".supermemory-cursor");
11
+ var CREDENTIALS_FILE = path.join(CREDENTIALS_DIR, "credentials.json");
12
+ var AUTH_PORT = 19878;
13
+ var AUTH_URL = "https://console.supermemory.ai/auth/connect";
14
+ var SUCCESS_HTML = `<!DOCTYPE html>
15
+ <html><head><style>
16
+ body { background: #111; color: #fff; font-family: system-ui; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; }
17
+ h1 { font-size: 2rem; }
18
+ </style></head><body><h1>Connected to Cursor!</h1></body></html>`;
19
+ function loadCredentials() {
20
+ try {
21
+ if (!fs.existsSync(CREDENTIALS_FILE))
22
+ return null;
23
+ const data = JSON.parse(fs.readFileSync(CREDENTIALS_FILE, "utf-8"));
24
+ if (data.apiKey)
25
+ return data;
26
+ return null;
27
+ } catch {
28
+ return null;
29
+ }
30
+ }
31
+ function saveCredentials(apiKey) {
32
+ fs.mkdirSync(CREDENTIALS_DIR, { recursive: true, mode: 448 });
33
+ const data = { apiKey, createdAt: new Date().toISOString() };
34
+ fs.writeFileSync(CREDENTIALS_FILE, JSON.stringify(data, null, 2), { mode: 384 });
35
+ }
36
+ function clearCredentials() {
37
+ try {
38
+ if (fs.existsSync(CREDENTIALS_FILE)) {
39
+ fs.unlinkSync(CREDENTIALS_FILE);
40
+ return true;
41
+ }
42
+ return false;
43
+ } catch {
44
+ return false;
45
+ }
46
+ }
47
+ async function startAuthFlow(timeoutMs = 120000) {
48
+ return new Promise((resolve) => {
49
+ let settled = false;
50
+ const server = Bun.serve({
51
+ port: AUTH_PORT,
52
+ hostname: "127.0.0.1",
53
+ fetch(req) {
54
+ const url = new URL(req.url);
55
+ if (url.pathname !== "/callback") {
56
+ return new Response("Not found", { status: 404 });
57
+ }
58
+ const apiKey = url.searchParams.get("apikey") || url.searchParams.get("api_key");
59
+ if (!apiKey?.startsWith("sm_")) {
60
+ return new Response("Invalid API key", { status: 400 });
61
+ }
62
+ saveCredentials(apiKey);
63
+ settled = true;
64
+ server.stop();
65
+ clearTimeout(timer);
66
+ resolve({ success: true, apiKey });
67
+ return new Response(SUCCESS_HTML, {
68
+ headers: { "Content-Type": "text/html" }
69
+ });
70
+ }
71
+ });
72
+ const callbackUrl = `http://localhost:${AUTH_PORT}/callback`;
73
+ const authUrl = `${AUTH_URL}?callback=${encodeURIComponent(callbackUrl)}&client=cursor`;
74
+ process.stderr.write(`
75
+ Open this URL to connect Supermemory to Cursor:
76
+
77
+ ${authUrl}
78
+
79
+ Waiting...
80
+ `);
81
+ const opener = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
82
+ Bun.$`${opener} ${authUrl}`.quiet().nothrow();
83
+ const timer = setTimeout(() => {
84
+ if (!settled) {
85
+ server.stop();
86
+ resolve({ success: false, error: "Authentication timed out" });
87
+ }
88
+ }, timeoutMs);
89
+ });
90
+ }
91
+
92
+ // src/config.ts
93
+ var DEFAULTS = {
94
+ similarityThreshold: 0.3,
95
+ maxMemories: 10,
96
+ maxProjectMemories: 5,
97
+ injectProfile: true,
98
+ userContainerTag: null,
99
+ projectContainerTag: null
100
+ };
101
+ function readJson(filePath) {
102
+ try {
103
+ if (!fs2.existsSync(filePath))
104
+ return null;
105
+ return JSON.parse(fs2.readFileSync(filePath, "utf-8"));
106
+ } catch {
107
+ return null;
108
+ }
109
+ }
110
+ function findProjectConfig(cwd) {
111
+ let dir = cwd;
112
+ while (true) {
113
+ const configPath = path2.join(dir, ".cursor", ".supermemory", "config.json");
114
+ const data = readJson(configPath);
115
+ if (data)
116
+ return data;
117
+ const parent = path2.dirname(dir);
118
+ if (parent === dir)
119
+ break;
120
+ dir = parent;
121
+ }
122
+ return null;
123
+ }
124
+ function loadConfig(cwd) {
125
+ const projectConfig = findProjectConfig(cwd || process.cwd());
126
+ const globalConfig = readJson(path2.join(os2.homedir(), ".config", "cursor", "supermemory.json"));
127
+ const merged = { ...DEFAULTS, ...globalConfig, ...projectConfig };
128
+ return {
129
+ apiKey: process.env.SUPERMEMORY_API_KEY ?? merged.apiKey ?? null,
130
+ similarityThreshold: merged.similarityThreshold,
131
+ maxMemories: merged.maxMemories,
132
+ maxProjectMemories: merged.maxProjectMemories,
133
+ injectProfile: merged.injectProfile,
134
+ userContainerTag: merged.userContainerTag,
135
+ projectContainerTag: merged.projectContainerTag
136
+ };
137
+ }
138
+ function getApiKey(config) {
139
+ if (config.apiKey)
140
+ return config.apiKey;
141
+ const creds = loadCredentials();
142
+ return creds?.apiKey ?? null;
143
+ }
144
+
145
+ // src/tags.ts
146
+ import crypto from "node:crypto";
147
+ import os3 from "node:os";
148
+ import { execSync } from "node:child_process";
149
+ function sha256(input) {
150
+ return crypto.createHash("sha256").update(input).digest("hex").slice(0, 16);
151
+ }
152
+ function getGitEmail() {
153
+ try {
154
+ return execSync("git config user.email", {
155
+ encoding: "utf-8",
156
+ stdio: ["pipe", "pipe", "pipe"]
157
+ }).trim() || null;
158
+ } catch {
159
+ return null;
160
+ }
161
+ }
162
+ function getGitRoot(dir) {
163
+ try {
164
+ return execSync("git rev-parse --show-toplevel", {
165
+ cwd: dir,
166
+ encoding: "utf-8",
167
+ stdio: ["pipe", "pipe", "pipe"]
168
+ }).trim() || null;
169
+ } catch {
170
+ return null;
171
+ }
172
+ }
173
+ function getMachineId() {
174
+ return `${os3.hostname()}_${os3.userInfo().username}`;
175
+ }
176
+ function getUserTag(config) {
177
+ const identity = config.userContainerTag ?? process.env.SUPERMEMORY_USER_TAG ?? process.env.CURSOR_USER_EMAIL ?? getGitEmail() ?? getMachineId();
178
+ return `cursor_user_${sha256(identity)}`;
179
+ }
180
+ function getProjectTag(workspaceRoot, config) {
181
+ const identity = config.projectContainerTag ?? process.env.SUPERMEMORY_PROJECT_TAG ?? (getGitRoot(workspaceRoot) || workspaceRoot);
182
+ return `cursor_project_${sha256(identity)}`;
183
+ }
184
+
185
+ // node_modules/supermemory/internal/tslib.mjs
186
+ function __classPrivateFieldSet(receiver, state, value, kind, f) {
187
+ if (kind === "m")
188
+ throw new TypeError("Private method is not writable");
189
+ if (kind === "a" && !f)
190
+ throw new TypeError("Private accessor was defined without a setter");
191
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
192
+ throw new TypeError("Cannot write private member to an object whose class did not declare it");
193
+ return kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value;
194
+ }
195
+ function __classPrivateFieldGet(receiver, state, kind, f) {
196
+ if (kind === "a" && !f)
197
+ throw new TypeError("Private accessor was defined without a getter");
198
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
199
+ throw new TypeError("Cannot read private member from an object whose class did not declare it");
200
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
201
+ }
202
+
203
+ // node_modules/supermemory/internal/utils/uuid.mjs
204
+ var uuid4 = function() {
205
+ const { crypto: crypto2 } = globalThis;
206
+ if (crypto2?.randomUUID) {
207
+ uuid4 = crypto2.randomUUID.bind(crypto2);
208
+ return crypto2.randomUUID();
209
+ }
210
+ const u8 = new Uint8Array(1);
211
+ const randomByte = crypto2 ? () => crypto2.getRandomValues(u8)[0] : () => Math.random() * 255 & 255;
212
+ return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => (+c ^ randomByte() & 15 >> +c / 4).toString(16));
213
+ };
214
+
215
+ // node_modules/supermemory/internal/errors.mjs
216
+ function isAbortError(err) {
217
+ return typeof err === "object" && err !== null && (("name" in err) && err.name === "AbortError" || ("message" in err) && String(err.message).includes("FetchRequestCanceledException"));
218
+ }
219
+ var castToError = (err) => {
220
+ if (err instanceof Error)
221
+ return err;
222
+ if (typeof err === "object" && err !== null) {
223
+ try {
224
+ if (Object.prototype.toString.call(err) === "[object Error]") {
225
+ const error = new Error(err.message, err.cause ? { cause: err.cause } : {});
226
+ if (err.stack)
227
+ error.stack = err.stack;
228
+ if (err.cause && !error.cause)
229
+ error.cause = err.cause;
230
+ if (err.name)
231
+ error.name = err.name;
232
+ return error;
233
+ }
234
+ } catch {}
235
+ try {
236
+ return new Error(JSON.stringify(err));
237
+ } catch {}
238
+ }
239
+ return new Error(err);
240
+ };
241
+
242
+ // node_modules/supermemory/core/error.mjs
243
+ class SupermemoryError extends Error {
244
+ }
245
+
246
+ class APIError extends SupermemoryError {
247
+ constructor(status, error, message, headers) {
248
+ super(`${APIError.makeMessage(status, error, message)}`);
249
+ this.status = status;
250
+ this.headers = headers;
251
+ this.error = error;
252
+ }
253
+ static makeMessage(status, error, message) {
254
+ const msg = error?.message ? typeof error.message === "string" ? error.message : JSON.stringify(error.message) : error ? JSON.stringify(error) : message;
255
+ if (status && msg) {
256
+ return `${status} ${msg}`;
257
+ }
258
+ if (status) {
259
+ return `${status} status code (no body)`;
260
+ }
261
+ if (msg) {
262
+ return msg;
263
+ }
264
+ return "(no status code or body)";
265
+ }
266
+ static generate(status, errorResponse, message, headers) {
267
+ if (!status || !headers) {
268
+ return new APIConnectionError({ message, cause: castToError(errorResponse) });
269
+ }
270
+ const error = errorResponse;
271
+ if (status === 400) {
272
+ return new BadRequestError(status, error, message, headers);
273
+ }
274
+ if (status === 401) {
275
+ return new AuthenticationError(status, error, message, headers);
276
+ }
277
+ if (status === 403) {
278
+ return new PermissionDeniedError(status, error, message, headers);
279
+ }
280
+ if (status === 404) {
281
+ return new NotFoundError(status, error, message, headers);
282
+ }
283
+ if (status === 409) {
284
+ return new ConflictError(status, error, message, headers);
285
+ }
286
+ if (status === 422) {
287
+ return new UnprocessableEntityError(status, error, message, headers);
288
+ }
289
+ if (status === 429) {
290
+ return new RateLimitError(status, error, message, headers);
291
+ }
292
+ if (status >= 500) {
293
+ return new InternalServerError(status, error, message, headers);
294
+ }
295
+ return new APIError(status, error, message, headers);
296
+ }
297
+ }
298
+
299
+ class APIUserAbortError extends APIError {
300
+ constructor({ message } = {}) {
301
+ super(undefined, undefined, message || "Request was aborted.", undefined);
302
+ }
303
+ }
304
+
305
+ class APIConnectionError extends APIError {
306
+ constructor({ message, cause }) {
307
+ super(undefined, undefined, message || "Connection error.", undefined);
308
+ if (cause)
309
+ this.cause = cause;
310
+ }
311
+ }
312
+
313
+ class APIConnectionTimeoutError extends APIConnectionError {
314
+ constructor({ message } = {}) {
315
+ super({ message: message ?? "Request timed out." });
316
+ }
317
+ }
318
+
319
+ class BadRequestError extends APIError {
320
+ }
321
+
322
+ class AuthenticationError extends APIError {
323
+ }
324
+
325
+ class PermissionDeniedError extends APIError {
326
+ }
327
+
328
+ class NotFoundError extends APIError {
329
+ }
330
+
331
+ class ConflictError extends APIError {
332
+ }
333
+
334
+ class UnprocessableEntityError extends APIError {
335
+ }
336
+
337
+ class RateLimitError extends APIError {
338
+ }
339
+
340
+ class InternalServerError extends APIError {
341
+ }
342
+
343
+ // node_modules/supermemory/internal/utils/values.mjs
344
+ var startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i;
345
+ var isAbsoluteURL = (url) => {
346
+ return startsWithSchemeRegexp.test(url);
347
+ };
348
+ var isArray = (val) => (isArray = Array.isArray, isArray(val));
349
+ var isReadonlyArray = isArray;
350
+ function isEmptyObj(obj) {
351
+ if (!obj)
352
+ return true;
353
+ for (const _k in obj)
354
+ return false;
355
+ return true;
356
+ }
357
+ function hasOwn(obj, key) {
358
+ return Object.prototype.hasOwnProperty.call(obj, key);
359
+ }
360
+ var validatePositiveInteger = (name, n) => {
361
+ if (typeof n !== "number" || !Number.isInteger(n)) {
362
+ throw new SupermemoryError(`${name} must be an integer`);
363
+ }
364
+ if (n < 0) {
365
+ throw new SupermemoryError(`${name} must be a positive integer`);
366
+ }
367
+ return n;
368
+ };
369
+ var safeJSON = (text) => {
370
+ try {
371
+ return JSON.parse(text);
372
+ } catch (err) {
373
+ return;
374
+ }
375
+ };
376
+
377
+ // node_modules/supermemory/internal/utils/sleep.mjs
378
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
379
+
380
+ // node_modules/supermemory/version.mjs
381
+ var VERSION = "4.11.1";
382
+
383
+ // node_modules/supermemory/internal/detect-platform.mjs
384
+ function getDetectedPlatform() {
385
+ if (typeof Deno !== "undefined" && Deno.build != null) {
386
+ return "deno";
387
+ }
388
+ if (typeof EdgeRuntime !== "undefined") {
389
+ return "edge";
390
+ }
391
+ if (Object.prototype.toString.call(typeof globalThis.process !== "undefined" ? globalThis.process : 0) === "[object process]") {
392
+ return "node";
393
+ }
394
+ return "unknown";
395
+ }
396
+ var getPlatformProperties = () => {
397
+ const detectedPlatform = getDetectedPlatform();
398
+ if (detectedPlatform === "deno") {
399
+ return {
400
+ "X-Stainless-Lang": "js",
401
+ "X-Stainless-Package-Version": VERSION,
402
+ "X-Stainless-OS": normalizePlatform(Deno.build.os),
403
+ "X-Stainless-Arch": normalizeArch(Deno.build.arch),
404
+ "X-Stainless-Runtime": "deno",
405
+ "X-Stainless-Runtime-Version": typeof Deno.version === "string" ? Deno.version : Deno.version?.deno ?? "unknown"
406
+ };
407
+ }
408
+ if (typeof EdgeRuntime !== "undefined") {
409
+ return {
410
+ "X-Stainless-Lang": "js",
411
+ "X-Stainless-Package-Version": VERSION,
412
+ "X-Stainless-OS": "Unknown",
413
+ "X-Stainless-Arch": `other:${EdgeRuntime}`,
414
+ "X-Stainless-Runtime": "edge",
415
+ "X-Stainless-Runtime-Version": globalThis.process.version
416
+ };
417
+ }
418
+ if (detectedPlatform === "node") {
419
+ return {
420
+ "X-Stainless-Lang": "js",
421
+ "X-Stainless-Package-Version": VERSION,
422
+ "X-Stainless-OS": normalizePlatform(globalThis.process.platform ?? "unknown"),
423
+ "X-Stainless-Arch": normalizeArch(globalThis.process.arch ?? "unknown"),
424
+ "X-Stainless-Runtime": "node",
425
+ "X-Stainless-Runtime-Version": globalThis.process.version ?? "unknown"
426
+ };
427
+ }
428
+ const browserInfo = getBrowserInfo();
429
+ if (browserInfo) {
430
+ return {
431
+ "X-Stainless-Lang": "js",
432
+ "X-Stainless-Package-Version": VERSION,
433
+ "X-Stainless-OS": "Unknown",
434
+ "X-Stainless-Arch": "unknown",
435
+ "X-Stainless-Runtime": `browser:${browserInfo.browser}`,
436
+ "X-Stainless-Runtime-Version": browserInfo.version
437
+ };
438
+ }
439
+ return {
440
+ "X-Stainless-Lang": "js",
441
+ "X-Stainless-Package-Version": VERSION,
442
+ "X-Stainless-OS": "Unknown",
443
+ "X-Stainless-Arch": "unknown",
444
+ "X-Stainless-Runtime": "unknown",
445
+ "X-Stainless-Runtime-Version": "unknown"
446
+ };
447
+ };
448
+ function getBrowserInfo() {
449
+ if (typeof navigator === "undefined" || !navigator) {
450
+ return null;
451
+ }
452
+ const browserPatterns = [
453
+ { key: "edge", pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
454
+ { key: "ie", pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
455
+ { key: "ie", pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ },
456
+ { key: "chrome", pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
457
+ { key: "firefox", pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
458
+ { key: "safari", pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ }
459
+ ];
460
+ for (const { key, pattern } of browserPatterns) {
461
+ const match = pattern.exec(navigator.userAgent);
462
+ if (match) {
463
+ const major = match[1] || 0;
464
+ const minor = match[2] || 0;
465
+ const patch = match[3] || 0;
466
+ return { browser: key, version: `${major}.${minor}.${patch}` };
467
+ }
468
+ }
469
+ return null;
470
+ }
471
+ var normalizeArch = (arch) => {
472
+ if (arch === "x32")
473
+ return "x32";
474
+ if (arch === "x86_64" || arch === "x64")
475
+ return "x64";
476
+ if (arch === "arm")
477
+ return "arm";
478
+ if (arch === "aarch64" || arch === "arm64")
479
+ return "arm64";
480
+ if (arch)
481
+ return `other:${arch}`;
482
+ return "unknown";
483
+ };
484
+ var normalizePlatform = (platform) => {
485
+ platform = platform.toLowerCase();
486
+ if (platform.includes("ios"))
487
+ return "iOS";
488
+ if (platform === "android")
489
+ return "Android";
490
+ if (platform === "darwin")
491
+ return "MacOS";
492
+ if (platform === "win32")
493
+ return "Windows";
494
+ if (platform === "freebsd")
495
+ return "FreeBSD";
496
+ if (platform === "openbsd")
497
+ return "OpenBSD";
498
+ if (platform === "linux")
499
+ return "Linux";
500
+ if (platform)
501
+ return `Other:${platform}`;
502
+ return "Unknown";
503
+ };
504
+ var _platformHeaders;
505
+ var getPlatformHeaders = () => {
506
+ return _platformHeaders ?? (_platformHeaders = getPlatformProperties());
507
+ };
508
+
509
+ // node_modules/supermemory/internal/shims.mjs
510
+ function getDefaultFetch() {
511
+ if (typeof fetch !== "undefined") {
512
+ return fetch;
513
+ }
514
+ throw new Error("`fetch` is not defined as a global; Either pass `fetch` to the client, `new Supermemory({ fetch })` or polyfill the global, `globalThis.fetch = fetch`");
515
+ }
516
+ function makeReadableStream(...args) {
517
+ const ReadableStream = globalThis.ReadableStream;
518
+ if (typeof ReadableStream === "undefined") {
519
+ throw new Error("`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`");
520
+ }
521
+ return new ReadableStream(...args);
522
+ }
523
+ function ReadableStreamFrom(iterable) {
524
+ let iter = Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
525
+ return makeReadableStream({
526
+ async pull(controller) {
527
+ const { done, value } = await iter.next();
528
+ if (done) {
529
+ controller.close();
530
+ } else {
531
+ controller.enqueue(value);
532
+ }
533
+ },
534
+ async cancel() {
535
+ await iter.return?.();
536
+ }
537
+ });
538
+ }
539
+ async function CancelReadableStream(stream) {
540
+ if (stream === null || typeof stream !== "object")
541
+ return;
542
+ if (stream[Symbol.asyncIterator]) {
543
+ await stream[Symbol.asyncIterator]().return?.();
544
+ return;
545
+ }
546
+ const reader = stream.getReader();
547
+ const cancelPromise = reader.cancel();
548
+ reader.releaseLock();
549
+ await cancelPromise;
550
+ }
551
+
552
+ // node_modules/supermemory/internal/request-options.mjs
553
+ var FallbackEncoder = ({ headers, body }) => {
554
+ return {
555
+ bodyHeaders: {
556
+ "content-type": "application/json"
557
+ },
558
+ body: JSON.stringify(body)
559
+ };
560
+ };
561
+
562
+ // node_modules/supermemory/internal/uploads.mjs
563
+ var checkFileSupport = () => {
564
+ if (typeof File === "undefined") {
565
+ const { process: process2 } = globalThis;
566
+ const isOldNode = typeof process2?.versions?.node === "string" && parseInt(process2.versions.node.split(".")) < 20;
567
+ throw new Error("`File` is not defined as a global, which is required for file uploads." + (isOldNode ? " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`." : ""));
568
+ }
569
+ };
570
+ function makeFile(fileBits, fileName, options) {
571
+ checkFileSupport();
572
+ return new File(fileBits, fileName ?? "unknown_file", options);
573
+ }
574
+ function getName(value) {
575
+ return (typeof value === "object" && value !== null && (("name" in value) && value.name && String(value.name) || ("url" in value) && value.url && String(value.url) || ("filename" in value) && value.filename && String(value.filename) || ("path" in value) && value.path && String(value.path)) || "").split(/[\\/]/).pop() || undefined;
576
+ }
577
+ var isAsyncIterable = (value) => value != null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
578
+ var multipartFormRequestOptions = async (opts, fetch2) => {
579
+ return { ...opts, body: await createForm(opts.body, fetch2) };
580
+ };
581
+ var supportsFormDataMap = /* @__PURE__ */ new WeakMap;
582
+ function supportsFormData(fetchObject) {
583
+ const fetch2 = typeof fetchObject === "function" ? fetchObject : fetchObject.fetch;
584
+ const cached = supportsFormDataMap.get(fetch2);
585
+ if (cached)
586
+ return cached;
587
+ const promise = (async () => {
588
+ try {
589
+ const FetchResponse = "Response" in fetch2 ? fetch2.Response : (await fetch2("data:,")).constructor;
590
+ const data = new FormData;
591
+ if (data.toString() === await new FetchResponse(data).text()) {
592
+ return false;
593
+ }
594
+ return true;
595
+ } catch {
596
+ return true;
597
+ }
598
+ })();
599
+ supportsFormDataMap.set(fetch2, promise);
600
+ return promise;
601
+ }
602
+ var createForm = async (body, fetch2) => {
603
+ if (!await supportsFormData(fetch2)) {
604
+ throw new TypeError("The provided fetch function does not support file uploads with the current global FormData class.");
605
+ }
606
+ const form = new FormData;
607
+ await Promise.all(Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value)));
608
+ return form;
609
+ };
610
+ var isNamedBlob = (value) => value instanceof Blob && ("name" in value);
611
+ var addFormValue = async (form, key, value) => {
612
+ if (value === undefined)
613
+ return;
614
+ if (value == null) {
615
+ throw new TypeError(`Received null for "${key}"; to pass null in FormData, you must use the string 'null'`);
616
+ }
617
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
618
+ form.append(key, String(value));
619
+ } else if (value instanceof Response) {
620
+ form.append(key, makeFile([await value.blob()], getName(value)));
621
+ } else if (isAsyncIterable(value)) {
622
+ form.append(key, makeFile([await new Response(ReadableStreamFrom(value)).blob()], getName(value)));
623
+ } else if (isNamedBlob(value)) {
624
+ form.append(key, value, getName(value));
625
+ } else if (Array.isArray(value)) {
626
+ await Promise.all(value.map((entry) => addFormValue(form, key + "[]", entry)));
627
+ } else if (typeof value === "object") {
628
+ await Promise.all(Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop)));
629
+ } else {
630
+ throw new TypeError(`Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`);
631
+ }
632
+ };
633
+
634
+ // node_modules/supermemory/internal/to-file.mjs
635
+ var isBlobLike = (value) => value != null && typeof value === "object" && typeof value.size === "number" && typeof value.type === "string" && typeof value.text === "function" && typeof value.slice === "function" && typeof value.arrayBuffer === "function";
636
+ var isFileLike = (value) => value != null && typeof value === "object" && typeof value.name === "string" && typeof value.lastModified === "number" && isBlobLike(value);
637
+ var isResponseLike = (value) => value != null && typeof value === "object" && typeof value.url === "string" && typeof value.blob === "function";
638
+ async function toFile(value, name, options) {
639
+ checkFileSupport();
640
+ value = await value;
641
+ if (isFileLike(value)) {
642
+ if (value instanceof File) {
643
+ return value;
644
+ }
645
+ return makeFile([await value.arrayBuffer()], value.name);
646
+ }
647
+ if (isResponseLike(value)) {
648
+ const blob = await value.blob();
649
+ name || (name = new URL(value.url).pathname.split(/[\\/]/).pop());
650
+ return makeFile(await getBytes(blob), name, options);
651
+ }
652
+ const parts = await getBytes(value);
653
+ name || (name = getName(value));
654
+ if (!options?.type) {
655
+ const type = parts.find((part) => typeof part === "object" && ("type" in part) && part.type);
656
+ if (typeof type === "string") {
657
+ options = { ...options, type };
658
+ }
659
+ }
660
+ return makeFile(parts, name, options);
661
+ }
662
+ async function getBytes(value) {
663
+ let parts = [];
664
+ if (typeof value === "string" || ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
665
+ parts.push(value);
666
+ } else if (isBlobLike(value)) {
667
+ parts.push(value instanceof Blob ? value : await value.arrayBuffer());
668
+ } else if (isAsyncIterable(value)) {
669
+ for await (const chunk of value) {
670
+ parts.push(...await getBytes(chunk));
671
+ }
672
+ } else {
673
+ const constructor = value?.constructor?.name;
674
+ throw new Error(`Unexpected data type: ${typeof value}${constructor ? `; constructor: ${constructor}` : ""}${propsForError(value)}`);
675
+ }
676
+ return parts;
677
+ }
678
+ function propsForError(value) {
679
+ if (typeof value !== "object" || value === null)
680
+ return "";
681
+ const props = Object.getOwnPropertyNames(value);
682
+ return `; props: [${props.map((p) => `"${p}"`).join(", ")}]`;
683
+ }
684
+ // node_modules/supermemory/core/resource.mjs
685
+ class APIResource {
686
+ constructor(client) {
687
+ this._client = client;
688
+ }
689
+ }
690
+
691
+ // node_modules/supermemory/internal/headers.mjs
692
+ var brand_privateNullableHeaders = /* @__PURE__ */ Symbol("brand.privateNullableHeaders");
693
+ function* iterateHeaders(headers) {
694
+ if (!headers)
695
+ return;
696
+ if (brand_privateNullableHeaders in headers) {
697
+ const { values, nulls } = headers;
698
+ yield* values.entries();
699
+ for (const name of nulls) {
700
+ yield [name, null];
701
+ }
702
+ return;
703
+ }
704
+ let shouldClear = false;
705
+ let iter;
706
+ if (headers instanceof Headers) {
707
+ iter = headers.entries();
708
+ } else if (isReadonlyArray(headers)) {
709
+ iter = headers;
710
+ } else {
711
+ shouldClear = true;
712
+ iter = Object.entries(headers ?? {});
713
+ }
714
+ for (let row of iter) {
715
+ const name = row[0];
716
+ if (typeof name !== "string")
717
+ throw new TypeError("expected header name to be a string");
718
+ const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];
719
+ let didClear = false;
720
+ for (const value of values) {
721
+ if (value === undefined)
722
+ continue;
723
+ if (shouldClear && !didClear) {
724
+ didClear = true;
725
+ yield [name, null];
726
+ }
727
+ yield [name, value];
728
+ }
729
+ }
730
+ }
731
+ var buildHeaders = (newHeaders) => {
732
+ const targetHeaders = new Headers;
733
+ const nullHeaders = new Set;
734
+ for (const headers of newHeaders) {
735
+ const seenHeaders = new Set;
736
+ for (const [name, value] of iterateHeaders(headers)) {
737
+ const lowerName = name.toLowerCase();
738
+ if (!seenHeaders.has(lowerName)) {
739
+ targetHeaders.delete(name);
740
+ seenHeaders.add(lowerName);
741
+ }
742
+ if (value === null) {
743
+ targetHeaders.delete(name);
744
+ nullHeaders.add(lowerName);
745
+ } else {
746
+ targetHeaders.append(name, value);
747
+ nullHeaders.delete(lowerName);
748
+ }
749
+ }
750
+ }
751
+ return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };
752
+ };
753
+
754
+ // node_modules/supermemory/internal/utils/path.mjs
755
+ function encodeURIPath(str) {
756
+ return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
757
+ }
758
+ var EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
759
+ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path(statics, ...params) {
760
+ if (statics.length === 1)
761
+ return statics[0];
762
+ let postPath = false;
763
+ const invalidSegments = [];
764
+ const path3 = statics.reduce((previousValue, currentValue, index) => {
765
+ if (/[?#]/.test(currentValue)) {
766
+ postPath = true;
767
+ }
768
+ const value = params[index];
769
+ let encoded = (postPath ? encodeURIComponent : pathEncoder)("" + value);
770
+ if (index !== params.length && (value == null || typeof value === "object" && value.toString === Object.getPrototypeOf(Object.getPrototypeOf(value.hasOwnProperty ?? EMPTY) ?? EMPTY)?.toString)) {
771
+ encoded = value + "";
772
+ invalidSegments.push({
773
+ start: previousValue.length + currentValue.length,
774
+ length: encoded.length,
775
+ error: `Value of type ${Object.prototype.toString.call(value).slice(8, -1)} is not a valid path parameter`
776
+ });
777
+ }
778
+ return previousValue + currentValue + (index === params.length ? "" : encoded);
779
+ }, "");
780
+ const pathOnly = path3.split(/[?#]/, 1)[0];
781
+ const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
782
+ let match;
783
+ while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
784
+ invalidSegments.push({
785
+ start: match.index,
786
+ length: match[0].length,
787
+ error: `Value "${match[0]}" can't be safely passed as a path parameter`
788
+ });
789
+ }
790
+ invalidSegments.sort((a, b) => a.start - b.start);
791
+ if (invalidSegments.length > 0) {
792
+ let lastEnd = 0;
793
+ const underline = invalidSegments.reduce((acc, segment) => {
794
+ const spaces = " ".repeat(segment.start - lastEnd);
795
+ const arrows = "^".repeat(segment.length);
796
+ lastEnd = segment.start + segment.length;
797
+ return acc + spaces + arrows;
798
+ }, "");
799
+ throw new SupermemoryError(`Path parameters result in path with invalid segments:
800
+ ${invalidSegments.map((e) => e.error).join(`
801
+ `)}
802
+ ${path3}
803
+ ${underline}`);
804
+ }
805
+ return path3;
806
+ };
807
+ var path3 = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
808
+
809
+ // node_modules/supermemory/resources/connections.mjs
810
+ class Connections extends APIResource {
811
+ create(provider, body = {}, options) {
812
+ return this._client.post(path3`/v3/connections/${provider}`, { body, ...options });
813
+ }
814
+ list(body = {}, options) {
815
+ return this._client.post("/v3/connections/list", { body, ...options });
816
+ }
817
+ configure(connectionID, body, options) {
818
+ return this._client.post(path3`/v3/connections/${connectionID}/configure`, { body, ...options });
819
+ }
820
+ deleteByID(connectionID, options) {
821
+ return this._client.delete(path3`/v3/connections/${connectionID}`, options);
822
+ }
823
+ deleteByProvider(provider, body, options) {
824
+ return this._client.delete(path3`/v3/connections/${provider}`, { body, ...options });
825
+ }
826
+ getByID(connectionID, options) {
827
+ return this._client.get(path3`/v3/connections/${connectionID}`, options);
828
+ }
829
+ getByTag(provider, body, options) {
830
+ return this._client.post(path3`/v3/connections/${provider}/connection`, { body, ...options });
831
+ }
832
+ import(provider, body = {}, options) {
833
+ return this._client.post(path3`/v3/connections/${provider}/import`, {
834
+ body,
835
+ ...options,
836
+ headers: buildHeaders([{ Accept: "text/plain" }, options?.headers])
837
+ });
838
+ }
839
+ listDocuments(provider, body = {}, options) {
840
+ return this._client.post(path3`/v3/connections/${provider}/documents`, { body, ...options });
841
+ }
842
+ resources(connectionID, query = {}, options) {
843
+ return this._client.get(path3`/v3/connections/${connectionID}/resources`, { query, ...options });
844
+ }
845
+ }
846
+ // node_modules/supermemory/resources/documents.mjs
847
+ class Documents extends APIResource {
848
+ update(id, body = {}, options) {
849
+ return this._client.patch(path3`/v3/documents/${id}`, { body, ...options });
850
+ }
851
+ list(body = {}, options) {
852
+ return this._client.post("/v3/documents/list", { body, ...options });
853
+ }
854
+ delete(id, options) {
855
+ return this._client.delete(path3`/v3/documents/${id}`, {
856
+ ...options,
857
+ headers: buildHeaders([{ Accept: "*/*" }, options?.headers])
858
+ });
859
+ }
860
+ add(body, options) {
861
+ return this._client.post("/v3/documents", { body, ...options });
862
+ }
863
+ batchAdd(body, options) {
864
+ return this._client.post("/v3/documents/batch", { body, ...options });
865
+ }
866
+ deleteBulk(body = {}, options) {
867
+ return this._client.delete("/v3/documents/bulk", { body, ...options });
868
+ }
869
+ get(id, options) {
870
+ return this._client.get(path3`/v3/documents/${id}`, options);
871
+ }
872
+ listProcessing(options) {
873
+ return this._client.get("/v3/documents/processing", options);
874
+ }
875
+ uploadFile(body, options) {
876
+ return this._client.post("/v3/documents/file", multipartFormRequestOptions({ body, ...options }, this._client));
877
+ }
878
+ }
879
+ // node_modules/supermemory/resources/memories.mjs
880
+ class Memories extends APIResource {
881
+ forget(body, options) {
882
+ return this._client.delete("/v4/memories", { body, ...options });
883
+ }
884
+ updateMemory(body, options) {
885
+ return this._client.patch("/v4/memories", { body, ...options });
886
+ }
887
+ }
888
+ // node_modules/supermemory/resources/search.mjs
889
+ class Search extends APIResource {
890
+ documents(body, options) {
891
+ return this._client.post("/v3/search", { body, ...options });
892
+ }
893
+ execute(body, options) {
894
+ return this._client.post("/v3/search", { body, ...options });
895
+ }
896
+ memories(body, options) {
897
+ return this._client.post("/v4/search", { body, ...options });
898
+ }
899
+ }
900
+ // node_modules/supermemory/resources/settings.mjs
901
+ class Settings extends APIResource {
902
+ update(body = {}, options) {
903
+ return this._client.patch("/v3/settings", { body, ...options });
904
+ }
905
+ get(options) {
906
+ return this._client.get("/v3/settings", options);
907
+ }
908
+ }
909
+ // node_modules/supermemory/internal/utils/log.mjs
910
+ var levelNumbers = {
911
+ off: 0,
912
+ error: 200,
913
+ warn: 300,
914
+ info: 400,
915
+ debug: 500
916
+ };
917
+ var parseLogLevel = (maybeLevel, sourceName, client) => {
918
+ if (!maybeLevel) {
919
+ return;
920
+ }
921
+ if (hasOwn(levelNumbers, maybeLevel)) {
922
+ return maybeLevel;
923
+ }
924
+ loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`);
925
+ return;
926
+ };
927
+ function noop() {}
928
+ function makeLogFn(fnLevel, logger, logLevel) {
929
+ if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) {
930
+ return noop;
931
+ } else {
932
+ return logger[fnLevel].bind(logger);
933
+ }
934
+ }
935
+ var noopLogger = {
936
+ error: noop,
937
+ warn: noop,
938
+ info: noop,
939
+ debug: noop
940
+ };
941
+ var cachedLoggers = /* @__PURE__ */ new WeakMap;
942
+ function loggerFor(client) {
943
+ const logger = client.logger;
944
+ const logLevel = client.logLevel ?? "off";
945
+ if (!logger) {
946
+ return noopLogger;
947
+ }
948
+ const cachedLogger = cachedLoggers.get(logger);
949
+ if (cachedLogger && cachedLogger[0] === logLevel) {
950
+ return cachedLogger[1];
951
+ }
952
+ const levelLogger = {
953
+ error: makeLogFn("error", logger, logLevel),
954
+ warn: makeLogFn("warn", logger, logLevel),
955
+ info: makeLogFn("info", logger, logLevel),
956
+ debug: makeLogFn("debug", logger, logLevel)
957
+ };
958
+ cachedLoggers.set(logger, [logLevel, levelLogger]);
959
+ return levelLogger;
960
+ }
961
+ var formatRequestDetails = (details) => {
962
+ if (details.options) {
963
+ details.options = { ...details.options };
964
+ delete details.options["headers"];
965
+ }
966
+ if (details.headers) {
967
+ details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [
968
+ name,
969
+ name.toLowerCase() === "authorization" || name.toLowerCase() === "cookie" || name.toLowerCase() === "set-cookie" ? "***" : value
970
+ ]));
971
+ }
972
+ if ("retryOfRequestLogID" in details) {
973
+ if (details.retryOfRequestLogID) {
974
+ details.retryOf = details.retryOfRequestLogID;
975
+ }
976
+ delete details.retryOfRequestLogID;
977
+ }
978
+ return details;
979
+ };
980
+
981
+ // node_modules/supermemory/internal/parse.mjs
982
+ async function defaultParseResponse(client, props) {
983
+ const { response, requestLogID, retryOfRequestLogID, startTime } = props;
984
+ const body = await (async () => {
985
+ if (response.status === 204) {
986
+ return null;
987
+ }
988
+ if (props.options.__binaryResponse) {
989
+ return response;
990
+ }
991
+ const contentType = response.headers.get("content-type");
992
+ const mediaType = contentType?.split(";")[0]?.trim();
993
+ const isJSON = mediaType?.includes("application/json") || mediaType?.endsWith("+json");
994
+ if (isJSON) {
995
+ const contentLength = response.headers.get("content-length");
996
+ if (contentLength === "0") {
997
+ return;
998
+ }
999
+ const json = await response.json();
1000
+ return json;
1001
+ }
1002
+ const text = await response.text();
1003
+ return text;
1004
+ })();
1005
+ loggerFor(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails({
1006
+ retryOfRequestLogID,
1007
+ url: response.url,
1008
+ status: response.status,
1009
+ body,
1010
+ durationMs: Date.now() - startTime
1011
+ }));
1012
+ return body;
1013
+ }
1014
+
1015
+ // node_modules/supermemory/core/api-promise.mjs
1016
+ var _APIPromise_client;
1017
+
1018
+ class APIPromise extends Promise {
1019
+ constructor(client, responsePromise, parseResponse = defaultParseResponse) {
1020
+ super((resolve) => {
1021
+ resolve(null);
1022
+ });
1023
+ this.responsePromise = responsePromise;
1024
+ this.parseResponse = parseResponse;
1025
+ _APIPromise_client.set(this, undefined);
1026
+ __classPrivateFieldSet(this, _APIPromise_client, client, "f");
1027
+ }
1028
+ _thenUnwrap(transform) {
1029
+ return new APIPromise(__classPrivateFieldGet(this, _APIPromise_client, "f"), this.responsePromise, async (client, props) => transform(await this.parseResponse(client, props), props));
1030
+ }
1031
+ asResponse() {
1032
+ return this.responsePromise.then((p) => p.response);
1033
+ }
1034
+ async withResponse() {
1035
+ const [data, response] = await Promise.all([this.parse(), this.asResponse()]);
1036
+ return { data, response };
1037
+ }
1038
+ parse() {
1039
+ if (!this.parsedPromise) {
1040
+ this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(__classPrivateFieldGet(this, _APIPromise_client, "f"), data));
1041
+ }
1042
+ return this.parsedPromise;
1043
+ }
1044
+ then(onfulfilled, onrejected) {
1045
+ return this.parse().then(onfulfilled, onrejected);
1046
+ }
1047
+ catch(onrejected) {
1048
+ return this.parse().catch(onrejected);
1049
+ }
1050
+ finally(onfinally) {
1051
+ return this.parse().finally(onfinally);
1052
+ }
1053
+ }
1054
+ _APIPromise_client = new WeakMap;
1055
+
1056
+ // node_modules/supermemory/internal/utils/env.mjs
1057
+ var readEnv = (env) => {
1058
+ if (typeof globalThis.process !== "undefined") {
1059
+ return globalThis.process.env?.[env]?.trim() ?? undefined;
1060
+ }
1061
+ if (typeof globalThis.Deno !== "undefined") {
1062
+ return globalThis.Deno.env?.get?.(env)?.trim();
1063
+ }
1064
+ return;
1065
+ };
1066
+
1067
+ // node_modules/supermemory/client.mjs
1068
+ var _Supermemory_instances;
1069
+ var _a;
1070
+ var _Supermemory_encoder;
1071
+ var _Supermemory_baseURLOverridden;
1072
+
1073
+ class Supermemory {
1074
+ constructor({ baseURL = readEnv("SUPERMEMORY_BASE_URL"), apiKey = readEnv("SUPERMEMORY_API_KEY"), ...opts } = {}) {
1075
+ _Supermemory_instances.add(this);
1076
+ _Supermemory_encoder.set(this, undefined);
1077
+ this.memories = new Memories(this);
1078
+ this.documents = new Documents(this);
1079
+ this.search = new Search(this);
1080
+ this.settings = new Settings(this);
1081
+ this.connections = new Connections(this);
1082
+ if (apiKey === undefined) {
1083
+ throw new SupermemoryError("The SUPERMEMORY_API_KEY environment variable is missing or empty; either provide it, or instantiate the Supermemory client with an apiKey option, like new Supermemory({ apiKey: 'My API Key' }).");
1084
+ }
1085
+ const options = {
1086
+ apiKey,
1087
+ ...opts,
1088
+ baseURL: baseURL || `https://api.supermemory.ai`
1089
+ };
1090
+ this.baseURL = options.baseURL;
1091
+ this.timeout = options.timeout ?? _a.DEFAULT_TIMEOUT;
1092
+ this.logger = options.logger ?? console;
1093
+ const defaultLogLevel = "warn";
1094
+ this.logLevel = defaultLogLevel;
1095
+ this.logLevel = parseLogLevel(options.logLevel, "ClientOptions.logLevel", this) ?? parseLogLevel(readEnv("SUPERMEMORY_LOG"), "process.env['SUPERMEMORY_LOG']", this) ?? defaultLogLevel;
1096
+ this.fetchOptions = options.fetchOptions;
1097
+ this.maxRetries = options.maxRetries ?? 2;
1098
+ this.fetch = options.fetch ?? getDefaultFetch();
1099
+ __classPrivateFieldSet(this, _Supermemory_encoder, FallbackEncoder, "f");
1100
+ this._options = options;
1101
+ this.apiKey = apiKey;
1102
+ }
1103
+ withOptions(options) {
1104
+ const client = new this.constructor({
1105
+ ...this._options,
1106
+ baseURL: this.baseURL,
1107
+ maxRetries: this.maxRetries,
1108
+ timeout: this.timeout,
1109
+ logger: this.logger,
1110
+ logLevel: this.logLevel,
1111
+ fetch: this.fetch,
1112
+ fetchOptions: this.fetchOptions,
1113
+ apiKey: this.apiKey,
1114
+ ...options
1115
+ });
1116
+ return client;
1117
+ }
1118
+ add(body, options) {
1119
+ return this.post("/v3/documents", { body, ...options });
1120
+ }
1121
+ profile(body, options) {
1122
+ return this.post("/v4/profile", { body, ...options });
1123
+ }
1124
+ defaultQuery() {
1125
+ return this._options.defaultQuery;
1126
+ }
1127
+ validateHeaders({ values, nulls }) {
1128
+ return;
1129
+ }
1130
+ async authHeaders(opts) {
1131
+ return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]);
1132
+ }
1133
+ stringifyQuery(query) {
1134
+ return Object.entries(query).filter(([_, value]) => typeof value !== "undefined").map(([key, value]) => {
1135
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1136
+ return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
1137
+ }
1138
+ if (value === null) {
1139
+ return `${encodeURIComponent(key)}=`;
1140
+ }
1141
+ throw new SupermemoryError(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`);
1142
+ }).join("&");
1143
+ }
1144
+ getUserAgent() {
1145
+ return `${this.constructor.name}/JS ${VERSION}`;
1146
+ }
1147
+ defaultIdempotencyKey() {
1148
+ return `stainless-node-retry-${uuid4()}`;
1149
+ }
1150
+ makeStatusError(status, error, message, headers) {
1151
+ return APIError.generate(status, error, message, headers);
1152
+ }
1153
+ buildURL(path4, query, defaultBaseURL) {
1154
+ const baseURL = !__classPrivateFieldGet(this, _Supermemory_instances, "m", _Supermemory_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
1155
+ const url = isAbsoluteURL(path4) ? new URL(path4) : new URL(baseURL + (baseURL.endsWith("/") && path4.startsWith("/") ? path4.slice(1) : path4));
1156
+ const defaultQuery = this.defaultQuery();
1157
+ if (!isEmptyObj(defaultQuery)) {
1158
+ query = { ...defaultQuery, ...query };
1159
+ }
1160
+ if (typeof query === "object" && query && !Array.isArray(query)) {
1161
+ url.search = this.stringifyQuery(query);
1162
+ }
1163
+ return url.toString();
1164
+ }
1165
+ async prepareOptions(options) {}
1166
+ async prepareRequest(request, { url, options }) {}
1167
+ get(path4, opts) {
1168
+ return this.methodRequest("get", path4, opts);
1169
+ }
1170
+ post(path4, opts) {
1171
+ return this.methodRequest("post", path4, opts);
1172
+ }
1173
+ patch(path4, opts) {
1174
+ return this.methodRequest("patch", path4, opts);
1175
+ }
1176
+ put(path4, opts) {
1177
+ return this.methodRequest("put", path4, opts);
1178
+ }
1179
+ delete(path4, opts) {
1180
+ return this.methodRequest("delete", path4, opts);
1181
+ }
1182
+ methodRequest(method, path4, opts) {
1183
+ return this.request(Promise.resolve(opts).then((opts2) => {
1184
+ return { method, path: path4, ...opts2 };
1185
+ }));
1186
+ }
1187
+ request(options, remainingRetries = null) {
1188
+ return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined));
1189
+ }
1190
+ async makeRequest(optionsInput, retriesRemaining, retryOfRequestLogID) {
1191
+ const options = await optionsInput;
1192
+ const maxRetries = options.maxRetries ?? this.maxRetries;
1193
+ if (retriesRemaining == null) {
1194
+ retriesRemaining = maxRetries;
1195
+ }
1196
+ await this.prepareOptions(options);
1197
+ const { req, url, timeout } = await this.buildRequest(options, {
1198
+ retryCount: maxRetries - retriesRemaining
1199
+ });
1200
+ await this.prepareRequest(req, { url, options });
1201
+ const requestLogID = "log_" + (Math.random() * (1 << 24) | 0).toString(16).padStart(6, "0");
1202
+ const retryLogStr = retryOfRequestLogID === undefined ? "" : `, retryOf: ${retryOfRequestLogID}`;
1203
+ const startTime = Date.now();
1204
+ loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({
1205
+ retryOfRequestLogID,
1206
+ method: options.method,
1207
+ url,
1208
+ options,
1209
+ headers: req.headers
1210
+ }));
1211
+ if (options.signal?.aborted) {
1212
+ throw new APIUserAbortError;
1213
+ }
1214
+ const controller = new AbortController;
1215
+ const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);
1216
+ const headersTime = Date.now();
1217
+ if (response instanceof globalThis.Error) {
1218
+ const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
1219
+ if (options.signal?.aborted) {
1220
+ throw new APIUserAbortError;
1221
+ }
1222
+ const isTimeout = isAbortError(response) || /timed? ?out/i.test(String(response) + ("cause" in response ? String(response.cause) : ""));
1223
+ if (retriesRemaining) {
1224
+ loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? "timed out" : "failed"} - ${retryMessage}`);
1225
+ loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? "timed out" : "failed"} (${retryMessage})`, formatRequestDetails({
1226
+ retryOfRequestLogID,
1227
+ url,
1228
+ durationMs: headersTime - startTime,
1229
+ message: response.message
1230
+ }));
1231
+ return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID);
1232
+ }
1233
+ loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? "timed out" : "failed"} - error; no more retries left`);
1234
+ loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? "timed out" : "failed"} (error; no more retries left)`, formatRequestDetails({
1235
+ retryOfRequestLogID,
1236
+ url,
1237
+ durationMs: headersTime - startTime,
1238
+ message: response.message
1239
+ }));
1240
+ if (isTimeout) {
1241
+ throw new APIConnectionTimeoutError;
1242
+ }
1243
+ throw new APIConnectionError({ cause: response });
1244
+ }
1245
+ const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${response.ok ? "succeeded" : "failed"} with status ${response.status} in ${headersTime - startTime}ms`;
1246
+ if (!response.ok) {
1247
+ const shouldRetry = await this.shouldRetry(response);
1248
+ if (retriesRemaining && shouldRetry) {
1249
+ const retryMessage2 = `retrying, ${retriesRemaining} attempts remaining`;
1250
+ await CancelReadableStream(response.body);
1251
+ loggerFor(this).info(`${responseInfo} - ${retryMessage2}`);
1252
+ loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage2})`, formatRequestDetails({
1253
+ retryOfRequestLogID,
1254
+ url: response.url,
1255
+ status: response.status,
1256
+ headers: response.headers,
1257
+ durationMs: headersTime - startTime
1258
+ }));
1259
+ return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID, response.headers);
1260
+ }
1261
+ const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;
1262
+ loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
1263
+ const errText = await response.text().catch((err2) => castToError(err2).message);
1264
+ const errJSON = safeJSON(errText);
1265
+ const errMessage = errJSON ? undefined : errText;
1266
+ loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({
1267
+ retryOfRequestLogID,
1268
+ url: response.url,
1269
+ status: response.status,
1270
+ headers: response.headers,
1271
+ message: errMessage,
1272
+ durationMs: Date.now() - startTime
1273
+ }));
1274
+ const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
1275
+ throw err;
1276
+ }
1277
+ loggerFor(this).info(responseInfo);
1278
+ loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({
1279
+ retryOfRequestLogID,
1280
+ url: response.url,
1281
+ status: response.status,
1282
+ headers: response.headers,
1283
+ durationMs: headersTime - startTime
1284
+ }));
1285
+ return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
1286
+ }
1287
+ async fetchWithTimeout(url, init, ms, controller) {
1288
+ const { signal, method, ...options } = init || {};
1289
+ const abort = this._makeAbort(controller);
1290
+ if (signal)
1291
+ signal.addEventListener("abort", abort, { once: true });
1292
+ const timeout = setTimeout(abort, ms);
1293
+ const isReadableBody = globalThis.ReadableStream && options.body instanceof globalThis.ReadableStream || typeof options.body === "object" && options.body !== null && Symbol.asyncIterator in options.body;
1294
+ const fetchOptions = {
1295
+ signal: controller.signal,
1296
+ ...isReadableBody ? { duplex: "half" } : {},
1297
+ method: "GET",
1298
+ ...options
1299
+ };
1300
+ if (method) {
1301
+ fetchOptions.method = method.toUpperCase();
1302
+ }
1303
+ try {
1304
+ return await this.fetch.call(undefined, url, fetchOptions);
1305
+ } finally {
1306
+ clearTimeout(timeout);
1307
+ }
1308
+ }
1309
+ async shouldRetry(response) {
1310
+ const shouldRetryHeader = response.headers.get("x-should-retry");
1311
+ if (shouldRetryHeader === "true")
1312
+ return true;
1313
+ if (shouldRetryHeader === "false")
1314
+ return false;
1315
+ if (response.status === 408)
1316
+ return true;
1317
+ if (response.status === 409)
1318
+ return true;
1319
+ if (response.status === 429)
1320
+ return true;
1321
+ if (response.status >= 500)
1322
+ return true;
1323
+ return false;
1324
+ }
1325
+ async retryRequest(options, retriesRemaining, requestLogID, responseHeaders) {
1326
+ let timeoutMillis;
1327
+ const retryAfterMillisHeader = responseHeaders?.get("retry-after-ms");
1328
+ if (retryAfterMillisHeader) {
1329
+ const timeoutMs = parseFloat(retryAfterMillisHeader);
1330
+ if (!Number.isNaN(timeoutMs)) {
1331
+ timeoutMillis = timeoutMs;
1332
+ }
1333
+ }
1334
+ const retryAfterHeader = responseHeaders?.get("retry-after");
1335
+ if (retryAfterHeader && !timeoutMillis) {
1336
+ const timeoutSeconds = parseFloat(retryAfterHeader);
1337
+ if (!Number.isNaN(timeoutSeconds)) {
1338
+ timeoutMillis = timeoutSeconds * 1000;
1339
+ } else {
1340
+ timeoutMillis = Date.parse(retryAfterHeader) - Date.now();
1341
+ }
1342
+ }
1343
+ if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) {
1344
+ const maxRetries = options.maxRetries ?? this.maxRetries;
1345
+ timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);
1346
+ }
1347
+ await sleep(timeoutMillis);
1348
+ return this.makeRequest(options, retriesRemaining - 1, requestLogID);
1349
+ }
1350
+ calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) {
1351
+ const initialRetryDelay = 0.5;
1352
+ const maxRetryDelay = 8;
1353
+ const numRetries = maxRetries - retriesRemaining;
1354
+ const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay);
1355
+ const jitter = 1 - Math.random() * 0.25;
1356
+ return sleepSeconds * jitter * 1000;
1357
+ }
1358
+ async buildRequest(inputOptions, { retryCount = 0 } = {}) {
1359
+ const options = { ...inputOptions };
1360
+ const { method, path: path4, query, defaultBaseURL } = options;
1361
+ const url = this.buildURL(path4, query, defaultBaseURL);
1362
+ if ("timeout" in options)
1363
+ validatePositiveInteger("timeout", options.timeout);
1364
+ options.timeout = options.timeout ?? this.timeout;
1365
+ const { bodyHeaders, body } = this.buildBody({ options });
1366
+ const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });
1367
+ const req = {
1368
+ method,
1369
+ headers: reqHeaders,
1370
+ ...options.signal && { signal: options.signal },
1371
+ ...globalThis.ReadableStream && body instanceof globalThis.ReadableStream && { duplex: "half" },
1372
+ ...body && { body },
1373
+ ...this.fetchOptions ?? {},
1374
+ ...options.fetchOptions ?? {}
1375
+ };
1376
+ return { req, url, timeout: options.timeout };
1377
+ }
1378
+ async buildHeaders({ options, method, bodyHeaders, retryCount }) {
1379
+ let idempotencyHeaders = {};
1380
+ if (this.idempotencyHeader && method !== "get") {
1381
+ if (!options.idempotencyKey)
1382
+ options.idempotencyKey = this.defaultIdempotencyKey();
1383
+ idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey;
1384
+ }
1385
+ const headers = buildHeaders([
1386
+ idempotencyHeaders,
1387
+ {
1388
+ Accept: "application/json",
1389
+ "User-Agent": this.getUserAgent(),
1390
+ "X-Stainless-Retry-Count": String(retryCount),
1391
+ ...options.timeout ? { "X-Stainless-Timeout": String(Math.trunc(options.timeout / 1000)) } : {},
1392
+ ...getPlatformHeaders()
1393
+ },
1394
+ await this.authHeaders(options),
1395
+ this._options.defaultHeaders,
1396
+ bodyHeaders,
1397
+ options.headers
1398
+ ]);
1399
+ this.validateHeaders(headers);
1400
+ return headers.values;
1401
+ }
1402
+ _makeAbort(controller) {
1403
+ return () => controller.abort();
1404
+ }
1405
+ buildBody({ options: { body, headers: rawHeaders } }) {
1406
+ if (!body) {
1407
+ return { bodyHeaders: undefined, body: undefined };
1408
+ }
1409
+ const headers = buildHeaders([rawHeaders]);
1410
+ if (ArrayBuffer.isView(body) || body instanceof ArrayBuffer || body instanceof DataView || typeof body === "string" && headers.values.has("content-type") || globalThis.Blob && body instanceof globalThis.Blob || body instanceof FormData || body instanceof URLSearchParams || globalThis.ReadableStream && body instanceof globalThis.ReadableStream) {
1411
+ return { bodyHeaders: undefined, body };
1412
+ } else if (typeof body === "object" && ((Symbol.asyncIterator in body) || (Symbol.iterator in body) && ("next" in body) && typeof body.next === "function")) {
1413
+ return { bodyHeaders: undefined, body: ReadableStreamFrom(body) };
1414
+ } else {
1415
+ return __classPrivateFieldGet(this, _Supermemory_encoder, "f").call(this, { body, headers });
1416
+ }
1417
+ }
1418
+ }
1419
+ _a = Supermemory, _Supermemory_encoder = new WeakMap, _Supermemory_instances = new WeakSet, _Supermemory_baseURLOverridden = function _Supermemory_baseURLOverridden2() {
1420
+ return this.baseURL !== "https://api.supermemory.ai";
1421
+ };
1422
+ Supermemory.Supermemory = _a;
1423
+ Supermemory.DEFAULT_TIMEOUT = 60000;
1424
+ Supermemory.SupermemoryError = SupermemoryError;
1425
+ Supermemory.APIError = APIError;
1426
+ Supermemory.APIConnectionError = APIConnectionError;
1427
+ Supermemory.APIConnectionTimeoutError = APIConnectionTimeoutError;
1428
+ Supermemory.APIUserAbortError = APIUserAbortError;
1429
+ Supermemory.NotFoundError = NotFoundError;
1430
+ Supermemory.ConflictError = ConflictError;
1431
+ Supermemory.RateLimitError = RateLimitError;
1432
+ Supermemory.BadRequestError = BadRequestError;
1433
+ Supermemory.AuthenticationError = AuthenticationError;
1434
+ Supermemory.InternalServerError = InternalServerError;
1435
+ Supermemory.PermissionDeniedError = PermissionDeniedError;
1436
+ Supermemory.UnprocessableEntityError = UnprocessableEntityError;
1437
+ Supermemory.toFile = toFile;
1438
+ Supermemory.Memories = Memories;
1439
+ Supermemory.Documents = Documents;
1440
+ Supermemory.Search = Search;
1441
+ Supermemory.Settings = Settings;
1442
+ Supermemory.Connections = Connections;
1443
+ // src/client.ts
1444
+ import { createHash, createHmac } from "node:crypto";
1445
+ var INTEGRITY_VERSION = 1;
1446
+ var SEED = "7f2a9c4b8e1d6f3a5c0b9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a";
1447
+ function sha2562(input) {
1448
+ return createHash("sha256").update(input).digest("hex");
1449
+ }
1450
+ function integrityHeaders(apiKey, containerTag) {
1451
+ const contentHash = sha2562(containerTag);
1452
+ const payload = [sha2562(apiKey), contentHash, INTEGRITY_VERSION].join(":");
1453
+ const sig = createHmac("sha256", SEED).update(payload).digest("base64url");
1454
+ return {
1455
+ "X-Content-Hash": contentHash,
1456
+ "X-Request-Integrity": `v${INTEGRITY_VERSION}.${sig}`
1457
+ };
1458
+ }
1459
+ function createClient(apiKey, containerTag = "cursor") {
1460
+ return new Supermemory({
1461
+ apiKey,
1462
+ defaultHeaders: integrityHeaders(apiKey, containerTag)
1463
+ });
1464
+ }
1465
+
1466
+ // src/mcp-server.ts
1467
+ var TOOLS = [
1468
+ {
1469
+ name: "supermemory_search",
1470
+ description: "Search the user's memory for relevant information. Use this to find previously stored knowledge, preferences, and context.",
1471
+ inputSchema: {
1472
+ type: "object",
1473
+ properties: {
1474
+ query: { type: "string", description: "Search query" },
1475
+ container: {
1476
+ type: "string",
1477
+ enum: ["user", "project"],
1478
+ description: "Search user memories or project memories",
1479
+ default: "user"
1480
+ },
1481
+ limit: {
1482
+ type: "number",
1483
+ description: "Max results to return",
1484
+ default: 10
1485
+ }
1486
+ },
1487
+ required: ["query"]
1488
+ }
1489
+ },
1490
+ {
1491
+ name: "supermemory_add",
1492
+ description: "Save information to the user's memory. Use this to remember preferences, facts, decisions, or any knowledge worth persisting.",
1493
+ inputSchema: {
1494
+ type: "object",
1495
+ properties: {
1496
+ content: { type: "string", description: "Content to save" },
1497
+ container: {
1498
+ type: "string",
1499
+ enum: ["user", "project"],
1500
+ description: "Save to user memories or project memories",
1501
+ default: "user"
1502
+ }
1503
+ },
1504
+ required: ["content"]
1505
+ }
1506
+ },
1507
+ {
1508
+ name: "supermemory_profile",
1509
+ description: "Get the user's profile summary — a distilled view of who they are based on their memories.",
1510
+ inputSchema: {
1511
+ type: "object",
1512
+ properties: {
1513
+ query: {
1514
+ type: "string",
1515
+ description: "Optional search query to include relevant results"
1516
+ }
1517
+ }
1518
+ }
1519
+ },
1520
+ {
1521
+ name: "supermemory_list",
1522
+ description: "List stored documents/memories.",
1523
+ inputSchema: {
1524
+ type: "object",
1525
+ properties: {
1526
+ limit: { type: "number", description: "Max items", default: 20 },
1527
+ page: { type: "number", description: "Page number", default: 1 }
1528
+ }
1529
+ }
1530
+ },
1531
+ {
1532
+ name: "supermemory_forget",
1533
+ description: "Forget a specific memory. Use when the user asks to remove or forget something.",
1534
+ inputSchema: {
1535
+ type: "object",
1536
+ properties: {
1537
+ id: { type: "string", description: "Memory ID to forget" },
1538
+ content: {
1539
+ type: "string",
1540
+ description: "Exact content match (if ID unknown)"
1541
+ },
1542
+ container: {
1543
+ type: "string",
1544
+ enum: ["user", "project"],
1545
+ default: "user"
1546
+ }
1547
+ }
1548
+ }
1549
+ }
1550
+ ];
1551
+ function getAuth() {
1552
+ const config = loadConfig();
1553
+ const apiKey = getApiKey(config);
1554
+ if (!apiKey) {
1555
+ throw new Error("Not authenticated. Run `cursor-supermemory login` to connect your account.");
1556
+ }
1557
+ const userTag = getUserTag(config);
1558
+ const projectTag = getProjectTag(process.cwd(), config);
1559
+ return { apiKey, userTag, projectTag };
1560
+ }
1561
+ function containerTag(auth, container) {
1562
+ return container === "project" ? auth.projectTag : auth.userTag;
1563
+ }
1564
+ async function handleSearch(args) {
1565
+ const auth = getAuth();
1566
+ const tag = containerTag(auth, args.container);
1567
+ const client = createClient(auth.apiKey, tag);
1568
+ const result = await client.search.memories({
1569
+ q: args.query,
1570
+ containerTag: tag,
1571
+ limit: args.limit || 10
1572
+ });
1573
+ const formatted = result.results.map((r) => ({
1574
+ id: r.id,
1575
+ memory: r.memory ?? r.chunk ?? "",
1576
+ similarity: r.similarity,
1577
+ updatedAt: r.updatedAt
1578
+ }));
1579
+ return JSON.stringify(formatted, null, 2);
1580
+ }
1581
+ async function handleAdd(args) {
1582
+ const auth = getAuth();
1583
+ const tag = containerTag(auth, args.container);
1584
+ const client = createClient(auth.apiKey, tag);
1585
+ const result = await client.add({
1586
+ content: args.content,
1587
+ containerTag: tag
1588
+ });
1589
+ return JSON.stringify(result, null, 2);
1590
+ }
1591
+ async function handleProfile(args) {
1592
+ const auth = getAuth();
1593
+ const client = createClient(auth.apiKey, auth.userTag);
1594
+ const result = await client.profile({
1595
+ containerTag: auth.userTag,
1596
+ q: args.query
1597
+ });
1598
+ return JSON.stringify(result, null, 2);
1599
+ }
1600
+ async function handleList(args) {
1601
+ const auth = getAuth();
1602
+ const client = createClient(auth.apiKey, auth.userTag);
1603
+ const result = await client.documents.list({
1604
+ limit: args.limit || 20,
1605
+ page: args.page || 1
1606
+ });
1607
+ return JSON.stringify(result, null, 2);
1608
+ }
1609
+ async function handleForget(args) {
1610
+ const auth = getAuth();
1611
+ const tag = containerTag(auth, args.container);
1612
+ const client = createClient(auth.apiKey, tag);
1613
+ const params = {
1614
+ containerTag: containerTag(auth, args.container)
1615
+ };
1616
+ if (args.id)
1617
+ params.id = args.id;
1618
+ if (args.content)
1619
+ params.content = args.content;
1620
+ if (!params.id && !params.content) {
1621
+ throw new Error("Provide either id or content to forget.");
1622
+ }
1623
+ const result = await client.memories.forget(params);
1624
+ return JSON.stringify(result, null, 2);
1625
+ }
1626
+ var HANDLERS = {
1627
+ supermemory_search: handleSearch,
1628
+ supermemory_add: handleAdd,
1629
+ supermemory_profile: handleProfile,
1630
+ supermemory_list: handleList,
1631
+ supermemory_forget: handleForget
1632
+ };
1633
+ function jsonRpcResponse(id, result) {
1634
+ return JSON.stringify({ jsonrpc: "2.0", id, result });
1635
+ }
1636
+ function jsonRpcError(id, code, message) {
1637
+ return JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } });
1638
+ }
1639
+ async function handleMessage(msg) {
1640
+ const { id, method, params } = msg;
1641
+ switch (method) {
1642
+ case "initialize":
1643
+ return jsonRpcResponse(id, {
1644
+ protocolVersion: "2024-11-05",
1645
+ capabilities: { tools: {} },
1646
+ serverInfo: { name: "supermemory", version: "1.0.0" }
1647
+ });
1648
+ case "notifications/initialized":
1649
+ return null;
1650
+ case "tools/list":
1651
+ return jsonRpcResponse(id, { tools: TOOLS });
1652
+ case "tools/call": {
1653
+ const toolName = params?.name;
1654
+ const handler = HANDLERS[toolName];
1655
+ if (!handler) {
1656
+ return jsonRpcError(id, -32601, `Unknown tool: ${toolName}`);
1657
+ }
1658
+ try {
1659
+ const text = await handler(params?.arguments ?? {});
1660
+ return jsonRpcResponse(id, {
1661
+ content: [{ type: "text", text }]
1662
+ });
1663
+ } catch (err) {
1664
+ return jsonRpcResponse(id, {
1665
+ content: [{ type: "text", text: `Error: ${err.message}` }],
1666
+ isError: true
1667
+ });
1668
+ }
1669
+ }
1670
+ default:
1671
+ if (id !== undefined) {
1672
+ return jsonRpcError(id, -32601, `Method not found: ${method}`);
1673
+ }
1674
+ return null;
1675
+ }
1676
+ }
1677
+ async function startMcpServer() {
1678
+ const decoder = new TextDecoder;
1679
+ let buffer = "";
1680
+ for await (const chunk of Bun.stdin.stream()) {
1681
+ buffer += decoder.decode(chunk, { stream: true });
1682
+ while (true) {
1683
+ const headerEnd = buffer.indexOf(`\r
1684
+ \r
1685
+ `);
1686
+ if (headerEnd === -1)
1687
+ break;
1688
+ const header = buffer.slice(0, headerEnd);
1689
+ const match = header.match(/Content-Length:\s*(\d+)/i);
1690
+ if (!match) {
1691
+ buffer = buffer.slice(headerEnd + 4);
1692
+ continue;
1693
+ }
1694
+ const contentLength = parseInt(match[1], 10);
1695
+ const bodyStart = headerEnd + 4;
1696
+ if (buffer.length < bodyStart + contentLength)
1697
+ break;
1698
+ const body = buffer.slice(bodyStart, bodyStart + contentLength);
1699
+ buffer = buffer.slice(bodyStart + contentLength);
1700
+ try {
1701
+ const msg = JSON.parse(body);
1702
+ const response = await handleMessage(msg);
1703
+ if (response) {
1704
+ const out = `Content-Length: ${Buffer.byteLength(response)}\r
1705
+ \r
1706
+ ${response}`;
1707
+ process.stdout.write(out);
1708
+ }
1709
+ } catch (err) {
1710
+ const errResp = jsonRpcError(null, -32700, "Parse error");
1711
+ const out = `Content-Length: ${Buffer.byteLength(errResp)}\r
1712
+ \r
1713
+ ${errResp}`;
1714
+ process.stdout.write(out);
1715
+ }
1716
+ }
1717
+ }
1718
+ }
1719
+
1720
+ // src/cli.ts
1721
+ var command = process.argv[2];
1722
+ switch (command) {
1723
+ case "mcp":
1724
+ await startMcpServer();
1725
+ break;
1726
+ case "login": {
1727
+ const existing = loadCredentials();
1728
+ if (existing) {
1729
+ console.log("Already authenticated. Use `logout` first to re-authenticate.");
1730
+ process.exit(0);
1731
+ }
1732
+ console.log("Opening browser to authenticate...");
1733
+ const result = await startAuthFlow();
1734
+ if (result.success) {
1735
+ console.log("Authenticated successfully.");
1736
+ } else {
1737
+ console.error(`Authentication failed: ${result.error}`);
1738
+ process.exit(1);
1739
+ }
1740
+ break;
1741
+ }
1742
+ case "logout": {
1743
+ const removed = clearCredentials();
1744
+ console.log(removed ? "Logged out." : "No credentials found.");
1745
+ break;
1746
+ }
1747
+ case "status": {
1748
+ const creds = loadCredentials();
1749
+ if (creds) {
1750
+ console.log(`Authenticated since ${creds.createdAt}`);
1751
+ console.log(`API key: ${creds.apiKey.slice(0, 6)}...${creds.apiKey.slice(-4)}`);
1752
+ } else {
1753
+ console.log("Not authenticated. Run `cursor-supermemory login` to connect.");
1754
+ }
1755
+ break;
1756
+ }
1757
+ default:
1758
+ console.log(`cursor-supermemory — Persistent AI memory for Cursor
1759
+
1760
+ Commands:
1761
+ mcp Start the MCP server (stdio)
1762
+ login Authenticate with Supermemory
1763
+ logout Remove stored credentials
1764
+ status Show authentication status`);
1765
+ if (command)
1766
+ process.exit(1);
1767
+ }