opencode-mem 2.8.2 → 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.
@@ -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.2",
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",