@vymalo/opencode-browser 0.7.2 → 0.7.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
@@ -12,7 +12,8 @@ can call and hosts a localhost WebSocket **bridge**. A companion **browser exten
12
12
  (Chromium MV3 + Firefox) connects to the bridge and drives real tabs.
13
13
 
14
14
  > Browser extensions can't host servers, so the plugin is the server and the extension dials
15
- > out to it. The plugin runs on Bun (inside OpenCode) and serves the bridge with `Bun.serve`.
15
+ > out to it. The bridge is served with the `ws` package, which runs under both runtimes OpenCode
16
+ > uses — Bun (CLI / `opencode web`) and Node (the desktop app) — so it works in either.
16
17
 
17
18
  ```mermaid
18
19
  flowchart LR
@@ -14,6 +14,13 @@ export interface EndpointOptions {
14
14
  label?: string;
15
15
  /** Delay before retrying election after a drop. */
16
16
  reelectMs?: number;
17
+ /**
18
+ * Fired whenever this endpoint becomes the host — on the initial election AND
19
+ * on any later failover re-election. Use it for host-only side effects like
20
+ * advertising the bridge token, so they recur on every host transition rather
21
+ * than only once at startup.
22
+ */
23
+ onHost?: () => void;
17
24
  }
18
25
  export interface EndpointDeps {
19
26
  logger: Logger;
package/dist/endpoint.js CHANGED
@@ -34,26 +34,39 @@ export async function createEndpoint(opts, deps) {
34
34
  return;
35
35
  }
36
36
  mode = "electing";
37
- // 1) Try to host (win the bind).
38
- const transport = deps.createServerTransport();
39
- const candidate = new Broker({
40
- host: opts.host,
41
- port: opts.port,
42
- token: opts.token,
43
- executor: opts.executor,
44
- timeoutMs: opts.timeoutMs
45
- }, { logger: deps.logger, transport });
37
+ // 1) Try to host (win the bind). Everything is inside the try so a transport
38
+ // that throws at construction (or a Broker that fails to start) degrades to
39
+ // guest instead of crashing the plugin load.
40
+ let candidate = null;
46
41
  try {
42
+ const transport = deps.createServerTransport();
43
+ candidate = new Broker({
44
+ host: opts.host,
45
+ port: opts.port,
46
+ token: opts.token,
47
+ executor: opts.executor,
48
+ timeoutMs: opts.timeoutMs
49
+ }, { logger: deps.logger, transport });
47
50
  await candidate.start();
48
51
  broker = candidate;
49
52
  current = candidate.createLocalAgent();
50
53
  mode = "host";
51
54
  deps.logger.info("browser_endpoint_mode", { mode: "host" });
55
+ // Isolate the side-effect callback: a throw here must NOT reach the outer
56
+ // catch, which would stop the freshly-started broker and degrade to guest.
57
+ try {
58
+ opts.onHost?.();
59
+ }
60
+ catch (onHostErr) {
61
+ deps.logger.error("browser_endpoint_onhost_error", {
62
+ message: onHostErr instanceof Error ? onHostErr.message : String(onHostErr)
63
+ });
64
+ }
52
65
  return;
53
66
  }
54
67
  catch (err) {
55
68
  try {
56
- candidate.stop();
69
+ candidate?.stop();
57
70
  }
58
71
  catch {
59
72
  /* never bound */
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"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"}
package/dist/lib.d.ts CHANGED
@@ -2,7 +2,8 @@ export { type BrowserPluginFactoryOptions, createBrowserPlugin, OpencodeBrowserP
2
2
  export { type AgentEndpoint, Broker, BrokerError, type BrokerDeps, type BrokerOptions } from "./broker.js";
3
3
  export { AgentClient, AgentClientError, type AgentClientDeps, type AgentClientOptions, type AgentSocket, type AgentSocketFactory, type AgentSocketHandlers } from "./agent-client.js";
4
4
  export { createEndpoint, type Endpoint, type EndpointDeps, type EndpointMode, type EndpointOptions } from "./endpoint.js";
5
- export { type BridgeTransport, type ClientConnection, createBunTransport, isAddrInUse, type TransportHandlers } from "./transport.js";
5
+ export { type BridgeTransport, type ClientConnection, isAddrInUse, type TransportHandlers } from "./transport.js";
6
+ export { createNodeAgentSocket, createNodeTransport } from "./node-transport.js";
6
7
  export { type BridgeFile, readBridgeFile, resolveSharedToken, type TokenSource, writeBridgeFile } from "./token-file.js";
7
8
  export { createBrowserTools, type SaveScreenshot, type SendFn, type ToolDeps } from "./tools.js";
8
9
  export { BROWSER_TOOLS, DEFAULT_GROUPS, type NeutralResult, TOOL_GROUPS, type ToolGroup, type ToolSpec } from "./catalog.js";
package/dist/lib.js CHANGED
@@ -2,7 +2,8 @@ export { createBrowserPlugin, OpencodeBrowserPlugin } from "./opencode.js";
2
2
  export { Broker, BrokerError } from "./broker.js";
3
3
  export { AgentClient, AgentClientError } from "./agent-client.js";
4
4
  export { createEndpoint } from "./endpoint.js";
5
- export { createBunTransport, isAddrInUse } from "./transport.js";
5
+ export { isAddrInUse } from "./transport.js";
6
+ export { createNodeAgentSocket, createNodeTransport } from "./node-transport.js";
6
7
  export { readBridgeFile, resolveSharedToken, writeBridgeFile } from "./token-file.js";
7
8
  export { createBrowserTools } from "./tools.js";
8
9
  export { BROWSER_TOOLS, DEFAULT_GROUPS, TOOL_GROUPS } from "./catalog.js";
package/dist/lib.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAEL,MAAM,EACN,WAAW,EAGZ,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,WAAW,EACX,gBAAgB,EAMjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,cAAc,EAKf,MAAM,eAAe,CAAC;AAEvB,OAAO,EAGL,kBAAkB,EAClB,WAAW,EAEZ,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAEL,cAAc,EACd,kBAAkB,EAElB,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,kBAAkB,EAAmD,MAAM,YAAY,CAAC;AAEjG,OAAO,EACL,aAAa,EACb,cAAc,EAEd,WAAW,EAGZ,MAAM,cAAc,CAAC;AAEtB,OAAO,EAA+C,YAAY,EAAE,MAAM,aAAa,CAAC;AAExF,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EAIrB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,eAAe,EAKf,WAAW,EACX,WAAW,EAIX,UAAU,EACV,MAAM,EACN,gBAAgB,EAGjB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAEL,MAAM,EACN,WAAW,EAGZ,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,WAAW,EACX,gBAAgB,EAMjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,cAAc,EAKf,MAAM,eAAe,CAAC;AAEvB,OAAO,EAGL,WAAW,EAEZ,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAEjF,OAAO,EAEL,cAAc,EACd,kBAAkB,EAElB,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,kBAAkB,EAAmD,MAAM,YAAY,CAAC;AAEjG,OAAO,EACL,aAAa,EACb,cAAc,EAEd,WAAW,EAGZ,MAAM,cAAc,CAAC;AAEtB,OAAO,EAA+C,YAAY,EAAE,MAAM,aAAa,CAAC;AAExF,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EAIrB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,eAAe,EAKf,WAAW,EACX,WAAW,EAIX,UAAU,EACV,MAAM,EACN,gBAAgB,EAGjB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { AgentSocket, AgentSocketHandlers } from "./agent-client.js";
2
+ import type { BridgeTransport } from "./transport.js";
3
+ /**
4
+ * `BridgeTransport` backed by the Node `ws` package. This is the bridge's single
5
+ * host transport: `ws` runs under both Node *and* Bun, so it covers every
6
+ * runtime OpenCode loads the plugin in — the Bun CLI/web *and* the Node desktop
7
+ * app — without a Bun-specific code path. `listen` resolves once bound and
8
+ * rejects on `EADDRINUSE`, which drives the endpoint's host-vs-guest election.
9
+ */
10
+ export declare function createNodeTransport(): BridgeTransport;
11
+ /** Agent-socket factory backed by the Node `ws` client (guest mode). */
12
+ export declare function createNodeAgentSocket(url: string, handlers: AgentSocketHandlers): AgentSocket;
@@ -0,0 +1,52 @@
1
+ import { WebSocket, WebSocketServer } from "ws";
2
+ /**
3
+ * `BridgeTransport` backed by the Node `ws` package. This is the bridge's single
4
+ * host transport: `ws` runs under both Node *and* Bun, so it covers every
5
+ * runtime OpenCode loads the plugin in — the Bun CLI/web *and* the Node desktop
6
+ * app — without a Bun-specific code path. `listen` resolves once bound and
7
+ * rejects on `EADDRINUSE`, which drives the endpoint's host-vs-guest election.
8
+ */
9
+ export function createNodeTransport() {
10
+ let server = null;
11
+ return {
12
+ listen({ host, port }, handlers) {
13
+ return new Promise((resolve, reject) => {
14
+ const wss = new WebSocketServer({ host, port });
15
+ server = wss;
16
+ wss.once("listening", () => resolve());
17
+ wss.once("error", (err) => reject(err));
18
+ wss.on("connection", (ws) => {
19
+ const conn = {
20
+ send: (data) => ws.send(data),
21
+ close: () => ws.close()
22
+ };
23
+ handlers.onOpen(conn);
24
+ ws.on("message", (data) => handlers.onMessage(conn, data.toString()));
25
+ ws.on("close", () => handlers.onClose(conn));
26
+ ws.on("error", () => {
27
+ /* close follows */
28
+ });
29
+ });
30
+ });
31
+ },
32
+ stop() {
33
+ server?.close();
34
+ server = null;
35
+ }
36
+ };
37
+ }
38
+ /** Agent-socket factory backed by the Node `ws` client (guest mode). */
39
+ export function createNodeAgentSocket(url, handlers) {
40
+ const ws = new WebSocket(url);
41
+ ws.on("open", () => handlers.onOpen());
42
+ ws.on("message", (data) => handlers.onMessage(data.toString()));
43
+ ws.on("close", () => handlers.onClose());
44
+ ws.on("error", () => {
45
+ /* close follows */
46
+ });
47
+ return {
48
+ send: (data) => ws.send(data),
49
+ close: () => ws.close()
50
+ };
51
+ }
52
+ //# sourceMappingURL=node-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-transport.js","sourceRoot":"","sources":["../src/node-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAKhD;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB;IACjC,IAAI,MAAM,GAA2B,IAAI,CAAC;IAE1C,OAAO;QACL,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,QAAQ;YAC7B,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC3C,MAAM,GAAG,GAAG,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAChD,MAAM,GAAG,GAAG,CAAC;gBACb,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;gBACvC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBACxC,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,EAAa,EAAE,EAAE;oBACrC,MAAM,IAAI,GAAqB;wBAC7B,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;wBAC7B,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE;qBACxB,CAAC;oBACF,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;oBACtB,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;oBACtE,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;oBAC7C,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;wBAClB,mBAAmB;oBACrB,CAAC,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;QACD,IAAI;YACF,MAAM,EAAE,KAAK,EAAE,CAAC;YAChB,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,qBAAqB,CAAC,GAAW,EAAE,QAA6B;IAC9E,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;IAC9B,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACvC,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAChE,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACzC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAClB,mBAAmB;IACrB,CAAC,CAAC,CAAC;IACH,OAAO;QACL,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;QAC7B,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE;KACxB,CAAC;AACJ,CAAC"}
@@ -2,7 +2,7 @@ import type { Plugin } from "@opencode-ai/plugin";
2
2
  import type { AgentSocketFactory } from "./agent-client.js";
3
3
  import { type Logger } from "./logging.js";
4
4
  import { type SaveScreenshot } from "./tools.js";
5
- import { type BridgeTransport } from "./transport.js";
5
+ import type { BridgeTransport } from "./transport.js";
6
6
  export interface BrowserPluginFactoryOptions {
7
7
  /** Inject a logger (defaults to the OpenCode-piped logger). */
8
8
  logger?: Logger;
package/dist/opencode.js CHANGED
@@ -3,21 +3,8 @@ import { DEFAULT_GROUPS, TOOL_GROUPS } from "./catalog.js";
3
3
  import { createEndpoint } from "./endpoint.js";
4
4
  import { createJsonConsoleLogger, DEFAULT_LOG_LEVEL, fromOpenCodeLogLevel, LOG_LEVEL_PRIORITY } from "./logging.js";
5
5
  import { resolveSharedToken, writeBridgeFile } from "./token-file.js";
6
+ import { createNodeAgentSocket, createNodeTransport } from "./node-transport.js";
6
7
  import { createBrowserTools } from "./tools.js";
7
- import { createBunTransport } from "./transport.js";
8
- /** Agent-socket factory using the runtime's global WebSocket (Bun provides one). */
9
- const bunAgentSocket = (url, handlers) => {
10
- const Ctor = globalThis.WebSocket;
11
- if (!Ctor) {
12
- throw new Error("global WebSocket is not available in this runtime");
13
- }
14
- const ws = new Ctor(url);
15
- ws.addEventListener("open", () => handlers.onOpen());
16
- ws.addEventListener("message", (event) => handlers.onMessage(typeof event.data === "string" ? event.data : String(event.data)));
17
- ws.addEventListener("close", () => handlers.onClose());
18
- ws.addEventListener("error", () => { });
19
- return { send: (data) => ws.send(data), close: () => ws.close() };
20
- };
21
8
  function resolveGroups(raw) {
22
9
  if (!Array.isArray(raw)) {
23
10
  return [...DEFAULT_GROUPS];
@@ -106,6 +93,16 @@ export function createBrowserPlugin(factoryOptions = {}) {
106
93
  // Share the token across adapters via the per-user state file (explicit wins).
107
94
  const { token, source } = resolveSharedToken(options.port, tokenProvided ? options.token : undefined, generateToken);
108
95
  writeBridgeFile(options.port, token);
96
+ // Only the host advertises the token (guests reuse the same one from the
97
+ // shared file — reprinting it per session is just noise, and re-emits the
98
+ // secret). Fired via onHost so a host reached by failover re-election still
99
+ // advertises it, not only the initial host. The `paste_into_extension` field
100
+ // name dodges the logger's redaction filter so the value stays copyable.
101
+ const advertiseToken = () => {
102
+ if (source !== "explicit") {
103
+ logger.info("browser_bridge_token", { paste_into_extension: token, source, mode: "host" });
104
+ }
105
+ };
109
106
  // Auto-elect: host the broker (win the bind) or join an existing one as a guest.
110
107
  const endpoint = await createEndpoint({
111
108
  host: options.host,
@@ -113,11 +110,12 @@ export function createBrowserPlugin(factoryOptions = {}) {
113
110
  token,
114
111
  executor: executorProvided ? options.executor : undefined,
115
112
  timeoutMs: options.timeoutMs,
116
- label: "opencode-plugin"
113
+ label: "opencode-plugin",
114
+ onHost: advertiseToken
117
115
  }, {
118
116
  logger,
119
- createServerTransport: factoryOptions.createServerTransport ?? createBunTransport,
120
- createAgentSocket: factoryOptions.createAgentSocket ?? bunAgentSocket
117
+ createServerTransport: factoryOptions.createServerTransport ?? createNodeTransport,
118
+ createAgentSocket: factoryOptions.createAgentSocket ?? createNodeAgentSocket
121
119
  });
122
120
  // When OpenCode exits, hand the browser back automatically — the user
123
121
  // shouldn't have to click Disconnect.
@@ -129,17 +127,6 @@ export function createBrowserPlugin(factoryOptions = {}) {
129
127
  /* best-effort */
130
128
  }
131
129
  });
132
- if (endpoint.mode() === "host" && source !== "explicit") {
133
- // Only the host advertises the token (guests reuse the same one from the
134
- // shared file — reprinting it per session is just noise, and re-emits the
135
- // secret). The `paste_into_extension` field name dodges the logger's
136
- // redaction filter so the value stays copyable.
137
- logger.info("browser_bridge_token", {
138
- paste_into_extension: token,
139
- source,
140
- mode: "host"
141
- });
142
- }
143
130
  const tools = createBrowserTools({
144
131
  send: endpoint.send,
145
132
  options,
@@ -1 +1 @@
1
- {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../src/opencode.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../src/opencode.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  /**
2
- * The transport seam for the bridge/broker. The real implementation wraps
3
- * `Bun.serve`'s WebSocket support; the MCP server provides a Node `ws` variant;
2
+ * The transport seam for the bridge/broker. The real implementation is the Node
3
+ * `ws` variant in `node-transport.ts` (which runs under both Node and Bun);
4
4
  * tests inject a fake. `listen` is **async** and resolves only once the port is
5
5
  * actually bound (and rejects on `EADDRINUSE`) — that's what the broker election
6
6
  * relies on to decide host-vs-guest.
@@ -25,8 +25,3 @@ export interface BridgeTransport {
25
25
  }
26
26
  /** True for an "address already in use" style bind error (→ become a guest). */
27
27
  export declare function isAddrInUse(err: unknown): boolean;
28
- /**
29
- * Real transport backed by `Bun.serve` — the production path inside OpenCode
30
- * (which runs on Bun). Throws if invoked outside Bun.
31
- */
32
- export declare function createBunTransport(): BridgeTransport;
package/dist/transport.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
- * The transport seam for the bridge/broker. The real implementation wraps
3
- * `Bun.serve`'s WebSocket support; the MCP server provides a Node `ws` variant;
2
+ * The transport seam for the bridge/broker. The real implementation is the Node
3
+ * `ws` variant in `node-transport.ts` (which runs under both Node and Bun);
4
4
  * tests inject a fake. `listen` is **async** and resolves only once the port is
5
5
  * actually bound (and rejects on `EADDRINUSE`) — that's what the broker election
6
6
  * relies on to decide host-vs-guest.
@@ -10,62 +10,4 @@ export function isAddrInUse(err) {
10
10
  const msg = err instanceof Error ? err.message : String(err);
11
11
  return /eaddrinuse|address already in use|in use/i.test(msg);
12
12
  }
13
- /**
14
- * Real transport backed by `Bun.serve` — the production path inside OpenCode
15
- * (which runs on Bun). Throws if invoked outside Bun.
16
- */
17
- export function createBunTransport() {
18
- const bun = globalThis.Bun;
19
- if (!bun) {
20
- throw new Error("the opencode-browser bridge requires the Bun runtime (Bun.serve not found)");
21
- }
22
- let server = null;
23
- const conns = new WeakMap();
24
- return {
25
- listen({ host, port }, handlers) {
26
- return new Promise((resolve, reject) => {
27
- try {
28
- server = bun.serve({
29
- hostname: host,
30
- port,
31
- fetch(req, srv) {
32
- if (srv.upgrade(req)) {
33
- return undefined;
34
- }
35
- return new Response("opencode-browser bridge: websocket only", { status: 426 });
36
- },
37
- websocket: {
38
- open(ws) {
39
- const conn = { send: (d) => ws.send(d), close: () => ws.close() };
40
- conns.set(ws, conn);
41
- handlers.onOpen(conn);
42
- },
43
- message(ws, message) {
44
- const conn = conns.get(ws);
45
- if (conn) {
46
- handlers.onMessage(conn, typeof message === "string" ? message : Buffer.from(message).toString());
47
- }
48
- },
49
- close(ws) {
50
- const conn = conns.get(ws);
51
- conns.delete(ws);
52
- if (conn) {
53
- handlers.onClose(conn);
54
- }
55
- }
56
- }
57
- });
58
- resolve(); // Bun.serve throws synchronously on EADDRINUSE; reaching here = bound.
59
- }
60
- catch (err) {
61
- reject(err);
62
- }
63
- });
64
- },
65
- stop() {
66
- server?.stop(true);
67
- server = null;
68
- }
69
- };
70
- }
71
13
  //# sourceMappingURL=transport.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAoBH,gFAAgF;AAChF,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,2CAA2C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/D,CAAC;AAUD;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,GAAG,GAAI,UAAgC,CAAC,GAAG,CAAC;IAClD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAC;IAChG,CAAC;IACD,IAAI,MAAM,GAAiD,IAAI,CAAC;IAChE,MAAM,KAAK,GAAG,IAAI,OAAO,EAA4B,CAAC;IAEtD,OAAO;QACL,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,QAAQ;YAC7B,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC3C,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC;wBACjB,QAAQ,EAAE,IAAI;wBACd,IAAI;wBACJ,KAAK,CAAC,GAAY,EAAE,GAAuC;4BACzD,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gCACrB,OAAO,SAAS,CAAC;4BACnB,CAAC;4BACD,OAAO,IAAI,QAAQ,CAAC,yCAAyC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;wBAClF,CAAC;wBACD,SAAS,EAAE;4BACT,IAAI,CAAC,EAAgB;gCACnB,MAAM,IAAI,GAAqB,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;gCACpF,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;gCACpB,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;4BACxB,CAAC;4BACD,OAAO,CAAC,EAAgB,EAAE,OAAiC;gCACzD,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gCAC3B,IAAI,IAAI,EAAE,CAAC;oCACT,QAAQ,CAAC,SAAS,CAChB,IAAI,EACJ,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CACxE,CAAC;gCACJ,CAAC;4BACH,CAAC;4BACD,KAAK,CAAC,EAAgB;gCACpB,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gCAC3B,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gCACjB,IAAI,IAAI,EAAE,CAAC;oCACT,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gCACzB,CAAC;4BACH,CAAC;yBACF;qBACF,CAAC,CAAC;oBACH,OAAO,EAAE,CAAC,CAAC,uEAAuE;gBACpF,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QACD,IAAI;YACF,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAoBH,gFAAgF;AAChF,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,2CAA2C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vymalo/opencode-browser",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "OpenCode plugin that gives the model hands in a real browser: it registers browser_* tools (open, click, type, scroll, screenshot, snapshot, …) and hosts a localhost WebSocket bridge that a companion Chromium/Firefox extension connects to. Tabs are organized into named groups so each task stays isolated and inspectable.",
5
5
  "license": "MIT",
6
6
  "author": "vymalo contributors",
@@ -49,9 +49,11 @@
49
49
  "access": "public"
50
50
  },
51
51
  "dependencies": {
52
- "@opencode-ai/plugin": "1.15.10"
52
+ "@opencode-ai/plugin": "1.15.10",
53
+ "ws": "^8.21.0"
53
54
  },
54
55
  "devDependencies": {
56
+ "@types/ws": "^8.18.0",
55
57
  "vite": "^8.0.14",
56
58
  "vitest": "^4.1.7"
57
59
  },