@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.
- package/README.md +18 -30
- package/dist/cli.js +13 -2
- 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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
86
|
+
etch.connectAs('homepage');
|
|
82
87
|
```
|
|
83
88
|
|
|
84
|
-
(`
|
|
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.
|
|
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
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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.
|
|
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.
|
|
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
|