om-memory-system 3.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.
Files changed (221) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +587 -0
  3. package/dist/adapters/opencode/auto-capture-host.d.ts +3 -0
  4. package/dist/adapters/opencode/auto-capture-host.js +29 -0
  5. package/dist/adapters/opencode/auto-capture-summary.d.ts +4 -0
  6. package/dist/adapters/opencode/auto-capture-summary.js +147 -0
  7. package/dist/adapters/opencode/conversation.d.ts +2 -0
  8. package/dist/adapters/opencode/conversation.js +50 -0
  9. package/dist/adapters/opencode/user-prompt.d.ts +9 -0
  10. package/dist/adapters/opencode/user-prompt.js +26 -0
  11. package/dist/adapters/pi/capture.d.ts +41 -0
  12. package/dist/adapters/pi/capture.js +91 -0
  13. package/dist/adapters/pi/conversation.d.ts +38 -0
  14. package/dist/adapters/pi/conversation.js +118 -0
  15. package/dist/adapters/pi/extension.d.ts +18 -0
  16. package/dist/adapters/pi/extension.js +234 -0
  17. package/dist/adapters/pi/import-command.d.ts +29 -0
  18. package/dist/adapters/pi/import-command.js +232 -0
  19. package/dist/adapters/pi/profile.d.ts +39 -0
  20. package/dist/adapters/pi/profile.js +148 -0
  21. package/dist/adapters/pi/provider.d.ts +50 -0
  22. package/dist/adapters/pi/provider.js +77 -0
  23. package/dist/config.d.ts +290 -0
  24. package/dist/config.js +742 -0
  25. package/dist/core/capture-context.d.ts +4 -0
  26. package/dist/core/capture-context.js +132 -0
  27. package/dist/core/capture.d.ts +15 -0
  28. package/dist/core/capture.js +68 -0
  29. package/dist/core/extraction.d.ts +80 -0
  30. package/dist/core/extraction.js +140 -0
  31. package/dist/core/host.d.ts +52 -0
  32. package/dist/core/host.js +1 -0
  33. package/dist/core/memory-operations.d.ts +27 -0
  34. package/dist/core/memory-operations.js +247 -0
  35. package/dist/core/retrieval.d.ts +12 -0
  36. package/dist/core/retrieval.js +72 -0
  37. package/dist/importer/discovery.d.ts +31 -0
  38. package/dist/importer/discovery.js +88 -0
  39. package/dist/importer/importer.d.ts +87 -0
  40. package/dist/importer/importer.js +260 -0
  41. package/dist/importer/ledger.d.ts +44 -0
  42. package/dist/importer/ledger.js +137 -0
  43. package/dist/importer/session-loader.d.ts +19 -0
  44. package/dist/importer/session-loader.js +12 -0
  45. package/dist/index.d.ts +24 -0
  46. package/dist/index.js +601 -0
  47. package/dist/plugin.d.ts +9 -0
  48. package/dist/plugin.js +11 -0
  49. package/dist/services/ai/ai-provider-factory.d.ts +7 -0
  50. package/dist/services/ai/ai-provider-factory.js +41 -0
  51. package/dist/services/ai/api-key-placeholder.d.ts +1 -0
  52. package/dist/services/ai/api-key-placeholder.js +14 -0
  53. package/dist/services/ai/internal-capture-sessions.d.ts +6 -0
  54. package/dist/services/ai/internal-capture-sessions.js +33 -0
  55. package/dist/services/ai/opencode-diagnostics.d.ts +7 -0
  56. package/dist/services/ai/opencode-diagnostics.js +36 -0
  57. package/dist/services/ai/opencode-host-config.d.ts +10 -0
  58. package/dist/services/ai/opencode-host-config.js +51 -0
  59. package/dist/services/ai/opencode-provider-loader.d.ts +3 -0
  60. package/dist/services/ai/opencode-provider-loader.js +4 -0
  61. package/dist/services/ai/opencode-provider.d.ts +92 -0
  62. package/dist/services/ai/opencode-provider.js +419 -0
  63. package/dist/services/ai/opencode-sdk-client.d.ts +6 -0
  64. package/dist/services/ai/opencode-sdk-client.js +38 -0
  65. package/dist/services/ai/profile-llm-client.d.ts +2 -0
  66. package/dist/services/ai/profile-llm-client.js +27 -0
  67. package/dist/services/ai/provider-config.d.ts +17 -0
  68. package/dist/services/ai/provider-config.js +30 -0
  69. package/dist/services/ai/providers/anthropic-messages.d.ts +34 -0
  70. package/dist/services/ai/providers/anthropic-messages.js +220 -0
  71. package/dist/services/ai/providers/base-provider.d.ts +24 -0
  72. package/dist/services/ai/providers/base-provider.js +24 -0
  73. package/dist/services/ai/providers/google-gemini.d.ts +15 -0
  74. package/dist/services/ai/providers/google-gemini.js +228 -0
  75. package/dist/services/ai/providers/minimax.d.ts +35 -0
  76. package/dist/services/ai/providers/minimax.js +55 -0
  77. package/dist/services/ai/providers/openai-chat-completion.d.ts +22 -0
  78. package/dist/services/ai/providers/openai-chat-completion.js +387 -0
  79. package/dist/services/ai/providers/openai-responses.d.ts +13 -0
  80. package/dist/services/ai/providers/openai-responses.js +182 -0
  81. package/dist/services/ai/providers/orcarouter.d.ts +51 -0
  82. package/dist/services/ai/providers/orcarouter.js +66 -0
  83. package/dist/services/ai/session/ai-session-manager.d.ts +24 -0
  84. package/dist/services/ai/session/ai-session-manager.js +211 -0
  85. package/dist/services/ai/session/session-types.d.ts +42 -0
  86. package/dist/services/ai/session/session-types.js +1 -0
  87. package/dist/services/ai/tools/tool-schema.d.ts +40 -0
  88. package/dist/services/ai/tools/tool-schema.js +24 -0
  89. package/dist/services/ai/validators/user-profile-validator.d.ts +12 -0
  90. package/dist/services/ai/validators/user-profile-validator.js +114 -0
  91. package/dist/services/api-handlers.d.ts +186 -0
  92. package/dist/services/api-handlers.js +1284 -0
  93. package/dist/services/auth-token.d.ts +14 -0
  94. package/dist/services/auth-token.js +59 -0
  95. package/dist/services/auto-capture.d.ts +3 -0
  96. package/dist/services/auto-capture.js +127 -0
  97. package/dist/services/cleanup-service.d.ts +22 -0
  98. package/dist/services/cleanup-service.js +109 -0
  99. package/dist/services/client.d.ts +134 -0
  100. package/dist/services/client.js +327 -0
  101. package/dist/services/context.d.ts +10 -0
  102. package/dist/services/context.js +27 -0
  103. package/dist/services/cors.d.ts +12 -0
  104. package/dist/services/cors.js +52 -0
  105. package/dist/services/deduplication-service.d.ts +28 -0
  106. package/dist/services/deduplication-service.js +111 -0
  107. package/dist/services/embedding.d.ts +36 -0
  108. package/dist/services/embedding.js +200 -0
  109. package/dist/services/jsonc.d.ts +6 -0
  110. package/dist/services/jsonc.js +76 -0
  111. package/dist/services/language-detector.d.ts +2 -0
  112. package/dist/services/language-detector.js +33 -0
  113. package/dist/services/legacy-migration.d.ts +77 -0
  114. package/dist/services/legacy-migration.js +343 -0
  115. package/dist/services/logger.d.ts +1 -0
  116. package/dist/services/logger.js +119 -0
  117. package/dist/services/memory-portability-service.d.ts +37 -0
  118. package/dist/services/memory-portability-service.js +340 -0
  119. package/dist/services/memory-scope.d.ts +16 -0
  120. package/dist/services/memory-scope.js +43 -0
  121. package/dist/services/migration-service.d.ts +42 -0
  122. package/dist/services/migration-service.js +307 -0
  123. package/dist/services/onnxruntime-resolve.d.ts +24 -0
  124. package/dist/services/onnxruntime-resolve.js +174 -0
  125. package/dist/services/privacy.d.ts +26 -0
  126. package/dist/services/privacy.js +69 -0
  127. package/dist/services/request-timeouts.d.ts +9 -0
  128. package/dist/services/request-timeouts.js +11 -0
  129. package/dist/services/runtime-require.d.ts +17 -0
  130. package/dist/services/runtime-require.js +75 -0
  131. package/dist/services/secret-resolver.d.ts +1 -0
  132. package/dist/services/secret-resolver.js +65 -0
  133. package/dist/services/shard-inventory-service.d.ts +69 -0
  134. package/dist/services/shard-inventory-service.js +315 -0
  135. package/dist/services/shard-path-migration-service.d.ts +31 -0
  136. package/dist/services/shard-path-migration-service.js +367 -0
  137. package/dist/services/tag-prefix-migration.d.ts +60 -0
  138. package/dist/services/tag-prefix-migration.js +439 -0
  139. package/dist/services/tag-prefix-scan.d.ts +26 -0
  140. package/dist/services/tag-prefix-scan.js +91 -0
  141. package/dist/services/tags.d.ts +29 -0
  142. package/dist/services/tags.js +251 -0
  143. package/dist/services/turso/connection-manager.d.ts +15 -0
  144. package/dist/services/turso/connection-manager.js +163 -0
  145. package/dist/services/turso/cross-process-write-lock.d.ts +1 -0
  146. package/dist/services/turso/cross-process-write-lock.js +89 -0
  147. package/dist/services/turso/legacy-migrator.d.ts +1 -0
  148. package/dist/services/turso/legacy-migrator.js +540 -0
  149. package/dist/services/turso/lifecycle.d.ts +1 -0
  150. package/dist/services/turso/lifecycle.js +14 -0
  151. package/dist/services/turso/operation-lock.d.ts +2 -0
  152. package/dist/services/turso/operation-lock.js +61 -0
  153. package/dist/services/turso/ready.d.ts +2 -0
  154. package/dist/services/turso/ready.js +36 -0
  155. package/dist/services/turso/shard-manager.d.ts +38 -0
  156. package/dist/services/turso/shard-manager.js +496 -0
  157. package/dist/services/turso/sqlite-handle-release.d.ts +16 -0
  158. package/dist/services/turso/sqlite-handle-release.js +56 -0
  159. package/dist/services/turso/turso-db.d.ts +18 -0
  160. package/dist/services/turso/turso-db.js +53 -0
  161. package/dist/services/turso/types.d.ts +42 -0
  162. package/dist/services/turso/types.js +1 -0
  163. package/dist/services/turso/vector-search.d.ts +41 -0
  164. package/dist/services/turso/vector-search.js +384 -0
  165. package/dist/services/turso/vector-utils.d.ts +7 -0
  166. package/dist/services/turso/vector-utils.js +67 -0
  167. package/dist/services/user-memory-learning.d.ts +97 -0
  168. package/dist/services/user-memory-learning.js +673 -0
  169. package/dist/services/user-profile/ai-cleanup.d.ts +58 -0
  170. package/dist/services/user-profile/ai-cleanup.js +486 -0
  171. package/dist/services/user-profile/profile-context.d.ts +1 -0
  172. package/dist/services/user-profile/profile-context.js +105 -0
  173. package/dist/services/user-profile/profile-utils.d.ts +2 -0
  174. package/dist/services/user-profile/profile-utils.js +45 -0
  175. package/dist/services/user-profile/types.d.ts +92 -0
  176. package/dist/services/user-profile/types.js +1 -0
  177. package/dist/services/user-profile/user-profile-manager.d.ts +65 -0
  178. package/dist/services/user-profile/user-profile-manager.js +1660 -0
  179. package/dist/services/user-prompt/user-prompt-manager.d.ts +53 -0
  180. package/dist/services/user-prompt/user-prompt-manager.js +303 -0
  181. package/dist/services/web-api-auth.d.ts +3 -0
  182. package/dist/services/web-api-auth.js +25 -0
  183. package/dist/services/web-auth.d.ts +46 -0
  184. package/dist/services/web-auth.js +105 -0
  185. package/dist/services/web-server.d.ts +57 -0
  186. package/dist/services/web-server.js +659 -0
  187. package/dist/shared/api/index.d.ts +4 -0
  188. package/dist/shared/api/index.js +2 -0
  189. package/dist/shared/api/portability-schemas.d.ts +56 -0
  190. package/dist/shared/api/portability-schemas.js +39 -0
  191. package/dist/shared/api/schemas.d.ts +295 -0
  192. package/dist/shared/api/schemas.js +134 -0
  193. package/dist/shared/api/types.d.ts +28 -0
  194. package/dist/shared/api/types.js +1 -0
  195. package/dist/types/index.d.ts +27 -0
  196. package/dist/types/index.js +1 -0
  197. package/dist/utils/context-limit.d.ts +10 -0
  198. package/dist/utils/context-limit.js +43 -0
  199. package/dist/utils/math.d.ts +7 -0
  200. package/dist/utils/math.js +48 -0
  201. package/dist/utils/profile.d.ts +2 -0
  202. package/dist/utils/profile.js +15 -0
  203. package/dist/v2/adapter.d.ts +5 -0
  204. package/dist/v2/adapter.js +218 -0
  205. package/dist/v2/legacy-client.d.ts +15 -0
  206. package/dist/v2/legacy-client.js +257 -0
  207. package/dist/v2/memory-bridge.d.ts +18 -0
  208. package/dist/v2/memory-bridge.js +29 -0
  209. package/dist/v2/plugin.d.ts +3 -0
  210. package/dist/v2/plugin.js +24 -0
  211. package/dist/web/assets/index-DPjEpD1h.css +2 -0
  212. package/dist/web/assets/index-do26c4JJ.js +122 -0
  213. package/dist/web/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  214. package/dist/web/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  215. package/dist/web/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  216. package/dist/web/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  217. package/dist/web/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  218. package/dist/web/favicon.ico +0 -0
  219. package/dist/web/index.html +14 -0
  220. package/dist/web/omms-icon.png +0 -0
  221. package/package.json +138 -0
