@opencode/browse 0.0.6-dev.20 → 0.0.6-dev.21
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/dist/{cli-anqhds1e.mjs → cli-qcdv8aqh.mjs} +85 -84
- package/dist/cli.mjs +14 -9
- package/dist/{helpers-n4k4pdag.mjs → helpers-d74qp3s1.mjs} +2 -1
- package/dist/{main-ma25hhqh.mjs → main-0m569gdn.mjs} +165 -127
- package/dist/{main-3rsfghef.mjs → main-33kf3cfr.mjs} +12 -4
- package/dist/main-3gthmkzw.mjs +112 -0
- package/dist/{main-hywb9qbv.mjs → main-6bjnpchg.mjs} +4 -4
- package/dist/{main-20ahaz2q.mjs → main-7qs0mwvc.mjs} +1 -1
- package/dist/main-ek76h9k1.mjs +4 -0
- package/dist/{main-0nta0a2z.mjs → main-qm2keaeb.mjs} +18 -12
- package/dist/{main-42qfr69q.mjs → main-ybvatjk0.mjs} +5 -5
- package/dist/{main-yd1d7qr1.mjs → main-yq58hnwq.mjs} +10 -10
- package/dist/{mcp-j9e2da4y.mjs → mcp-qmq1yerr.mjs} +38 -39
- package/dist/{relay-cvhz2f0a.mjs → relay-446cn6cs.mjs} +95 -69
- package/dist/{runtime-update-baranjc5.mjs → runtime-update-fj4s270v.mjs} +6 -5
- package/dist/{setup-7shrgdza.mjs → setup-atsf76r6.mjs} +3844 -3132
- package/dist/skill-text-v35020jn.mjs +1007 -0
- package/dist/supervisor-bvnx7xgg.mjs +154 -0
- package/dist/{update-vkspb2rz.mjs → update-38wp6pt4.mjs} +4 -2
- package/dist/{version-gfpqxbzm.mjs → version-x7djen82.mjs} +1 -1
- package/package.json +3 -2
- package/skills/browse/SKILL.md +29 -29
- package/dist/main-arx3pfyn.mjs +0 -4
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
|
-
cliCommand,
|
|
3
|
-
installCommand,
|
|
4
|
-
npmRuntime,
|
|
5
2
|
unpackedExtensionId,
|
|
6
3
|
extensionReconnectAlarmPeriodMs,
|
|
7
4
|
extensionProtocolAdvice,
|
|
8
5
|
parseJsonObject
|
|
9
|
-
} from "./main-
|
|
6
|
+
} from "./main-3gthmkzw.mjs";
|
|
10
7
|
import {
|
|
11
8
|
relayAuthorization
|
|
12
|
-
} from "./main-
|
|
9
|
+
} from "./main-7qs0mwvc.mjs";
|
|
13
10
|
import {
|
|
14
11
|
opencodeBrowserBuildId2
|
|
15
|
-
} from "./main-
|
|
12
|
+
} from "./main-ek76h9k1.mjs";
|
|
13
|
+
import {
|
|
14
|
+
compiledBinary,
|
|
15
|
+
scriptEntry,
|
|
16
|
+
cliCommand,
|
|
17
|
+
installCommand,
|
|
18
|
+
npmRuntime
|
|
19
|
+
} from "./main-0m569gdn.mjs";
|
|
16
20
|
|
|
17
21
|
// src/relay/helpers.ts
|
|
18
22
|
import { Option, Predicate, Schema as Schema3 } from "effect";
|
|
@@ -1039,7 +1043,7 @@ var make = Effect2.fn("RelayClient.make")(function* (options) {
|
|
|
1039
1043
|
})));
|
|
1040
1044
|
}));
|
|
1041
1045
|
const transportError = (path) => (cause) => new RelayUnreachable({
|
|
1042
|
-
message: `
|
|
1046
|
+
message: `browse relay is not reachable at ${endpoint}. Relay-backed CLI commands start it automatically; use \`${cliCommand("serve")}\` only for foreground debugging.`,
|
|
1043
1047
|
endpoint,
|
|
1044
1048
|
path,
|
|
1045
1049
|
cause
|
|
@@ -1134,7 +1138,7 @@ function mcpClientPid() {
|
|
|
1134
1138
|
var layerFetchMcp = Layer.effect(Service, make({ clientPid: mcpClientPid() })).pipe(Layer.provide(NodeHttpClient.layerNodeHttp));
|
|
1135
1139
|
|
|
1136
1140
|
// src/relay/lifecycle.ts
|
|
1137
|
-
var loadedCliEntrypoint = fileURLToPath(new URL(import.meta.url.endsWith(".ts") ? "../main.ts" : "./cli.mjs", import.meta.url));
|
|
1141
|
+
var loadedCliEntrypoint = compiledBinary() ? process2.execPath : fileURLToPath(new URL(import.meta.url.endsWith(".ts") ? "../main.ts" : "./cli.mjs", import.meta.url));
|
|
1138
1142
|
var clientInstanceId = crypto2.randomUUID();
|
|
1139
1143
|
function shouldWaitForExtensionReconnect(readiness) {
|
|
1140
1144
|
return readiness.started || readiness.waitForReconnect === true;
|
|
@@ -1212,7 +1216,7 @@ function waitForRelayReady(options) {
|
|
|
1212
1216
|
schedule: Schedule.spaced(options.retryDelayMs ?? 50),
|
|
1213
1217
|
while: isRelayStartingOrUnreachable
|
|
1214
1218
|
}), Effect3.mapError((error) => isRelayStartingOrUnreachable(error) ? new RelayStartFailed({
|
|
1215
|
-
message: `
|
|
1219
|
+
message: `browse relay did not start at ${options.relay.endpoint}`,
|
|
1216
1220
|
endpoint: options.relay.endpoint,
|
|
1217
1221
|
cause: error
|
|
1218
1222
|
}) : error));
|
|
@@ -1285,7 +1289,7 @@ var restartRelay = Effect3.fn("RelayLifecycle.restartRelay")(function* (options)
|
|
|
1285
1289
|
return { version: replacement, started, waitForReconnect: true };
|
|
1286
1290
|
});
|
|
1287
1291
|
function waitForRelayExitOrReplacement(options) {
|
|
1288
|
-
return options.relay.version.pipe(Effect3.flatMap((version) => isSameRelayInstance(options.version, version) ? Effect3.fail(new RelayStillRunning("
|
|
1292
|
+
return options.relay.version.pipe(Effect3.flatMap((version) => isSameRelayInstance(options.version, version) ? Effect3.fail(new RelayStillRunning("browse relay is still draining; no replacement was started")) : Effect3.succeed(version)), Effect3.catch((error) => isRelayUnreachable(error) ? Effect3.succeed(undefined) : Effect3.fail(error)), Effect3.retry({
|
|
1289
1293
|
times: options.retryTimes ?? 200,
|
|
1290
1294
|
schedule: Schedule.spaced(options.retryDelayMs ?? 50),
|
|
1291
1295
|
while: (error) => error instanceof RelayStillRunning || isRelayStarting(error)
|
|
@@ -1318,7 +1322,7 @@ var ensureExtensionConnected = Effect3.fn("RelayLifecycle.ensureExtensionConnect
|
|
|
1318
1322
|
}));
|
|
1319
1323
|
}
|
|
1320
1324
|
return status.connected ? Effect3.succeed(status) : Effect3.fail(new ExtensionDisconnected({
|
|
1321
|
-
message: status.nextStep ?? `
|
|
1325
|
+
message: status.nextStep ?? `browse extension is not connected. Open the browser with browse installed (\`${installCommand()}\`); it reconnects automatically after relay or browser startup.`,
|
|
1322
1326
|
needsPairing: status.pairingState === "refused" || status.pairingState === "unpaired"
|
|
1323
1327
|
}));
|
|
1324
1328
|
}));
|
|
@@ -1358,7 +1362,7 @@ function startManagedRelay(entrypoint = loadedCliEntrypoint, executable = proces
|
|
|
1358
1362
|
});
|
|
1359
1363
|
child.unref();
|
|
1360
1364
|
},
|
|
1361
|
-
catch: (cause) => cause instanceof Error ? cause : new Error("Failed to start
|
|
1365
|
+
catch: (cause) => cause instanceof Error ? cause : new Error("Failed to start browse relay", { cause })
|
|
1362
1366
|
});
|
|
1363
1367
|
}
|
|
1364
1368
|
var relayEnvironmentNames = new Set([
|
|
@@ -1410,6 +1414,8 @@ function relayEnvironment(env) {
|
|
|
1410
1414
|
}));
|
|
1411
1415
|
}
|
|
1412
1416
|
function managedRelayLaunch(entrypoint = loadedCliEntrypoint, executable = process2.execPath, execArgv = process2.execArgv) {
|
|
1417
|
+
if (!scriptEntry(entrypoint))
|
|
1418
|
+
return { executable: entrypoint, args: ["serve"] };
|
|
1413
1419
|
return {
|
|
1414
1420
|
executable,
|
|
1415
1421
|
args: [...execArgv, managedRelayEntrypoint(entrypoint), "serve"]
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isNodeError
|
|
3
|
-
} from "./main-
|
|
4
|
-
import {
|
|
5
|
-
dataRoot
|
|
6
|
-
} from "./main-ma25hhqh.mjs";
|
|
3
|
+
} from "./main-7qs0mwvc.mjs";
|
|
7
4
|
import {
|
|
8
5
|
isValidSessionId2
|
|
9
|
-
} from "./main-
|
|
6
|
+
} from "./main-qm2keaeb.mjs";
|
|
7
|
+
import {
|
|
8
|
+
dataRoot
|
|
9
|
+
} from "./main-0m569gdn.mjs";
|
|
10
10
|
|
|
11
11
|
// src/session-manager/journal.ts
|
|
12
12
|
import fs from "node:fs";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
dataRoot,
|
|
3
|
-
cliCommand
|
|
4
|
-
} from "./main-ma25hhqh.mjs";
|
|
5
1
|
import {
|
|
6
2
|
parseTargetSelection2,
|
|
7
3
|
getObject2,
|
|
8
4
|
getString2
|
|
9
|
-
} from "./main-
|
|
5
|
+
} from "./main-qm2keaeb.mjs";
|
|
10
6
|
import {
|
|
11
7
|
isNodeError,
|
|
12
8
|
writeJsonFileAtomically
|
|
13
|
-
} from "./main-
|
|
9
|
+
} from "./main-7qs0mwvc.mjs";
|
|
10
|
+
import {
|
|
11
|
+
dataRoot,
|
|
12
|
+
cliCommand
|
|
13
|
+
} from "./main-0m569gdn.mjs";
|
|
14
14
|
|
|
15
15
|
// src/relay/user-settings.ts
|
|
16
16
|
var settingKeys = ["window", "grouping", "idleMinutes", "cursor", "humanInput", "handoffNotifications", "autoUpdate"];
|
|
@@ -145,7 +145,7 @@ function browsersNote2(browsers) {
|
|
|
145
145
|
return ` Connected browsers: ${list}. Pass browser to use one other than the default.`;
|
|
146
146
|
}
|
|
147
147
|
function mcpUpdateNote2(notice) {
|
|
148
|
-
return `Note:
|
|
148
|
+
return `Note: browse has an update: ${notice.summary}. Tell the user they can run \`${notice.command}\` and then restart opencode, or ask you to run it for them.`;
|
|
149
149
|
}
|
|
150
150
|
function objectSchema(properties, required = []) {
|
|
151
151
|
return {
|
|
@@ -410,7 +410,7 @@ function errorCode(code) {
|
|
|
410
410
|
}
|
|
411
411
|
var errorHints = {
|
|
412
412
|
locked: "Deadbolt is locked, so agent sign-ins are paused until the user unlocks it.",
|
|
413
|
-
forbidden: "Deadbolt doesn't know this
|
|
413
|
+
forbidden: "Deadbolt doesn't know this browse install (its client was removed or revoked). Ask the user to run `opencode-browser deadbolt connect`.",
|
|
414
414
|
rate_limited: "Deadbolt is rate-limiting this client; wait before trying again."
|
|
415
415
|
};
|
|
416
416
|
function rawRequest(socket, request, timeoutMs = requestTimeoutMs) {
|
|
@@ -502,7 +502,7 @@ function toLogin(raw) {
|
|
|
502
502
|
function connect(options = {}) {
|
|
503
503
|
const client = options.client ?? readClient(options.root);
|
|
504
504
|
if (!client) {
|
|
505
|
-
throw new DeadboltError("not_connected", "
|
|
505
|
+
throw new DeadboltError("not_connected", "browse isn't connected to Deadbolt. Ask the user to run `opencode-browser deadbolt connect` and to allow the logins agents may use with `deadbolt agents allow <site>`.");
|
|
506
506
|
}
|
|
507
507
|
const socket = options.socket ?? socketPath();
|
|
508
508
|
let protocol;
|
|
@@ -604,7 +604,7 @@ function pickLogin(logins, site, username, field) {
|
|
|
604
604
|
if (candidates.length === 1)
|
|
605
605
|
return candidates[0];
|
|
606
606
|
if (candidates.length === 0) {
|
|
607
|
-
throw new DeadboltError("not_granted", username === undefined ? `No Deadbolt login is granted to
|
|
607
|
+
throw new DeadboltError("not_granted", username === undefined ? `No Deadbolt login is granted to browse for ${site}${field ? ` (${field})` : ""}. Ask the user to allow one with \`deadbolt agents allow ${site}\`.` : `No Deadbolt login for ${username} is granted to browse for ${site}${field ? ` (${field})` : ""}. Ask the user to allow it with \`deadbolt agents allow ${site} --login ${username}\`.`, { site, ...username ? { login: username } : {} });
|
|
608
608
|
}
|
|
609
609
|
throw new DeadboltError("failed", `Several Deadbolt logins are granted for ${site}; name one: deadbolt:${site}/<username> (${candidates.map((login) => login.username ?? login.title).join(", ")})`);
|
|
610
610
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
opencodeBrowserVersion2
|
|
3
|
+
} from "./main-ek76h9k1.mjs";
|
|
1
4
|
import {
|
|
2
5
|
autoUpdateStatus
|
|
3
|
-
} from "./main-
|
|
6
|
+
} from "./main-0m569gdn.mjs";
|
|
7
|
+
import"./main-3gthmkzw.mjs";
|
|
4
8
|
import {
|
|
5
9
|
getObject2,
|
|
6
10
|
Service,
|
|
@@ -8,15 +12,12 @@ import {
|
|
|
8
12
|
relayBuildProblem,
|
|
9
13
|
ensureRelay,
|
|
10
14
|
ensureExtensionConnected
|
|
11
|
-
} from "./main-
|
|
12
|
-
import"./main-
|
|
13
|
-
import {
|
|
14
|
-
opencodeBrowserVersion2
|
|
15
|
-
} from "./main-arx3pfyn.mjs";
|
|
15
|
+
} from "./main-qm2keaeb.mjs";
|
|
16
|
+
import"./main-7qs0mwvc.mjs";
|
|
16
17
|
import {
|
|
17
18
|
updateJson2,
|
|
18
19
|
createUpdateWatcher2
|
|
19
|
-
} from "./main-
|
|
20
|
+
} from "./main-33kf3cfr.mjs";
|
|
20
21
|
import {
|
|
21
22
|
settingKeys,
|
|
22
23
|
settingSpecs,
|
|
@@ -42,19 +43,17 @@ import {
|
|
|
42
43
|
toolResult,
|
|
43
44
|
readClient,
|
|
44
45
|
listSecrets
|
|
45
|
-
} from "./main-
|
|
46
|
+
} from "./main-yq58hnwq.mjs";
|
|
46
47
|
|
|
47
48
|
// src/mcp.ts
|
|
48
49
|
import { NodeStdio } from "@effect/platform-node";
|
|
49
50
|
import { Config, Context, Effect as Effect7, Layer, Option, Schedule } from "effect";
|
|
50
51
|
import { McpProtocol, McpSchema, McpServer } from "effect/ai";
|
|
51
|
-
import
|
|
52
|
+
import path4 from "node:path";
|
|
52
53
|
import { fileURLToPath } from "node:url";
|
|
53
54
|
|
|
54
55
|
// src/mcp/browser.ts
|
|
55
56
|
import { Effect } from "effect";
|
|
56
|
-
import fs from "node:fs/promises";
|
|
57
|
-
import path from "node:path";
|
|
58
57
|
|
|
59
58
|
// src/mcp/registry.ts
|
|
60
59
|
var groups = [];
|
|
@@ -128,7 +127,7 @@ registerMcpTools({
|
|
|
128
127
|
build: (ctx) => [
|
|
129
128
|
{
|
|
130
129
|
name: "tabs_cleanup",
|
|
131
|
-
description: "Close tabs agents opened that nobody has used for a while (no agent command and not visited by the user). Tabs the user shared or pinned, the active tab, tabs playing audio, recording, or waiting for a handoff stay open. Call it when you finish a task to leave the user's browser tidy;
|
|
130
|
+
description: "Close tabs agents opened that nobody has used for a while (no agent command and not visited by the user). Tabs the user shared or pinned, the active tab, tabs playing audio, recording, or waiting for a handoff stay open. Call it when you finish a task to leave the user's browser tidy; browse also does this automatically after the user's idle setting (10 minutes unless they changed it).",
|
|
132
131
|
inputSchema: objectSchema({
|
|
133
132
|
idleMinutes: {
|
|
134
133
|
type: "integer",
|
|
@@ -146,7 +145,7 @@ registerMcpTools({
|
|
|
146
145
|
},
|
|
147
146
|
{
|
|
148
147
|
name: "settings",
|
|
149
|
-
description: `Read or change the user's
|
|
148
|
+
description: `Read or change the user's browse settings, the same ones as the extension's options page: where agent tabs open (window), how they're grouped (grouping), when untouched agent tabs close (idleMinutes), the agent cursor (cursor), human-like input (humanInput) and handoff notifications (handoffNotifications). Use it only when the user asks to change how browse behaves, never on your own initiative. Without \`set\` it returns each setting's stored value, the value in effect, and the relay environment variable that overrides it, if any. With \`set\` it validates every value strictly, applies the change at once (the options page updates live) and returns what changed: tell the user what you changed. A setting an environment variable fixes is not changed, and the result says so. Security switches (${securityVariables.join(", ")}) are environment-only and can never be read or changed here.`,
|
|
150
149
|
inputSchema: objectSchema({
|
|
151
150
|
set: {
|
|
152
151
|
type: "object",
|
|
@@ -174,13 +173,13 @@ registerMcpTools({
|
|
|
174
173
|
{
|
|
175
174
|
name: "skill",
|
|
176
175
|
requiresRelayCompatibility: false,
|
|
177
|
-
description: "Return the
|
|
176
|
+
description: "Return the browse agent skill instructions.",
|
|
178
177
|
inputSchema: emptyInputSchema,
|
|
179
178
|
readOnly: true,
|
|
180
179
|
destructive: false,
|
|
181
180
|
idempotent: true,
|
|
182
181
|
handle: () => Effect.tryPromise({
|
|
183
|
-
try: () =>
|
|
182
|
+
try: () => import("./skill-text-v35020jn.mjs").then((module) => module.skillText),
|
|
184
183
|
catch: (cause) => new Error("read opencode-browser skill", { cause })
|
|
185
184
|
})
|
|
186
185
|
}
|
|
@@ -195,7 +194,7 @@ registerMcpTools({
|
|
|
195
194
|
{
|
|
196
195
|
name: "execute",
|
|
197
196
|
listsBrowsers: true,
|
|
198
|
-
description: `Execute Playwright JavaScript against the
|
|
197
|
+
description: `Execute Playwright JavaScript against the browse session. Code runs in a sandbox on the relay without process, require, import(), fs, child_process, http/https or Node fetch; save and read files with the files helper inside the execute file roots, and cookie access is limited to the session's pages. The result includes console logs, warnings, a bounded execution-context diagnostic when relevant, and an aftermath summary (URL movement, navigations, error counts, handoffs, and a bot challenge or block page when one appears: hand interactive ones to the user with handoff(), never solve or retry-loop them).${ctx.browserNote}`,
|
|
199
198
|
inputSchema: objectSchema({
|
|
200
199
|
code: {
|
|
201
200
|
type: "string",
|
|
@@ -203,7 +202,7 @@ registerMcpTools({
|
|
|
203
202
|
},
|
|
204
203
|
session: {
|
|
205
204
|
type: "string",
|
|
206
|
-
description: "Optional existing
|
|
205
|
+
description: "Optional existing browse session id. Explicit ids must already exist; omit this field to use the MCP server's current session, which is created when needed."
|
|
207
206
|
},
|
|
208
207
|
targetUrl: {
|
|
209
208
|
type: "string",
|
|
@@ -249,13 +248,13 @@ registerMcpTools({
|
|
|
249
248
|
|
|
250
249
|
// src/mcp/network.ts
|
|
251
250
|
import { Effect as Effect3 } from "effect";
|
|
252
|
-
import
|
|
251
|
+
import path from "node:path";
|
|
253
252
|
registerMcpTools({
|
|
254
253
|
order: 300,
|
|
255
254
|
build: (ctx) => [
|
|
256
255
|
{
|
|
257
256
|
name: "network_start",
|
|
258
|
-
description: "Start session-scoped network capture.
|
|
257
|
+
description: "Start session-scoped network capture. browse records normalized Playwright exchanges; HAR is only the optional export format. Bodies are embedded by default with per-body and total memory limits.",
|
|
259
258
|
inputSchema: objectSchema({
|
|
260
259
|
session: {
|
|
261
260
|
type: "string",
|
|
@@ -367,7 +366,7 @@ registerMcpTools({
|
|
|
367
366
|
}
|
|
368
367
|
return yield* ctx.relay.networkStop({
|
|
369
368
|
sessionId,
|
|
370
|
-
...outputPath ? { outputPath:
|
|
369
|
+
...outputPath ? { outputPath: path.resolve(outputPath) } : {},
|
|
371
370
|
...secrets ? { secrets } : {}
|
|
372
371
|
});
|
|
373
372
|
})
|
|
@@ -386,7 +385,7 @@ registerMcpTools({
|
|
|
386
385
|
|
|
387
386
|
// src/mcp/recording.ts
|
|
388
387
|
import { Effect as Effect4 } from "effect";
|
|
389
|
-
import
|
|
388
|
+
import path2 from "node:path";
|
|
390
389
|
registerMcpTools({
|
|
391
390
|
order: 400,
|
|
392
391
|
build: (ctx) => [
|
|
@@ -409,7 +408,7 @@ registerMcpTools({
|
|
|
409
408
|
maxDurationMs: { type: "integer", minimum: 1, description: "Maximum recording duration in milliseconds." },
|
|
410
409
|
cursor: {
|
|
411
410
|
type: "boolean",
|
|
412
|
-
description: "Draw the ghost cursor in the recording, for demo videos. Off by default: recordings show only the page, with nothing from
|
|
411
|
+
description: "Draw the ghost cursor in the recording, for demo videos. Off by default: recordings show only the page, with nothing from browse in the frame."
|
|
413
412
|
}
|
|
414
413
|
}, ["outputPath"]),
|
|
415
414
|
readOnly: false,
|
|
@@ -429,7 +428,7 @@ registerMcpTools({
|
|
|
429
428
|
const cursor = optionalBooleanField(object, "cursor");
|
|
430
429
|
return ctx.relay.recordingStart({
|
|
431
430
|
sessionId: ctx.resolveSessionId(object),
|
|
432
|
-
outputPath:
|
|
431
|
+
outputPath: path2.resolve(requiredStringField(object, "outputPath")),
|
|
433
432
|
...mode ? { mode } : {},
|
|
434
433
|
...audio === undefined ? {} : { audio },
|
|
435
434
|
...frameRate === undefined ? {} : { frameRate },
|
|
@@ -539,7 +538,7 @@ registerMcpTools({
|
|
|
539
538
|
const durationMs = optionalPositiveIntegerField(object, "durationMs");
|
|
540
539
|
return ctx.relay.flightRecorderSaveLast({
|
|
541
540
|
sessionId: ctx.resolveSessionId(object),
|
|
542
|
-
outputPath:
|
|
541
|
+
outputPath: path2.resolve(requiredStringField(object, "outputPath")),
|
|
543
542
|
...durationMs === undefined ? {} : { durationMs }
|
|
544
543
|
});
|
|
545
544
|
}
|
|
@@ -558,14 +557,14 @@ registerMcpTools({
|
|
|
558
557
|
|
|
559
558
|
// src/mcp/secrets.ts
|
|
560
559
|
import { Effect as Effect5 } from "effect";
|
|
561
|
-
import
|
|
560
|
+
import path3 from "node:path";
|
|
562
561
|
registerMcpTools({
|
|
563
562
|
order: 600,
|
|
564
563
|
build: (ctx) => [
|
|
565
564
|
{
|
|
566
565
|
name: "secrets_list",
|
|
567
566
|
requiresRelayCompatibility: false,
|
|
568
|
-
description: 'List what agents may type without seeing: site secrets the user stored (names, kinds and allowed origins; type them with secrets.type(target, name) in execute; only the user adds them with `opencode-browser secrets add`), and Deadbolt logins the user granted to
|
|
567
|
+
description: 'List what agents may type without seeing: site secrets the user stored (names, kinds and allowed origins; type them with secrets.type(target, name) in execute; only the user adds them with `opencode-browser secrets add`), and Deadbolt logins the user granted to browse for this session\'s allowed sites (title, username, which values and passkeys, never values; sign in with the signin tool or secrets.signIn(), or type one value with secrets.type(target, "deadbolt:<site>[/<username>]", { field })). Passkeys are listed by account (username, displayName). Only the user grants Deadbolt logins, in Deadbolt (`deadbolt agents allow <site>`, or `deadbolt agents allow --all`).',
|
|
569
568
|
inputSchema: sessionOnlyInputSchema,
|
|
570
569
|
readOnly: true,
|
|
571
570
|
destructive: false,
|
|
@@ -579,7 +578,7 @@ registerMcpTools({
|
|
|
579
578
|
connected: false,
|
|
580
579
|
logins: [],
|
|
581
580
|
passkeys: [],
|
|
582
|
-
note: "
|
|
581
|
+
note: "browse isn't connected to Deadbolt. The user can connect it with `opencode-browser deadbolt connect` and grant logins with `deadbolt agents allow <site>`."
|
|
583
582
|
}
|
|
584
583
|
};
|
|
585
584
|
}
|
|
@@ -595,7 +594,7 @@ registerMcpTools({
|
|
|
595
594
|
},
|
|
596
595
|
{
|
|
597
596
|
name: "signin",
|
|
598
|
-
description: 'Sign in to a site in the session\'s page with a Deadbolt login the user granted to
|
|
597
|
+
description: 'Sign in to a site in the session\'s page with a Deadbolt login the user granted to browse, without seeing any value. The relay does the whole sign-in in one call: username, submit, password, an authenticator (TOTP) code when asked (split boxes too), "Use password instead" toggles, and Sign in with Google when a Google login is granted. A username also picks the passkey account when the site signs in with a passkey. Returns only {status: signed_in | needs_user | needs_choice | not_granted | failed, step, reason}; needs_choice comes with choices [{username, displayName}] when several passkeys could sign in: call again with one username. needs_user means a captcha, a code sent by SMS or email, a push approval or a new-device check: hand it to the user with handoff() in execute. not_granted: tell the user what to allow (`deadbolt agents allow <site>`). Navigate to the sign-in page first, or pass site.',
|
|
599
598
|
inputSchema: objectSchema({
|
|
600
599
|
site: {
|
|
601
600
|
type: "string",
|
|
@@ -697,7 +696,7 @@ registerMcpTools({
|
|
|
697
696
|
name: requiredStringField(object, "name"),
|
|
698
697
|
command: requiredStringField(object, "command"),
|
|
699
698
|
...args ? { args } : {},
|
|
700
|
-
cwd:
|
|
699
|
+
cwd: path3.resolve(cwd ?? process.cwd()),
|
|
701
700
|
...timeoutMs === undefined ? {} : { timeoutMs }
|
|
702
701
|
});
|
|
703
702
|
}
|
|
@@ -713,7 +712,7 @@ registerMcpTools({
|
|
|
713
712
|
{
|
|
714
713
|
name: "session_new",
|
|
715
714
|
listsBrowsers: true,
|
|
716
|
-
description: `Create a
|
|
715
|
+
description: `Create a browse session and make it current for this MCP server.${ctx.browserNote}`,
|
|
717
716
|
inputSchema: objectSchema({
|
|
718
717
|
browser: ctx.browserProperty,
|
|
719
718
|
id: { type: "string", description: "Optional lowercase session id." },
|
|
@@ -770,7 +769,7 @@ registerMcpTools({
|
|
|
770
769
|
{
|
|
771
770
|
name: "session_list",
|
|
772
771
|
requiresRelayCompatibility: false,
|
|
773
|
-
description: "List
|
|
772
|
+
description: "List browse sessions.",
|
|
774
773
|
inputSchema: emptyInputSchema,
|
|
775
774
|
readOnly: true,
|
|
776
775
|
destructive: false,
|
|
@@ -780,7 +779,7 @@ registerMcpTools({
|
|
|
780
779
|
{
|
|
781
780
|
name: "session_current",
|
|
782
781
|
requiresRelayCompatibility: false,
|
|
783
|
-
description: "Return this MCP server's current
|
|
782
|
+
description: "Return this MCP server's current browse session id.",
|
|
784
783
|
inputSchema: emptyInputSchema,
|
|
785
784
|
readOnly: true,
|
|
786
785
|
destructive: false,
|
|
@@ -789,9 +788,9 @@ registerMcpTools({
|
|
|
789
788
|
},
|
|
790
789
|
{
|
|
791
790
|
name: "session_use",
|
|
792
|
-
description: "Set this MCP server's current
|
|
791
|
+
description: "Set this MCP server's current browse session id.",
|
|
793
792
|
inputSchema: objectSchema({
|
|
794
|
-
id: { type: "string", description: "Existing
|
|
793
|
+
id: { type: "string", description: "Existing browse session id." }
|
|
795
794
|
}, ["id"]),
|
|
796
795
|
readOnly: false,
|
|
797
796
|
destructive: false,
|
|
@@ -805,7 +804,7 @@ registerMcpTools({
|
|
|
805
804
|
},
|
|
806
805
|
{
|
|
807
806
|
name: "session_reset",
|
|
808
|
-
description: "Reset a
|
|
807
|
+
description: "Reset a browse session's state and page.",
|
|
809
808
|
inputSchema: objectSchema({
|
|
810
809
|
id: sessionSchemaProperty,
|
|
811
810
|
session: sessionAliasSchemaProperty
|
|
@@ -822,7 +821,7 @@ registerMcpTools({
|
|
|
822
821
|
},
|
|
823
822
|
{
|
|
824
823
|
name: "session_delete",
|
|
825
|
-
description: "Delete a
|
|
824
|
+
description: "Delete a browse session.",
|
|
826
825
|
inputSchema: objectSchema({
|
|
827
826
|
id: sessionSchemaProperty,
|
|
828
827
|
session: sessionAliasSchemaProperty
|
|
@@ -842,11 +841,11 @@ registerMcpTools({
|
|
|
842
841
|
},
|
|
843
842
|
{
|
|
844
843
|
name: "session_adopt",
|
|
845
|
-
description: "Make an attached tab the
|
|
844
|
+
description: "Make an attached tab the browse session's default page for subsequent bare execute calls. Omit targetUrl and targetIndex when only one user-attached tab is available.",
|
|
846
845
|
inputSchema: objectSchema({
|
|
847
846
|
session: {
|
|
848
847
|
type: "string",
|
|
849
|
-
description: "Optional existing
|
|
848
|
+
description: "Optional existing browse session id. Explicit ids must already exist; omit this field to use the MCP server's current session, which is created when needed."
|
|
850
849
|
},
|
|
851
850
|
targetUrl: {
|
|
852
851
|
type: "string",
|
|
@@ -885,7 +884,7 @@ registerMcpTools({
|
|
|
885
884
|
});
|
|
886
885
|
|
|
887
886
|
// src/mcp.ts
|
|
888
|
-
var packageRoot =
|
|
887
|
+
var packageRoot = path4.dirname(path4.dirname(fileURLToPath(import.meta.url)));
|
|
889
888
|
function shimSession() {
|
|
890
889
|
const value = process.env.OPENCODE_BROWSER_MCP_SESSION;
|
|
891
890
|
return value && /^mcp-[0-9a-f]{8}$/.test(value) ? value : undefined;
|