opencode-browser-annotation-plugin 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/dist/plugin.js +17 -16
  2. package/package.json +1 -1
package/dist/plugin.js CHANGED
@@ -97,14 +97,15 @@ async function readJsonBody(req, limitBytes = 2_000_000) {
97
97
  }
98
98
  function sendJson(res, status, body) {
99
99
  const payload = JSON.stringify(body);
100
- res.writeHead(status, {
101
- "content-type": "application/json",
102
- "content-length": Buffer.byteLength(payload),
103
- // The extension calls from a browser origin; allow it to read the response.
104
- "access-control-allow-origin": "*",
105
- "access-control-allow-headers": "content-type",
106
- "access-control-allow-methods": "POST, GET, OPTIONS",
107
- });
100
+ // Set headers individually and assign statusCode before end(). Combined
101
+ // writeHead(status, headers) is not reliably flushed by the Bun node:http
102
+ // compatibility layer that OpenCode runs under, which yields empty replies.
103
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
104
+ // The extension calls from a browser origin; allow it to read the response.
105
+ res.setHeader("Access-Control-Allow-Origin", "*");
106
+ res.setHeader("Access-Control-Allow-Headers", "content-type");
107
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
108
+ res.statusCode = status;
108
109
  res.end(payload);
109
110
  }
110
111
  export const BrowserAnnotationPlugin = async ({ client, directory }) => {
@@ -173,19 +174,22 @@ export const BrowserAnnotationPlugin = async ({ client, directory }) => {
173
174
  sendJson(res, 404, { ok: false, error: "Not found" });
174
175
  }
175
176
  function start() {
177
+ if (server)
178
+ return; // never double-listen (the plugin may init more than once)
176
179
  const s = createServer(handle);
180
+ server = s; // claim synchronously so a re-entrant start() is a no-op
177
181
  s.on("error", (error) => {
178
- if (error.code === "EADDRINUSE") {
179
- log("error", `Port ${port} on ${host} is already in use; annotation server not started.`);
180
- }
181
- else {
182
+ // Another instance already owns the port. Drop this half-open server so we
183
+ // don't leave a listener that resets connections without responding.
184
+ server = null;
185
+ s.close();
186
+ if (error.code !== "EADDRINUSE") {
182
187
  log("error", `Annotation server error: ${error.message}`);
183
188
  }
184
189
  });
185
190
  s.listen(port, host, () => {
186
191
  log("info", `Browser annotation server listening on http://${host}:${port}`);
187
192
  });
188
- server = s;
189
193
  }
190
194
  start();
191
195
  return {
@@ -198,9 +202,6 @@ export const BrowserAnnotationPlugin = async ({ client, directory }) => {
198
202
  if (event.properties.info.id === activeSessionID)
199
203
  activeSessionID = null;
200
204
  }
201
- else if (event.type === "server.connected" && !server) {
202
- start();
203
- }
204
205
  },
205
206
  };
206
207
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-browser-annotation-plugin",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Select an element in your browser, type an instruction, and send it to your OpenCode agent over a loopback + SSH tunnel. Text and element metadata only (no screenshots).",
5
5
  "keywords": [
6
6
  "opencode",