opencode-mem 2.6.1 → 2.7.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/index.d.ts.map +1 -1
- package/dist/index.js +25 -9
- package/dist/services/ai/providers/openai-chat-completion.d.ts.map +1 -1
- package/dist/services/ai/providers/openai-chat-completion.js +0 -4
- package/dist/services/ai/providers/openai-responses.d.ts.map +1 -1
- package/dist/services/ai/providers/openai-responses.js +0 -10
- package/dist/services/api-handlers.d.ts.map +1 -1
- package/dist/services/api-handlers.js +2 -2
- package/dist/services/auto-capture.d.ts.map +1 -1
- package/dist/services/auto-capture.js +10 -20
- package/dist/services/cleanup-service.d.ts.map +1 -1
- package/dist/services/cleanup-service.js +0 -13
- package/dist/services/client.d.ts.map +1 -1
- package/dist/services/client.js +1 -4
- package/dist/services/deduplication-service.d.ts.map +1 -1
- package/dist/services/deduplication-service.js +4 -9
- package/dist/services/embedding.d.ts +3 -0
- package/dist/services/embedding.d.ts.map +1 -1
- package/dist/services/embedding.js +26 -6
- package/dist/services/logger.d.ts.map +1 -1
- package/dist/services/logger.js +17 -1
- package/dist/services/migration-service.d.ts.map +1 -1
- package/dist/services/migration-service.js +1 -9
- package/dist/services/sqlite/connection-manager.d.ts +1 -0
- package/dist/services/sqlite/connection-manager.d.ts.map +1 -1
- package/dist/services/sqlite/connection-manager.js +12 -6
- package/dist/services/sqlite/shard-manager.d.ts.map +1 -1
- package/dist/services/sqlite/shard-manager.js +2 -5
- package/dist/services/sqlite/vector-search.d.ts +2 -2
- package/dist/services/sqlite/vector-search.d.ts.map +1 -1
- package/dist/services/sqlite/vector-search.js +27 -14
- package/dist/services/user-memory-learning.d.ts.map +1 -1
- package/dist/services/user-memory-learning.js +6 -20
- package/dist/services/user-prompt/user-prompt-manager.d.ts +1 -0
- package/dist/services/user-prompt/user-prompt-manager.d.ts.map +1 -1
- package/dist/services/user-prompt/user-prompt-manager.js +6 -0
- package/dist/services/web-server.d.ts.map +1 -1
- package/dist/services/web-server.js +0 -1
- package/dist/web/app.js +1 -1
- package/dist/web/index.html +12 -1
- package/package.json +1 -1
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AAkB/D,eAAO,MAAM,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AAkB/D,eAAO,MAAM,iBAAiB,EAAE,MAiV/B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -14,15 +14,14 @@ export const OpenCodeMemPlugin = async (ctx) => {
|
|
|
14
14
|
const { directory } = ctx;
|
|
15
15
|
const tags = getTags(directory);
|
|
16
16
|
let webServer = null;
|
|
17
|
+
let idleTimeout = null;
|
|
17
18
|
if (!isConfigured()) {
|
|
18
|
-
log("Plugin disabled - memory system not configured");
|
|
19
19
|
}
|
|
20
20
|
const GLOBAL_PLUGIN_WARMUP_KEY = Symbol.for("opencode-mem.plugin.warmedup");
|
|
21
21
|
if (!globalThis[GLOBAL_PLUGIN_WARMUP_KEY] && isConfigured()) {
|
|
22
22
|
try {
|
|
23
23
|
await memoryClient.warmup();
|
|
24
24
|
globalThis[GLOBAL_PLUGIN_WARMUP_KEY] = true;
|
|
25
|
-
log("Plugin warmup completed");
|
|
26
25
|
}
|
|
27
26
|
catch (error) {
|
|
28
27
|
log("Plugin warmup failed", { error: String(error) });
|
|
@@ -219,7 +218,7 @@ export const OpenCodeMemPlugin = async (ctx) => {
|
|
|
219
218
|
return JSON.stringify({ success: false, error: "Private content blocked" });
|
|
220
219
|
const tagInfo = tags.project;
|
|
221
220
|
const parsedTags = args.tags
|
|
222
|
-
? args.tags.split(",").map((t) => t.trim())
|
|
221
|
+
? args.tags.split(",").map((t) => t.trim().toLowerCase())
|
|
223
222
|
: undefined;
|
|
224
223
|
const result = await memoryClient.addMemory(sanitizedContent, tagInfo.tag, {
|
|
225
224
|
type: args.type,
|
|
@@ -292,12 +291,29 @@ export const OpenCodeMemPlugin = async (ctx) => {
|
|
|
292
291
|
if (!isConfigured())
|
|
293
292
|
return;
|
|
294
293
|
const sessionID = event.properties?.sessionID;
|
|
295
|
-
if (sessionID)
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
294
|
+
if (!sessionID)
|
|
295
|
+
return;
|
|
296
|
+
if (idleTimeout)
|
|
297
|
+
clearTimeout(idleTimeout);
|
|
298
|
+
idleTimeout = setTimeout(async () => {
|
|
299
|
+
try {
|
|
300
|
+
await performAutoCapture(ctx, sessionID, directory);
|
|
301
|
+
if (webServer?.isServerOwner()) {
|
|
302
|
+
await performUserProfileLearning(ctx, directory);
|
|
303
|
+
const { cleanupService } = await import("./services/cleanup-service.js");
|
|
304
|
+
if (await cleanupService.shouldRunCleanup())
|
|
305
|
+
await cleanupService.runCleanup();
|
|
306
|
+
const { connectionManager } = await import("./services/sqlite/connection-manager.js");
|
|
307
|
+
connectionManager.checkpointAll();
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
log("Idle processing error", { error: String(error) });
|
|
312
|
+
}
|
|
313
|
+
finally {
|
|
314
|
+
idleTimeout = null;
|
|
315
|
+
}
|
|
316
|
+
}, 10000);
|
|
301
317
|
}
|
|
302
318
|
},
|
|
303
319
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-chat-completion.d.ts","sourceRoot":"","sources":["../../../../src/services/ai/providers/openai-chat-completion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAqBlE,qBAAa,4BAA6B,SAAQ,cAAc;IAC9D,OAAO,CAAC,gBAAgB,CAAmB;gBAE/B,MAAM,EAAE,GAAG,EAAE,gBAAgB,EAAE,gBAAgB;IAK3D,eAAe,IAAI,MAAM;IAIzB,eAAe,IAAI,OAAO;IAI1B,OAAO,CAAC,eAAe;IAqBvB,OAAO,CAAC,iCAAiC;
|
|
1
|
+
{"version":3,"file":"openai-chat-completion.d.ts","sourceRoot":"","sources":["../../../../src/services/ai/providers/openai-chat-completion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAqBlE,qBAAa,4BAA6B,SAAQ,cAAc;IAC9D,OAAO,CAAC,gBAAgB,CAAmB;gBAE/B,MAAM,EAAE,GAAG,EAAE,gBAAgB,EAAE,gBAAgB;IAK3D,eAAe,IAAI,MAAM;IAIzB,eAAe,IAAI,OAAO;IAI1B,OAAO,CAAC,eAAe;IAqBvB,OAAO,CAAC,iCAAiC;IAoCnC,eAAe,CACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC;CAyO3B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../../../../src/services/ai/providers/openai-responses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAsBvF,qBAAa,uBAAwB,SAAQ,cAAc;IACzD,OAAO,CAAC,gBAAgB,CAAmB;gBAE/B,MAAM,EAAE,GAAG,EAAE,gBAAgB,EAAE,gBAAgB;IAK3D,eAAe,IAAI,MAAM;IAIzB,eAAe,IAAI,OAAO;IAIpB,eAAe,CACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../../../../src/services/ai/providers/openai-responses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAsBvF,qBAAa,uBAAwB,SAAQ,cAAc;IACzD,OAAO,CAAC,gBAAgB,CAAmB;gBAE/B,MAAM,EAAE,GAAG,EAAE,gBAAgB,EAAE,gBAAgB;IAK3D,eAAe,IAAI,MAAM;IAIzB,eAAe,IAAI,OAAO;IAIpB,eAAe,CACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC;IAoH1B,OAAO,CAAC,eAAe;IA+BvB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,gBAAgB;CAsBzB"}
|
|
@@ -89,10 +89,6 @@ export class OpenAIResponsesProvider extends BaseAIProvider {
|
|
|
89
89
|
iterations,
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
|
-
log("No tool call found, retrying", {
|
|
93
|
-
iteration: iterations,
|
|
94
|
-
expectedTool: toolSchema.function.name,
|
|
95
|
-
});
|
|
96
92
|
currentPrompt = this.buildRetryPrompt(data);
|
|
97
93
|
}
|
|
98
94
|
catch (error) {
|
|
@@ -119,7 +115,6 @@ export class OpenAIResponsesProvider extends BaseAIProvider {
|
|
|
119
115
|
}
|
|
120
116
|
extractToolCall(data, expectedToolName) {
|
|
121
117
|
if (!data.output || !Array.isArray(data.output)) {
|
|
122
|
-
log("Extract tool call: no output array", { hasOutput: !!data.output });
|
|
123
118
|
return null;
|
|
124
119
|
}
|
|
125
120
|
for (const item of data.output) {
|
|
@@ -146,11 +141,6 @@ export class OpenAIResponsesProvider extends BaseAIProvider {
|
|
|
146
141
|
}
|
|
147
142
|
}
|
|
148
143
|
}
|
|
149
|
-
log("No matching function call found", {
|
|
150
|
-
expectedTool: expectedToolName,
|
|
151
|
-
foundTypes: data.output.map((item) => item.type),
|
|
152
|
-
foundNames: data.output.map((item) => item.name).filter(Boolean),
|
|
153
|
-
});
|
|
154
144
|
return null;
|
|
155
145
|
}
|
|
156
146
|
buildRetryPrompt(data) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-handlers.d.ts","sourceRoot":"","sources":["../../src/services/api-handlers.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,UAAU,WAAW,CAAC,CAAC,GAAG,GAAG;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,MAAM;IACd,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,OAAO;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,iBAAiB,CAAC,CAAC;IAC3B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAmDD,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAAE,OAAO,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,CAAC,CAiCnF;AAED,wBAAsB,kBAAkB,CACtC,GAAG,CAAC,EAAE,MAAM,EACZ,IAAI,GAAE,MAAU,EAChB,QAAQ,GAAE,MAAW,EACrB,cAAc,GAAE,OAAc,GAC7B,OAAO,CAAC,WAAW,CAAC,iBAAiB,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAsIvD;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,WAAW,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"api-handlers.d.ts","sourceRoot":"","sources":["../../src/services/api-handlers.ts"],"names":[],"mappings":"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"}
|
|
@@ -228,7 +228,7 @@ export async function handleAddMemory(data) {
|
|
|
228
228
|
return { success: false, error: "content and containerTag are required" };
|
|
229
229
|
}
|
|
230
230
|
await embeddingService.warmup();
|
|
231
|
-
const tags = data.tags || [];
|
|
231
|
+
const tags = (data.tags || []).map((t) => t.trim().toLowerCase());
|
|
232
232
|
const embeddingInput = tags.length > 0 ? `${data.content}\nTags: ${tags.join(", ")}` : data.content;
|
|
233
233
|
const vector = await embeddingService.embedWithTimeout(embeddingInput);
|
|
234
234
|
let tagsVector = undefined;
|
|
@@ -822,7 +822,7 @@ export async function handleRunTagMigration() {
|
|
|
822
822
|
let currentTags = m.tags
|
|
823
823
|
? m.tags
|
|
824
824
|
.split(",")
|
|
825
|
-
.map((t) => t.trim())
|
|
825
|
+
.map((t) => t.trim().toLowerCase())
|
|
826
826
|
.filter((t) => t)
|
|
827
827
|
: [];
|
|
828
828
|
if (currentTags.length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-capture.d.ts","sourceRoot":"","sources":["../../src/services/auto-capture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"auto-capture.d.ts","sourceRoot":"","sources":["../../src/services/auto-capture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAgBvD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA2Ff"}
|
|
@@ -4,12 +4,19 @@ import { log } from "./logger.js";
|
|
|
4
4
|
import { CONFIG } from "../config.js";
|
|
5
5
|
import { userPromptManager } from "./user-prompt/user-prompt-manager.js";
|
|
6
6
|
const MAX_TOOL_INPUT_LENGTH = 100;
|
|
7
|
+
let isCaptureRunning = false;
|
|
7
8
|
export async function performAutoCapture(ctx, sessionID, directory) {
|
|
9
|
+
if (isCaptureRunning)
|
|
10
|
+
return;
|
|
11
|
+
isCaptureRunning = true;
|
|
8
12
|
try {
|
|
9
13
|
const prompt = userPromptManager.getLastUncapturedPrompt(sessionID);
|
|
10
14
|
if (!prompt) {
|
|
11
15
|
return;
|
|
12
16
|
}
|
|
17
|
+
if (!userPromptManager.claimPrompt(prompt.id)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
13
20
|
if (!ctx.client) {
|
|
14
21
|
throw new Error("Client not available");
|
|
15
22
|
}
|
|
@@ -17,13 +24,11 @@ export async function performAutoCapture(ctx, sessionID, directory) {
|
|
|
17
24
|
path: { id: sessionID },
|
|
18
25
|
});
|
|
19
26
|
if (!response.data) {
|
|
20
|
-
log("Auto-capture: no messages in session", { sessionID });
|
|
21
27
|
return;
|
|
22
28
|
}
|
|
23
29
|
const messages = response.data;
|
|
24
30
|
const promptIndex = messages.findIndex((m) => m.info?.id === prompt.messageId);
|
|
25
31
|
if (promptIndex === -1) {
|
|
26
|
-
log("Auto-capture: prompt message not found", { sessionID, messageId: prompt.messageId });
|
|
27
32
|
return;
|
|
28
33
|
}
|
|
29
34
|
const aiMessages = messages.slice(promptIndex + 1);
|
|
@@ -39,7 +44,6 @@ export async function performAutoCapture(ctx, sessionID, directory) {
|
|
|
39
44
|
const context = buildMarkdownContext(prompt.content, textResponses, toolCalls, latestMemory);
|
|
40
45
|
const summaryResult = await generateSummary(context, sessionID, prompt.content);
|
|
41
46
|
if (!summaryResult || summaryResult.type === "skip") {
|
|
42
|
-
log("Auto-capture: skipped non-technical conversation", { sessionID });
|
|
43
47
|
userPromptManager.deletePrompt(prompt.id);
|
|
44
48
|
return;
|
|
45
49
|
}
|
|
@@ -74,20 +78,8 @@ export async function performAutoCapture(ctx, sessionID, directory) {
|
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (CONFIG.showErrorToasts) {
|
|
80
|
-
await ctx.client?.tui
|
|
81
|
-
.showToast({
|
|
82
|
-
body: {
|
|
83
|
-
title: "Auto-Capture Failed",
|
|
84
|
-
message: String(error),
|
|
85
|
-
variant: "error",
|
|
86
|
-
duration: 5000,
|
|
87
|
-
},
|
|
88
|
-
})
|
|
89
|
-
.catch(() => { });
|
|
90
|
-
}
|
|
81
|
+
finally {
|
|
82
|
+
isCaptureRunning = false;
|
|
91
83
|
}
|
|
92
84
|
}
|
|
93
85
|
function extractAIContent(messages) {
|
|
@@ -133,8 +125,6 @@ function extractAIContent(messages) {
|
|
|
133
125
|
async function getLatestProjectMemory(containerTag) {
|
|
134
126
|
try {
|
|
135
127
|
const result = await memoryClient.listMemories(containerTag, 1);
|
|
136
|
-
log("Auto-capture: latest memory list result", { result });
|
|
137
|
-
log("Auto-capture: container tag", { containerTag });
|
|
138
128
|
if (!result.success || result.memories.length === 0) {
|
|
139
129
|
return null;
|
|
140
130
|
}
|
|
@@ -258,6 +248,6 @@ Analyze this conversation. If it contains technical work (code, bugs, features,
|
|
|
258
248
|
return {
|
|
259
249
|
summary: result.data.summary,
|
|
260
250
|
type: result.data.type,
|
|
261
|
-
tags: result.data.tags || [],
|
|
251
|
+
tags: (result.data.tags || []).map((t) => t.toLowerCase().trim()),
|
|
262
252
|
};
|
|
263
253
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cleanup-service.d.ts","sourceRoot":"","sources":["../../src/services/cleanup-service.ts"],"names":[],"mappings":"AAOA,UAAU,aAAa;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,SAAS,CAAkB;IAE7B,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAcpC,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cleanup-service.d.ts","sourceRoot":"","sources":["../../src/services/cleanup-service.ts"],"names":[],"mappings":"AAOA,UAAU,aAAa;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,SAAS,CAAkB;IAE7B,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAcpC,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC;IAsF1C,SAAS;;;;;;CAQV;AAED,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
|
|
@@ -26,7 +26,6 @@ export class CleanupService {
|
|
|
26
26
|
this.isRunning = true;
|
|
27
27
|
this.lastCleanupTime = Date.now();
|
|
28
28
|
try {
|
|
29
|
-
log("Cleanup: starting", { retentionDays: CONFIG.autoCleanupRetentionDays });
|
|
30
29
|
const cutoffTime = Date.now() - CONFIG.autoCleanupRetentionDays * 24 * 60 * 60 * 1000;
|
|
31
30
|
const userShards = shardManager.getAllShards("user", "");
|
|
32
31
|
const projectShards = shardManager.getAllShards("project", "");
|
|
@@ -60,9 +59,6 @@ export class CleanupService {
|
|
|
60
59
|
continue;
|
|
61
60
|
}
|
|
62
61
|
if (protectedMemoryIds.has(memory.id)) {
|
|
63
|
-
if (linkedMemoryIds.has(memory.id)) {
|
|
64
|
-
log("Cleanup: skipped linked memory", { memoryId: memory.id });
|
|
65
|
-
}
|
|
66
62
|
continue;
|
|
67
63
|
}
|
|
68
64
|
vectorSearch.deleteVector(db, memory.id);
|
|
@@ -81,15 +77,6 @@ export class CleanupService {
|
|
|
81
77
|
}
|
|
82
78
|
}
|
|
83
79
|
const promptsDeleted = promptCleanupResult.deleted - linkedMemoryIds.size;
|
|
84
|
-
log("Cleanup: completed", {
|
|
85
|
-
totalDeleted,
|
|
86
|
-
userDeleted,
|
|
87
|
-
projectDeleted,
|
|
88
|
-
promptsDeleted,
|
|
89
|
-
linkedMemoriesProtected: linkedMemoryIds.size,
|
|
90
|
-
pinnedMemoriesSkipped: pinnedSkipped,
|
|
91
|
-
cutoffTime: new Date(cutoffTime).toISOString(),
|
|
92
|
-
});
|
|
93
80
|
return {
|
|
94
81
|
deletedCount: totalDeleted,
|
|
95
82
|
userCount: userDeleted,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/services/client.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AA4CpD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,aAAa,CAAkB;;YAIzB,UAAU;IAiBlB,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjE,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAIjC,SAAS,IAAI;QACX,WAAW,EAAE,OAAO,CAAC;QACrB,WAAW,EAAE,OAAO,CAAC;QACrB,KAAK,EAAE,OAAO,CAAC;KAChB;IAQD,KAAK,IAAI,IAAI;IAIP,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;;;;;;;;;;;;;IA6BlD,SAAS,CACb,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE;QACT,IAAI,CAAC,EAAE,UAAU,CAAC;QAClB,MAAM,CAAC,EAAE,QAAQ,GAAG,cAAc,GAAG,QAAQ,GAAG,KAAK,CAAC;QACtD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB;;;;;;;;;IA+DG,YAAY,CAAC,QAAQ,EAAE,MAAM;;;;;;;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/services/client.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AA4CpD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,aAAa,CAAkB;;YAIzB,UAAU;IAiBlB,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjE,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAIjC,SAAS,IAAI;QACX,WAAW,EAAE,OAAO,CAAC;QACrB,WAAW,EAAE,OAAO,CAAC;QACrB,KAAK,EAAE,OAAO,CAAC;KAChB;IAQD,KAAK,IAAI,IAAI;IAIP,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;;;;;;;;;;;;;IA6BlD,SAAS,CACb,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE;QACT,IAAI,CAAC,EAAE,UAAU,CAAC;QAClB,MAAM,CAAC,EAAE,QAAQ,GAAG,cAAc,GAAG,QAAQ,GAAG,KAAK,CAAC;QACtD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB;;;;;;;;;IA+DG,YAAY,CAAC,QAAQ,EAAE,MAAM;;;;;;;IA0B7B,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,SAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsDpD;AAED,eAAO,MAAM,YAAY,mBAA0B,CAAC"}
|
package/dist/services/client.js
CHANGED
|
@@ -84,10 +84,9 @@ export class LocalMemoryClient {
|
|
|
84
84
|
const { scope, hash } = extractScopeFromContainerTag(containerTag);
|
|
85
85
|
const shards = shardManager.getAllShards(scope, hash);
|
|
86
86
|
if (shards.length === 0) {
|
|
87
|
-
log("searchMemories: no shards found", { containerTag });
|
|
88
87
|
return { success: true, results: [], total: 0, timing: 0 };
|
|
89
88
|
}
|
|
90
|
-
const results = await vectorSearch.searchAcrossShards(shards, queryVector, containerTag, CONFIG.maxMemories, CONFIG.similarityThreshold);
|
|
89
|
+
const results = await vectorSearch.searchAcrossShards(shards, queryVector, containerTag, CONFIG.maxMemories, CONFIG.similarityThreshold, query);
|
|
91
90
|
return { success: true, results, total: results.length, timing: 0 };
|
|
92
91
|
}
|
|
93
92
|
catch (error) {
|
|
@@ -153,7 +152,6 @@ export class LocalMemoryClient {
|
|
|
153
152
|
return { success: true };
|
|
154
153
|
}
|
|
155
154
|
}
|
|
156
|
-
log("deleteMemory: not found", { memoryId });
|
|
157
155
|
return { success: false, error: "Memory not found" };
|
|
158
156
|
}
|
|
159
157
|
catch (error) {
|
|
@@ -168,7 +166,6 @@ export class LocalMemoryClient {
|
|
|
168
166
|
const { scope, hash } = extractScopeFromContainerTag(containerTag);
|
|
169
167
|
const shards = shardManager.getAllShards(scope, hash);
|
|
170
168
|
if (shards.length === 0) {
|
|
171
|
-
log("listMemories: no shards found", { containerTag });
|
|
172
169
|
return {
|
|
173
170
|
success: true,
|
|
174
171
|
memories: [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deduplication-service.d.ts","sourceRoot":"","sources":["../../src/services/deduplication-service.ts"],"names":[],"mappings":"AAMA,UAAU,cAAc;IACtB,cAAc,EAAE;QACd,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,UAAU,EAAE,KAAK,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ;AAED,UAAU,mBAAmB;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,mBAAmB,EAAE,cAAc,EAAE,CAAC;CACvC;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,SAAS,CAAkB;IAE7B,yBAAyB,IAAI,OAAO,CAAC,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"deduplication-service.d.ts","sourceRoot":"","sources":["../../src/services/deduplication-service.ts"],"names":[],"mappings":"AAMA,UAAU,cAAc;IACtB,cAAc,EAAE;QACd,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,UAAU,EAAE,KAAK,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ;AAED,UAAU,mBAAmB;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,mBAAmB,EAAE,cAAc,EAAE,CAAC;CACvC;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,SAAS,CAAkB;IAE7B,yBAAyB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAwG/D,OAAO,CAAC,gBAAgB;IAoBxB,SAAS;;;;;CAOV;AAED,eAAO,MAAM,oBAAoB,sBAA6B,CAAC"}
|
|
@@ -14,9 +14,6 @@ export class DeduplicationService {
|
|
|
14
14
|
}
|
|
15
15
|
this.isRunning = true;
|
|
16
16
|
try {
|
|
17
|
-
log("Deduplication: starting", {
|
|
18
|
-
threshold: CONFIG.deduplicationSimilarityThreshold,
|
|
19
|
-
});
|
|
20
17
|
const userShards = shardManager.getAllShards("user", "");
|
|
21
18
|
const projectShards = shardManager.getAllShards("project", "");
|
|
22
19
|
const allShards = [...userShards, ...projectShards];
|
|
@@ -53,9 +50,10 @@ export class DeduplicationService {
|
|
|
53
50
|
}
|
|
54
51
|
}
|
|
55
52
|
const uniqueMemories = Array.from(contentMap.values()).map((arr) => arr[0]);
|
|
53
|
+
const processedIds = new Set();
|
|
56
54
|
for (let i = 0; i < uniqueMemories.length; i++) {
|
|
57
55
|
const mem1 = uniqueMemories[i];
|
|
58
|
-
if (!mem1.vector)
|
|
56
|
+
if (!mem1.vector || processedIds.has(mem1.id))
|
|
59
57
|
continue;
|
|
60
58
|
const vector1 = new Float32Array(new Uint8Array(mem1.vector).buffer);
|
|
61
59
|
const similarGroup = {
|
|
@@ -69,7 +67,7 @@ export class DeduplicationService {
|
|
|
69
67
|
};
|
|
70
68
|
for (let j = i + 1; j < uniqueMemories.length; j++) {
|
|
71
69
|
const mem2 = uniqueMemories[j];
|
|
72
|
-
if (!mem2.vector)
|
|
70
|
+
if (!mem2.vector || processedIds.has(mem2.id))
|
|
73
71
|
continue;
|
|
74
72
|
if (mem1.container_tag !== mem2.container_tag)
|
|
75
73
|
continue;
|
|
@@ -81,6 +79,7 @@ export class DeduplicationService {
|
|
|
81
79
|
content: mem2.content,
|
|
82
80
|
similarity,
|
|
83
81
|
});
|
|
82
|
+
processedIds.add(mem2.id);
|
|
84
83
|
}
|
|
85
84
|
}
|
|
86
85
|
if (similarGroup.duplicates.length > 0) {
|
|
@@ -88,10 +87,6 @@ export class DeduplicationService {
|
|
|
88
87
|
}
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
|
-
log("Deduplication: completed", {
|
|
92
|
-
exactDeleted,
|
|
93
|
-
nearDuplicateGroupsFound: nearDuplicateGroups.length,
|
|
94
|
-
});
|
|
95
90
|
return {
|
|
96
91
|
exactDuplicatesDeleted: exactDeleted,
|
|
97
92
|
nearDuplicateGroups,
|
|
@@ -2,11 +2,14 @@ export declare class EmbeddingService {
|
|
|
2
2
|
private pipe;
|
|
3
3
|
private initPromise;
|
|
4
4
|
isWarmedUp: boolean;
|
|
5
|
+
private cache;
|
|
6
|
+
private cachedModelName;
|
|
5
7
|
static getInstance(): EmbeddingService;
|
|
6
8
|
warmup(progressCallback?: (progress: any) => void): Promise<void>;
|
|
7
9
|
private initializeModel;
|
|
8
10
|
embed(text: string): Promise<Float32Array>;
|
|
9
11
|
embedWithTimeout(text: string): Promise<Float32Array>;
|
|
12
|
+
clearCache(): void;
|
|
10
13
|
}
|
|
11
14
|
export declare const embeddingService: EmbeddingService;
|
|
12
15
|
//# sourceMappingURL=embedding.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../src/services/embedding.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../src/services/embedding.ts"],"names":[],"mappings":"AAoBA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,WAAW,CAA8B;IAC1C,UAAU,EAAE,OAAO,CAAS;IACnC,OAAO,CAAC,KAAK,CAAwC;IACrD,OAAO,CAAC,eAAe,CAAuB;IAE9C,MAAM,CAAC,WAAW,IAAI,gBAAgB;IAOhC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAOzD,eAAe;IAiBvB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAmD1C,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAI3D,UAAU,IAAI,IAAI;CAGnB;AAED,eAAO,MAAM,gBAAgB,kBAAiC,CAAC"}
|
|
@@ -7,6 +7,7 @@ env.allowRemoteModels = true;
|
|
|
7
7
|
env.cacheDir = join(CONFIG.storagePath, ".cache");
|
|
8
8
|
const TIMEOUT_MS = 30000;
|
|
9
9
|
const GLOBAL_EMBEDDING_KEY = Symbol.for("opencode-mem.embedding.instance");
|
|
10
|
+
const MAX_CACHE_SIZE = 100;
|
|
10
11
|
function withTimeout(promise, ms) {
|
|
11
12
|
return Promise.race([
|
|
12
13
|
promise,
|
|
@@ -17,6 +18,8 @@ export class EmbeddingService {
|
|
|
17
18
|
pipe = null;
|
|
18
19
|
initPromise = null;
|
|
19
20
|
isWarmedUp = false;
|
|
21
|
+
cache = new Map();
|
|
22
|
+
cachedModelName = null;
|
|
20
23
|
static getInstance() {
|
|
21
24
|
if (!globalThis[GLOBAL_EMBEDDING_KEY]) {
|
|
22
25
|
globalThis[GLOBAL_EMBEDDING_KEY] = new EmbeddingService();
|
|
@@ -34,16 +37,13 @@ export class EmbeddingService {
|
|
|
34
37
|
async initializeModel(progressCallback) {
|
|
35
38
|
try {
|
|
36
39
|
if (CONFIG.embeddingApiUrl && CONFIG.embeddingApiKey) {
|
|
37
|
-
log("Using OpenAI-compatible API for embeddings");
|
|
38
40
|
this.isWarmedUp = true;
|
|
39
41
|
return;
|
|
40
42
|
}
|
|
41
|
-
log("Downloading embedding model", { model: CONFIG.embeddingModel });
|
|
42
43
|
this.pipe = await pipeline("feature-extraction", CONFIG.embeddingModel, {
|
|
43
44
|
progress_callback: progressCallback,
|
|
44
45
|
});
|
|
45
46
|
this.isWarmedUp = true;
|
|
46
|
-
log("Embedding model ready");
|
|
47
47
|
}
|
|
48
48
|
catch (error) {
|
|
49
49
|
this.initPromise = null;
|
|
@@ -52,12 +52,20 @@ export class EmbeddingService {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
async embed(text) {
|
|
55
|
+
if (this.cachedModelName !== CONFIG.embeddingModel) {
|
|
56
|
+
this.clearCache();
|
|
57
|
+
this.cachedModelName = CONFIG.embeddingModel;
|
|
58
|
+
}
|
|
59
|
+
const cached = this.cache.get(text);
|
|
60
|
+
if (cached)
|
|
61
|
+
return cached;
|
|
55
62
|
if (!this.isWarmedUp && !this.initPromise) {
|
|
56
63
|
await this.warmup();
|
|
57
64
|
}
|
|
58
65
|
if (this.initPromise) {
|
|
59
66
|
await this.initPromise;
|
|
60
67
|
}
|
|
68
|
+
let result;
|
|
61
69
|
if (CONFIG.embeddingApiUrl && CONFIG.embeddingApiKey) {
|
|
62
70
|
const response = await fetch(`${CONFIG.embeddingApiUrl}/embeddings`, {
|
|
63
71
|
method: "POST",
|
|
@@ -74,13 +82,25 @@ export class EmbeddingService {
|
|
|
74
82
|
throw new Error(`API embedding failed: ${response.statusText}`);
|
|
75
83
|
}
|
|
76
84
|
const data = await response.json();
|
|
77
|
-
|
|
85
|
+
result = new Float32Array(data.data[0].embedding);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const output = await this.pipe(text, { pooling: "mean", normalize: true });
|
|
89
|
+
result = new Float32Array(output.data);
|
|
78
90
|
}
|
|
79
|
-
|
|
80
|
-
|
|
91
|
+
if (this.cache.size >= MAX_CACHE_SIZE) {
|
|
92
|
+
const firstKey = this.cache.keys().next().value;
|
|
93
|
+
if (firstKey !== undefined)
|
|
94
|
+
this.cache.delete(firstKey);
|
|
95
|
+
}
|
|
96
|
+
this.cache.set(text, result);
|
|
97
|
+
return result;
|
|
81
98
|
}
|
|
82
99
|
async embedWithTimeout(text) {
|
|
83
100
|
return withTimeout(this.embed(text), TIMEOUT_MS);
|
|
84
101
|
}
|
|
102
|
+
clearCache() {
|
|
103
|
+
this.cache.clear();
|
|
104
|
+
}
|
|
85
105
|
}
|
|
86
106
|
export const embeddingService = EmbeddingService.getInstance();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/services/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/services/logger.ts"],"names":[],"mappings":"AA0CA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,QAOlD"}
|
package/dist/services/logger.js
CHANGED
|
@@ -1,15 +1,31 @@
|
|
|
1
|
-
import { appendFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
1
|
+
import { appendFileSync, writeFileSync, existsSync, mkdirSync, statSync, renameSync, unlinkSync, } from "fs";
|
|
2
2
|
import { homedir } from "os";
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
const LOG_DIR = join(homedir(), ".opencode-mem");
|
|
5
5
|
const LOG_FILE = join(LOG_DIR, "opencode-mem.log");
|
|
6
|
+
const MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
6
7
|
const GLOBAL_LOGGER_KEY = Symbol.for("opencode-mem.logger.initialized");
|
|
8
|
+
function rotateLog() {
|
|
9
|
+
try {
|
|
10
|
+
if (!existsSync(LOG_FILE))
|
|
11
|
+
return;
|
|
12
|
+
const stats = statSync(LOG_FILE);
|
|
13
|
+
if (stats.size < MAX_LOG_SIZE)
|
|
14
|
+
return;
|
|
15
|
+
const oldLog = LOG_FILE + ".old";
|
|
16
|
+
if (existsSync(oldLog))
|
|
17
|
+
unlinkSync(oldLog);
|
|
18
|
+
renameSync(LOG_FILE, oldLog);
|
|
19
|
+
}
|
|
20
|
+
catch { }
|
|
21
|
+
}
|
|
7
22
|
function ensureLoggerInitialized() {
|
|
8
23
|
if (globalThis[GLOBAL_LOGGER_KEY])
|
|
9
24
|
return;
|
|
10
25
|
if (!existsSync(LOG_DIR)) {
|
|
11
26
|
mkdirSync(LOG_DIR, { recursive: true });
|
|
12
27
|
}
|
|
28
|
+
rotateLog();
|
|
13
29
|
writeFileSync(LOG_FILE, `\n--- Session started: ${new Date().toISOString()} ---\n`, {
|
|
14
30
|
flag: "a",
|
|
15
31
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-service.d.ts","sourceRoot":"","sources":["../../src/services/migration-service.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,KAAK,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,WAAW,GAAG,cAAc,GAAG,SAAS,GAAG,UAAU,CAAC;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,aAAa,GAAG,UAAU,CAAC;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,gBAAgB,CAAC,CAAwC;IAE3D,uBAAuB,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAoDrD,iBAAiB,CACrB,QAAQ,EAAE,aAAa,GAAG,UAAU,EACpC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,GACvD,OAAO,CAAC,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"migration-service.d.ts","sourceRoot":"","sources":["../../src/services/migration-service.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,KAAK,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,WAAW,GAAG,cAAc,GAAG,SAAS,GAAG,UAAU,CAAC;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,aAAa,GAAG,UAAU,CAAC;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,gBAAgB,CAAC,CAAwC;IAE3D,uBAAuB,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAoDrD,iBAAiB,CACrB,QAAQ,EAAE,aAAa,GAAG,UAAU,EACpC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,GACvD,OAAO,CAAC,eAAe,CAAC;YA2Cb,mBAAmB;YA8CnB,gBAAgB;IA2I9B,OAAO,CAAC,cAAc;IAMtB,SAAS;;;;;CAOV;AAED,eAAO,MAAM,gBAAgB,kBAAyB,CAAC"}
|
|
@@ -57,7 +57,6 @@ export class MigrationService {
|
|
|
57
57
|
this.progressCallback = progressCallback;
|
|
58
58
|
const startTime = Date.now();
|
|
59
59
|
try {
|
|
60
|
-
log("Migration: starting", { strategy, model: CONFIG.embeddingModel });
|
|
61
60
|
const mismatch = await this.detectDimensionMismatch();
|
|
62
61
|
if (!mismatch.needsMigration) {
|
|
63
62
|
return {
|
|
@@ -108,10 +107,6 @@ export class MigrationService {
|
|
|
108
107
|
});
|
|
109
108
|
shardManager.deleteShard(shardInfo.shardId);
|
|
110
109
|
deletedShards++;
|
|
111
|
-
log("Migration: deleted shard", {
|
|
112
|
-
shardId: shardInfo.shardId,
|
|
113
|
-
vectorCount: shardInfo.vectorCount,
|
|
114
|
-
});
|
|
115
110
|
}
|
|
116
111
|
catch (error) {
|
|
117
112
|
log("Migration: error deleting shard", {
|
|
@@ -135,6 +130,7 @@ export class MigrationService {
|
|
|
135
130
|
}
|
|
136
131
|
async reEmbedMigration(mismatch, startTime) {
|
|
137
132
|
await embeddingService.warmup();
|
|
133
|
+
embeddingService.clearCache();
|
|
138
134
|
const totalMemories = mismatch.shardMismatches.reduce((sum, s) => sum + s.vectorCount, 0);
|
|
139
135
|
this.reportProgress({
|
|
140
136
|
phase: "preparing",
|
|
@@ -217,10 +213,6 @@ export class MigrationService {
|
|
|
217
213
|
processedCount++;
|
|
218
214
|
}
|
|
219
215
|
}
|
|
220
|
-
log("Migration: re-embedded shard", {
|
|
221
|
-
shardId: shardInfo.shardId,
|
|
222
|
-
count: tempMemories.length,
|
|
223
|
-
});
|
|
224
216
|
}
|
|
225
217
|
catch (error) {
|
|
226
218
|
log("Migration: error processing shard", {
|
|
@@ -8,6 +8,7 @@ export declare class ConnectionManager {
|
|
|
8
8
|
getConnection(dbPath: string): Database;
|
|
9
9
|
closeConnection(dbPath: string): void;
|
|
10
10
|
closeAll(): void;
|
|
11
|
+
checkpointAll(): void;
|
|
11
12
|
}
|
|
12
13
|
export declare const connectionManager: ConnectionManager;
|
|
13
14
|
//# sourceMappingURL=connection-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/connection-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOtC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/connection-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOtC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,eAAe;IA2EvB,OAAO,CAAC,YAAY;IAwBpB,OAAO,CAAC,aAAa;IAoBrB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAmBvC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IASrC,QAAQ,IAAI,IAAI;IAYhB,aAAa,IAAI,IAAI;CAStB;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|
|
@@ -21,12 +21,10 @@ export class ConnectionManager {
|
|
|
21
21
|
}
|
|
22
22
|
try {
|
|
23
23
|
Database.setCustomSQLite(customPath);
|
|
24
|
-
log("Using custom SQLite library", { path: customPath });
|
|
25
24
|
}
|
|
26
25
|
catch (error) {
|
|
27
26
|
const errorStr = String(error);
|
|
28
27
|
if (errorStr.includes("SQLite already loaded")) {
|
|
29
|
-
log("SQLite already loaded, skipping custom path configuration");
|
|
30
28
|
}
|
|
31
29
|
else {
|
|
32
30
|
throw new Error(`Failed to load custom SQLite library: ${error}\n` + `Path: ${customPath}`);
|
|
@@ -48,12 +46,10 @@ export class ConnectionManager {
|
|
|
48
46
|
if (foundPath) {
|
|
49
47
|
try {
|
|
50
48
|
Database.setCustomSQLite(foundPath);
|
|
51
|
-
log("Auto-detected and using Homebrew SQLite", { path: foundPath });
|
|
52
49
|
}
|
|
53
50
|
catch (error) {
|
|
54
51
|
const errorStr = String(error);
|
|
55
52
|
if (errorStr.includes("SQLite already loaded")) {
|
|
56
|
-
log("SQLite already loaded, skipping auto-detected path configuration");
|
|
57
53
|
}
|
|
58
54
|
else {
|
|
59
55
|
throw new Error(`Failed to load Homebrew SQLite: ${error}\n` + `Path: ${foundPath}`);
|
|
@@ -81,6 +77,7 @@ export class ConnectionManager {
|
|
|
81
77
|
this.sqliteConfigured = true;
|
|
82
78
|
}
|
|
83
79
|
initDatabase(db) {
|
|
80
|
+
db.run("PRAGMA busy_timeout = 5000");
|
|
84
81
|
db.run("PRAGMA journal_mode = WAL");
|
|
85
82
|
db.run("PRAGMA synchronous = NORMAL");
|
|
86
83
|
db.run("PRAGMA cache_size = -64000");
|
|
@@ -105,12 +102,11 @@ export class ConnectionManager {
|
|
|
105
102
|
const hasTags = columns.some((c) => c.name === "tags");
|
|
106
103
|
if (!hasTags && columns.length > 0) {
|
|
107
104
|
db.run("ALTER TABLE memories ADD COLUMN tags TEXT");
|
|
108
|
-
log("Migrated schema: added tags column to memories table");
|
|
109
105
|
}
|
|
110
106
|
db.run(`
|
|
111
107
|
CREATE VIRTUAL TABLE IF NOT EXISTS vec_tags USING vec0(
|
|
112
108
|
memory_id TEXT PRIMARY KEY,
|
|
113
|
-
embedding float32[${CONFIG.embeddingDimensions}]
|
|
109
|
+
embedding float32[${CONFIG.embeddingDimensions}] distance_metric=cosine
|
|
114
110
|
)
|
|
115
111
|
`);
|
|
116
112
|
}
|
|
@@ -152,5 +148,15 @@ export class ConnectionManager {
|
|
|
152
148
|
}
|
|
153
149
|
this.connections.clear();
|
|
154
150
|
}
|
|
151
|
+
checkpointAll() {
|
|
152
|
+
for (const [path, db] of this.connections) {
|
|
153
|
+
try {
|
|
154
|
+
db.run("PRAGMA wal_checkpoint(PASSIVE)");
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
log("Error checkpointing database", { path, error: String(error) });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
155
161
|
}
|
|
156
162
|
export const connectionManager = new ConnectionManager();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shard-manager.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/shard-manager.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAI5C,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAW;IAC7B,OAAO,CAAC,YAAY,CAAS;;IAQ7B,OAAO,CAAC,cAAc;IAqBtB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,iBAAiB;IAKzB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAsB9E,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE;IAgCvE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS;
|
|
1
|
+
{"version":3,"file":"shard-manager.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/shard-manager.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAI5C,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAW;IAC7B,OAAO,CAAC,YAAY,CAAS;;IAQ7B,OAAO,CAAC,cAAc;IAqBtB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,iBAAiB;IAKzB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAsB9E,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE;IAgCvE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS;IA2BxF,OAAO,CAAC,WAAW;IA2DnB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS;IAetE,OAAO,CAAC,iBAAiB;IAOzB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAO3C,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAO3C,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAkBhD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAqBnC;AAED,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
@@ -100,7 +100,6 @@ export class ShardManager {
|
|
|
100
100
|
const result = stmt.run(scope, scopeHash, shardIndex, storedPath, now);
|
|
101
101
|
const db = connectionManager.getConnection(fullPath);
|
|
102
102
|
this.initShardDb(db);
|
|
103
|
-
log("Shard created", { scope, scopeHash, shardIndex, fullPath });
|
|
104
103
|
return {
|
|
105
104
|
id: Number(result.lastInsertRowid),
|
|
106
105
|
scope,
|
|
@@ -150,13 +149,13 @@ export class ShardManager {
|
|
|
150
149
|
db.run(`
|
|
151
150
|
CREATE VIRTUAL TABLE IF NOT EXISTS vec_memories USING vec0(
|
|
152
151
|
memory_id TEXT PRIMARY KEY,
|
|
153
|
-
embedding float32[${CONFIG.embeddingDimensions}]
|
|
152
|
+
embedding float32[${CONFIG.embeddingDimensions}] distance_metric=cosine
|
|
154
153
|
)
|
|
155
154
|
`);
|
|
156
155
|
db.run(`
|
|
157
156
|
CREATE VIRTUAL TABLE IF NOT EXISTS vec_tags USING vec0(
|
|
158
157
|
memory_id TEXT PRIMARY KEY,
|
|
159
|
-
embedding float32[${CONFIG.embeddingDimensions}]
|
|
158
|
+
embedding float32[${CONFIG.embeddingDimensions}] distance_metric=cosine
|
|
160
159
|
)
|
|
161
160
|
`);
|
|
162
161
|
db.run(`CREATE INDEX IF NOT EXISTS idx_container_tag ON memories(container_tag)`);
|
|
@@ -180,7 +179,6 @@ export class ShardManager {
|
|
|
180
179
|
UPDATE shards SET is_active = 0 WHERE id = ?
|
|
181
180
|
`);
|
|
182
181
|
stmt.run(shardId);
|
|
183
|
-
log("Shard marked read-only", { shardId });
|
|
184
182
|
}
|
|
185
183
|
incrementVectorCount(shardId) {
|
|
186
184
|
const stmt = this.metadataDb.prepare(`
|
|
@@ -228,7 +226,6 @@ export class ShardManager {
|
|
|
228
226
|
}
|
|
229
227
|
const deleteStmt = this.metadataDb.prepare(`DELETE FROM shards WHERE id = ?`);
|
|
230
228
|
deleteStmt.run(shardId);
|
|
231
|
-
log("Shard deleted", { shardId, dbPath: fullPath });
|
|
232
229
|
}
|
|
233
230
|
}
|
|
234
231
|
}
|
|
@@ -2,8 +2,8 @@ import { Database } from "bun:sqlite";
|
|
|
2
2
|
import type { MemoryRecord, SearchResult, ShardInfo } from "./types.js";
|
|
3
3
|
export declare class VectorSearch {
|
|
4
4
|
insertVector(db: Database, record: MemoryRecord): void;
|
|
5
|
-
searchInShard(shard: ShardInfo, queryVector: Float32Array, containerTag: string, limit: number): SearchResult[];
|
|
6
|
-
searchAcrossShards(shards: ShardInfo[], queryVector: Float32Array, containerTag: string, limit: number, similarityThreshold: number): Promise<SearchResult[]>;
|
|
5
|
+
searchInShard(shard: ShardInfo, queryVector: Float32Array, containerTag: string, limit: number, queryText?: string): SearchResult[];
|
|
6
|
+
searchAcrossShards(shards: ShardInfo[], queryVector: Float32Array, containerTag: string, limit: number, similarityThreshold: number, queryText?: string): Promise<SearchResult[]>;
|
|
7
7
|
deleteVector(db: Database, memoryId: string): void;
|
|
8
8
|
listMemories(db: Database, containerTag: string, limit: number): any[];
|
|
9
9
|
getAllMemories(db: Database): any[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vector-search.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/vector-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExE,qBAAa,YAAY;IACvB,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI;IA0CtD,aAAa,CACX,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,YAAY,EACzB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"vector-search.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/vector-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExE,qBAAa,YAAY;IACvB,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI;IA0CtD,aAAa,CACX,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,YAAY,EACzB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,YAAY,EAAE;IA0FX,kBAAkB,CACtB,MAAM,EAAE,SAAS,EAAE,EACnB,WAAW,EAAE,YAAY,EACzB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,mBAAmB,EAAE,MAAM,EAC3B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC;IAiB1B,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAMlD,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE;IAWtE,cAAc,CAAC,EAAE,EAAE,QAAQ,GAAG,GAAG,EAAE;IAKnC,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAKzD,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAMxD,eAAe,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM;IAMrC,eAAe,CAAC,EAAE,EAAE,QAAQ,GAAG,GAAG,EAAE;IAepC,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK/C,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;CAIlD;AAED,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
@@ -23,7 +23,7 @@ export class VectorSearch {
|
|
|
23
23
|
insertTagsVec.run(record.id, tagsVectorBuffer);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
searchInShard(shard, queryVector, containerTag, limit) {
|
|
26
|
+
searchInShard(shard, queryVector, containerTag, limit, queryText) {
|
|
27
27
|
const db = connectionManager.getConnection(shard.dbPath);
|
|
28
28
|
const queryBuffer = new Uint8Array(queryVector.buffer);
|
|
29
29
|
const contentResults = db
|
|
@@ -42,11 +42,11 @@ export class VectorSearch {
|
|
|
42
42
|
.all(queryBuffer, limit * 4);
|
|
43
43
|
const scoreMap = new Map();
|
|
44
44
|
for (const r of contentResults) {
|
|
45
|
-
scoreMap.set(r.memory_id, {
|
|
45
|
+
scoreMap.set(r.memory_id, { contentSim: 1 - r.distance, tagsSim: 0 });
|
|
46
46
|
}
|
|
47
47
|
for (const r of tagsResults) {
|
|
48
|
-
const entry = scoreMap.get(r.memory_id) || {
|
|
49
|
-
entry.
|
|
48
|
+
const entry = scoreMap.get(r.memory_id) || { contentSim: 0, tagsSim: 0 };
|
|
49
|
+
entry.tagsSim = 1 - r.distance;
|
|
50
50
|
scoreMap.set(r.memory_id, entry);
|
|
51
51
|
}
|
|
52
52
|
const ids = Array.from(scoreMap.keys());
|
|
@@ -59,16 +59,28 @@ export class VectorSearch {
|
|
|
59
59
|
WHERE id IN (${placeholders}) AND container_tag = ?
|
|
60
60
|
`)
|
|
61
61
|
.all(...ids, containerTag);
|
|
62
|
+
const queryWords = queryText
|
|
63
|
+
? queryText
|
|
64
|
+
.toLowerCase()
|
|
65
|
+
.split(/[\s,]+/)
|
|
66
|
+
.filter((w) => w.length > 1)
|
|
67
|
+
: [];
|
|
62
68
|
return rows.map((row) => {
|
|
63
69
|
const scores = scoreMap.get(row.id);
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
|
|
70
|
+
const memoryTagsStr = row.tags || "";
|
|
71
|
+
const memoryTags = memoryTagsStr.split(",").map((t) => t.trim().toLowerCase());
|
|
72
|
+
let exactMatchBoost = 0;
|
|
73
|
+
if (queryWords.length > 0 && memoryTags.length > 0) {
|
|
74
|
+
const matches = queryWords.filter((w) => memoryTags.some((t) => t.includes(w) || w.includes(t))).length;
|
|
75
|
+
exactMatchBoost = matches / Math.max(queryWords.length, 1);
|
|
76
|
+
}
|
|
77
|
+
const tagSim = Math.max(scores.tagsSim, exactMatchBoost);
|
|
78
|
+
const similarity = tagSim * 0.8 + scores.contentSim * 0.2;
|
|
67
79
|
return {
|
|
68
80
|
id: row.id,
|
|
69
81
|
memory: row.content,
|
|
70
82
|
similarity,
|
|
71
|
-
tags:
|
|
83
|
+
tags: memoryTagsStr ? memoryTagsStr.split(",") : [],
|
|
72
84
|
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
73
85
|
containerTag: row.container_tag,
|
|
74
86
|
displayName: row.display_name,
|
|
@@ -81,17 +93,18 @@ export class VectorSearch {
|
|
|
81
93
|
};
|
|
82
94
|
});
|
|
83
95
|
}
|
|
84
|
-
async searchAcrossShards(shards, queryVector, containerTag, limit, similarityThreshold) {
|
|
85
|
-
const
|
|
86
|
-
for (const shard of shards) {
|
|
96
|
+
async searchAcrossShards(shards, queryVector, containerTag, limit, similarityThreshold, queryText) {
|
|
97
|
+
const shardPromises = shards.map(async (shard) => {
|
|
87
98
|
try {
|
|
88
|
-
|
|
89
|
-
allResults.push(...results);
|
|
99
|
+
return this.searchInShard(shard, queryVector, containerTag, limit, queryText);
|
|
90
100
|
}
|
|
91
101
|
catch (error) {
|
|
92
102
|
log("Shard search error", { shardId: shard.id, error: String(error) });
|
|
103
|
+
return [];
|
|
93
104
|
}
|
|
94
|
-
}
|
|
105
|
+
});
|
|
106
|
+
const resultsArray = await Promise.all(shardPromises);
|
|
107
|
+
const allResults = resultsArray.flat();
|
|
95
108
|
allResults.sort((a, b) => b.similarity - a.similarity);
|
|
96
109
|
return allResults.filter((r) => r.similarity >= similarityThreshold).slice(0, limit);
|
|
97
110
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-memory-learning.d.ts","sourceRoot":"","sources":["../../src/services/user-memory-learning.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"user-memory-learning.d.ts","sourceRoot":"","sources":["../../src/services/user-memory-learning.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAWvD,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAsEf"}
|
|
@@ -3,7 +3,11 @@ import { log } from "./logger.js";
|
|
|
3
3
|
import { CONFIG } from "../config.js";
|
|
4
4
|
import { userPromptManager } from "./user-prompt/user-prompt-manager.js";
|
|
5
5
|
import { userProfileManager } from "./user-profile/user-profile-manager.js";
|
|
6
|
+
let isLearningRunning = false;
|
|
6
7
|
export async function performUserProfileLearning(ctx, directory) {
|
|
8
|
+
if (isLearningRunning)
|
|
9
|
+
return;
|
|
10
|
+
isLearningRunning = true;
|
|
7
11
|
try {
|
|
8
12
|
const count = userPromptManager.countUnanalyzedForUserLearning();
|
|
9
13
|
const threshold = CONFIG.userProfileAnalysisInterval;
|
|
@@ -20,7 +24,6 @@ export async function performUserProfileLearning(ctx, directory) {
|
|
|
20
24
|
const context = buildUserAnalysisContext(prompts, existingProfile);
|
|
21
25
|
const updatedProfileData = await analyzeUserProfile(context, existingProfile);
|
|
22
26
|
if (!updatedProfileData) {
|
|
23
|
-
log("User memory learning: no profile updates", { promptCount: prompts.length });
|
|
24
27
|
userPromptManager.markMultipleAsUserLearningCaptured(prompts.map((p) => p.id));
|
|
25
28
|
return;
|
|
26
29
|
}
|
|
@@ -45,25 +48,8 @@ export async function performUserProfileLearning(ctx, directory) {
|
|
|
45
48
|
.catch(() => { });
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
log("User memory learning error", {
|
|
51
|
-
error: String(error),
|
|
52
|
-
stack: errorStack,
|
|
53
|
-
errorType: error instanceof Error ? error.constructor.name : typeof error,
|
|
54
|
-
});
|
|
55
|
-
if (CONFIG.showErrorToasts) {
|
|
56
|
-
await ctx.client?.tui
|
|
57
|
-
.showToast({
|
|
58
|
-
body: {
|
|
59
|
-
title: "User Profile Update Failed",
|
|
60
|
-
message: String(error),
|
|
61
|
-
variant: "error",
|
|
62
|
-
duration: 5000,
|
|
63
|
-
},
|
|
64
|
-
})
|
|
65
|
-
.catch(() => { });
|
|
66
|
-
}
|
|
51
|
+
finally {
|
|
52
|
+
isLearningRunning = false;
|
|
67
53
|
}
|
|
68
54
|
}
|
|
69
55
|
function generateChangeSummary(oldProfile, newProfile) {
|
|
@@ -18,6 +18,7 @@ export declare class UserPromptManager {
|
|
|
18
18
|
getLastUncapturedPrompt(sessionId: string): UserPrompt | null;
|
|
19
19
|
deletePrompt(promptId: string): void;
|
|
20
20
|
markAsCaptured(promptId: string): void;
|
|
21
|
+
claimPrompt(promptId: string): boolean;
|
|
21
22
|
countUncapturedPrompts(): number;
|
|
22
23
|
getUncapturedPrompts(limit: number): UserPrompt[];
|
|
23
24
|
markMultipleAsCaptured(promptIds: string[]): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-prompt-manager.d.ts","sourceRoot":"","sources":["../../../src/services/user-prompt/user-prompt-manager.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;IAQhC,OAAO,CAAC,YAAY;
|
|
1
|
+
{"version":3,"file":"user-prompt-manager.d.ts","sourceRoot":"","sources":["../../../src/services/user-prompt/user-prompt-manager.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;IAQhC,OAAO,CAAC,YAAY;IAiCpB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAa9F,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAc7D,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKtC,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAQtC,sBAAsB,IAAI,MAAM;IAMhC,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE;IAYjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAUjD,8BAA8B,IAAI,MAAM;IAQxC,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE;IAYtD,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKlD,kCAAkC,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAU7D,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE;IAiBpF,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK5D,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAOlD,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;IAgBtD,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,UAAU,EAAE;IAiBpF,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE;IAQ5C,OAAO,CAAC,WAAW;CAapB;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|
|
@@ -25,6 +25,7 @@ export class UserPromptManager {
|
|
|
25
25
|
linked_memory_id TEXT
|
|
26
26
|
)
|
|
27
27
|
`);
|
|
28
|
+
this.db.run("UPDATE user_prompts SET captured = 0 WHERE captured = 2");
|
|
28
29
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_session ON user_prompts(session_id)");
|
|
29
30
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_captured ON user_prompts(captured)");
|
|
30
31
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_created ON user_prompts(created_at DESC)");
|
|
@@ -62,6 +63,11 @@ export class UserPromptManager {
|
|
|
62
63
|
const stmt = this.db.prepare(`UPDATE user_prompts SET captured = 1 WHERE id = ?`);
|
|
63
64
|
stmt.run(promptId);
|
|
64
65
|
}
|
|
66
|
+
claimPrompt(promptId) {
|
|
67
|
+
const stmt = this.db.prepare(`UPDATE user_prompts SET captured = 2 WHERE id = ? AND captured = 0`);
|
|
68
|
+
const result = stmt.run(promptId);
|
|
69
|
+
return result.changes > 0;
|
|
70
|
+
}
|
|
65
71
|
countUncapturedPrompts() {
|
|
66
72
|
const stmt = this.db.prepare(`SELECT COUNT(*) as count FROM user_prompts WHERE captured = 0`);
|
|
67
73
|
const row = stmt.get();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-server.d.ts","sourceRoot":"","sources":["../../src/services/web-server.ts"],"names":[],"mappings":"AAOA,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAeD,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,YAAY,CAA8B;gBAEtC,MAAM,EAAE,eAAe;IAI7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YASd,MAAM;
|
|
1
|
+
{"version":3,"file":"web-server.d.ts","sourceRoot":"","sources":["../../src/services/web-server.ts"],"names":[],"mappings":"AAOA,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAeD,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,YAAY,CAA8B;gBAEtC,MAAM,EAAE,eAAe;IAI7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YASd,MAAM;IAyEd,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC3B,SAAS,IAAI,OAAO;IAIpB,aAAa,IAAI,OAAO;IAIxB,MAAM,IAAI,MAAM;IAIV,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;CAW/C;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CAIhF"}
|
package/dist/web/app.js
CHANGED
|
@@ -387,7 +387,7 @@ async function addMemory(e) {
|
|
|
387
387
|
|
|
388
388
|
const content = document.getElementById("add-content").value.trim();
|
|
389
389
|
const containerTag = document.getElementById("add-tag").value;
|
|
390
|
-
const type = document.getElementById("add-type").value
|
|
390
|
+
const type = document.getElementById("add-type").value;
|
|
391
391
|
const tagsStr = document.getElementById("add-tags").value.trim();
|
|
392
392
|
const tags = tagsStr
|
|
393
393
|
? tagsStr
|
package/dist/web/index.html
CHANGED
|
@@ -152,7 +152,18 @@
|
|
|
152
152
|
|
|
153
153
|
<div class="form-group">
|
|
154
154
|
<label>Type:</label>
|
|
155
|
-
<
|
|
155
|
+
<select id="add-type">
|
|
156
|
+
<option value="">other</option>
|
|
157
|
+
<option value="feature">feature</option>
|
|
158
|
+
<option value="bug-fix">bug-fix</option>
|
|
159
|
+
<option value="refactor">refactor</option>
|
|
160
|
+
<option value="architecture">architecture</option>
|
|
161
|
+
<option value="rule">rule</option>
|
|
162
|
+
<option value="documentation">documentation</option>
|
|
163
|
+
<option value="discussion">discussion</option>
|
|
164
|
+
<option value="analysis">analysis</option>
|
|
165
|
+
<option value="configuration">configuration</option>
|
|
166
|
+
</select>
|
|
156
167
|
</div>
|
|
157
168
|
|
|
158
169
|
<div class="form-group">
|