@digital-gravy/etch-connector 0.1.3 → 0.1.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.
Files changed (3) hide show
  1. package/README.md +18 -30
  2. package/dist/cli.js +13 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -23,7 +23,7 @@ Claude Code / Cowork
23
23
  │ shell: etch-connector eval -t homepage "return ..."
24
24
  ▼
25
25
  etch-connector (the `serve` daemon)
26
- │ ▲ WebSocket (tab dials in via etch.connectTo)
26
+ │ ▲ WebSocket (tab dials in via etch.connectAs)
27
27
  ▼ │
28
28
  Etch builder tab ──► window.etch.*
29
29
  ```
@@ -32,8 +32,7 @@ Claude Code / Cowork
32
32
 
33
33
  This is an **eval relay**: the harness sends a JavaScript snippet, the page runs
34
34
  it as an async function, and the return value + console output come back. It is
35
- intentionally _not_ an MCP server yet, but it is built so that becoming one is a
36
- thin add — see [Going to MCP](#going-to-mcp-later).
35
+ not an MCP server yet — see [Going to MCP](#going-to-mcp-later).
37
36
 
38
37
  Scripts run in a **page-enforced safe mode**: the script sees only `etch` and
39
38
  the standard JS built-ins. `window`, `document`, `fetch`, storage, `eval`, … are
@@ -75,13 +74,19 @@ etch-connector serve
75
74
 
76
75
  ### 2. Connect a tab
77
76
 
78
- Open an Etch builder page and, in the browser console:
77
+ **Primary way — the AI button.** Enable the **AI Connector** in the Etch
78
+ Settings, then open an Etch builder page and click the **AI button** in the left
79
+ sidebar. It connects this tab for you, registering it under your site name (it
80
+ just calls `connectAs` under the hood). Click it again to disconnect.
81
+
82
+ **Secondary way — the console.** You can also connect manually from the browser
83
+ console:
79
84
 
80
85
  ```js
81
- etch.connectTo('homepage');
86
+ etch.connectAs('homepage');
82
87
  ```
83
88
 
84
- (`connectTo` is part of the public API; it opens the WebSocket back to the
89
+ (`connectAs` is part of the public API; it opens the WebSocket back to the
85
90
  daemon and registers this tab under the given name. Pass `{ port: <n> }` if you
86
91
  started the daemon on a non-default WebSocket port.)
87
92
 
@@ -144,7 +149,7 @@ Usage:
144
149
  etch-connector computed <selector> [-t name] [--props a,b,c] (CDP)
145
150
 
146
151
  Two backends:
147
- bridge (default) the tab dials in via etch.connectTo(); page-sandboxed.
152
+ bridge (default) the tab dials in via etch.connectAs(); page-sandboxed.
148
153
  Scripts see only "etch" + the standard JS built-ins.
149
154
  cdp connect OUT to a Chrome started with --remote-debugging-port=9222.
150
155
  No daemon. Runs at DevTools privilege: full "window", plus screenshots,
@@ -191,22 +196,10 @@ the same one a future MCP server would call):
191
196
 
192
197
  ## Going to MCP later
193
198
 
194
- Nothing in the transport changes. An MCP server is `new BridgeServer()` plus two
195
- tool definitions over the same core:
196
-
197
- ```ts
198
- import { BridgeServer } from 'etch-connector';
199
-
200
- const bridge = new BridgeServer();
201
- await bridge.listen();
202
-
203
- // list_etch_tabs -> bridge.listTabs()
204
- // eval_etch_script -> bridge.evalInTab(code, { tab })
205
- ```
206
-
207
- When you want first-class per-tool MCP tools (rather than one eval tool), have
208
- the Etch tab advertise a tool manifest in its `hello` and register those
209
- dynamically — keeping a single source of truth in the browser registry.
199
+ Today this is a CLI eval relay. A future version will expose the same bridge as
200
+ a proper MCP server, so an AI harness can call first-class tools (list tabs, run
201
+ a script) directly instead of shelling out — without changing how you connect a
202
+ tab.
210
203
 
211
204
  ## Security
212
205
 
@@ -223,10 +216,5 @@ hardened sandbox**: because the script shares the page's JS realm, a _determined
223
216
  author can still reach globals through prototype / constructor chains (e.g.
224
217
  `({}).constructor.constructor`). It reliably keeps casual and AI-authored
225
218
  scripts on the `etch` surface and closes the obvious escape hatches; it does
226
- **not** contain hostile code.
227
-
228
- For a true boundary against adversarial scripts you would need to harden the
229
- realm (SES `lockdown()`), which freezes all intrinsics app-wide and is out of
230
- scope for this relay. The enforcement lives in the Etch page (`bridge.ts`), not
231
- this connector — the connector only carries the requested mode; a string filter
232
- here would be theater.
219
+ **not** contain hostile code. For a true boundary against adversarial scripts,
220
+ run the daemon only on a trusted machine.
package/dist/cli.js CHANGED
@@ -133,7 +133,7 @@ async function runServe(flags) {
133
133
  console.error(`[etch-connector] control ${controlBaseUrl({ host: controlHost, port: controlPort })}`);
134
134
  console.error(`[etch-connector] default mode: ${defaultMode}${defaultMode === 'unsafe' ? ' ⚠ scripts get full access to the page' : ' (scripts see only window.etch + JS built-ins)'}`);
135
135
  console.error('[etch-connector] In an Etch builder tab, run:');
136
- console.error(`[etch-connector] etch.connectTo('my-tab'${boundWsPort === DEFAULT_WS_PORT ? '' : `, { port: ${boundWsPort} }`})`);
136
+ console.error(`[etch-connector] etch.connectAs('my-tab'${boundWsPort === DEFAULT_WS_PORT ? '' : `, { port: ${boundWsPort} }`})`);
137
137
  console.error('[etch-connector] then drive it with: etch-connector eval -t my-tab "return window.etch.apiVersion"');
138
138
  const shutdown = () => {
139
139
  clearInterval(heartbeat);
@@ -403,7 +403,7 @@ Usage:
403
403
  etch-connector computed <selector> [-t name] [--props a,b,c] (CDP)
404
404
 
405
405
  Two backends:
406
- bridge (default) the tab dials in via etch.connectTo(); page-sandboxed.
406
+ bridge (default) the tab dials in via etch.connectAs(); page-sandboxed.
407
407
  Scripts see only "etch" + the standard JS built-ins.
408
408
  cdp connect OUT to a Chrome started with --remote-debugging-port=${DEFAULT_CDP_PORT}.
409
409
  No daemon. Runs at DevTools privilege: full "window", plus screenshots,
@@ -414,6 +414,17 @@ AGENT: before running anything, ask the user how they want to connect — bridge
414
414
  (API only) or cdp (DevTools privilege: full page access). cdp grants more reach;
415
415
  don't assume — let the user choose.
416
416
 
417
+ Connecting a bridge tab (AGENT: walk the user through activating it — the AI
418
+ button is the primary path; don't just wait for a tab to appear):
419
+ 1. Tell them to open Etch Settings and enable the AI Connector.
420
+ 2. Tell them to open a builder page and click the AI button in the left
421
+ sidebar — it connects the tab and registers it under the site name (calls
422
+ connectAs under the hood); clicking it again disconnects.
423
+ Fallback — they can connect from the browser console:
424
+ etch.connectAs('homepage') (add { port: <n> } for a non-default WS port)
425
+ cdp needs no connect step — start Chrome with --remote-debugging-port and
426
+ target a tab with -t.
427
+
417
428
  Examples:
418
429
  etch-connector serve
419
430
  etch-connector tabs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digital-gravy/etch-connector",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },