opencode-mem 2.8.1 → 2.8.3

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/README.md CHANGED
@@ -32,7 +32,7 @@ Add to your OpenCode configuration at `~/.config/opencode/opencode.json`:
32
32
  }
33
33
  ```
34
34
 
35
- The plugin downloads automatically on next startup. macOS users with Apple Silicon must install Homebrew SQLite and configure the custom path - see our Wiki for details.
35
+ The plugin downloads automatically on next startup. macOS users with Apple Silicon must install Homebrew SQLite and configure the custom path.
36
36
 
37
37
  ## Usage Examples
38
38
 
@@ -95,14 +95,7 @@ Configure at `~/.config/opencode/opencode-mem.jsonc`:
95
95
  "memoryApiKey": "env://OPENAI_API_KEY"
96
96
  ```
97
97
 
98
- Full documentation available in our [Configuration Guide](https://github.com/tickernelz/opencode-mem/wiki/Configuration-Guide).
99
-
100
- ## Documentation
101
-
102
- - [Installation Guide](https://github.com/tickernelz/opencode-mem/wiki/Installation-Guide)
103
- - [API Reference](https://github.com/tickernelz/opencode-mem/wiki/API-Reference)
104
- - [Troubleshooting](https://github.com/tickernelz/opencode-mem/wiki/Troubleshooting)
105
- - [Complete Wiki](https://github.com/tickernelz/opencode-mem/wiki)
98
+ Full documentation available in this README.
106
99
 
107
100
  ## Development & Contribution
108
101
 
@@ -122,7 +115,6 @@ This project is actively seeking contributions to become the definitive memory p
122
115
  MIT License - see LICENSE file
123
116
 
124
117
  - **Repository**: https://github.com/tickernelz/opencode-mem
125
- - **Wiki**: https://github.com/tickernelz/opencode-mem/wiki
126
118
  - **Issues**: https://github.com/tickernelz/opencode-mem/issues
127
119
  - **OpenCode Platform**: https://opencode.ai
128
120
 
@@ -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,MA+Z/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;AAkB/D,eAAO,MAAM,iBAAiB,EAAE,MA8a/B,CAAC"}
package/dist/index.js CHANGED
@@ -36,6 +36,20 @@ export const OpenCodeMemPlugin = async (ctx) => {
36
36
  .then((server) => {
37
37
  webServer = server;
38
38
  const url = webServer.getUrl();
39
+ webServer.setOnTakeoverCallback(async () => {
40
+ if (ctx.client?.tui) {
41
+ ctx.client.tui
42
+ .showToast({
43
+ body: {
44
+ title: "Memory Explorer",
45
+ message: "Took over web server ownership",
46
+ variant: "success",
47
+ duration: 3000,
48
+ },
49
+ })
50
+ .catch(() => { });
51
+ }
52
+ });
39
53
  if (webServer.isServerOwner()) {
40
54
  if (ctx.client?.tui) {
41
55
  ctx.client.tui
@@ -8,9 +8,15 @@ export declare class WebServer {
8
8
  private config;
9
9
  private isOwner;
10
10
  private startPromise;
11
+ private healthCheckInterval;
12
+ private onTakeoverCallback;
11
13
  constructor(config: WebServerConfig);
14
+ setOnTakeoverCallback(callback: () => Promise<void>): void;
12
15
  start(): Promise<void>;
13
16
  private _start;
17
+ private startHealthCheckLoop;
18
+ private stopHealthCheckLoop;
19
+ private attemptTakeover;
14
20
  stop(): Promise<void>;
15
21
  isRunning(): boolean;
16
22
  isServerOwner(): boolean;
@@ -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;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"}
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;IAClD,OAAO,CAAC,mBAAmB,CAA+B;IAC1D,OAAO,CAAC,kBAAkB,CAAsC;gBAEpD,MAAM,EAAE,eAAe;IAInC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YASd,MAAM;IA6EpB,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,mBAAmB;YAOb,eAAe;IA2BvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmC3B,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"}
@@ -8,9 +8,14 @@ export class WebServer {
8
8
  config;
9
9
  isOwner = false;
10
10
  startPromise = null;
11
+ healthCheckInterval = null;
12
+ onTakeoverCallback = null;
11
13
  constructor(config) {
12
14
  this.config = config;
13
15
  }
16
+ setOnTakeoverCallback(callback) {
17
+ this.onTakeoverCallback = callback;
18
+ }
14
19
  async start() {
15
20
  if (this.startPromise) {
16
21
  return this.startPromise;
@@ -73,6 +78,9 @@ export class WebServer {
73
78
  host: this.config.host,
74
79
  });
75
80
  await startedPromise;
81
+ if (!this.isOwner) {
82
+ this.startHealthCheckLoop();
83
+ }
76
84
  }
77
85
  catch (error) {
78
86
  this.isOwner = false;
@@ -84,7 +92,51 @@ export class WebServer {
84
92
  throw error;
85
93
  }
86
94
  }
95
+ startHealthCheckLoop() {
96
+ if (this.healthCheckInterval) {
97
+ return;
98
+ }
99
+ this.healthCheckInterval = setInterval(async () => {
100
+ const isAvailable = await this.checkServerAvailable();
101
+ if (!isAvailable) {
102
+ this.stopHealthCheckLoop();
103
+ await this.attemptTakeover();
104
+ }
105
+ }, 5000);
106
+ }
107
+ stopHealthCheckLoop() {
108
+ if (this.healthCheckInterval) {
109
+ clearInterval(this.healthCheckInterval);
110
+ this.healthCheckInterval = null;
111
+ }
112
+ }
113
+ async attemptTakeover() {
114
+ // prevent thundering herd: multiple non-owners racing to bind port
115
+ const jitterMs = 500 + Math.random() * 1000;
116
+ await new Promise((resolve) => setTimeout(resolve, jitterMs));
117
+ if (await this.checkServerAvailable()) {
118
+ this.startHealthCheckLoop();
119
+ return;
120
+ }
121
+ try {
122
+ await this._start();
123
+ this.isOwner = true;
124
+ log("Web server takeover successful", { port: this.config.port });
125
+ if (this.onTakeoverCallback) {
126
+ try {
127
+ await this.onTakeoverCallback();
128
+ }
129
+ catch (error) {
130
+ log("Takeover callback error", { error: String(error) });
131
+ }
132
+ }
133
+ }
134
+ catch (error) {
135
+ this.startHealthCheckLoop();
136
+ }
137
+ }
87
138
  async stop() {
139
+ this.stopHealthCheckLoop();
88
140
  if (!this.isOwner || !this.worker) {
89
141
  return;
90
142
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-mem",
3
- "version": "2.8.1",
3
+ "version": "2.8.3",
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",