@opencode/browse 0.0.6-dev.25 → 0.0.6-dev.28
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-df3reayk.mjs → cli-wgxfjgb3.mjs} +10 -67
- package/dist/cli.mjs +12 -13
- package/dist/{helpers-wjdq3qza.mjs → helpers-3fm1nwkt.mjs} +1 -1
- package/dist/main-4t3a1fw9.mjs +4 -0
- package/dist/{main-7pxrvrp0.mjs → main-8h1nwn45.mjs} +4 -34
- package/dist/{main-hh2mneh8.mjs → main-8ncff5jp.mjs} +4 -3
- package/dist/{main-xj8td7qw.mjs → main-rsqahh12.mjs} +33 -468
- package/dist/{main-spqvtmdy.mjs → main-scyv26xb.mjs} +2 -2
- package/dist/{main-mm82qqzb.mjs → main-tfkqwwrb.mjs} +3 -3
- package/dist/{main-tf22ynec.mjs → main-x8w3s3rv.mjs} +1 -1
- package/dist/{main-e83a20ce.mjs → main-xg3r1ze3.mjs} +2 -2
- package/dist/{mcp-dm33x3m1.mjs → mcp-7jjntfwf.mjs} +11 -78
- package/dist/{relay-qqjvahw5.mjs → relay-epeqzmcr.mjs} +38 -1107
- package/dist/{runtime-update-ypj67htb.mjs → runtime-update-3925nwpw.mjs} +4 -4
- package/dist/{setup-wwftne2g.mjs → setup-ys0qf6by.mjs} +20 -67
- package/dist/{skill-text-v35020jn.mjs → skill-text-rc6te209.mjs} +2 -78
- package/dist/{supervisor-sdq88esk.mjs → supervisor-yb615ygt.mjs} +3 -3
- package/dist/{update-fgnt6628.mjs → update-wjkqfk5f.mjs} +3 -3
- package/dist/{version-gv6f38gy.mjs → version-rh26jqa2.mjs} +1 -1
- package/package.json +1 -1
- package/skills/browse/SKILL.md +2 -78
- package/dist/main-sdmv8gfv.mjs +0 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import"./main-
|
|
1
|
+
import"./main-4t3a1fw9.mjs";
|
|
2
2
|
import {
|
|
3
3
|
cliCommand,
|
|
4
4
|
installCommand,
|
|
@@ -17,15 +17,15 @@ import {
|
|
|
17
17
|
installVersion,
|
|
18
18
|
pruneVersions,
|
|
19
19
|
switchVersion
|
|
20
|
-
} from "./main-
|
|
20
|
+
} from "./main-8ncff5jp.mjs";
|
|
21
21
|
import"./main-3gthmkzw.mjs";
|
|
22
22
|
import {
|
|
23
23
|
Service,
|
|
24
24
|
layerFetch,
|
|
25
25
|
restartRelay,
|
|
26
26
|
startManagedRelay
|
|
27
|
-
} from "./main-
|
|
28
|
-
import"./main-
|
|
27
|
+
} from "./main-8h1nwn45.mjs";
|
|
28
|
+
import"./main-x8w3s3rv.mjs";
|
|
29
29
|
|
|
30
30
|
// src/update/runtime-update.ts
|
|
31
31
|
import { Effect } from "effect";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
opencodeBrowserVersion2
|
|
3
|
-
} from "./main-
|
|
3
|
+
} from "./main-4t3a1fw9.mjs";
|
|
4
4
|
import {
|
|
5
5
|
dataRoot,
|
|
6
6
|
oldStoreMarker,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
entryCommand,
|
|
10
10
|
runningEntry,
|
|
11
11
|
cliCommand,
|
|
12
|
+
PUBLIC_STORE_ID,
|
|
12
13
|
storeConfig,
|
|
13
14
|
devExtension,
|
|
14
15
|
devExtensionFolder,
|
|
@@ -24,10 +25,10 @@ import {
|
|
|
24
25
|
installVersion,
|
|
25
26
|
pruneVersions,
|
|
26
27
|
switchVersion
|
|
27
|
-
} from "./main-
|
|
28
|
+
} from "./main-8ncff5jp.mjs";
|
|
28
29
|
import {
|
|
29
30
|
relayAuthorization
|
|
30
|
-
} from "./main-
|
|
31
|
+
} from "./main-x8w3s3rv.mjs";
|
|
31
32
|
import {
|
|
32
33
|
parseHostname,
|
|
33
34
|
readRelayConfig,
|
|
@@ -44,10 +45,9 @@ import {
|
|
|
44
45
|
legacyPairingCode,
|
|
45
46
|
removeLegacyPairingCode,
|
|
46
47
|
syncDevExtension
|
|
47
|
-
} from "./main-
|
|
48
|
+
} from "./main-xg3r1ze3.mjs";
|
|
48
49
|
import {
|
|
49
50
|
unpackedExtensionId,
|
|
50
|
-
unpackedReloadAdvice,
|
|
51
51
|
extensionProtocolSkew,
|
|
52
52
|
extensionProtocolAdvice
|
|
53
53
|
} from "./main-3gthmkzw.mjs";
|
|
@@ -10803,9 +10803,9 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
10803
10803
|
import { homedir } from "node:os";
|
|
10804
10804
|
import path2 from "node:path";
|
|
10805
10805
|
import { fileURLToPath } from "node:url";
|
|
10806
|
-
var
|
|
10807
|
-
var STORE_IDS = [
|
|
10808
|
-
var STORE_URL =
|
|
10806
|
+
var storeId = storeConfig().id ?? PUBLIC_STORE_ID;
|
|
10807
|
+
var STORE_IDS = [storeId];
|
|
10808
|
+
var STORE_URL = storeUrl(storeId);
|
|
10809
10809
|
var PACKAGE = "@opencode/browse";
|
|
10810
10810
|
var MCP_NAME = "browse";
|
|
10811
10811
|
var LEGACY_MCP_NAME = "opencode-browser";
|
|
@@ -10841,7 +10841,7 @@ var checkoutExtensionDirs = (() => {
|
|
|
10841
10841
|
})();
|
|
10842
10842
|
var dev = fromSource ? undefined : devExtension();
|
|
10843
10843
|
var unpackedFolder = () => checkoutExtensionDirs[1] ?? (dev ? devExtensionFolder(root) : undefined);
|
|
10844
|
-
var connectedMessage = "✓ Connected to your browser.
|
|
10844
|
+
var connectedMessage = "✓ Connected to your browser. Ask your agent to open a page.";
|
|
10845
10845
|
var pairedOfflineMessage = "! Not connected yet. Open the browser profile already paired with browse and make sure the extension is enabled. It reconnects automatically.";
|
|
10846
10846
|
var manualPair = (code) => `Open the Extensions menu → browse → Options, enter ${formatPairingCode(code)} as the pairing code, then click Pair.`;
|
|
10847
10847
|
function flag(args, name) {
|
|
@@ -11008,10 +11008,6 @@ function browsers() {
|
|
|
11008
11008
|
browser("Helium", configRoot, "net.imput.helium", ["helium", "helium-browser"])
|
|
11009
11009
|
];
|
|
11010
11010
|
}
|
|
11011
|
-
function extensionsPage(browser) {
|
|
11012
|
-
const scheme = { "Microsoft Edge": "edge", Brave: "brave", Vivaldi: "vivaldi", Opera: "opera" }[browser.name];
|
|
11013
|
-
return `${scheme ?? "chrome"}://extensions`;
|
|
11014
|
-
}
|
|
11015
11011
|
function detectBrowsers() {
|
|
11016
11012
|
return browsers().flatMap((browser) => {
|
|
11017
11013
|
const state = readLocked(path3.join(browser.userData, "Local State"));
|
|
@@ -11298,24 +11294,11 @@ ${block}`, `
|
|
|
11298
11294
|
function locateExtension(options, effects = systemEffects) {
|
|
11299
11295
|
const { log } = effects;
|
|
11300
11296
|
const listing = options.storeUrl ?? STORE_URL;
|
|
11301
|
-
const noListing = () => log(`! This package doesn't know its Chrome Web Store item, so it can't install the extension. Install a released version (\`npx @opencode/browse install\`), or set up browse from a checkout.`);
|
|
11302
|
-
const pairLater = () => log(` Once it's added, run \`${cliCommand("install")}\` again to pair it with the relay.`);
|
|
11303
11297
|
if (options.pairedOffline)
|
|
11304
11298
|
return log(pairedOfflineMessage), "ready";
|
|
11305
|
-
if (options.env.ssh) {
|
|
11306
|
-
if (options.connected)
|
|
11307
|
-
return log(connectedMessage), "ready";
|
|
11308
|
-
if (options.folder)
|
|
11309
|
-
unpackedSteps({ folder: options.folder, platform: options.env.platform, log });
|
|
11310
|
-
else if (listing)
|
|
11311
|
-
log(`Install browse in your browser from the Chrome Web Store: ${listing}`), pairLater();
|
|
11312
|
-
else
|
|
11313
|
-
noListing();
|
|
11314
|
-
return "guided";
|
|
11315
|
-
}
|
|
11316
11299
|
if (options.connected)
|
|
11317
11300
|
return log(connectedMessage), "ready";
|
|
11318
|
-
if (options.detections.some((detection) => detection.enabled.length))
|
|
11301
|
+
if (!options.env.ssh && options.detections.some((detection) => detection.enabled.length))
|
|
11319
11302
|
return "ready";
|
|
11320
11303
|
const off = options.detections.flatMap((detection) => detection.disabled);
|
|
11321
11304
|
if (off.length) {
|
|
@@ -11326,26 +11309,9 @@ function locateExtension(options, effects = systemEffects) {
|
|
|
11326
11309
|
if (blocked.length)
|
|
11327
11310
|
log(`! Couldn't check ${blocked.join(", ")} for browse (${blockedReason()})`);
|
|
11328
11311
|
const target = options.preferred ?? options.detections.find((detection) => !detection.blocked)?.browser;
|
|
11329
|
-
const interactive = options.allowOpen && options.env.display;
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
return noListing(), "guided";
|
|
11333
|
-
const opened = interactive && !blocked.length && (target ? effects.open(target, listing) : effects.openDefault?.(listing));
|
|
11334
|
-
log(`Add browse to ${target?.name ?? "your browser"} from the Chrome Web Store${opened ? " (opened)" : ""}: ${listing}`);
|
|
11335
|
-
return "guided";
|
|
11336
|
-
}
|
|
11337
|
-
const act = interactive && !blocked.length;
|
|
11338
|
-
const page = target ? extensionsPage(target) : "chrome://extensions";
|
|
11339
|
-
unpackedSteps({
|
|
11340
|
-
folder: options.folder,
|
|
11341
|
-
platform: options.env.platform,
|
|
11342
|
-
log,
|
|
11343
|
-
browser: target?.name,
|
|
11344
|
-
page,
|
|
11345
|
-
opened: act && target !== undefined && effects.open(target, page),
|
|
11346
|
-
revealed: act && options.env.tty && effects.reveal(options.folder),
|
|
11347
|
-
copied: act && options.env.tty && effects.copy(options.folder)
|
|
11348
|
-
});
|
|
11312
|
+
const interactive = options.allowOpen && options.env.display && !options.env.ssh;
|
|
11313
|
+
const opened = interactive && !blocked.length && (target ? effects.open(target, listing) : effects.openDefault?.(listing));
|
|
11314
|
+
log(`Add browse to ${target?.name ?? "your browser"} from the Chrome Web Store${opened ? " (opened)" : ""}: ${listing}`);
|
|
11349
11315
|
return "guided";
|
|
11350
11316
|
}
|
|
11351
11317
|
function pairStoreExtension(options, effects = systemEffects) {
|
|
@@ -11362,13 +11328,6 @@ function pairStoreExtension(options, effects = systemEffects) {
|
|
|
11362
11328
|
effects.log(`To connect browse in ${match.browser.name}: ${manualPair(options.code())}`);
|
|
11363
11329
|
return "manual";
|
|
11364
11330
|
}
|
|
11365
|
-
function unpackedSteps(step) {
|
|
11366
|
-
const { log } = step;
|
|
11367
|
-
const page = step.page ?? "chrome://extensions";
|
|
11368
|
-
const fileManager = step.platform === "darwin" ? "Finder" : step.platform === "win32" ? "Explorer" : "your file manager";
|
|
11369
|
-
const paste = step.platform === "darwin" ? "press Cmd+Shift+G in the folder picker and paste" : "paste it into the folder picker";
|
|
11370
|
-
log(`Load browse in ${step.browser ?? "your browser"}: open ${page}${step.opened ? " (opened)" : ""}, turn on Developer mode, click Load unpacked and choose ${step.folder}${step.copied ? ` (path copied: ${paste})` : step.revealed ? ` (shown in ${fileManager})` : ""}`);
|
|
11371
|
-
}
|
|
11372
11331
|
async function waitForExtension(options) {
|
|
11373
11332
|
const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
11374
11333
|
for (let waited = 0;; waited += options.intervalMs) {
|
|
@@ -11599,8 +11558,7 @@ async function syncDev() {
|
|
|
11599
11558
|
if (!dev)
|
|
11600
11559
|
return;
|
|
11601
11560
|
try {
|
|
11602
|
-
|
|
11603
|
-
log2(result === "updated" ? `✓ Downloaded the dev extension (${dev.file}) to ${devExtensionFolder(root)}` : `✓ Dev extension ${dev.file} is in ${devExtensionFolder(root)}`);
|
|
11561
|
+
await syncDevExtension(dev, { root });
|
|
11604
11562
|
} catch (error) {
|
|
11605
11563
|
fail(`Could not get the dev extension: ${error.message}`);
|
|
11606
11564
|
}
|
|
@@ -11873,7 +11831,7 @@ async function install(args) {
|
|
|
11873
11831
|
if (!rail.active)
|
|
11874
11832
|
return;
|
|
11875
11833
|
rail.waiting?.stop();
|
|
11876
|
-
outro(process.exitCode ? "browse isn't fully set up yet. Fix the steps above, then run browse install again." : byHand ? "Done. Add the MCP server above to your agent,
|
|
11834
|
+
outro(process.exitCode ? "browse isn't fully set up yet. Fix the steps above, then run browse install again." : byHand ? "Done. Add the MCP server above to your agent, then ask it to open a page." : "Done. Ask your agent to open a page.");
|
|
11877
11835
|
}
|
|
11878
11836
|
var byHand = false;
|
|
11879
11837
|
function showManualMcp(command, caller) {
|
|
@@ -11992,8 +11950,6 @@ async function installSteps(args, tty, caller) {
|
|
|
11992
11950
|
const reload = connected ? await reloadOutdatedExtension(connected, folder) : "current";
|
|
11993
11951
|
if (reload === "reloaded")
|
|
11994
11952
|
log2("✓ Reloaded browse in your browser");
|
|
11995
|
-
if (reload === "stale")
|
|
11996
|
-
return log2(`! ${unpackedReloadAdvice}`);
|
|
11997
11953
|
}
|
|
11998
11954
|
const reportMismatch = (status) => {
|
|
11999
11955
|
const advice = status.nextStep ?? extensionProtocolAdvice(status.protocolVersion, { install: installCommand() });
|
|
@@ -12030,12 +11986,11 @@ async function installSteps(args, tty, caller) {
|
|
|
12030
11986
|
allowOpen: !args.includes("--no-open"),
|
|
12031
11987
|
connected: !!connected,
|
|
12032
11988
|
pairedOffline,
|
|
12033
|
-
...folder ? { folder } : {},
|
|
12034
11989
|
detections,
|
|
12035
11990
|
preferred: ssh ? undefined : defaultBrowser(detections.map((detection) => detection.browser)),
|
|
12036
11991
|
env
|
|
12037
11992
|
});
|
|
12038
|
-
if (connected || found === "off" || pairedOffline
|
|
11993
|
+
if (connected || found === "off" || pairedOffline)
|
|
12039
11994
|
return;
|
|
12040
11995
|
ensureRelay(entry);
|
|
12041
11996
|
let code;
|
|
@@ -12051,11 +12006,9 @@ async function installSteps(args, tty, caller) {
|
|
|
12051
12006
|
const blocked = detections.filter((d) => d.blocked).map((d) => d.browser.name);
|
|
12052
12007
|
if (offer === "none" && blocked.length)
|
|
12053
12008
|
log2(`Couldn't check ${blocked.join(", ")}. If browse is already installed there, pair it manually. ${manualPair(pairingCode())}`);
|
|
12054
|
-
const next =
|
|
12009
|
+
const next = `If browse isn't connected after you add it, run \`${cliCommand("install")}\` again to pair it.`;
|
|
12055
12010
|
const agentNext = () => {
|
|
12056
|
-
|
|
12057
|
-
return `Agent: if browse is already loaded unpacked, ask the user: ${unpackedReloadAdvice} Otherwise ask them to load ${folder}. Check the connection with the browse status tool.`;
|
|
12058
|
-
return `Agent: ${offer === "opened" ? "ask the user to open browse's status page in their browser" : offer === "manual" || blocked.length ? "ask the user to finish pairing in browse's Options" : "ask the user to add browse in their browser"}. Then re-run \`${cliCommand("install")}\` to finish, or call the browse status tool to check the connection.`;
|
|
12011
|
+
return `Agent: ${offer === "opened" ? "ask the user to open browse's status page in their browser" : offer === "manual" || blocked.length ? "ask the user to finish pairing in browse's Options" : "ask the user to add browse from the Chrome Web Store"}. Then re-run \`${cliCommand("install")}\` to finish, or call the browse status tool to check the connection.`;
|
|
12059
12012
|
};
|
|
12060
12013
|
if (!env.tty)
|
|
12061
12014
|
log2(agentNext());
|
|
@@ -12088,7 +12041,7 @@ async function installSteps(args, tty, caller) {
|
|
|
12088
12041
|
return log2(connectedMessage);
|
|
12089
12042
|
if (status?.pairingState === "paired-offline")
|
|
12090
12043
|
return log2(pairedOfflineMessage);
|
|
12091
|
-
if (
|
|
12044
|
+
if (offer === "none") {
|
|
12092
12045
|
const scan = detectBrowsers();
|
|
12093
12046
|
if (!checkStore(scan))
|
|
12094
12047
|
return;
|
|
@@ -12128,7 +12081,7 @@ async function runSetup(command, args) {
|
|
|
12128
12081
|
if (command === "set")
|
|
12129
12082
|
return set(args);
|
|
12130
12083
|
if (command === "rollback") {
|
|
12131
|
-
const { runRollback } = await import("./runtime-update-
|
|
12084
|
+
const { runRollback } = await import("./runtime-update-3925nwpw.mjs");
|
|
12132
12085
|
return runRollback(args);
|
|
12133
12086
|
}
|
|
12134
12087
|
}
|
|
@@ -581,81 +581,6 @@ secret in a session without an allowlist adds a loud warning: set one first.
|
|
|
581
581
|
Once typed, the value is in the page, so don't read it back or copy it
|
|
582
582
|
elsewhere.
|
|
583
583
|
|
|
584
|
-
### Signing in with Deadbolt
|
|
585
|
-
|
|
586
|
-
When the user connected browse to Deadbolt (\`opencode-browser deadbolt
|
|
587
|
-
connect\`), you can sign in with the logins they granted to agents, without
|
|
588
|
-
seeing any value. \`secrets_list\` shows them for the session's allowed sites:
|
|
589
|
-
title, username, \`granted\`, which \`fields\` (username, password, totp) and
|
|
590
|
-
whether \`passkeys\` are allowed, plus the site's passkey accounts (\`username\`,
|
|
591
|
-
\`displayName\`). Only the user grants, in Deadbolt: \`deadbolt agents allow
|
|
592
|
-
<site>\` (everything for that site's logins: username, password, one-time code
|
|
593
|
-
and passkeys, unless narrowed with \`--login\`, \`--fields\`, \`--no-passkeys\`,
|
|
594
|
-
\`--expires\`) or
|
|
595
|
-
\`deadbolt agents allow --all\` (every login).
|
|
596
|
-
Never try to grant, pair or unlock yourself; Deadbolt refuses AI callers.
|
|
597
|
-
|
|
598
|
-
Prefer the whole sign-in in one call (the \`signin\` tool, or in execute):
|
|
599
|
-
|
|
600
|
-
\`\`\`js
|
|
601
|
-
await page.goto("https://github.com/login")
|
|
602
|
-
const result = await secrets.signIn() // or { site: "github.com", username: "me@example.com" }
|
|
603
|
-
// { status: "signed_in" | "needs_user" | "not_granted" | "failed", step, reason }
|
|
604
|
-
\`\`\`
|
|
605
|
-
|
|
606
|
-
It fills the username, submits, waits, fills the password, types an
|
|
607
|
-
authenticator (TOTP) code when the site asks for one (single field or split
|
|
608
|
-
boxes), follows "Use password instead", and follows Sign in with Google when
|
|
609
|
-
Deadbolt grants a Google login, all inside the relay. Then:
|
|
610
|
-
|
|
611
|
-
- \`signed_in\`: carry on.
|
|
612
|
-
- \`needs_user\`: a captcha, a code sent by SMS or email, a push approval, a
|
|
613
|
-
new-device or "verify it's you" check, or Deadbolt is locked. Call
|
|
614
|
-
\`handoff("Finish signing in, then click Continue")\` so the user does it.
|
|
615
|
-
Don't retry in a loop.
|
|
616
|
-
- \`needs_choice\`: several passkeys can sign in; \`choices\` lists their
|
|
617
|
-
\`username\` / \`displayName\`. Ask the user which one if it isn't obvious, then
|
|
618
|
-
call again with \`{ username }\`.
|
|
619
|
-
- \`not_granted\`: tell the user what to allow (the reason names the site and
|
|
620
|
-
login).
|
|
621
|
-
- \`failed\`: the reason says why (no form found, wrong password, the page didn't
|
|
622
|
-
move on). Don't loop.
|
|
623
|
-
|
|
624
|
-
It doesn't handle security questions, image or canvas keypads, closed shadow
|
|
625
|
-
roots, or sign-in providers other than Google; those return \`needs_user\` or
|
|
626
|
-
\`failed\`. When it stops after a fill it empties the password and code fields
|
|
627
|
-
first. For a form it misreads, type one value at a time: a username on its
|
|
628
|
-
own, a password or code only with \`{ submit: true }\`, which types it, submits
|
|
629
|
-
the form, waits for the page to move on and empties password and code fields
|
|
630
|
-
in that frame, all in the same call:
|
|
631
|
-
|
|
632
|
-
\`\`\`js
|
|
633
|
-
await secrets.type("#login", "deadbolt:github.com/me@example.com", { field: "username" })
|
|
634
|
-
await secrets.type("#password", "deadbolt:github.com/me@example.com", { submit: true }) // field defaults to "password"
|
|
635
|
-
\`\`\`
|
|
636
|
-
|
|
637
|
-
The same origin checks as stored secrets apply (the field's frame must be on
|
|
638
|
-
the login's site and in the session allowlist; Deadbolt checks again), and
|
|
639
|
-
values never appear in what you get back. Errors start with the code:
|
|
640
|
-
\`submit_required\`, \`domain_not_allowed\`, \`not_granted\`, \`locked\`, \`forbidden\`
|
|
641
|
-
(the user must reconnect), \`rate_limited\`, \`page_hooks\`. \`page_hooks\` means
|
|
642
|
-
this session's code set up request interception or listeners
|
|
643
|
-
(\`page.route\`, \`page.on("request")\`, \`waitForRequest\`...), init scripts,
|
|
644
|
-
exposed functions or a CDP session: Deadbolt passwords and codes aren't typed
|
|
645
|
-
then. Sign in first, in a fresh session (\`session_reset\`), and set those up
|
|
646
|
-
afterwards. Never try to read or capture a value that was typed: the user
|
|
647
|
-
grants logins on the understanding that you don't. Set a session allowlist
|
|
648
|
-
before signing in.
|
|
649
|
-
|
|
650
|
-
Passkeys: in tabs you opened, a site's passkey sign-in
|
|
651
|
-
(\`navigator.credentials.get\`) is answered by Deadbolt when the grant allows
|
|
652
|
-
passkeys. \`signIn({ username })\` picks that account's passkey; to choose one
|
|
653
|
-
before your own click on a "Sign in with a passkey" button, call
|
|
654
|
-
\`await secrets.usePasskey({ site: "example.com", username: "me@example.com" })\`
|
|
655
|
-
(it applies to the tab's next passkey request, once). Deadbolt never verifies the user, so sites that require that fall back to
|
|
656
|
-
other methods. Otherwise the request fails with NotAllowedError, as if the user
|
|
657
|
-
dismissed it. WebAuthn CDP methods are blocked.
|
|
658
|
-
|
|
659
584
|
For destructive UI work, use a two-phase **read, confirm, verify** flow:
|
|
660
585
|
|
|
661
586
|
1. Read candidates and return exact stable identifiers or row text.
|
|
@@ -900,8 +825,7 @@ with the command it names. If the user asks you to update browse, run that
|
|
|
900
825
|
command yourself (\`node <browse>/cli/dist/cli.mjs update\`): it fast-forwards the
|
|
901
826
|
git clone and reruns setup, and refuses with the fix when the clone has local
|
|
902
827
|
changes or has diverged. Pass its refusal on rather than resolving git state
|
|
903
|
-
yourself.
|
|
904
|
-
browser work first and tell them to restart.
|
|
828
|
+
yourself. Finish in-flight browser work before you run it.
|
|
905
829
|
|
|
906
830
|
## Troubleshooting
|
|
907
831
|
|
|
@@ -922,7 +846,7 @@ Common diagnoses:
|
|
|
922
846
|
\`unpaired\` or \`refused\` means browse is installed: re-run install to pair it, **not** the store.
|
|
923
847
|
\`paired-offline\`: reopen the paired browser profile and enable browse; its worker wakes every 30 seconds.
|
|
924
848
|
\`not-seen\`: the relay hasn't heard from a browser. If browse is already added, open that browser and
|
|
925
|
-
rerun install. Otherwise follow install's store
|
|
849
|
+
rerun install. Otherwise follow install's store step.
|
|
926
850
|
- Incompatible extension protocol: follow \`extension.nextStep\`. For an older unpacked extension after setup,
|
|
927
851
|
ask the user: “Reload browse on your browser's extensions page (↻).” Running setup again does not reload older workers.
|
|
928
852
|
- Competing browser/profile connections: the active browser is preserved and
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import"./main-
|
|
1
|
+
import"./main-4t3a1fw9.mjs";
|
|
2
2
|
import {
|
|
3
3
|
versionEntry,
|
|
4
4
|
readCurrent,
|
|
5
5
|
npmRuntime
|
|
6
|
-
} from "./main-
|
|
6
|
+
} from "./main-8ncff5jp.mjs";
|
|
7
7
|
|
|
8
8
|
// src/mcp/supervisor.ts
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
@@ -14,7 +14,7 @@ async function runBinaryMcp(args) {
|
|
|
14
14
|
const runtime = npmRuntime();
|
|
15
15
|
if (!runtime) {
|
|
16
16
|
process.env[directEnvironmentVariable] = "1";
|
|
17
|
-
const { runCli } = await import("./cli-
|
|
17
|
+
const { runCli } = await import("./cli-wgxfjgb3.mjs");
|
|
18
18
|
return runCli();
|
|
19
19
|
}
|
|
20
20
|
const { layout } = runtime;
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
updateNotice2,
|
|
5
5
|
createUpdateWatcher2,
|
|
6
6
|
runUpdateCommand2
|
|
7
|
-
} from "./main-
|
|
8
|
-
import"./main-
|
|
9
|
-
import"./main-
|
|
7
|
+
} from "./main-scyv26xb.mjs";
|
|
8
|
+
import"./main-8ncff5jp.mjs";
|
|
9
|
+
import"./main-4t3a1fw9.mjs";
|
|
10
10
|
import"./main-3gthmkzw.mjs";
|
|
11
11
|
export {
|
|
12
12
|
createUpdateWatcher2 as createUpdateWatcher,
|
package/package.json
CHANGED
package/skills/browse/SKILL.md
CHANGED
|
@@ -580,81 +580,6 @@ secret in a session without an allowlist adds a loud warning: set one first.
|
|
|
580
580
|
Once typed, the value is in the page, so don't read it back or copy it
|
|
581
581
|
elsewhere.
|
|
582
582
|
|
|
583
|
-
### Signing in with Deadbolt
|
|
584
|
-
|
|
585
|
-
When the user connected browse to Deadbolt (`opencode-browser deadbolt
|
|
586
|
-
connect`), you can sign in with the logins they granted to agents, without
|
|
587
|
-
seeing any value. `secrets_list` shows them for the session's allowed sites:
|
|
588
|
-
title, username, `granted`, which `fields` (username, password, totp) and
|
|
589
|
-
whether `passkeys` are allowed, plus the site's passkey accounts (`username`,
|
|
590
|
-
`displayName`). Only the user grants, in Deadbolt: `deadbolt agents allow
|
|
591
|
-
<site>` (everything for that site's logins: username, password, one-time code
|
|
592
|
-
and passkeys, unless narrowed with `--login`, `--fields`, `--no-passkeys`,
|
|
593
|
-
`--expires`) or
|
|
594
|
-
`deadbolt agents allow --all` (every login).
|
|
595
|
-
Never try to grant, pair or unlock yourself; Deadbolt refuses AI callers.
|
|
596
|
-
|
|
597
|
-
Prefer the whole sign-in in one call (the `signin` tool, or in execute):
|
|
598
|
-
|
|
599
|
-
```js
|
|
600
|
-
await page.goto("https://github.com/login")
|
|
601
|
-
const result = await secrets.signIn() // or { site: "github.com", username: "me@example.com" }
|
|
602
|
-
// { status: "signed_in" | "needs_user" | "not_granted" | "failed", step, reason }
|
|
603
|
-
```
|
|
604
|
-
|
|
605
|
-
It fills the username, submits, waits, fills the password, types an
|
|
606
|
-
authenticator (TOTP) code when the site asks for one (single field or split
|
|
607
|
-
boxes), follows "Use password instead", and follows Sign in with Google when
|
|
608
|
-
Deadbolt grants a Google login, all inside the relay. Then:
|
|
609
|
-
|
|
610
|
-
- `signed_in`: carry on.
|
|
611
|
-
- `needs_user`: a captcha, a code sent by SMS or email, a push approval, a
|
|
612
|
-
new-device or "verify it's you" check, or Deadbolt is locked. Call
|
|
613
|
-
`handoff("Finish signing in, then click Continue")` so the user does it.
|
|
614
|
-
Don't retry in a loop.
|
|
615
|
-
- `needs_choice`: several passkeys can sign in; `choices` lists their
|
|
616
|
-
`username` / `displayName`. Ask the user which one if it isn't obvious, then
|
|
617
|
-
call again with `{ username }`.
|
|
618
|
-
- `not_granted`: tell the user what to allow (the reason names the site and
|
|
619
|
-
login).
|
|
620
|
-
- `failed`: the reason says why (no form found, wrong password, the page didn't
|
|
621
|
-
move on). Don't loop.
|
|
622
|
-
|
|
623
|
-
It doesn't handle security questions, image or canvas keypads, closed shadow
|
|
624
|
-
roots, or sign-in providers other than Google; those return `needs_user` or
|
|
625
|
-
`failed`. When it stops after a fill it empties the password and code fields
|
|
626
|
-
first. For a form it misreads, type one value at a time: a username on its
|
|
627
|
-
own, a password or code only with `{ submit: true }`, which types it, submits
|
|
628
|
-
the form, waits for the page to move on and empties password and code fields
|
|
629
|
-
in that frame, all in the same call:
|
|
630
|
-
|
|
631
|
-
```js
|
|
632
|
-
await secrets.type("#login", "deadbolt:github.com/me@example.com", { field: "username" })
|
|
633
|
-
await secrets.type("#password", "deadbolt:github.com/me@example.com", { submit: true }) // field defaults to "password"
|
|
634
|
-
```
|
|
635
|
-
|
|
636
|
-
The same origin checks as stored secrets apply (the field's frame must be on
|
|
637
|
-
the login's site and in the session allowlist; Deadbolt checks again), and
|
|
638
|
-
values never appear in what you get back. Errors start with the code:
|
|
639
|
-
`submit_required`, `domain_not_allowed`, `not_granted`, `locked`, `forbidden`
|
|
640
|
-
(the user must reconnect), `rate_limited`, `page_hooks`. `page_hooks` means
|
|
641
|
-
this session's code set up request interception or listeners
|
|
642
|
-
(`page.route`, `page.on("request")`, `waitForRequest`...), init scripts,
|
|
643
|
-
exposed functions or a CDP session: Deadbolt passwords and codes aren't typed
|
|
644
|
-
then. Sign in first, in a fresh session (`session_reset`), and set those up
|
|
645
|
-
afterwards. Never try to read or capture a value that was typed: the user
|
|
646
|
-
grants logins on the understanding that you don't. Set a session allowlist
|
|
647
|
-
before signing in.
|
|
648
|
-
|
|
649
|
-
Passkeys: in tabs you opened, a site's passkey sign-in
|
|
650
|
-
(`navigator.credentials.get`) is answered by Deadbolt when the grant allows
|
|
651
|
-
passkeys. `signIn({ username })` picks that account's passkey; to choose one
|
|
652
|
-
before your own click on a "Sign in with a passkey" button, call
|
|
653
|
-
`await secrets.usePasskey({ site: "example.com", username: "me@example.com" })`
|
|
654
|
-
(it applies to the tab's next passkey request, once). Deadbolt never verifies the user, so sites that require that fall back to
|
|
655
|
-
other methods. Otherwise the request fails with NotAllowedError, as if the user
|
|
656
|
-
dismissed it. WebAuthn CDP methods are blocked.
|
|
657
|
-
|
|
658
583
|
For destructive UI work, use a two-phase **read, confirm, verify** flow:
|
|
659
584
|
|
|
660
585
|
1. Read candidates and return exact stable identifiers or row text.
|
|
@@ -899,8 +824,7 @@ with the command it names. If the user asks you to update browse, run that
|
|
|
899
824
|
command yourself (`node <browse>/cli/dist/cli.mjs update`): it fast-forwards the
|
|
900
825
|
git clone and reruns setup, and refuses with the fix when the clone has local
|
|
901
826
|
changes or has diverged. Pass its refusal on rather than resolving git state
|
|
902
|
-
yourself.
|
|
903
|
-
browser work first and tell them to restart.
|
|
827
|
+
yourself. Finish in-flight browser work before you run it.
|
|
904
828
|
|
|
905
829
|
## Troubleshooting
|
|
906
830
|
|
|
@@ -921,7 +845,7 @@ Common diagnoses:
|
|
|
921
845
|
`unpaired` or `refused` means browse is installed: re-run install to pair it, **not** the store.
|
|
922
846
|
`paired-offline`: reopen the paired browser profile and enable browse; its worker wakes every 30 seconds.
|
|
923
847
|
`not-seen`: the relay hasn't heard from a browser. If browse is already added, open that browser and
|
|
924
|
-
rerun install. Otherwise follow install's store
|
|
848
|
+
rerun install. Otherwise follow install's store step.
|
|
925
849
|
- Incompatible extension protocol: follow `extension.nextStep`. For an older unpacked extension after setup,
|
|
926
850
|
ask the user: “Reload browse on your browser's extensions page (↻).” Running setup again does not reload older workers.
|
|
927
851
|
- Competing browser/profile connections: the active browser is preserved and
|
package/dist/main-sdmv8gfv.mjs
DELETED