opencode-memory-pro 1.3.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/utils.js ADDED
@@ -0,0 +1,214 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ export function expandHomePath(input) {
5
+ if (input === "~")
6
+ return homedir();
7
+ if (input.startsWith("~/"))
8
+ return join(homedir(), input.slice(2));
9
+ return input;
10
+ }
11
+ export function toNumber(value, fallback) {
12
+ if (typeof value === "number" && Number.isFinite(value))
13
+ return value;
14
+ if (typeof value === "string" && value.trim()) {
15
+ const parsed = Number(value);
16
+ if (Number.isFinite(parsed))
17
+ return parsed;
18
+ }
19
+ return fallback;
20
+ }
21
+ export function toBoolean(value, fallback) {
22
+ if (typeof value === "boolean")
23
+ return value;
24
+ if (typeof value === "string") {
25
+ const normalized = value.trim().toLowerCase();
26
+ if (["1", "true", "yes", "on"].includes(normalized))
27
+ return true;
28
+ if (["0", "false", "no", "off"].includes(normalized))
29
+ return false;
30
+ }
31
+ return fallback;
32
+ }
33
+ export function clamp(value, min, max) {
34
+ return Math.max(min, Math.min(max, value));
35
+ }
36
+ export function stableHash(input) {
37
+ return createHash("sha256").update(input, "utf8").digest("hex");
38
+ }
39
+ export function tokenize(text) {
40
+ return text
41
+ .toLowerCase()
42
+ .replace(/[^\p{L}\p{N}\s_-]+/gu, " ")
43
+ .split(/\s+/)
44
+ .filter((token) => token.length > 1);
45
+ }
46
+ export function cosineSimilarity(a, b) {
47
+ if (a.length === 0 || b.length === 0 || a.length !== b.length)
48
+ return 0;
49
+ let dot = 0;
50
+ let normA = 0;
51
+ let normB = 0;
52
+ for (let i = 0; i < a.length; i += 1) {
53
+ dot += a[i] * b[i];
54
+ normA += a[i] * a[i];
55
+ normB += b[i] * b[i];
56
+ }
57
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
58
+ return denom === 0 ? 0 : dot / denom;
59
+ }
60
+ export function generateId() {
61
+ return randomUUID();
62
+ }
63
+ export function parseJsonObject(value, fallback) {
64
+ if (!value)
65
+ return fallback;
66
+ try {
67
+ const parsed = JSON.parse(value);
68
+ return parsed;
69
+ }
70
+ catch {
71
+ return fallback;
72
+ }
73
+ }
74
+ const SYNTAX_PATTERNS = [
75
+ /SyntaxError/i,
76
+ /unexpected token/i,
77
+ /unexpected character/i,
78
+ /parse error/i,
79
+ /Invalid syntax/i,
80
+ /syntax error/i,
81
+ /unterminated string/i,
82
+ /unterminated/i,
83
+ /Expected .+ but found/i,
84
+ ];
85
+ const RUNTIME_PATTERNS = [
86
+ /ReferenceError/i,
87
+ /TypeError/i,
88
+ /RangeError/i,
89
+ /ReferenceError/i,
90
+ /^Error:/i,
91
+ /^Exception:/i,
92
+ /Cannot read property/i,
93
+ /is not a function/i,
94
+ /is not defined/i,
95
+ /Cannot read/i,
96
+ /is null/i,
97
+ /is not an object/i,
98
+ /unhandled promise rejection/i,
99
+ /UnhandledPromiseRejection/i,
100
+ ];
101
+ const LOGIC_PATTERNS = [
102
+ /AssertionError/i,
103
+ /assert.*failed/i,
104
+ /expected .+ but got/i,
105
+ /expected .+ received/i,
106
+ /test failed/i,
107
+ /assertion failed/i,
108
+ /does not equal/i,
109
+ /not equal/i,
110
+ ];
111
+ const RESOURCE_PATTERNS = [
112
+ /OutOfMemoryError/i,
113
+ /JavaScript heap out of memory/i,
114
+ /ETIMEDOUT/i,
115
+ /ECONNREFUSED/i,
116
+ /ECONNRESET/i,
117
+ /ENOMEM/i,
118
+ /EADDRINUSE/i,
119
+ /timeout/i,
120
+ /memory limit/i,
121
+ /disk full/i,
122
+ /no space left/i,
123
+ /resource.*exhausted/i,
124
+ ];
125
+ export function classifyFailure(errorMessage) {
126
+ const lowerMessage = errorMessage.toLowerCase();
127
+ for (const pattern of SYNTAX_PATTERNS) {
128
+ if (pattern.test(errorMessage)) {
129
+ return "syntax";
130
+ }
131
+ }
132
+ for (const pattern of RUNTIME_PATTERNS) {
133
+ if (pattern.test(errorMessage)) {
134
+ return "runtime";
135
+ }
136
+ }
137
+ for (const pattern of LOGIC_PATTERNS) {
138
+ if (pattern.test(errorMessage)) {
139
+ return "logic";
140
+ }
141
+ }
142
+ for (const pattern of RESOURCE_PATTERNS) {
143
+ if (pattern.test(errorMessage)) {
144
+ return "resource";
145
+ }
146
+ }
147
+ return "unknown";
148
+ }
149
+ const TYPE_CHECK_PATTERNS = [
150
+ /tsc|typescript.*error/i,
151
+ /type error/i,
152
+ /property .* does not exist/i,
153
+ /argument of type/i,
154
+ /Type '.*' is not assignable/i,
155
+ ];
156
+ const BUILD_PATTERNS = [
157
+ /build failed/i,
158
+ /compilation failed/i,
159
+ /webpack.*error/i,
160
+ /vite.*error/i,
161
+ /esbuild.*error/i,
162
+ /rollup.*error/i,
163
+ /failed to build/i,
164
+ ];
165
+ const TEST_PATTERNS = [
166
+ /test.*failed/i,
167
+ /\d+ passed, \d+ failed/i,
168
+ /PASS|FAIL/i,
169
+ /failed.*test/i,
170
+ ];
171
+ export function parseValidationOutput(output, type) {
172
+ const hasError = (pattern) => pattern.test(output);
173
+ const extractCount = (pattern) => {
174
+ const match = output.match(pattern);
175
+ return match ? parseInt(match[1], 10) : undefined;
176
+ };
177
+ switch (type) {
178
+ case "type-check": {
179
+ const errorCount = extractCount(/(\d+)\s+error/i) || extractCount(/Found (\d+) error/i);
180
+ if (errorCount !== undefined) {
181
+ return {
182
+ status: errorCount > 0 ? "fail" : "pass",
183
+ errorCount,
184
+ errorTypes: TYPE_CHECK_PATTERNS.filter(p => hasError(p)).map(p => p.source),
185
+ };
186
+ }
187
+ return { status: hasError(/error|fail/i) ? "fail" : "pass" };
188
+ }
189
+ case "build": {
190
+ const errorCount = extractCount(/(\d+)\s+error/i);
191
+ if (errorCount !== undefined) {
192
+ return {
193
+ status: errorCount > 0 ? "fail" : "pass",
194
+ errorCount,
195
+ };
196
+ }
197
+ return { status: hasError(/failed|error/i) ? "fail" : "pass" };
198
+ }
199
+ case "test": {
200
+ const passed = extractCount(/(\d+)\s+passed/i);
201
+ const failed = extractCount(/(\d+)\s+failed/i);
202
+ if (passed !== undefined || failed !== undefined) {
203
+ return {
204
+ status: (failed && failed > 0) ? "fail" : "pass",
205
+ passedCount: passed,
206
+ failedCount: failed,
207
+ };
208
+ }
209
+ return { status: hasError(/fail|error/i) ? "fail" : "pass" };
210
+ }
211
+ default:
212
+ return { status: "skipped" };
213
+ }
214
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "opencode-memory-pro",
3
+ "version": "1.3.0",
4
+ "description": "LanceDB-backed long-term memory provider for OpenCode — standalone fork of lancedb-opencode-pro with entity graph, lifecycle, and retention",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "types": "dist/index.d.ts",
14
+ "sideEffects": false,
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "keywords": [
21
+ "opencode",
22
+ "plugin",
23
+ "memory",
24
+ "lancedb",
25
+ "entity-graph",
26
+ "retention"
27
+ ],
28
+ "license": "MIT",
29
+ "engines": {
30
+ "node": ">=22"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public",
34
+ "registry": "https://registry.npmjs.org/"
35
+ },
36
+ "scripts": {
37
+ "test": "node --test",
38
+ "verify": "npm test && npm pack --dry-run"
39
+ },
40
+ "dependencies": {
41
+ "@lancedb/lancedb": "^0.38.0",
42
+ "@opencode-ai/plugin": "^1.4.10",
43
+ "@opencode-ai/sdk": "^1.4.10"
44
+ },
45
+ "devDependencies": {
46
+ "@types/node": "^22.13.9",
47
+ "typescript": "^5.8.2"
48
+ }
49
+ }