opencode-mem 2.11.0 → 2.11.2
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/services/ai/providers/openai-chat-completion.d.ts.map +1 -1
- package/dist/services/ai/providers/openai-chat-completion.js +17 -1
- package/dist/services/sqlite/hnsw-index.d.ts +1 -0
- package/dist/services/sqlite/hnsw-index.d.ts.map +1 -1
- package/dist/services/sqlite/hnsw-index.js +16 -19
- package/package.json +2 -2
|
@@ -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;IAoCnC,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-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;CAyQ3B"}
|
|
@@ -115,7 +115,7 @@ export class OpenAIChatCompletionProvider extends BaseAIProvider {
|
|
|
115
115
|
model: this.config.model,
|
|
116
116
|
messages,
|
|
117
117
|
tools: [toolSchema],
|
|
118
|
-
tool_choice:
|
|
118
|
+
tool_choice: "auto",
|
|
119
119
|
};
|
|
120
120
|
if (this.config.memoryTemperature !== false) {
|
|
121
121
|
requestBody.temperature = this.config.memoryTemperature ?? 0.3;
|
|
@@ -154,7 +154,23 @@ export class OpenAIChatCompletionProvider extends BaseAIProvider {
|
|
|
154
154
|
};
|
|
155
155
|
}
|
|
156
156
|
const data = (await response.json());
|
|
157
|
+
if (data.status && data.msg) {
|
|
158
|
+
log("API returned error in response body", {
|
|
159
|
+
status: data.status,
|
|
160
|
+
msg: data.msg,
|
|
161
|
+
});
|
|
162
|
+
return {
|
|
163
|
+
success: false,
|
|
164
|
+
error: `API error: ${data.status} - ${data.msg}`,
|
|
165
|
+
iterations,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
157
168
|
if (!data.choices || !data.choices[0]) {
|
|
169
|
+
log("Invalid API response format", {
|
|
170
|
+
response: JSON.stringify(data).slice(0, 1000),
|
|
171
|
+
hasChoices: !!data.choices,
|
|
172
|
+
choicesLength: data.choices?.length,
|
|
173
|
+
});
|
|
158
174
|
return {
|
|
159
175
|
success: false,
|
|
160
176
|
error: "Invalid API response format",
|
|
@@ -13,6 +13,7 @@ export declare class HNSWIndex {
|
|
|
13
13
|
private initialized;
|
|
14
14
|
constructor(dimensions: number, indexPath: string);
|
|
15
15
|
private ensureInitialized;
|
|
16
|
+
private vectorToArray;
|
|
16
17
|
insert(id: string, vector: Float32Array): Promise<void>;
|
|
17
18
|
insertBatch(items: HNSWIndexData[]): Promise<void>;
|
|
18
19
|
search(queryVector: Float32Array, k: number): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hnsw-index.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/hnsw-index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hnsw-index.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/hnsw-index.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,WAAW,CAAkB;gBAEzB,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;YAKnC,iBAAiB;IAyC/B,OAAO,CAAC,aAAa;IAIf,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBvD,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBlD,MAAM,CAAC,WAAW,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAkBzF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB3B,QAAQ,IAAI,MAAM;CAGnB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,MAAM;IAO3B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS;IAWnE,gBAAgB,CACpB,EAAE,EAAE,GAAG,EACP,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAmBV,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAehF,sBAAsB,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CA0BpE"}
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
import { mkdirSync, existsSync, writeFileSync, readFileSync, unlinkSync, readdirSync,
|
|
1
|
+
import { mkdirSync, existsSync, writeFileSync, readFileSync, unlinkSync, readdirSync, } from "node:fs";
|
|
2
2
|
import { join, dirname, basename } from "node:path";
|
|
3
3
|
import { log } from "../logger.js";
|
|
4
4
|
import { CONFIG } from "../../config.js";
|
|
5
|
-
|
|
6
|
-
async function loadHNSWLib() {
|
|
7
|
-
if (!HNSWLib) {
|
|
8
|
-
const module = await import("hnswlib-wasm");
|
|
9
|
-
HNSWLib = module;
|
|
10
|
-
}
|
|
11
|
-
return HNSWLib;
|
|
12
|
-
}
|
|
5
|
+
import { HierarchicalNSW } from "hnswlib-node";
|
|
13
6
|
export class HNSWIndex {
|
|
14
7
|
index = null;
|
|
15
8
|
idMap = new Map();
|
|
@@ -26,15 +19,14 @@ export class HNSWIndex {
|
|
|
26
19
|
async ensureInitialized() {
|
|
27
20
|
if (this.initialized)
|
|
28
21
|
return;
|
|
29
|
-
const hnsw = await loadHNSWLib();
|
|
30
22
|
const dir = dirname(this.indexPath);
|
|
31
23
|
if (!existsSync(dir)) {
|
|
32
24
|
mkdirSync(dir, { recursive: true });
|
|
33
25
|
}
|
|
34
26
|
if (existsSync(this.indexPath)) {
|
|
35
27
|
try {
|
|
36
|
-
this.index = new
|
|
37
|
-
this.index.readIndex(this.indexPath);
|
|
28
|
+
this.index = new HierarchicalNSW("cosine", this.dimensions);
|
|
29
|
+
await this.index.readIndex(this.indexPath);
|
|
38
30
|
const metaPath = this.indexPath + ".meta";
|
|
39
31
|
if (existsSync(metaPath)) {
|
|
40
32
|
const meta = JSON.parse(readFileSync(metaPath, "utf-8"));
|
|
@@ -49,15 +41,20 @@ export class HNSWIndex {
|
|
|
49
41
|
path: this.indexPath,
|
|
50
42
|
error: String(error),
|
|
51
43
|
});
|
|
52
|
-
this.index = new
|
|
44
|
+
this.index = new HierarchicalNSW("cosine", this.dimensions);
|
|
45
|
+
await this.index.initIndex(this.maxElements);
|
|
53
46
|
}
|
|
54
47
|
}
|
|
55
48
|
else {
|
|
56
|
-
this.index = new
|
|
49
|
+
this.index = new HierarchicalNSW("cosine", this.dimensions);
|
|
50
|
+
await this.index.initIndex(this.maxElements);
|
|
57
51
|
log("HNSW index created", { path: this.indexPath, dimensions: this.dimensions });
|
|
58
52
|
}
|
|
59
53
|
this.initialized = true;
|
|
60
54
|
}
|
|
55
|
+
vectorToArray(vector) {
|
|
56
|
+
return Array.from(vector);
|
|
57
|
+
}
|
|
61
58
|
async insert(id, vector) {
|
|
62
59
|
await this.ensureInitialized();
|
|
63
60
|
if (this.reverseMap.has(id)) {
|
|
@@ -65,7 +62,7 @@ export class HNSWIndex {
|
|
|
65
62
|
this.index.markDelete(internalId);
|
|
66
63
|
}
|
|
67
64
|
const internalId = this.nextId++;
|
|
68
|
-
this.index.addPoint(vector, internalId);
|
|
65
|
+
await this.index.addPoint(this.vectorToArray(vector), internalId);
|
|
69
66
|
this.idMap.set(internalId, id);
|
|
70
67
|
this.reverseMap.set(id, internalId);
|
|
71
68
|
await this.save();
|
|
@@ -78,7 +75,7 @@ export class HNSWIndex {
|
|
|
78
75
|
this.index.markDelete(internalId);
|
|
79
76
|
}
|
|
80
77
|
const internalId = this.nextId++;
|
|
81
|
-
this.index.addPoint(item.vector, internalId);
|
|
78
|
+
await this.index.addPoint(this.vectorToArray(item.vector), internalId);
|
|
82
79
|
this.idMap.set(internalId, item.id);
|
|
83
80
|
this.reverseMap.set(item.id, internalId);
|
|
84
81
|
}
|
|
@@ -87,11 +84,11 @@ export class HNSWIndex {
|
|
|
87
84
|
async search(queryVector, k) {
|
|
88
85
|
await this.ensureInitialized();
|
|
89
86
|
try {
|
|
90
|
-
const results = this.index.searchKnn(queryVector, k);
|
|
87
|
+
const results = await this.index.searchKnn(this.vectorToArray(queryVector), k);
|
|
91
88
|
return results.neighbors
|
|
92
89
|
.map((internalId, idx) => ({
|
|
93
90
|
id: this.idMap.get(internalId) || "",
|
|
94
|
-
distance: results.distances[idx],
|
|
91
|
+
distance: results.distances[idx] ?? 0,
|
|
95
92
|
}))
|
|
96
93
|
.filter((r) => r.id);
|
|
97
94
|
}
|
|
@@ -117,7 +114,7 @@ export class HNSWIndex {
|
|
|
117
114
|
if (!existsSync(dir)) {
|
|
118
115
|
mkdirSync(dir, { recursive: true });
|
|
119
116
|
}
|
|
120
|
-
this.index.writeIndex(this.indexPath);
|
|
117
|
+
await this.index.writeIndex(this.indexPath);
|
|
121
118
|
const metaPath = this.indexPath + ".meta";
|
|
122
119
|
const meta = {
|
|
123
120
|
nextId: this.nextId,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-mem",
|
|
3
|
-
"version": "2.11.
|
|
3
|
+
"version": "2.11.2",
|
|
4
4
|
"description": "OpenCode plugin that gives coding agents persistent memory using local vector database",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/plugin.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@opencode-ai/plugin": "^1.0.162",
|
|
37
37
|
"@xenova/transformers": "^2.17.2",
|
|
38
38
|
"franc-min": "^6.2.0",
|
|
39
|
-
"hnswlib-
|
|
39
|
+
"hnswlib-node": "^3.0.0",
|
|
40
40
|
"iso-639-3": "^3.0.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|