opencode-mem 2.3.3 → 2.3.4

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.
@@ -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;AA0C/D,eAAO,MAAM,iBAAiB,EAAE,MAyhB/B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AA0C/D,eAAO,MAAM,iBAAiB,EAAE,MA0e/B,CAAC"}
package/dist/index.js CHANGED
@@ -37,6 +37,17 @@ export const OpenCodeMemPlugin = async (ctx) => {
37
37
  if (!isConfigured()) {
38
38
  log("Plugin disabled - memory system not configured");
39
39
  }
40
+ const GLOBAL_PLUGIN_WARMUP_KEY = Symbol.for("opencode-mem.plugin.warmedup");
41
+ if (!globalThis[GLOBAL_PLUGIN_WARMUP_KEY] && isConfigured()) {
42
+ try {
43
+ await memoryClient.warmup();
44
+ globalThis[GLOBAL_PLUGIN_WARMUP_KEY] = true;
45
+ log("Plugin warmup completed");
46
+ }
47
+ catch (error) {
48
+ log("Plugin warmup failed", { error: String(error) });
49
+ }
50
+ }
40
51
  if (CONFIG.webServerEnabled) {
41
52
  startWebServer({
42
53
  port: CONFIG.webServerPort,
@@ -132,58 +143,6 @@ export const OpenCodeMemPlugin = async (ctx) => {
132
143
  const isFirstMessage = !injectedSessions.has(input.sessionID);
133
144
  if (isFirstMessage) {
134
145
  injectedSessions.add(input.sessionID);
135
- const needsWarmup = !(await memoryClient.isReady());
136
- if (needsWarmup) {
137
- if (ctx.client?.tui) {
138
- await ctx.client.tui
139
- .showToast({
140
- body: {
141
- title: "Memory System",
142
- message: "Initializing (first time: 30-60s)...",
143
- variant: "info",
144
- duration: 5000,
145
- },
146
- })
147
- .catch(() => { });
148
- }
149
- try {
150
- await memoryClient.warmup();
151
- if (ctx.client?.tui) {
152
- const autoCaptureStatus = CONFIG.autoCaptureEnabled &&
153
- CONFIG.memoryModel &&
154
- CONFIG.memoryApiUrl &&
155
- CONFIG.memoryApiKey
156
- ? "Auto-capture: enabled"
157
- : "Auto-capture: disabled";
158
- await ctx.client.tui
159
- .showToast({
160
- body: {
161
- title: "Memory System Ready!",
162
- message: autoCaptureStatus,
163
- variant: CONFIG.autoCaptureEnabled ? "success" : "warning",
164
- duration: 3000,
165
- },
166
- })
167
- .catch(() => { });
168
- }
169
- }
170
- catch (warmupError) {
171
- log("Warmup failed", { error: String(warmupError) });
172
- if (ctx.client?.tui) {
173
- await ctx.client.tui
174
- .showToast({
175
- body: {
176
- title: "Memory System Error",
177
- message: `Failed to initialize: ${String(warmupError)}`,
178
- variant: "error",
179
- duration: 10000,
180
- },
181
- })
182
- .catch(() => { });
183
- }
184
- return;
185
- }
186
- }
187
146
  const projectMemoriesListResult = await memoryClient.listMemories(tags.project.tag, CONFIG.maxMemories);
188
147
  const projectMemoriesList = projectMemoriesListResult.success
189
148
  ? projectMemoriesListResult
@@ -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;AAcvD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA+Ff"}
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;AAcvD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAgGf"}
@@ -45,6 +45,7 @@ export async function performAutoCapture(ctx, sessionID, directory) {
45
45
  }
46
46
  const result = await memoryClient.addMemory(summaryResult.summary, tags.project.tag, {
47
47
  source: "auto-capture",
48
+ type: summaryResult.type,
48
49
  sessionID,
49
50
  promptId: prompt.id,
50
51
  captureTimestamp: Date.now(),
@@ -2,7 +2,9 @@ export declare class EmbeddingService {
2
2
  private pipe;
3
3
  private initPromise;
4
4
  isWarmedUp: boolean;
5
+ static getInstance(): EmbeddingService;
5
6
  warmup(progressCallback?: (progress: any) => void): Promise<void>;
7
+ private initializeModel;
6
8
  embed(text: string): Promise<Float32Array>;
7
9
  embedWithTimeout(text: string): Promise<Float32Array>;
8
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../src/services/embedding.ts"],"names":[],"mappings":"AAiBA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,WAAW,CAA8B;IAC1C,UAAU,EAAE,OAAO,CAAS;IAE7B,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BjE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAkC1C,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAG5D;AAED,eAAO,MAAM,gBAAgB,kBAAyB,CAAC"}
1
+ {"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../src/services/embedding.ts"],"names":[],"mappings":"AAkBA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,WAAW,CAA8B;IAC1C,UAAU,EAAE,OAAO,CAAS;IAEnC,MAAM,CAAC,WAAW,IAAI,gBAAgB;IAOhC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAQzD,eAAe;IAuBvB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAkC1C,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAG5D;AAED,eAAO,MAAM,gBAAgB,kBAAiC,CAAC"}
@@ -5,6 +5,7 @@ env.allowLocalModels = true;
5
5
  env.allowRemoteModels = true;
6
6
  env.cacheDir = CONFIG.storagePath + "/.cache";
7
7
  const TIMEOUT_MS = 30000;
8
+ const GLOBAL_EMBEDDING_KEY = Symbol.for("opencode-mem.embedding.instance");
8
9
  function withTimeout(promise, ms) {
9
10
  return Promise.race([
10
11
  promise,
@@ -15,32 +16,39 @@ export class EmbeddingService {
15
16
  pipe = null;
16
17
  initPromise = null;
17
18
  isWarmedUp = false;
19
+ static getInstance() {
20
+ if (!globalThis[GLOBAL_EMBEDDING_KEY]) {
21
+ globalThis[GLOBAL_EMBEDDING_KEY] = new EmbeddingService();
22
+ }
23
+ return globalThis[GLOBAL_EMBEDDING_KEY];
24
+ }
18
25
  async warmup(progressCallback) {
19
26
  if (this.isWarmedUp)
20
27
  return;
21
28
  if (this.initPromise)
22
29
  return this.initPromise;
23
- this.initPromise = (async () => {
24
- try {
25
- if (CONFIG.embeddingApiUrl && CONFIG.embeddingApiKey) {
26
- log("Using OpenAI-compatible API for embeddings");
27
- this.isWarmedUp = true;
28
- return;
29
- }
30
- log("Downloading embedding model", { model: CONFIG.embeddingModel });
31
- this.pipe = await pipeline("feature-extraction", CONFIG.embeddingModel, {
32
- progress_callback: progressCallback,
33
- });
30
+ this.initPromise = this.initializeModel(progressCallback);
31
+ return this.initPromise;
32
+ }
33
+ async initializeModel(progressCallback) {
34
+ try {
35
+ if (CONFIG.embeddingApiUrl && CONFIG.embeddingApiKey) {
36
+ log("Using OpenAI-compatible API for embeddings");
34
37
  this.isWarmedUp = true;
35
- log("Embedding model ready");
36
- }
37
- catch (error) {
38
- this.initPromise = null;
39
- log("Failed to initialize embedding model", { error: String(error) });
40
- throw error;
38
+ return;
41
39
  }
42
- })();
43
- return this.initPromise;
40
+ log("Downloading embedding model", { model: CONFIG.embeddingModel });
41
+ this.pipe = await pipeline("feature-extraction", CONFIG.embeddingModel, {
42
+ progress_callback: progressCallback,
43
+ });
44
+ this.isWarmedUp = true;
45
+ log("Embedding model ready");
46
+ }
47
+ catch (error) {
48
+ this.initPromise = null;
49
+ log("Failed to initialize embedding model", { error: String(error) });
50
+ throw error;
51
+ }
44
52
  }
45
53
  async embed(text) {
46
54
  if (!this.isWarmedUp && !this.initPromise) {
@@ -74,4 +82,4 @@ export class EmbeddingService {
74
82
  return withTimeout(this.embed(text), TIMEOUT_MS);
75
83
  }
76
84
  }
77
- export const embeddingService = new EmbeddingService();
85
+ export const embeddingService = EmbeddingService.getInstance();
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/services/logger.ts"],"names":[],"mappings":"AAaA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,QAMlD"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/services/logger.ts"],"names":[],"mappings":"AAkBA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,QAOlD"}
@@ -3,11 +3,18 @@ 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
- if (!existsSync(LOG_DIR)) {
7
- mkdirSync(LOG_DIR, { recursive: true });
6
+ const GLOBAL_LOGGER_KEY = Symbol.for("opencode-mem.logger.initialized");
7
+ function ensureLoggerInitialized() {
8
+ if (globalThis[GLOBAL_LOGGER_KEY])
9
+ return;
10
+ if (!existsSync(LOG_DIR)) {
11
+ mkdirSync(LOG_DIR, { recursive: true });
12
+ }
13
+ writeFileSync(LOG_FILE, `\n--- Session started: ${new Date().toISOString()} ---\n`, { flag: "a" });
14
+ globalThis[GLOBAL_LOGGER_KEY] = true;
8
15
  }
9
- writeFileSync(LOG_FILE, `\n--- Session started: ${new Date().toISOString()} ---\n`, { flag: "a" });
10
16
  export function log(message, data) {
17
+ ensureLoggerInitialized();
11
18
  const timestamp = new Date().toISOString();
12
19
  const line = data
13
20
  ? `[${timestamp}] ${message}: ${JSON.stringify(data)}\n`
package/dist/web/app.js CHANGED
@@ -413,7 +413,6 @@ function editMemory(id) {
413
413
  if (!memory) return;
414
414
 
415
415
  document.getElementById("edit-id").value = memory.id;
416
- document.getElementById("edit-type").value = memory.memoryType || "";
417
416
  document.getElementById("edit-content").value = memory.content;
418
417
 
419
418
  document.getElementById("edit-modal").classList.remove("hidden");
@@ -423,7 +422,6 @@ async function saveEdit(e) {
423
422
  e.preventDefault();
424
423
 
425
424
  const id = document.getElementById("edit-id").value;
426
- const type = document.getElementById("edit-type").value.trim();
427
425
  const content = document.getElementById("edit-content").value.trim();
428
426
 
429
427
  if (!content) {
@@ -434,7 +432,7 @@ async function saveEdit(e) {
434
432
  const result = await fetchAPI(`/api/memories/${id}`, {
435
433
  method: "PUT",
436
434
  headers: { "Content-Type": "application/json" },
437
- body: JSON.stringify({ content, type: type || undefined }),
435
+ body: JSON.stringify({ content }),
438
436
  });
439
437
 
440
438
  if (result.success) {
@@ -181,10 +181,6 @@
181
181
  </div>
182
182
  <form id="edit-form">
183
183
  <input type="hidden" id="edit-id" />
184
- <div class="form-group">
185
- <label>Type:</label>
186
- <input type="text" id="edit-type" />
187
- </div>
188
184
  <div class="form-group">
189
185
  <label>Content:</label>
190
186
  <textarea id="edit-content" rows="6" required></textarea>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-mem",
3
- "version": "2.3.3",
3
+ "version": "2.3.4",
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",