convex-supermemory 0.0.1

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 (52) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +306 -0
  3. package/dist/client/_generated/_ignore.d.ts +1 -0
  4. package/dist/client/_generated/_ignore.d.ts.map +1 -0
  5. package/dist/client/_generated/_ignore.js +3 -0
  6. package/dist/client/_generated/_ignore.js.map +1 -0
  7. package/dist/client/index.d.ts +188 -0
  8. package/dist/client/index.d.ts.map +1 -0
  9. package/dist/client/index.js +177 -0
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/component/_generated/api.d.ts +34 -0
  12. package/dist/component/_generated/api.d.ts.map +1 -0
  13. package/dist/component/_generated/api.js +31 -0
  14. package/dist/component/_generated/api.js.map +1 -0
  15. package/dist/component/_generated/component.d.ts +152 -0
  16. package/dist/component/_generated/component.d.ts.map +1 -0
  17. package/dist/component/_generated/component.js +11 -0
  18. package/dist/component/_generated/component.js.map +1 -0
  19. package/dist/component/_generated/dataModel.d.ts +46 -0
  20. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  21. package/dist/component/_generated/dataModel.js +11 -0
  22. package/dist/component/_generated/dataModel.js.map +1 -0
  23. package/dist/component/_generated/server.d.ts +133 -0
  24. package/dist/component/_generated/server.d.ts.map +1 -0
  25. package/dist/component/_generated/server.js +80 -0
  26. package/dist/component/_generated/server.js.map +1 -0
  27. package/dist/component/convex.config.d.ts +3 -0
  28. package/dist/component/convex.config.d.ts.map +1 -0
  29. package/dist/component/convex.config.js +4 -0
  30. package/dist/component/convex.config.js.map +1 -0
  31. package/dist/component/lib.d.ts +128 -0
  32. package/dist/component/lib.d.ts.map +1 -0
  33. package/dist/component/lib.js +196 -0
  34. package/dist/component/lib.js.map +1 -0
  35. package/dist/component/schema.d.ts +56 -0
  36. package/dist/component/schema.d.ts.map +1 -0
  37. package/dist/component/schema.js +33 -0
  38. package/dist/component/schema.js.map +1 -0
  39. package/package.json +106 -0
  40. package/src/client/_generated/_ignore.ts +1 -0
  41. package/src/client/index.ts +289 -0
  42. package/src/client/setup.test.ts +26 -0
  43. package/src/component/_generated/api.ts +50 -0
  44. package/src/component/_generated/component.ts +232 -0
  45. package/src/component/_generated/dataModel.ts +60 -0
  46. package/src/component/_generated/server.ts +169 -0
  47. package/src/component/convex.config.ts +5 -0
  48. package/src/component/lib.test.ts +127 -0
  49. package/src/component/lib.ts +224 -0
  50. package/src/component/schema.ts +43 -0
  51. package/src/component/setup.test.ts +11 -0
  52. package/src/test.ts +18 -0
