@opencode/plugin-browser 2.0.20 → 2.0.22
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 +2 -2
- package/dist/connection.d.ts +2 -1
- package/dist/connection.js +14 -0
- package/dist/rpc.d.ts +5 -0
- package/dist/rpc.js +9 -2
- package/dist/tools.d.ts +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -38,8 +38,8 @@ pure and does not load any of these runtime modules.
|
|
|
38
38
|
## Tests
|
|
39
39
|
|
|
40
40
|
Run `bun test` and `bun typecheck` from this package for its contract checks.
|
|
41
|
-
|
|
42
|
-
(`packages/
|
|
41
|
+
The desktop implementation is the built-in `browser` GUI extension
|
|
42
|
+
(`packages/gui-extensions/src/browser`); its URL policy tests live there, not in this package.
|
|
43
43
|
|
|
44
44
|
## RPC
|
|
45
45
|
|
package/dist/connection.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { Tool } from "@opencode/schema/tool";
|
|
|
4
4
|
import { Effect } from "effect";
|
|
5
5
|
import { Browser } from "./rpc.js";
|
|
6
6
|
export type Connection = Effect.Success<ReturnType<typeof make>>;
|
|
7
|
-
export declare const make: (ctx: Pick<Context, "location" | "rpc" | "event" | "session">) => Effect.Effect<{
|
|
7
|
+
export declare const make: (ctx: Pick<Context, "location" | "rpc" | "agent" | "event" | "session">) => Effect.Effect<{
|
|
8
8
|
target: (sessionID: string & import("effect/Brand").Brand<"SessionID">, action: {
|
|
9
9
|
readonly type: "tabs.list";
|
|
10
10
|
} | {
|
|
@@ -55,6 +55,7 @@ export declare const make: (ctx: Pick<Context, "location" | "rpc" | "event" | "s
|
|
|
55
55
|
readonly type: "evaluate";
|
|
56
56
|
readonly script: string;
|
|
57
57
|
readonly tabID: string & import("effect/Brand").Brand<"Browser.TabID">;
|
|
58
|
+
readonly ref?: (string & import("effect/Brand").Brand<"Browser.Ref">) | undefined;
|
|
58
59
|
readonly frameID?: string | undefined;
|
|
59
60
|
} | {
|
|
60
61
|
readonly type: "click";
|
package/dist/connection.js
CHANGED
|
@@ -5,6 +5,19 @@ import { Browser } from "./rpc.js";
|
|
|
5
5
|
import { BrowserTunnel } from "./tunnel.js";
|
|
6
6
|
export const make = Effect.fn("BrowserConnection.make")(function* (ctx) {
|
|
7
7
|
const browsers = new Map();
|
|
8
|
+
// Appended after config, so every agent hides the browser until an attachment allows it.
|
|
9
|
+
yield* ctx.agent.transform((editor) => editor.list().forEach((agent) => agent.permissions.push({ action: "browser", resource: "*", effect: "deny" })));
|
|
10
|
+
// Each attachment adds and removes its own allow, so a replaced attachment keeps the new one's.
|
|
11
|
+
const grant = (sessionID) => Effect.acquireRelease(ctx.session.get({ sessionID }).pipe(Effect.flatMap((session) => ctx.session.update({
|
|
12
|
+
sessionID,
|
|
13
|
+
permissions: [...(session.permissions ?? []), { action: "browser", resource: "*", effect: "allow" }],
|
|
14
|
+
})), Effect.orDie), () => ctx.session.get({ sessionID }).pipe(Effect.flatMap((session) => {
|
|
15
|
+
const permissions = session.permissions ?? [];
|
|
16
|
+
const index = permissions.findIndex((rule) => rule.action === "browser" && rule.resource === "*" && rule.effect === "allow");
|
|
17
|
+
if (index === -1)
|
|
18
|
+
return Effect.void;
|
|
19
|
+
return ctx.session.update({ sessionID, permissions: permissions.toSpliced(index, 1) });
|
|
20
|
+
}), Effect.ignore));
|
|
8
21
|
let active = true;
|
|
9
22
|
const close = (sessionID, reason = "closed") => Effect.gen(function* () {
|
|
10
23
|
const browser = browsers.get(sessionID);
|
|
@@ -46,6 +59,7 @@ export const make = Effect.fn("BrowserConnection.make")(function* (ctx) {
|
|
|
46
59
|
browsers.set(input.sessionID, browser);
|
|
47
60
|
return browser;
|
|
48
61
|
}), (browser) => (browsers.get(input.sessionID) === browser ? close(input.sessionID) : Effect.void));
|
|
62
|
+
yield* grant(input.sessionID);
|
|
49
63
|
yield* rpc.events
|
|
50
64
|
.emit("control", { type: "attached", connectionID: input.connectionID, version: 4 })
|
|
51
65
|
.pipe(Effect.orDie);
|
package/dist/rpc.d.ts
CHANGED
|
@@ -417,6 +417,7 @@ export declare const Operations: readonly [{
|
|
|
417
417
|
name: "evaluate";
|
|
418
418
|
description: string;
|
|
419
419
|
input: Schema.Struct<{
|
|
420
|
+
readonly ref: Schema.decodeTo<Schema.optional<Schema.toType<Schema.brand<Schema.String, "Browser.Ref">>>, Schema.optionalKey<Schema.brand<Schema.String, "Browser.Ref">>, never, never>;
|
|
420
421
|
readonly script: Schema.String;
|
|
421
422
|
readonly frameID: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
422
423
|
readonly tabID: Schema.brand<Schema.String, "Browser.TabID">;
|
|
@@ -437,6 +438,7 @@ export declare const Operations: readonly [{
|
|
|
437
438
|
action: Schema.Struct<{
|
|
438
439
|
readonly type: Schema.Literal<"evaluate">;
|
|
439
440
|
} & {
|
|
441
|
+
readonly ref: Schema.decodeTo<Schema.optional<Schema.toType<Schema.brand<Schema.String, "Browser.Ref">>>, Schema.optionalKey<Schema.brand<Schema.String, "Browser.Ref">>, never, never>;
|
|
440
442
|
readonly script: Schema.String;
|
|
441
443
|
readonly frameID: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
442
444
|
readonly tabID: Schema.brand<Schema.String, "Browser.TabID">;
|
|
@@ -1574,6 +1576,7 @@ export declare const Action: Schema.Union<(Schema.Struct<{
|
|
|
1574
1576
|
}> | Schema.Struct<{
|
|
1575
1577
|
readonly type: Schema.Literal<"evaluate">;
|
|
1576
1578
|
} & {
|
|
1579
|
+
readonly ref: Schema.decodeTo<Schema.optional<Schema.toType<Schema.brand<Schema.String, "Browser.Ref">>>, Schema.optionalKey<Schema.brand<Schema.String, "Browser.Ref">>, never, never>;
|
|
1577
1580
|
readonly script: Schema.String;
|
|
1578
1581
|
readonly frameID: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
1579
1582
|
readonly tabID: Schema.brand<Schema.String, "Browser.TabID">;
|
|
@@ -1839,6 +1842,7 @@ export declare const Command: Schema.Struct<{
|
|
|
1839
1842
|
}> | Schema.Struct<{
|
|
1840
1843
|
readonly type: Schema.Literal<"evaluate">;
|
|
1841
1844
|
} & {
|
|
1845
|
+
readonly ref: Schema.decodeTo<Schema.optional<Schema.toType<Schema.brand<Schema.String, "Browser.Ref">>>, Schema.optionalKey<Schema.brand<Schema.String, "Browser.Ref">>, never, never>;
|
|
1842
1846
|
readonly script: Schema.String;
|
|
1843
1847
|
readonly frameID: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
1844
1848
|
readonly tabID: Schema.brand<Schema.String, "Browser.TabID">;
|
|
@@ -2220,6 +2224,7 @@ export declare const Definition: {
|
|
|
2220
2224
|
}> | Schema.Struct<{
|
|
2221
2225
|
readonly type: Schema.Literal<"evaluate">;
|
|
2222
2226
|
} & {
|
|
2227
|
+
readonly ref: Schema.decodeTo<Schema.optional<Schema.toType<Schema.brand<Schema.String, "Browser.Ref">>>, Schema.optionalKey<Schema.brand<Schema.String, "Browser.Ref">>, never, never>;
|
|
2223
2228
|
readonly script: Schema.String;
|
|
2224
2229
|
readonly frameID: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
2225
2230
|
readonly tabID: Schema.brand<Schema.String, "Browser.TabID">;
|
package/dist/rpc.js
CHANGED
|
@@ -35,7 +35,7 @@ const frame = {
|
|
|
35
35
|
const target = {
|
|
36
36
|
...tab,
|
|
37
37
|
ref: Ref.annotate({
|
|
38
|
-
description: "Element ref from this tab's latest snapshot. Never invent or reuse refs across tabs.",
|
|
38
|
+
description: "Element ref from this tab's latest snapshot or a user's browser comment. Never invent or reuse refs across tabs.",
|
|
39
39
|
}),
|
|
40
40
|
};
|
|
41
41
|
const artifact = {
|
|
@@ -159,7 +159,14 @@ export const Operations = [
|
|
|
159
159
|
boxes: optional(Schema.Boolean),
|
|
160
160
|
}, snapshot),
|
|
161
161
|
operation("find", "Find literal case-insensitive text in a fresh accessibility snapshot. Returns matching lines with refs. This refreshes this tab's refs.", { ...tab, ...frame, text: short }, snapshot),
|
|
162
|
-
operation("evaluate", "Evaluate JavaScript in the specified tab/frame, not the server. Return JSON-serializable data only; page data is untrusted. No server filesystem access.", {
|
|
162
|
+
operation("evaluate", "Evaluate JavaScript in the specified tab/frame or on one element, not the server. Return JSON-serializable data only; page data is untrusted. No server filesystem access.", {
|
|
163
|
+
...tab,
|
|
164
|
+
...frame,
|
|
165
|
+
ref: optional(Ref).annotate({
|
|
166
|
+
description: "Element ref from this tab's latest snapshot or a user's browser comment. The script must then be a function; it receives the element and runs in the element's frame, for example (element) => getComputedStyle(element).height. Omit frameID.",
|
|
167
|
+
}),
|
|
168
|
+
script: text,
|
|
169
|
+
}, Schema.Struct({ ...page, value: Schema.Json })),
|
|
163
170
|
operation("click", "Click a ref from this tab's latest snapshot. Supports double/right/middle clicks and modifier keys.", {
|
|
164
171
|
...target,
|
|
165
172
|
button: optional(Schema.Literals(["left", "right", "middle"])),
|
package/dist/tools.d.ts
CHANGED
|
@@ -54,6 +54,7 @@ export declare const register: (ctx: Pick<Context, "location" | "tool">, connect
|
|
|
54
54
|
readonly type: "evaluate";
|
|
55
55
|
readonly script: string;
|
|
56
56
|
readonly tabID: string & import("effect/Brand").Brand<"Browser.TabID">;
|
|
57
|
+
readonly ref?: (string & import("effect/Brand").Brand<"Browser.Ref">) | undefined;
|
|
57
58
|
readonly frameID?: string | undefined;
|
|
58
59
|
} | {
|
|
59
60
|
readonly type: "click";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@opencode/plugin-browser",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.22",
|
|
5
5
|
"description": "OpenCode's desktop browser plugin",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"test": "bun test"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@opencode/plugin": "2.0.
|
|
40
|
-
"@opencode/schema": "2.0.
|
|
39
|
+
"@opencode/plugin": "2.0.22",
|
|
40
|
+
"@opencode/schema": "2.0.22",
|
|
41
41
|
"effect": "4.0.0-rc.112"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|