@@ -0,0 +1,14 @@
1
+ export declare const AUTH_HEADER = "x-omms-token";
2
+ /** Header sent by opencode-mem-era clients; still accepted. */
3
+ export declare const LEGACY_AUTH_HEADER = "x-opencode-mem-token";
4
+ /**
5
+ * A shared secret generated on first run and persisted to a local,
6
+ * user-only-readable file. Required on every /api/* request so that a
7
+ * malicious web page (which cannot read cross-origin/opaque responses,
8
+ * including the token injected into index.html) cannot drive the API via
9
+ * CSRF even though the CORS check alone lets no-Origin requests through.
10
+ */
11
+ export declare function getOrCreateAuthToken(): string;
12
+ /** The auth token from either the omms header or the legacy opencode-mem header. */
13
+ export declare function getRequestToken(req: Request): string | undefined;
14
+ export declare function isAuthorizedApiRequest(req: Request): boolean;
@@ -0,0 +1,59 @@
1
+ import { existsSync, readFileSync, writeFileSync, chmodSync, mkdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir, platform } from "node:os";
4
+ import { randomBytes } from "node:crypto";
5
+ const DATA_DIR = join(homedir(), ".omms");
6
+ const TOKEN_FILE = join(DATA_DIR, ".auth-token");
7
+ // Token written by opencode-mem builds; adopted once so open web UI tabs keep working.
8
+ const LEGACY_TOKEN_FILE = join(homedir(), ".opencode-mem", ".auth-token");
9
+ export const AUTH_HEADER = "x-omms-token";
10
+ /** Header sent by opencode-mem-era clients; still accepted. */
11
+ export const LEGACY_AUTH_HEADER = "x-opencode-mem-token";
12
+ let cachedToken = null;
13
+ function readToken(path) {
14
+ if (!existsSync(path))
15
+ return null;
16
+ const token = readFileSync(path, "utf-8").trim();
17
+ return token || null;
18
+ }
19
+ function writeToken(token) {
20
+ mkdirSync(DATA_DIR, { recursive: true, mode: 0o700 });
21
+ writeFileSync(TOKEN_FILE, token, { mode: 0o600 });
22
+ if (platform() !== "win32") {
23
+ try {
24
+ chmodSync(TOKEN_FILE, 0o600);
25
+ }
26
+ catch {
27
+ // best-effort; file was already created with mode 0o600 above
28
+ }
29
+ }
30
+ }
31
+ /**
32
+ * A shared secret generated on first run and persisted to a local,
33
+ * user-only-readable file. Required on every /api/* request so that a
34
+ * malicious web page (which cannot read cross-origin/opaque responses,
35
+ * including the token injected into index.html) cannot drive the API via
36
+ * CSRF even though the CORS check alone lets no-Origin requests through.
37
+ */
38
+ export function getOrCreateAuthToken() {
39
+ if (cachedToken) {
40
+ return cachedToken;
41
+ }
42
+ const existing = readToken(TOKEN_FILE);
43
+ if (existing) {
44
+ cachedToken = existing;
45
+ return cachedToken;
46
+ }
47
+ const token = readToken(LEGACY_TOKEN_FILE) ?? randomBytes(32).toString("hex");
48
+ writeToken(token);
49
+ cachedToken = token;
50
+ return cachedToken;
51
+ }
52
+ /** The auth token from either the omms header or the legacy opencode-mem header. */
53
+ export function getRequestToken(req) {
54
+ return (req.headers.get(AUTH_HEADER)?.trim() || req.headers.get(LEGACY_AUTH_HEADER)?.trim() || undefined);
55
+ }
56
+ export function isAuthorizedApiRequest(req) {
57
+ const token = getOrCreateAuthToken();
58
+ return getRequestToken(req) === token;
59
+ }
@@ -0,0 +1,3 @@
1
+ import type { AutoCaptureHost } from "../core/host.js";
2
+ export { buildBoundedSummaryPrompt, buildMarkdownContext, getAutoCaptureMarkdownBudget, } from "../core/capture-context.js";
3
+ export declare function performAutoCapture(host: AutoCaptureHost, sessionID: string, directory: string): Promise<void>;
@@ -0,0 +1,127 @@
1
+ import { CONFIG } from "../config.js";
2
+ import { captureConversation } from "../core/capture.js";
3
+ import { log } from "./logger.js";
4
+ import { userPromptManager } from "./user-prompt/user-prompt-manager.js";
5
+ export { buildBoundedSummaryPrompt, buildMarkdownContext, getAutoCaptureMarkdownBudget, } from "../core/capture-context.js";
6
+ const RETRY_BASE_DELAY_MS = 2000;
7
+ let isCaptureRunning = false;
8
+ async function notifySafely(host, notification) {
9
+ try {
10
+ await host.notify?.(notification);
11
+ }
12
+ catch {
13
+ // Host UI failures must never affect memory capture.
14
+ }
15
+ }
16
+ export async function performAutoCapture(host, sessionID, directory) {
17
+ if (isCaptureRunning)
18
+ return;
19
+ isCaptureRunning = true;
20
+ try {
21
+ const prompts = await userPromptManager.getUncapturedPromptsForSession(sessionID);
22
+ if (prompts.length === 0 || !host.isCaptureReady())
23
+ return;
24
+ const maxRetries = CONFIG.autoCaptureMaxRetries ?? 3;
25
+ for (const prompt of prompts) {
26
+ await capturePrompt(host, sessionID, directory, prompt, maxRetries);
27
+ }
28
+ }
29
+ finally {
30
+ isCaptureRunning = false;
31
+ }
32
+ }
33
+ async function capturePrompt(host, sessionID, directory, prompt, maxRetries) {
34
+ let claimedPromptId = null;
35
+ let attempt = prompt.capture_attempts || 0;
36
+ try {
37
+ if (!(await userPromptManager.claimPrompt(prompt.id)))
38
+ return;
39
+ claimedPromptId = prompt.id;
40
+ while (attempt < maxRetries) {
41
+ attempt++;
42
+ try {
43
+ const conversation = await host.getConversation(sessionID, prompt.messageId);
44
+ if (!conversation)
45
+ return;
46
+ if (conversation.textResponses.length === 0 && conversation.toolCalls.length === 0)
47
+ return;
48
+ const captureResult = await captureConversation({
49
+ host: host.host,
50
+ hostSessionId: sessionID,
51
+ sourceType: "live-capture",
52
+ projectDirectory: directory,
53
+ userPrompt: prompt.content,
54
+ promptId: prompt.id,
55
+ prompt: {
56
+ id: prompt.id,
57
+ providerId: prompt.providerId,
58
+ modelId: prompt.modelId,
59
+ },
60
+ ...conversation,
61
+ }, host);
62
+ if (captureResult.status === "skipped") {
63
+ log("Auto-capture skipped", {
64
+ promptId: prompt.id,
65
+ sessionID,
66
+ type: captureResult.type,
67
+ });
68
+ await userPromptManager.deletePrompt(prompt.id);
69
+ claimedPromptId = null;
70
+ return;
71
+ }
72
+ await userPromptManager.linkMemoryToPrompt(prompt.id, captureResult.memoryId);
73
+ await userPromptManager.markAsCaptured(prompt.id);
74
+ claimedPromptId = null;
75
+ log("Auto-capture memory persisted", {
76
+ promptId: prompt.id,
77
+ sessionID,
78
+ memoryId: captureResult.memoryId,
79
+ host: host.host,
80
+ });
81
+ if (CONFIG.showAutoCaptureToasts) {
82
+ await notifySafely(host, {
83
+ title: "Memory Captured",
84
+ message: "Project memory saved from conversation",
85
+ variant: "success",
86
+ duration: 3000,
87
+ });
88
+ }
89
+ return;
90
+ }
91
+ catch (error) {
92
+ const errMsg = error instanceof Error ? error.message : String(error);
93
+ await userPromptManager.recordFailedAttempt(prompt.id);
94
+ if (attempt < maxRetries) {
95
+ log(`Auto-capture warning (attempt ${attempt}/${maxRetries})`, { error: errMsg });
96
+ await new Promise((resolve) => setTimeout(resolve, RETRY_BASE_DELAY_MS * Math.pow(2, attempt - 1)));
97
+ }
98
+ else {
99
+ throw error;
100
+ }
101
+ }
102
+ }
103
+ }
104
+ catch (error) {
105
+ const errMsg = error instanceof Error ? error.message : String(error);
106
+ log(`Auto-capture final error after ${attempt} attempts`, { error: errMsg });
107
+ if (CONFIG.showErrorToasts) {
108
+ const shortReason = errMsg.length > 100 ? errMsg.substring(0, 100) + "..." : errMsg;
109
+ await notifySafely(host, {
110
+ title: "Auto Capture Failed",
111
+ message: shortReason,
112
+ variant: "error",
113
+ duration: 5000,
114
+ });
115
+ }
116
+ }
117
+ finally {
118
+ if (claimedPromptId !== null) {
119
+ try {
120
+ await userPromptManager.releaseClaim(claimedPromptId);
121
+ }
122
+ catch (releaseErr) {
123
+ log(`Failed to release captured=2 claim for prompt ${claimedPromptId}: ${releaseErr instanceof Error ? releaseErr.message : String(releaseErr)}`);
124
+ }
125
+ }
126
+ }
127
+ }
@@ -0,0 +1,22 @@
1
+ interface CleanupResult {
2
+ deletedCount: number;
3
+ userCount: number;
4
+ projectCount: number;
5
+ promptsDeleted: number;
6
+ linkedMemoriesDeleted: number;
7
+ pinnedMemoriesSkipped: number;
8
+ }
9
+ export declare class CleanupService {
10
+ private lastCleanupTime;
11
+ private isRunning;
12
+ shouldRunCleanup(): Promise<boolean>;
13
+ runCleanup(): Promise<CleanupResult>;
14
+ getStatus(): {
15
+ enabled: boolean;
16
+ retentionDays: number;
17
+ lastCleanupTime: number;
18
+ isRunning: boolean;
19
+ };
20
+ }
21
+ export declare const cleanupService: CleanupService;
22
+ export {};
@@ -0,0 +1,109 @@
1
+ import { tursoShardManager } from "./turso/shard-manager.js";
2
+ import { tursoVectorSearch } from "./turso/vector-search.js";
3
+ import { tursoConnectionManager } from "./turso/connection-manager.js";
4
+ import { ensureTursoReady } from "./turso/ready.js";
5
+ import { CONFIG } from "../config.js";
6
+ import { log } from "./logger.js";
7
+ import { userPromptManager } from "./user-prompt/user-prompt-manager.js";
8
+ export class CleanupService {
9
+ lastCleanupTime = 0;
10
+ isRunning = false;
11
+ async shouldRunCleanup() {
12
+ if (!CONFIG.autoCleanupEnabled)
13
+ return false;
14
+ if (this.isRunning)
15
+ return false;
16
+ const now = Date.now();
17
+ const oneDayMs = 24 * 60 * 60 * 1000;
18
+ if (now - this.lastCleanupTime < oneDayMs) {
19
+ return false;
20
+ }
21
+ return true;
22
+ }
23
+ async runCleanup() {
24
+ if (this.isRunning) {
25
+ throw new Error("Cleanup already running");
26
+ }
27
+ this.isRunning = true;
28
+ this.lastCleanupTime = Date.now();
29
+ try {
30
+ await ensureTursoReady();
31
+ const cutoffTime = Date.now() - CONFIG.autoCleanupRetentionDays * 24 * 60 * 60 * 1000;
32
+ const userShards = await tursoShardManager.getAllShards("user", "");
33
+ const projectShards = await tursoShardManager.getAllShards("project", "");
34
+ const allShards = [...userShards, ...projectShards];
35
+ const pinnedMemoryIds = new Set();
36
+ for (const shard of allShards) {
37
+ const db = await tursoConnectionManager.getConnection(shard.dbPath);
38
+ const pinned = await db.all(`SELECT id FROM memories WHERE is_pinned = 1`);
39
+ pinned.forEach((row) => pinnedMemoryIds.add(String(row.id)));
40
+ }
41
+ const promptCleanupResult = await userPromptManager.deleteOldPrompts(cutoffTime);
42
+ const linkedMemoryIds = new Set(promptCleanupResult.linkedMemoryIds);
43
+ const protectedMemoryIds = new Set([...pinnedMemoryIds, ...linkedMemoryIds]);
44
+ let totalDeleted = 0;
45
+ let userDeleted = 0;
46
+ let projectDeleted = 0;
47
+ const linkedMemoriesDeleted = 0;
48
+ let pinnedSkipped = 0;
49
+ for (const shard of allShards) {
50
+ const db = await tursoConnectionManager.getConnection(shard.dbPath);
51
+ const oldMemories = await db.all(`
52
+ SELECT id, container_tag, is_pinned FROM memories
53
+ WHERE updated_at < ?
54
+ `, [cutoffTime]);
55
+ for (const memory of oldMemories) {
56
+ try {
57
+ if (Number(memory.is_pinned) === 1) {
58
+ pinnedSkipped++;
59
+ continue;
60
+ }
61
+ if (protectedMemoryIds.has(String(memory.id))) {
62
+ continue;
63
+ }
64
+ await tursoVectorSearch.deleteVector(db, String(memory.id));
65
+ await tursoShardManager.decrementVectorCount(shard.id);
66
+ totalDeleted++;
67
+ if (String(memory.container_tag).includes("_user_")) {
68
+ userDeleted++;
69
+ }
70
+ else if (String(memory.container_tag).includes("_project_")) {
71
+ projectDeleted++;
72
+ }
73
+ }
74
+ catch (error) {
75
+ log("Cleanup: delete error", { memoryId: memory.id, error: String(error) });
76
+ }
77
+ }
78
+ }
79
+ const promptsDeleted = promptCleanupResult.deleted - linkedMemoryIds.size;
80
+ try {
81
+ await userPromptManager.vacuum();
82
+ log("Cleanup: VACUUM done", { db: "user-prompts.db" });
83
+ }
84
+ catch (err) {
85
+ log("Cleanup: VACUUM skipped (DB busy)", { error: String(err) });
86
+ }
87
+ return {
88
+ deletedCount: totalDeleted,
89
+ userCount: userDeleted,
90
+ projectCount: projectDeleted,
91
+ promptsDeleted,
92
+ linkedMemoriesDeleted,
93
+ pinnedMemoriesSkipped: pinnedSkipped,
94
+ };
95
+ }
96
+ finally {
97
+ this.isRunning = false;
98
+ }
99
+ }
100
+ getStatus() {
101
+ return {
102
+ enabled: CONFIG.autoCleanupEnabled,
103
+ retentionDays: CONFIG.autoCleanupRetentionDays,
104
+ lastCleanupTime: this.lastCleanupTime,
105
+ isRunning: this.isRunning,
106
+ };
107
+ }
108
+ }
109
+ export const cleanupService = new CleanupService();
@@ -0,0 +1,134 @@
1
+ import type { MemoryType } from "../types/index.js";
2
+ export type MemoryScope = "project" | "all-projects";
3
+ export declare class LocalMemoryClient {
4
+ private initPromise;
5
+ private isInitialized;
6
+ constructor();
7
+ private initialize;
8
+ warmup(progressCallback?: (progress: any) => void): Promise<void>;
9
+ isReady(): Promise<boolean>;
10
+ getEmbeddingInitError(): string | null;
11
+ getStatus(): {
12
+ dbConnected: boolean;
13
+ modelLoaded: boolean;
14
+ ready: boolean;
15
+ embeddingError: string | null;
16
+ };
17
+ reset(): void;
18
+ close(): Promise<void>;
19
+ searchMemories(query: string, containerTag: string, scope?: MemoryScope): Promise<{
20
+ warnings?: string[] | undefined;
21
+ success: true;
22
+ results: import("./turso/types.js").SearchResult[];
23
+ total: number;
24
+ timing: number;
25
+ error?: undefined;
26
+ } | {
27
+ success: false;
28
+ error: string;
29
+ results: never[];
30
+ total: number;
31
+ timing: number;
32
+ }>;
33
+ addMemory(content: string, containerTag: string, metadata?: {
34
+ type?: MemoryType;
35
+ source?: "manual" | "auto-capture" | "import" | "api";
36
+ tags?: string[];
37
+ tool?: string;
38
+ sessionID?: string;
39
+ reasoning?: string;
40
+ captureTimestamp?: number;
41
+ displayName?: string;
42
+ userName?: string;
43
+ userEmail?: string;
44
+ projectPath?: string;
45
+ projectName?: string;
46
+ gitRepoUrl?: string;
47
+ [key: string]: unknown;
48
+ }): Promise<{
49
+ success: true;
50
+ id: string;
51
+ } | {
52
+ success: false;
53
+ error: string;
54
+ }>;
55
+ deleteMemory(memoryId: string): Promise<{
56
+ success: boolean;
57
+ error?: undefined;
58
+ } | {
59
+ success: boolean;
60
+ error: string;
61
+ }>;
62
+ listMemories(containerTag: string, limit?: number, scope?: MemoryScope): Promise<{
63
+ success: true;
64
+ memories: {
65
+ id: any;
66
+ summary: any;
67
+ createdAt: string;
68
+ metadata: any;
69
+ displayName: any;
70
+ userName: any;
71
+ userEmail: any;
72
+ projectPath: any;
73
+ projectName: any;
74
+ gitRepoUrl: any;
75
+ }[];
76
+ pagination: {
77
+ currentPage: number;
78
+ totalItems: number;
79
+ totalPages: number;
80
+ };
81
+ error?: undefined;
82
+ } | {
83
+ success: false;
84
+ error: string;
85
+ memories: never[];
86
+ pagination: {
87
+ currentPage: number;
88
+ totalItems: number;
89
+ totalPages: number;
90
+ };
91
+ }>;
92
+ ensureStorageReady(): Promise<void>;
93
+ listShards(currentDirectory: string): Promise<import("./shard-inventory-service.js").ListShardsResult | {
94
+ success: false;
95
+ error: string;
96
+ }>;
97
+ migrateProjectPath(options: {
98
+ currentDirectory: string;
99
+ fromPath?: string;
100
+ fromHash?: string;
101
+ dryRun?: boolean;
102
+ allowLinkedSource?: boolean;
103
+ }): Promise<import("./shard-path-migration-service.js").PathMigrationResult>;
104
+ exportMemories(currentDirectory: string, outputPath: string): Promise<import("./memory-portability-service.js").ExportMemoriesResult>;
105
+ importMemories(currentDirectory: string, inputPath: string, dryRun?: boolean): Promise<import("./memory-portability-service.js").ImportMemoriesResult>;
106
+ searchMemoriesBySessionID(sessionID: string, containerTag: string, limit?: number): Promise<{
107
+ success: true;
108
+ results: {
109
+ id: any;
110
+ memory: any;
111
+ similarity: number;
112
+ tags: any;
113
+ metadata: any;
114
+ containerTag: any;
115
+ displayName: any;
116
+ userName: any;
117
+ userEmail: any;
118
+ projectPath: any;
119
+ projectName: any;
120
+ gitRepoUrl: any;
121
+ createdAt: any;
122
+ }[];
123
+ total: number;
124
+ timing: number;
125
+ error?: undefined;
126
+ } | {
127
+ success: false;
128
+ error: string;
129
+ results: never[];
130
+ total: number;
131
+ timing: number;
132
+ }>;
133
+ }
134
+ export declare const memoryClient: LocalMemoryClient;