@@ -0,0 +1,56 @@
1
+ declare const _default: import("convex/server").SchemaDefinition<{
2
+ memories: import("convex/server").TableDefinition<import("convex/values").VObject<{
3
+ metadata?: string | undefined;
4
+ forgetAfter?: number | undefined;
5
+ forgetReason?: string | undefined;
6
+ memoryId: string;
7
+ containerTag: string;
8
+ content: string;
9
+ isStatic: boolean;
10
+ forgotten: boolean;
11
+ createdAt: number;
12
+ updatedAt: number;
13
+ }, {
14
+ memoryId: import("convex/values").VString<string, "required">;
15
+ containerTag: import("convex/values").VString<string, "required">;
16
+ content: import("convex/values").VString<string, "required">;
17
+ isStatic: import("convex/values").VBoolean<boolean, "required">;
18
+ metadata: import("convex/values").VString<string | undefined, "optional">;
19
+ forgetAfter: import("convex/values").VFloat64<number | undefined, "optional">;
20
+ forgetReason: import("convex/values").VString<string | undefined, "optional">;
21
+ forgotten: import("convex/values").VBoolean<boolean, "required">;
22
+ createdAt: import("convex/values").VFloat64<number, "required">;
23
+ updatedAt: import("convex/values").VFloat64<number, "required">;
24
+ }, "required", "memoryId" | "containerTag" | "content" | "metadata" | "forgetAfter" | "forgetReason" | "isStatic" | "forgotten" | "createdAt" | "updatedAt">, {
25
+ by_memoryId: ["memoryId", "_creationTime"];
26
+ by_containerTag: ["containerTag", "_creationTime"];
27
+ }, {}, {}>;
28
+ documents: import("convex/server").TableDefinition<import("convex/values").VObject<{
29
+ content?: string | undefined;
30
+ customId?: string | undefined;
31
+ metadata?: string | undefined;
32
+ summary?: string | undefined;
33
+ title?: string | undefined;
34
+ documentId: string;
35
+ containerTag: string;
36
+ status: "unknown" | "queued" | "extracting" | "chunking" | "embedding" | "indexing" | "done" | "failed";
37
+ createdAt: number;
38
+ updatedAt: number;
39
+ }, {
40
+ documentId: import("convex/values").VString<string, "required">;
41
+ containerTag: import("convex/values").VString<string, "required">;
42
+ content: import("convex/values").VString<string | undefined, "optional">;
43
+ customId: import("convex/values").VString<string | undefined, "optional">;
44
+ metadata: import("convex/values").VString<string | undefined, "optional">;
45
+ status: import("convex/values").VUnion<"unknown" | "queued" | "extracting" | "chunking" | "embedding" | "indexing" | "done" | "failed", [import("convex/values").VLiteral<"unknown", "required">, import("convex/values").VLiteral<"queued", "required">, import("convex/values").VLiteral<"extracting", "required">, import("convex/values").VLiteral<"chunking", "required">, import("convex/values").VLiteral<"embedding", "required">, import("convex/values").VLiteral<"indexing", "required">, import("convex/values").VLiteral<"done", "required">, import("convex/values").VLiteral<"failed", "required">], "required", never>;
46
+ title: import("convex/values").VString<string | undefined, "optional">;
47
+ summary: import("convex/values").VString<string | undefined, "optional">;
48
+ createdAt: import("convex/values").VFloat64<number, "required">;
49
+ updatedAt: import("convex/values").VFloat64<number, "required">;
50
+ }, "required", "documentId" | "containerTag" | "content" | "customId" | "metadata" | "status" | "summary" | "title" | "createdAt" | "updatedAt">, {
51
+ by_documentId: ["documentId", "_creationTime"];
52
+ by_containerTag: ["containerTag", "_creationTime"];
53
+ }, {}, {}>;
54
+ }, true>;
55
+ export default _default;
56
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/component/schema.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,wBAuCG"}
@@ -0,0 +1,33 @@
1
+ import { defineSchema, defineTable } from "convex/server";
2
+ import { v } from "convex/values";
3
+ export default defineSchema({
4
+ memories: defineTable({
5
+ memoryId: v.string(),
6
+ containerTag: v.string(),
7
+ content: v.string(),
8
+ isStatic: v.boolean(),
9
+ metadata: v.optional(v.string()),
10
+ forgetAfter: v.optional(v.number()),
11
+ forgetReason: v.optional(v.string()),
12
+ forgotten: v.boolean(),
13
+ createdAt: v.number(),
14
+ updatedAt: v.number(),
15
+ })
16
+ .index("by_memoryId", ["memoryId"])
17
+ .index("by_containerTag", ["containerTag"]),
18
+ documents: defineTable({
19
+ documentId: v.string(),
20
+ containerTag: v.string(),
21
+ content: v.optional(v.string()),
22
+ customId: v.optional(v.string()),
23
+ metadata: v.optional(v.string()),
24
+ status: v.union(v.literal("unknown"), v.literal("queued"), v.literal("extracting"), v.literal("chunking"), v.literal("embedding"), v.literal("indexing"), v.literal("done"), v.literal("failed")),
25
+ title: v.optional(v.string()),
26
+ summary: v.optional(v.string()),
27
+ createdAt: v.number(),
28
+ updatedAt: v.number(),
29
+ })
30
+ .index("by_documentId", ["documentId"])
31
+ .index("by_containerTag", ["containerTag"]),
32
+ });
33
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/component/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAElC,eAAe,YAAY,CAAC;IAC1B,QAAQ,EAAE,WAAW,CAAC;QACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;QACpB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;QACxB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;QACnB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;QACrB,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAChC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QACnC,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QACpC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;QACtB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;QACrB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;KACtB,CAAC;SACC,KAAK,CAAC,aAAa,EAAE,CAAC,UAAU,CAAC,CAAC;SAClC,KAAK,CAAC,iBAAiB,EAAE,CAAC,cAAc,CAAC,CAAC;IAE7C,SAAS,EAAE,WAAW,CAAC;QACrB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;QACxB,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC/B,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAChC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAChC,MAAM,EAAE,CAAC,CAAC,KAAK,CACb,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EACpB,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EACnB,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,EACvB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EACrB,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,EACtB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EACrB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EACjB,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CACpB;QACD,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC7B,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;QACrB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;KACtB,CAAC;SACC,KAAK,CAAC,eAAe,EAAE,CAAC,YAAY,CAAC,CAAC;SACtC,KAAK,CAAC,iBAAiB,EAAE,CAAC,cAAc,CAAC,CAAC;CAC9C,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,106 @@
1
+ {
2
+ "name": "convex-supermemory",
3
+ "description": "Give your Convex app long-term, semantically searchable memory with Supermemory. Reactive local memory and document state, direct REST integration.",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/sholajegede/convex-supermemory.git"
7
+ },
8
+ "homepage": "https://github.com/sholajegede/convex-supermemory#readme",
9
+ "bugs": {
10
+ "url": "https://github.com/sholajegede/convex-supermemory/issues"
11
+ },
12
+ "version": "0.0.1",
13
+ "license": "Apache-2.0",
14
+ "keywords": [
15
+ "convex",
16
+ "component",
17
+ "supermemory",
18
+ "memory",
19
+ "rag",
20
+ "ai",
21
+ "agents",
22
+ "search"
23
+ ],
24
+ "type": "module",
25
+ "scripts": {
26
+ "dev": "run-p -r 'dev:*'",
27
+ "dev:backend": "convex dev --typecheck-components",
28
+ "dev:frontend": "cd example && vite --clearScreen false",
29
+ "dev:build": "chokidar 'tsconfig*.json' 'src/**/*.ts' -i '**/*.test.ts' -c 'npm run build:codegen' --initial",
30
+ "predev": "path-exists .env.local dist || (npm run build && convex dev --once)",
31
+ "build": "tsc --project ./tsconfig.build.json",
32
+ "build:codegen": "npx convex codegen --component-dir ./src/component && npm run build",
33
+ "build:clean": "rm -rf dist *.tsbuildinfo && npm run build:codegen",
34
+ "typecheck": "tsc --noEmit && tsc -p example && tsc -p example/convex",
35
+ "lint": "eslint .",
36
+ "all": "run-p -r 'dev:*' 'test:watch'",
37
+ "test": "vitest run --typecheck",
38
+ "test:watch": "vitest --typecheck --clearScreen false",
39
+ "test:debug": "vitest --inspect-brk --no-file-parallelism",
40
+ "test:coverage": "vitest run --coverage --coverage.reporter=text",
41
+ "preversion": "npm install --legacy-peer-deps && npm run build:clean && run-p test lint typecheck",
42
+ "prepublishOnly": "npm whoami || npm login",
43
+ "alpha": "npm version prerelease --preid alpha && npm publish --tag alpha && git push --follow-tags",
44
+ "release": "npm version patch && npm publish && git push --follow-tags",
45
+ "version": "vim -c 'normal o' -c 'normal o## '$npm_package_version CHANGELOG.md && prettier -w CHANGELOG.md && git add CHANGELOG.md"
46
+ },
47
+ "files": [
48
+ "dist",
49
+ "src"
50
+ ],
51
+ "exports": {
52
+ "./package.json": "./package.json",
53
+ ".": {
54
+ "types": "./dist/client/index.d.ts",
55
+ "default": "./dist/client/index.js"
56
+ },
57
+ "./test": "./src/test.ts",
58
+ "./_generated/component.js": {
59
+ "types": "./dist/component/_generated/component.d.ts"
60
+ },
61
+ "./_generated/component": {
62
+ "types": "./dist/component/_generated/component.d.ts"
63
+ },
64
+ "./convex.config.js": {
65
+ "types": "./dist/component/convex.config.d.ts",
66
+ "default": "./dist/component/convex.config.js"
67
+ },
68
+ "./convex.config": {
69
+ "types": "./dist/component/convex.config.d.ts",
70
+ "default": "./dist/component/convex.config.js"
71
+ }
72
+ },
73
+ "peerDependencies": {
74
+ "convex": "^1.34.1"
75
+ },
76
+ "devDependencies": {
77
+ "@convex-dev/eslint-plugin": "^1.2.0",
78
+ "@edge-runtime/vm": "^5.0.0",
79
+ "@eslint/eslintrc": "^3.3.5",
80
+ "@eslint/js": "9.39.4",
81
+ "@types/node": "^24.12.0",
82
+ "@types/react": "^19.2.14",
83
+ "@types/react-dom": "^19.2.3",
84
+ "@vitejs/plugin-react": "^5.2.0",
85
+ "chokidar-cli": "3.0.0",
86
+ "convex": "1.45.0",
87
+ "convex-test": "0.0.41",
88
+ "eslint": "9.39.4",
89
+ "eslint-plugin-react": "^7.37.5",
90
+ "eslint-plugin-react-hooks": "^7.0.1",
91
+ "eslint-plugin-react-refresh": "^0.5.2",
92
+ "globals": "^17.4.0",
93
+ "npm-run-all2": "8.0.4",
94
+ "path-exists-cli": "2.0.0",
95
+ "pkg-pr-new": "^0.0.66",
96
+ "prettier": "3.8.1",
97
+ "react": "^19.2.4",
98
+ "react-dom": "^19.2.4",
99
+ "typescript": "5.9.3",
100
+ "typescript-eslint": "8.57.1",
101
+ "vite": "7.3.1",
102
+ "vitest": "4.1.0"
103
+ },
104
+ "types": "./dist/client/index.d.ts",
105
+ "module": "./dist/client/index.js"
106
+ }
@@ -0,0 +1 @@
1
+ // This is only here so convex-test can detect a _generated folder
@@ -0,0 +1,289 @@
1
+ import type { GenericActionCtx, GenericDataModel } from "convex/server";
2
+ import type { ComponentApi } from "../component/_generated/component.js";
3
+
4
+ const SUPERMEMORY_API_BASE = "https://api.supermemory.ai";
5
+
6
+ export type SupermemoryOptions = {
7
+ apiKey: string;
8
+ baseUrl?: string;
9
+ };
10
+
11
+ export type AddMemoryArgs = {
12
+ containerTag: string;
13
+ content: string;
14
+ isStatic?: boolean;
15
+ metadata?: Record<string, unknown>;
16
+ forgetAfter?: number;
17
+ forgetReason?: string;
18
+ };
19
+
20
+ export type AddDocumentArgs = {
21
+ containerTag: string;
22
+ content: string;
23
+ customId?: string;
24
+ metadata?: Record<string, unknown>;
25
+ };
26
+
27
+ export type SearchArgs = {
28
+ containerTag: string;
29
+ query: string;
30
+ limit?: number;
31
+ rerank?: boolean;
32
+ includeFullDocs?: boolean;
33
+ };
34
+
35
+ export type SearchResult = {
36
+ documentId: string;
37
+ title: string | null;
38
+ score: number;
39
+ summary: string | null;
40
+ content: string | null;
41
+ chunks: Array<{ content: string; score: number; position: number; isRelevant: boolean }>;
42
+ };
43
+
44
+ export type SearchResponse = {
45
+ results: SearchResult[];
46
+ total: number;
47
+ timing?: number; // ms, when Supermemory reports it
48
+ };
49
+
50
+ export class Supermemory {
51
+ constructor(
52
+ private component: ComponentApi,
53
+ private options: SupermemoryOptions,
54
+ ) {}
55
+
56
+ private baseUrl(): string {
57
+ return this.options.baseUrl ?? SUPERMEMORY_API_BASE;
58
+ }
59
+
60
+ private headers(): Record<string, string> {
61
+ return {
62
+ Authorization: `Bearer ${this.options.apiKey}`,
63
+ "Content-Type": "application/json",
64
+ };
65
+ }
66
+
67
+ /** Store a single fact/memory directly (fast path — no chunking pipeline). */
68
+ async addMemory(
69
+ ctx: GenericActionCtx<GenericDataModel>,
70
+ args: AddMemoryArgs,
71
+ ): Promise<{ memoryId: string }> {
72
+ const res = await fetch(`${this.baseUrl()}/v4/memories`, {
73
+ method: "POST",
74
+ headers: this.headers(),
75
+ body: JSON.stringify({
76
+ containerTag: args.containerTag,
77
+ memories: [
78
+ {
79
+ content: args.content,
80
+ isStatic: args.isStatic ?? false,
81
+ metadata: args.metadata,
82
+ forgetAfter: args.forgetAfter
83
+ ? new Date(args.forgetAfter).toISOString()
84
+ : undefined,
85
+ forgetReason: args.forgetReason,
86
+ },
87
+ ],
88
+ }),
89
+ });
90
+ if (!res.ok) {
91
+ throw new Error(`Failed to add Supermemory memory: ${res.status} ${await res.text()}`);
92
+ }
93
+ const json = (await res.json()) as {
94
+ memories: Array<{ id: string; memory: string; isStatic: boolean; createdAt: string }>;
95
+ };
96
+ const memory = json.memories[0];
97
+
98
+ await ctx.runMutation(this.component.lib.recordMemory, {
99
+ memoryId: memory.id,
100
+ containerTag: args.containerTag,
101
+ content: args.content,
102
+ isStatic: args.isStatic ?? false,
103
+ metadata: args.metadata ? JSON.stringify(args.metadata) : undefined,
104
+ forgetAfter: args.forgetAfter,
105
+ forgetReason: args.forgetReason,
106
+ });
107
+
108
+ return { memoryId: memory.id };
109
+ }
110
+
111
+ /** Mark a memory as forgotten. Supermemory may forget it asynchronously. */
112
+ async forgetMemory(
113
+ ctx: GenericActionCtx<GenericDataModel>,
114
+ args: { containerTag: string; memoryId: string },
115
+ ): Promise<{ forgotten: boolean }> {
116
+ const res = await fetch(`${this.baseUrl()}/v4/memories`, {
117
+ method: "DELETE",
118
+ headers: this.headers(),
119
+ // containerTag is required by Supermemory to scope the delete —
120
+ // omitting it makes this a 400, not a silent no-op.
121
+ body: JSON.stringify({ id: args.memoryId, containerTag: args.containerTag }),
122
+ });
123
+ if (!res.ok) {
124
+ throw new Error(`Failed to forget Supermemory memory: ${res.status} ${await res.text()}`);
125
+ }
126
+ const json = (await res.json()) as { id: string; forgotten: boolean };
127
+
128
+ if (json.forgotten) {
129
+ await ctx.runMutation(this.component.lib.markMemoryForgotten, { memoryId: args.memoryId });
130
+ }
131
+
132
+ return { forgotten: json.forgotten };
133
+ }
134
+
135
+ /**
136
+ * Ingest a larger piece of content (a document, page, or conversation) through
137
+ * Supermemory's extraction/chunking pipeline. Use `getDocument`/`refreshDocument`
138
+ * to poll processing status.
139
+ */
140
+ async addDocument(
141
+ ctx: GenericActionCtx<GenericDataModel>,
142
+ args: AddDocumentArgs,
143
+ ): Promise<{ documentId: string; status: string }> {
144
+ const res = await fetch(`${this.baseUrl()}/v3/documents`, {
145
+ method: "POST",
146
+ headers: this.headers(),
147
+ body: JSON.stringify({
148
+ content: args.content,
149
+ containerTag: args.containerTag,
150
+ customId: args.customId,
151
+ metadata: args.metadata,
152
+ }),
153
+ });
154
+ if (!res.ok) {
155
+ throw new Error(`Failed to add Supermemory document: ${res.status} ${await res.text()}`);
156
+ }
157
+ const json = (await res.json()) as { id: string; status: string };
158
+
159
+ await ctx.runMutation(this.component.lib.recordDocument, {
160
+ documentId: json.id,
161
+ containerTag: args.containerTag,
162
+ content: args.content,
163
+ customId: args.customId,
164
+ metadata: args.metadata ? JSON.stringify(args.metadata) : undefined,
165
+ status: (json.status as
166
+ | "unknown"
167
+ | "queued"
168
+ | "extracting"
169
+ | "chunking"
170
+ | "embedding"
171
+ | "indexing"
172
+ | "done"
173
+ | "failed") ?? "queued",
174
+ });
175
+
176
+ return { documentId: json.id, status: json.status };
177
+ }
178
+
179
+ /** Refresh a document's processing status, title, and summary from Supermemory. */
180
+ async refreshDocument(
181
+ ctx: GenericActionCtx<GenericDataModel>,
182
+ args: { documentId: string },
183
+ ): Promise<void> {
184
+ const res = await fetch(`${this.baseUrl()}/v3/documents/${encodeURIComponent(args.documentId)}`, {
185
+ headers: this.headers(),
186
+ });
187
+ if (!res.ok) {
188
+ throw new Error(`Failed to fetch Supermemory document: ${res.status} ${await res.text()}`);
189
+ }
190
+ const json = (await res.json()) as {
191
+ id: string;
192
+ status: string;
193
+ title: string | null;
194
+ summary: string | null;
195
+ content: string | null;
196
+ metadata: Record<string, unknown> | null;
197
+ };
198
+
199
+ const existing = await ctx.runQuery(this.component.lib.getDocument, { documentId: args.documentId });
200
+
201
+ await ctx.runMutation(this.component.lib.recordDocument, {
202
+ documentId: json.id,
203
+ containerTag: existing?.containerTag ?? "",
204
+ content: json.content ?? existing?.content,
205
+ customId: existing?.customId,
206
+ metadata: json.metadata ? JSON.stringify(json.metadata) : existing?.metadata,
207
+ status: json.status as
208
+ | "unknown"
209
+ | "queued"
210
+ | "extracting"
211
+ | "chunking"
212
+ | "embedding"
213
+ | "indexing"
214
+ | "done"
215
+ | "failed",
216
+ title: json.title ?? undefined,
217
+ summary: json.summary ?? undefined,
218
+ });
219
+ }
220
+
221
+ async deleteDocument(
222
+ ctx: GenericActionCtx<GenericDataModel>,
223
+ args: { documentId: string },
224
+ ): Promise<void> {
225
+ const res = await fetch(`${this.baseUrl()}/v3/documents/${encodeURIComponent(args.documentId)}`, {
226
+ method: "DELETE",
227
+ headers: this.headers(),
228
+ });
229
+ if (!res.ok && res.status !== 204) {
230
+ throw new Error(`Failed to delete Supermemory document: ${res.status} ${await res.text()}`);
231
+ }
232
+ await ctx.runMutation(this.component.lib.deleteDocument, { documentId: args.documentId });
233
+ }
234
+
235
+ /** Semantic search over a container's document chunks. Always live — not cached locally. */
236
+ async search(args: SearchArgs): Promise<SearchResponse> {
237
+ const res = await fetch(`${this.baseUrl()}/v3/search`, {
238
+ method: "POST",
239
+ headers: this.headers(),
240
+ body: JSON.stringify({
241
+ q: args.query,
242
+ // Supermemory's /v3/search schema documents singular `containerTag` as
243
+ // valid, but the only worked example in their own docs uses the plural
244
+ // `containerTags` array — and in practice singular reliably returns
245
+ // zero matches even against fully-indexed content. Use the array form.
246
+ containerTags: [args.containerTag],
247
+ limit: args.limit ?? 10,
248
+ rerank: args.rerank ?? false,
249
+ includeFullDocs: args.includeFullDocs ?? false,
250
+ }),
251
+ });
252
+ if (!res.ok) {
253
+ throw new Error(`Failed to search Supermemory: ${res.status} ${await res.text()}`);
254
+ }
255
+ return (await res.json()) as SearchResponse;
256
+ }
257
+
258
+ async getMemory(ctx: RunQueryCtx, args: { memoryId: string }) {
259
+ return await ctx.runQuery(this.component.lib.getMemory, args);
260
+ }
261
+
262
+ async listMemories(ctx: RunQueryCtx, args: { containerTag: string; limit?: number }) {
263
+ return await ctx.runQuery(this.component.lib.listMemories, args);
264
+ }
265
+
266
+ async getDocument(ctx: RunQueryCtx, args: { documentId: string }) {
267
+ return await ctx.runQuery(this.component.lib.getDocument, args);
268
+ }
269
+
270
+ async listDocuments(ctx: RunQueryCtx, args: { containerTag: string; limit?: number }) {
271
+ return await ctx.runQuery(this.component.lib.listDocuments, args);
272
+ }
273
+
274
+ async getStats(ctx: RunQueryCtx) {
275
+ return await ctx.runQuery(this.component.lib.getStats, {});
276
+ }
277
+
278
+ async listRecentMemories(ctx: RunQueryCtx, args: { limit?: number } = {}) {
279
+ return await ctx.runQuery(this.component.lib.listRecentMemories, args);
280
+ }
281
+
282
+ async listRecentDocuments(ctx: RunQueryCtx, args: { limit?: number } = {}) {
283
+ return await ctx.runQuery(this.component.lib.listRecentDocuments, args);
284
+ }
285
+ }
286
+
287
+ type RunQueryCtx = {
288
+ runQuery: GenericActionCtx<GenericDataModel>["runQuery"];
289
+ };
@@ -0,0 +1,26 @@
1
+ /// <reference types="vite/client" />
2
+ import { test } from "vitest";
3
+ import { convexTest } from "convex-test";
4
+ export const modules = import.meta.glob("./**/*.*s");
5
+
6
+ import {
7
+ defineSchema,
8
+ type GenericSchema,
9
+ type SchemaDefinition,
10
+ } from "convex/server";
11
+ import { type ComponentApi } from "../component/_generated/component.js";
12
+ import { componentsGeneric } from "convex/server";
13
+ import { register } from "../test.js";
14
+
15
+ export function initConvexTest<
16
+ Schema extends SchemaDefinition<GenericSchema, boolean>,
17
+ >(schema?: Schema) {
18
+ const t = convexTest(schema ?? defineSchema({}), modules);
19
+ register(t);
20
+ return t;
21
+ }
22
+ export const components = componentsGeneric() as unknown as {
23
+ convexSupermemory: ComponentApi;
24
+ };
25
+
26
+ test("setup", () => {});
@@ -0,0 +1,50 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * Generated `api` utility.
4
+ *
5
+ * THIS CODE IS AUTOMATICALLY GENERATED.
6
+ *
7
+ * To regenerate, run `npx convex dev`.
8
+ * @module
9
+ */
10
+
11
+ import type * as lib from "../lib.js";
12
+
13
+ import type {
14
+ ApiFromModules,
15
+ FilterApi,
16
+ FunctionReference,
17
+ } from "convex/server";
18
+ import { anyApi, componentsGeneric } from "convex/server";
19
+
20
+ const fullApi: ApiFromModules<{
21
+ lib: typeof lib;
22
+ }> = anyApi as any;
23
+
24
+ /**
25
+ * A utility for referencing Convex functions in your app's public API.
26
+ *
27
+ * Usage:
28
+ * ```js
29
+ * const myFunctionReference = api.myModule.myFunction;
30
+ * ```
31
+ */
32
+ export const api: FilterApi<
33
+ typeof fullApi,
34
+ FunctionReference<any, "public">
35
+ > = anyApi as any;
36
+
37
+ /**
38
+ * A utility for referencing Convex functions in your app's internal API.
39
+ *
40
+ * Usage:
41
+ * ```js
42
+ * const myFunctionReference = internal.myModule.myFunction;
43
+ * ```
44
+ */
45
+ export const internal: FilterApi<
46
+ typeof fullApi,
47
+ FunctionReference<any, "internal">
48
+ > = anyApi as any;
49
+
50
+ export const components = componentsGeneric() as unknown as {};