@different-ai/opencode-browser 4.5.0 → 4.6.0
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 +41 -9
- package/bin/broker.cjs +21 -20
- package/dist/plugin.js +353 -90
- package/extension/background.js +601 -19
- package/extension/manifest.json +4 -2
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -58,6 +58,25 @@ Your `opencode.json` or `opencode.jsonc` should contain:
|
|
|
58
58
|
bunx @different-ai/opencode-browser@latest update
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
## Chrome Web Store maintainer flow
|
|
62
|
+
|
|
63
|
+
Build a store-ready extension package:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
bun run build:cws
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Outputs:
|
|
70
|
+
|
|
71
|
+
- `artifacts/chrome-web-store/opencode-browser-cws-v<version>.zip`
|
|
72
|
+
- `artifacts/chrome-web-store/manifest.chrome-web-store.json`
|
|
73
|
+
|
|
74
|
+
Submission checklist and guidance:
|
|
75
|
+
|
|
76
|
+
- `CHROME_WEB_STORE.md`
|
|
77
|
+
- `CHROME_WEB_STORE_REQUEST_TEMPLATE.md`
|
|
78
|
+
- `PRIVACY.md`
|
|
79
|
+
|
|
61
80
|
## How it works
|
|
62
81
|
|
|
63
82
|
```
|
|
@@ -111,11 +130,11 @@ export OPENCODE_BROWSER_AGENT_PORT=9833
|
|
|
111
130
|
|
|
112
131
|
## Per-tab ownership
|
|
113
132
|
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
- `browser_open_tab` always
|
|
133
|
+
- Each session owns its own tabs; tabs are never shared between sessions.
|
|
134
|
+
- If a session has no tab yet, the broker auto-creates a background tab on first tool use.
|
|
135
|
+
- `browser_open_tab` always creates and claims a new tab for the session.
|
|
117
136
|
- Claims expire after inactivity (`OPENCODE_BROWSER_CLAIM_TTL_MS`, default 5 minutes).
|
|
118
|
-
- Use `browser_status` or `browser_list_claims`
|
|
137
|
+
- Use `browser_status` or `browser_list_claims` for debugging.
|
|
119
138
|
|
|
120
139
|
## Available tools
|
|
121
140
|
|
|
@@ -126,6 +145,7 @@ Core primitives:
|
|
|
126
145
|
- `browser_claim_tab`
|
|
127
146
|
- `browser_release_tab`
|
|
128
147
|
- `browser_open_tab`
|
|
148
|
+
- `browser_close_tab`
|
|
129
149
|
- `browser_navigate`
|
|
130
150
|
- `browser_query` (modes: `text`, `value`, `list`, `exists`, `page_text`; optional `timeoutMs`/`pollMs`)
|
|
131
151
|
- `browser_click` (optional `timeoutMs`/`pollMs`)
|
|
@@ -134,6 +154,13 @@ Core primitives:
|
|
|
134
154
|
- `browser_scroll` (optional `timeoutMs`/`pollMs`)
|
|
135
155
|
- `browser_wait`
|
|
136
156
|
|
|
157
|
+
Downloads:
|
|
158
|
+
- `browser_download`
|
|
159
|
+
- `browser_list_downloads`
|
|
160
|
+
|
|
161
|
+
Uploads:
|
|
162
|
+
- `browser_set_file_input` (extension backend supports small files; use agent backend for larger uploads)
|
|
163
|
+
|
|
137
164
|
Selector helpers (usable in `selector`):
|
|
138
165
|
- `label:Mailing Address: City`
|
|
139
166
|
- `aria:Principal Address: City`
|
|
@@ -149,11 +176,11 @@ Diagnostics:
|
|
|
149
176
|
|
|
150
177
|
## Roadmap
|
|
151
178
|
|
|
152
|
-
- [ ] Add tab management tools (`browser_set_active_tab
|
|
179
|
+
- [ ] Add tab management tools (`browser_set_active_tab`)
|
|
153
180
|
- [ ] Add navigation helpers (`browser_back`, `browser_forward`, `browser_reload`)
|
|
154
181
|
- [ ] Add keyboard input tool (`browser_key`)
|
|
155
|
-
- [
|
|
156
|
-
- [
|
|
182
|
+
- [x] Add download support (`browser_download`, `browser_list_downloads`)
|
|
183
|
+
- [x] Add upload support (`browser_set_file_input`)
|
|
157
184
|
|
|
158
185
|
## Troubleshooting
|
|
159
186
|
|
|
@@ -162,8 +189,9 @@ Diagnostics:
|
|
|
162
189
|
- If you loaded a custom extension ID, rerun with `--extension-id <id>`
|
|
163
190
|
|
|
164
191
|
**Tab ownership errors**
|
|
165
|
-
-
|
|
166
|
-
- Use `
|
|
192
|
+
- Errors usually mean you passed a `tabId` owned by another session
|
|
193
|
+
- Use `browser_open_tab` to create a tab for your session (or omit `tabId` to use your default)
|
|
194
|
+
- Use `browser_status` or `browser_list_claims` for debugging
|
|
167
195
|
|
|
168
196
|
## Uninstall
|
|
169
197
|
|
|
@@ -172,3 +200,7 @@ npx @different-ai/opencode-browser uninstall
|
|
|
172
200
|
```
|
|
173
201
|
|
|
174
202
|
Then remove the unpacked extension in `chrome://extensions` and remove the plugin from `opencode.json` or `opencode.jsonc`.
|
|
203
|
+
|
|
204
|
+
## Privacy
|
|
205
|
+
|
|
206
|
+
- Privacy policy: `PRIVACY.md`
|
package/bin/broker.cjs
CHANGED
|
@@ -53,7 +53,7 @@ function writeJsonLine(socket, msg) {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
function wantsTab(toolName) {
|
|
56
|
-
return !["get_tabs", "get_active_tab", "open_tab"].includes(toolName);
|
|
56
|
+
return !["get_tabs", "get_active_tab", "open_tab", "list_downloads"].includes(toolName);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// --- State ---
|
|
@@ -206,10 +206,13 @@ function callExtension(tool, args, sessionId) {
|
|
|
206
206
|
});
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
-
async function
|
|
210
|
-
|
|
209
|
+
async function ensureSessionTab(sessionId) {
|
|
210
|
+
if (!sessionId) throw new Error("Missing sessionId for tab creation");
|
|
211
|
+
const res = await callExtension("open_tab", { active: false }, sessionId);
|
|
211
212
|
const tabId = res && typeof res.tabId === "number" ? res.tabId : undefined;
|
|
212
|
-
if (!tabId) throw new Error("
|
|
213
|
+
if (!tabId) throw new Error("Failed to create a new tab for this session");
|
|
214
|
+
touchClaim(tabId, sessionId);
|
|
215
|
+
setDefaultTab(sessionId, tabId);
|
|
213
216
|
return tabId;
|
|
214
217
|
}
|
|
215
218
|
|
|
@@ -222,13 +225,7 @@ async function handleTool(pluginSocket, req) {
|
|
|
222
225
|
let tabId = args.tabId;
|
|
223
226
|
const toolArgs = { ...args };
|
|
224
227
|
|
|
225
|
-
|
|
226
|
-
const activeTabId = await resolveActiveTab(sessionId);
|
|
227
|
-
const claimCheck = checkClaim(activeTabId, sessionId);
|
|
228
|
-
if (!claimCheck.ok) {
|
|
229
|
-
toolArgs.active = false;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
228
|
+
const isCloseTool = tool === "close_tab";
|
|
232
229
|
|
|
233
230
|
if (wantsTab(tool)) {
|
|
234
231
|
if (typeof tabId !== "number") {
|
|
@@ -236,14 +233,10 @@ async function handleTool(pluginSocket, req) {
|
|
|
236
233
|
const defaultTabId = state && Number.isFinite(state.defaultTabId) ? state.defaultTabId : null;
|
|
237
234
|
if (Number.isFinite(defaultTabId)) {
|
|
238
235
|
tabId = defaultTabId;
|
|
236
|
+
} else if (!isCloseTool) {
|
|
237
|
+
tabId = await ensureSessionTab(sessionId);
|
|
239
238
|
} else {
|
|
240
|
-
|
|
241
|
-
const claimCheck = checkClaim(activeTabId, sessionId);
|
|
242
|
-
if (!claimCheck.ok) {
|
|
243
|
-
throw new Error(`${claimCheck.error}. No default tab for session; open a new tab or claim one.`);
|
|
244
|
-
}
|
|
245
|
-
tabId = activeTabId;
|
|
246
|
-
setDefaultTab(sessionId, tabId);
|
|
239
|
+
throw new Error("No tab owned by this session. Open a new tab first.");
|
|
247
240
|
}
|
|
248
241
|
}
|
|
249
242
|
|
|
@@ -256,8 +249,16 @@ async function handleTool(pluginSocket, req) {
|
|
|
256
249
|
const usedTabId =
|
|
257
250
|
res && typeof res.tabId === "number" ? res.tabId : typeof tabId === "number" ? tabId : undefined;
|
|
258
251
|
if (typeof usedTabId === "number") {
|
|
259
|
-
|
|
260
|
-
|
|
252
|
+
if (isCloseTool) {
|
|
253
|
+
if (claims.has(usedTabId)) {
|
|
254
|
+
releaseClaim(usedTabId);
|
|
255
|
+
} else {
|
|
256
|
+
clearDefaultTab(sessionId, usedTabId);
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
259
|
+
touchClaim(usedTabId, sessionId);
|
|
260
|
+
setDefaultTab(sessionId, usedTabId);
|
|
261
|
+
}
|
|
261
262
|
}
|
|
262
263
|
|
|
263
264
|
return res;
|