lazycodex-ai 5.0.0-beta.81 → 5.0.0-beta.83
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.ja.md +2 -2
- package/README.ko.md +2 -2
- package/README.md +4 -4
- package/README.ru.md +2 -2
- package/README.zh-cn.md +2 -2
- package/dist/cli/index.js +439 -98
- package/dist/cli/install-native/index.d.ts +4 -0
- package/dist/cli/install-native/plan.d.ts +11 -0
- package/dist/cli/install-native/run-native-install.d.ts +23 -0
- package/dist/cli/install-native-dev/index.d.ts +4 -0
- package/dist/cli/native-dev-platform-flag.d.ts +5 -0
- package/dist/cli/native-edition-hint.d.ts +10 -0
- package/dist/cli/types.d.ts +3 -2
- package/dist/cli-node/index.js +439 -98
- package/package.json +2 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +111 -11
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +24 -10
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +8 -6
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +21 -4
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +10 -5
- package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +24 -6
- package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard-native-reviewer.test.ts +207 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +6 -4
- package/packages/omo-codex/plugin/components/ulw-loop/test/surface.test.ts +43 -4
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +12 -12
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/skills/browser/ATTRIBUTION.md +25 -0
- package/packages/omo-codex/plugin/skills/browser/SKILL.md +89 -0
- package/packages/omo-codex/plugin/skills/browser/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/browser/references/commands.md +90 -0
- package/packages/omo-codex/plugin/skills/browser/references/install.md +71 -0
- package/packages/omo-codex/plugin/skills/browser/references/owned-engine/README.md +42 -0
- package/packages/omo-codex/plugin/skills/browser/references/owned-engine/frames-and-humans.md +39 -0
- package/packages/omo-codex/plugin/skills/browser/references/owned-engine/ladder.md +59 -0
- package/packages/omo-codex/plugin/skills/browser/references/owned-engine/network.md +42 -0
- package/packages/omo-codex/plugin/skills/browser/references/recipes/1password.md +59 -0
- package/packages/omo-codex/plugin/skills/browser/references/remote.md +24 -0
- package/packages/omo-codex/plugin/skills/browser/scripts/browser-doctor.mjs +41 -0
- package/packages/omo-codex/plugin/skills/browser/scripts/browser-env.mjs +41 -0
- package/packages/omo-codex/plugin/skills/browser/scripts/browser-install.mjs +51 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +1 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +117 -17
- package/packages/shared-skills/skills/browser/ATTRIBUTION.md +25 -0
- package/packages/shared-skills/skills/browser/SKILL.md +89 -0
- package/packages/shared-skills/skills/browser/references/commands.md +90 -0
- package/packages/shared-skills/skills/browser/references/install.md +71 -0
- package/packages/shared-skills/skills/browser/references/owned-engine/README.md +42 -0
- package/packages/shared-skills/skills/browser/references/owned-engine/frames-and-humans.md +39 -0
- package/packages/shared-skills/skills/browser/references/owned-engine/ladder.md +59 -0
- package/packages/shared-skills/skills/browser/references/owned-engine/network.md +42 -0
- package/packages/shared-skills/skills/browser/references/recipes/1password.md +59 -0
- package/packages/shared-skills/skills/browser/references/remote.md +24 -0
- package/packages/shared-skills/skills/browser/scripts/browser-doctor.mjs +41 -0
- package/packages/shared-skills/skills/browser/scripts/browser-env.mjs +41 -0
- package/packages/shared-skills/skills/browser/scripts/browser-install.mjs +51 -0
- package/dist/cli/install-senpi/index.d.ts +0 -1
- package/dist/cli/senpi-platform-flag.d.ts +0 -4
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Reading a 1Password vault the user has unlocked
|
|
2
|
+
|
|
3
|
+
Scope: reading an item out of a vault **the user has already unlocked in their browser**. Signing
|
|
4
|
+
in is the user's job; see "Not in scope" below.
|
|
5
|
+
|
|
6
|
+
## The fact that shapes everything
|
|
7
|
+
|
|
8
|
+
1Password web is zero-knowledge. The unlocked vault key lives in **one tab's `sessionStorage`**,
|
|
9
|
+
not in a cookie. So:
|
|
10
|
+
|
|
11
|
+
- A **new** tab pointed at the vault redirects to the sign-in page even while a signed-in tab sits
|
|
12
|
+
right beside it. Opening your own tab does not work and never will.
|
|
13
|
+
- Navigating the authenticated tab away, or closing it, **destroys the session** until a human
|
|
14
|
+
signs in again.
|
|
15
|
+
|
|
16
|
+
Therefore: borrow the existing tab, read, return it. Do not open, do not navigate away, do not
|
|
17
|
+
"refresh to fix" anything.
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bsk tab list --scope user # find the already-signed-in tab
|
|
21
|
+
bsk tab borrow <tab-id>
|
|
22
|
+
# ... read ...
|
|
23
|
+
bsk tab return <tab-id>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Check liveness by URL, never by title
|
|
27
|
+
|
|
28
|
+
The app mutates its URL hash without updating the document title, so a signed-in vault can still
|
|
29
|
+
report a sign-in title. A live session's `location.href` contains the app path and never the
|
|
30
|
+
sign-in path. Read the URL.
|
|
31
|
+
|
|
32
|
+
## The browser may be shared
|
|
33
|
+
|
|
34
|
+
Other automation may be driving the same window.
|
|
35
|
+
|
|
36
|
+
- **Clear the search box before typing.** It often holds someone else's query, and typing alone
|
|
37
|
+
appends to it, returning confident results for the wrong search.
|
|
38
|
+
- **Read the autocomplete listbox, not the results grid.** The grid holds whatever query was last
|
|
39
|
+
committed, possibly by another actor. Scraping every option on the page silently merges two
|
|
40
|
+
different searches.
|
|
41
|
+
- **Leave the tab on the item list** when you are done, so the next actor starts clean.
|
|
42
|
+
|
|
43
|
+
## If it is locked
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
bsk request-help --session <id> --prompt "Please unlock 1Password in this tab, then continue."
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Then observe again.
|
|
50
|
+
|
|
51
|
+
## Not in scope
|
|
52
|
+
|
|
53
|
+
- **Do not type a master password, and do not automate the sign-in form.** Only the account owner
|
|
54
|
+
signs in. If the vault is locked, hand it to them.
|
|
55
|
+
- **Do not extract secrets through the page** beyond the single value the user asked for, and
|
|
56
|
+
report it masked (`abcd…9fb0 (len 37)`) unless they asked for the exact string.
|
|
57
|
+
- **Do not copy, inject, or reuse session cookies.** The session is device- and tab-bound; cookie
|
|
58
|
+
reuse cannot work and trips account protections.
|
|
59
|
+
- Clear the clipboard if you ever populate it.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Agent here, browser there
|
|
2
|
+
|
|
3
|
+
The agent and the browser do not have to be the same machine. Upstream supports this directly;
|
|
4
|
+
nothing in this package needs to bridge it.
|
|
5
|
+
|
|
6
|
+
Shape:
|
|
7
|
+
|
|
8
|
+
- The **browser machine** needs only the extension.
|
|
9
|
+
- The **agent machine** runs the `bsk` CLI and this skill.
|
|
10
|
+
- They are joined by a daemon in server mode plus a pairing link.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
bsk daemon start --mode server # on the machine the agent runs on
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Then follow upstream's pairing guide, which owns the current flag surface and the TLS
|
|
17
|
+
prerequisites: https://github.com/Tencent/BrowserSkill/blob/main/docs/remote-extension-connection.md
|
|
18
|
+
|
|
19
|
+
Once paired, every command in `commands.md` behaves identically; `--out` paths still resolve on
|
|
20
|
+
the machine that ran the command.
|
|
21
|
+
|
|
22
|
+
If pairing is not configured, say so and ask. Do not substitute a browser on the agent machine:
|
|
23
|
+
the point of the attached engine is the sessions that live in the user's browser, and a local
|
|
24
|
+
browser has none of them.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { platform } from "node:os"
|
|
3
|
+
import { connectedBrowsers, readStatus, resolveCli, STORE_LISTINGS, SUPPORTED_PLATFORMS } from "./browser-env.mjs"
|
|
4
|
+
|
|
5
|
+
const REMEDIES = {
|
|
6
|
+
ready: "Start a session: bsk session start --json --no-focus --name \"<task>\"",
|
|
7
|
+
"no-extension": `Ask the user to install and enable the extension, then re-run this doctor.\n Chrome: ${STORE_LISTINGS.chrome}\n Edge: ${STORE_LISTINGS.edge}`,
|
|
8
|
+
"no-cli": "Install the CLI: node \"<skill-root>/scripts/browser-install.mjs\", then re-run this doctor.",
|
|
9
|
+
"no-browser-support": "This platform has no supported browser. Say so and stop; do not substitute another engine.",
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function diagnose() {
|
|
13
|
+
if (!SUPPORTED_PLATFORMS.has(platform())) {
|
|
14
|
+
return { state: "no-browser-support", platform: platform() }
|
|
15
|
+
}
|
|
16
|
+
const cli = await resolveCli()
|
|
17
|
+
if (cli === undefined) return { state: "no-cli", platform: platform() }
|
|
18
|
+
|
|
19
|
+
let status
|
|
20
|
+
try {
|
|
21
|
+
status = await readStatus(cli)
|
|
22
|
+
} catch (error) {
|
|
23
|
+
return { state: "no-extension", platform: platform(), cli, detail: `status failed: ${error.message}` }
|
|
24
|
+
}
|
|
25
|
+
const browsers = connectedBrowsers(status)
|
|
26
|
+
if (browsers.length === 0) return { state: "no-extension", platform: platform(), cli }
|
|
27
|
+
return { state: "ready", platform: platform(), cli, browsers: browsers.length }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const report = await diagnose()
|
|
31
|
+
const json = process.argv.includes("--json")
|
|
32
|
+
if (json) {
|
|
33
|
+
console.log(JSON.stringify({ ...report, remedy: REMEDIES[report.state] }, null, 2))
|
|
34
|
+
} else {
|
|
35
|
+
console.log(`state: ${report.state}`)
|
|
36
|
+
if (report.cli) console.log(`cli: ${report.cli}`)
|
|
37
|
+
if (report.browsers) console.log(`browsers connected: ${report.browsers}`)
|
|
38
|
+
if (report.detail) console.log(`detail: ${report.detail}`)
|
|
39
|
+
console.log(`\n${REMEDIES[report.state]}`)
|
|
40
|
+
}
|
|
41
|
+
process.exit(report.state === "ready" ? 0 : 1)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { execFile } from "node:child_process"
|
|
2
|
+
import { existsSync } from "node:fs"
|
|
3
|
+
import { homedir, platform } from "node:os"
|
|
4
|
+
import { join } from "node:path"
|
|
5
|
+
import { promisify } from "node:util"
|
|
6
|
+
|
|
7
|
+
const run = promisify(execFile)
|
|
8
|
+
|
|
9
|
+
export const STORE_LISTINGS = {
|
|
10
|
+
chrome: "https://chromewebstore.google.com/detail/hhcmgoofomhgciiibhipgmgkgnoenaoi",
|
|
11
|
+
edge: "https://microsoftedge.microsoft.com/addons/detail/browserskill/emacgiaaaiojkkpkddmmdfhmokgmnikg",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const SUPPORTED_PLATFORMS = new Set(["darwin", "linux", "win32"])
|
|
15
|
+
|
|
16
|
+
export function localBinCandidates() {
|
|
17
|
+
const bin = join(homedir(), ".local", "bin")
|
|
18
|
+
return platform() === "win32" ? [join(bin, "bsk.exe"), join(bin, "bsk")] : [join(bin, "bsk")]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function resolveCli() {
|
|
22
|
+
for (const candidate of localBinCandidates()) {
|
|
23
|
+
if (existsSync(candidate)) return candidate
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
await run("bsk", ["--version"], { timeout: 15000, windowsHide: true })
|
|
27
|
+
return "bsk"
|
|
28
|
+
} catch {
|
|
29
|
+
return undefined
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function readStatus(cli) {
|
|
34
|
+
const { stdout } = await run(cli, ["status", "--json"], { timeout: 30000, windowsHide: true })
|
|
35
|
+
return JSON.parse(stdout)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function connectedBrowsers(status) {
|
|
39
|
+
const browsers = status?.browsers
|
|
40
|
+
return Array.isArray(browsers) ? browsers : []
|
|
41
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from "node:child_process"
|
|
3
|
+
import { platform } from "node:os"
|
|
4
|
+
import { resolveCli, STORE_LISTINGS, SUPPORTED_PLATFORMS } from "./browser-env.mjs"
|
|
5
|
+
|
|
6
|
+
const UNIX_INSTALL = "curl -fsSL https://raw.githubusercontent.com/Tencent/BrowserSkill/main/install.sh | sh"
|
|
7
|
+
const WINDOWS_INSTALL = "irm https://raw.githubusercontent.com/Tencent/BrowserSkill/main/install.ps1 | iex"
|
|
8
|
+
|
|
9
|
+
function installCommand() {
|
|
10
|
+
return platform() === "win32"
|
|
11
|
+
? { file: "powershell", args: ["-NoProfile", "-Command", WINDOWS_INSTALL], display: WINDOWS_INSTALL }
|
|
12
|
+
: { file: "sh", args: ["-c", UNIX_INSTALL], display: UNIX_INSTALL }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function spawnInstaller({ file, args }) {
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
const child = spawn(file, args, { stdio: "inherit", windowsHide: true })
|
|
18
|
+
child.on("error", () => resolve(1))
|
|
19
|
+
child.on("close", (code) => resolve(code ?? 1))
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!SUPPORTED_PLATFORMS.has(platform())) {
|
|
24
|
+
console.error(`unsupported platform: ${platform()}. macOS, Linux and Windows x64 only.`)
|
|
25
|
+
process.exit(1)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (await resolveCli()) {
|
|
29
|
+
console.log("bsk is already installed; run browser-doctor.mjs to check the extension.")
|
|
30
|
+
process.exit(0)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const command = installCommand()
|
|
34
|
+
console.log(`installing the bsk CLI with the upstream installer:\n ${command.display}\n`)
|
|
35
|
+
const code = await spawnInstaller(command)
|
|
36
|
+
if (code !== 0) {
|
|
37
|
+
console.error(`\ninstaller exited ${code}. Report this instead of retrying blindly.`)
|
|
38
|
+
process.exit(code)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
console.log([
|
|
42
|
+
"",
|
|
43
|
+
"CLI installed. Two things remain, and only the user can do the first:",
|
|
44
|
+
"",
|
|
45
|
+
"1. Install the browser extension from the store, then enable it:",
|
|
46
|
+
` Chrome: ${STORE_LISTINGS.chrome}`,
|
|
47
|
+
` Edge: ${STORE_LISTINGS.edge}`,
|
|
48
|
+
"2. Re-run: node \"<skill-root>/scripts/browser-doctor.mjs\"",
|
|
49
|
+
"",
|
|
50
|
+
"If PATH does not pick up the CLI in this shell, use its absolute path under ~/.local/bin.",
|
|
51
|
+
].join("\n"))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// omo-codex-install:
|
|
2
|
+
// omo-codex-install:88ab1eaf77d9f58468ed3f04e9c7d6c7dbb32d7c87feee69f45401431352184f:6f7e0588dc9a653cf42c9b4466272eea05e8c081bc8dc62082c03c1e5562cc31
|
|
3
3
|
var __esm = (fn, res, err) => () => {
|
|
4
4
|
if (fn)
|
|
5
5
|
try {
|
|
@@ -316,7 +316,7 @@ function shouldRetainLine(line, cutoffMs) {
|
|
|
316
316
|
function parseDiagnosticLine(line) {
|
|
317
317
|
try {
|
|
318
318
|
const parsed = JSON.parse(line);
|
|
319
|
-
if (!
|
|
319
|
+
if (!isRecord10(parsed)) {
|
|
320
320
|
return null;
|
|
321
321
|
}
|
|
322
322
|
return parsed;
|
|
@@ -327,7 +327,7 @@ function parseDiagnosticLine(line) {
|
|
|
327
327
|
throw error;
|
|
328
328
|
}
|
|
329
329
|
}
|
|
330
|
-
function
|
|
330
|
+
function isRecord10(value) {
|
|
331
331
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
332
332
|
}
|
|
333
333
|
function trimToMaxBytes(lines) {
|
|
@@ -7817,7 +7817,7 @@ function coerceBool(value) {
|
|
|
7817
7817
|
function coerceString(value) {
|
|
7818
7818
|
return typeof value == "string" ? value : undefined;
|
|
7819
7819
|
}
|
|
7820
|
-
function
|
|
7820
|
+
function isRecord11(value) {
|
|
7821
7821
|
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
7822
7822
|
}
|
|
7823
7823
|
function toRfc3339(timestamp) {
|
|
@@ -7839,7 +7839,7 @@ function relocateInto(properties, key, value) {
|
|
|
7839
7839
|
properties[key] = value;
|
|
7840
7840
|
}
|
|
7841
7841
|
function buildV1Event(message) {
|
|
7842
|
-
const sourceProperties =
|
|
7842
|
+
const sourceProperties = isRecord11(message.properties) ? message.properties : {};
|
|
7843
7843
|
const properties = {
|
|
7844
7844
|
...sourceProperties
|
|
7845
7845
|
};
|
|
@@ -9984,7 +9984,7 @@ var package_default;
|
|
|
9984
9984
|
var init_package = __esm(() => {
|
|
9985
9985
|
package_default = {
|
|
9986
9986
|
name: "@oh-my-opencode/omo-codex",
|
|
9987
|
-
version: "5.0.0-beta.
|
|
9987
|
+
version: "5.0.0-beta.83",
|
|
9988
9988
|
type: "module",
|
|
9989
9989
|
private: true,
|
|
9990
9990
|
description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
|
|
@@ -16515,8 +16515,10 @@ var OmoGitMasterSettingsSchema = OmoGitMasterSettingsLayerSchema.extend({
|
|
|
16515
16515
|
|
|
16516
16516
|
// packages/omo-config-core/src/schema/harness.ts
|
|
16517
16517
|
var HARNESS_IDS = ["codex", "opencode", "omo"];
|
|
16518
|
-
var OMO_CONFIG_HARNESS_IDS = ["opencode", "
|
|
16518
|
+
var OMO_CONFIG_HARNESS_IDS = ["opencode", "native", "codex"];
|
|
16519
16519
|
var OmoHarnessIdSchema = _enum(OMO_CONFIG_HARNESS_IDS);
|
|
16520
|
+
var OMO_CONFIG_LEGACY_HARNESS_ALIASES = { senpi: "native" };
|
|
16521
|
+
var OMO_CONFIG_LEGACY_HARNESS_IDS = Object.keys(OMO_CONFIG_LEGACY_HARNESS_ALIASES);
|
|
16520
16522
|
|
|
16521
16523
|
// packages/omo-config-core/src/schema/memory.ts
|
|
16522
16524
|
var OmoMemoryReflectionTriggerSchema = object({
|
|
@@ -16758,6 +16760,31 @@ var OmoTaskTeamSettingsSchema = object({
|
|
|
16758
16760
|
var OmoTaskWarningsSchema = object({
|
|
16759
16761
|
unavailable_categories: boolean2().default(true)
|
|
16760
16762
|
}).strict();
|
|
16763
|
+
var IsolationBackendKindSchema = _enum([
|
|
16764
|
+
"auto",
|
|
16765
|
+
"apfs",
|
|
16766
|
+
"btrfs",
|
|
16767
|
+
"zfs",
|
|
16768
|
+
"reflink",
|
|
16769
|
+
"overlayfs",
|
|
16770
|
+
"block-clone",
|
|
16771
|
+
"rcopy"
|
|
16772
|
+
]);
|
|
16773
|
+
var OmoTaskIsolationSchema = object({
|
|
16774
|
+
enabled: boolean2().default(false),
|
|
16775
|
+
backend: IsolationBackendKindSchema.default("auto"),
|
|
16776
|
+
apply: boolean2().default(true),
|
|
16777
|
+
merge: _enum(["patch", "branch"]).default("patch"),
|
|
16778
|
+
commits: _enum(["generic", "ai"]).default("generic")
|
|
16779
|
+
}).strict();
|
|
16780
|
+
var isolationDefaults = OmoTaskIsolationSchema.parse({});
|
|
16781
|
+
var OmoTaskIsolationLayerSchema = object({
|
|
16782
|
+
enabled: boolean2().optional(),
|
|
16783
|
+
backend: IsolationBackendKindSchema.optional(),
|
|
16784
|
+
apply: boolean2().optional(),
|
|
16785
|
+
merge: _enum(["patch", "branch"]).optional(),
|
|
16786
|
+
commits: _enum(["generic", "ai"]).optional()
|
|
16787
|
+
}).strict();
|
|
16761
16788
|
var OmoTaskDagSettingsSchema = object({
|
|
16762
16789
|
max_nodes_per_run: number2().int().positive().default(64),
|
|
16763
16790
|
max_runs_per_session: number2().int().positive().default(16),
|
|
@@ -16769,6 +16796,7 @@ var OmoTaskDagSettingsSchema = object({
|
|
|
16769
16796
|
max_prompt_bytes: number2().int().positive().default(262144)
|
|
16770
16797
|
}).strict();
|
|
16771
16798
|
var OmoTaskSettingsSchema = object({
|
|
16799
|
+
isolation: OmoTaskIsolationSchema.default(isolationDefaults),
|
|
16772
16800
|
default_execution_mode: _enum(["auto", "in-process", "process"]).default("auto"),
|
|
16773
16801
|
process_runner: _enum(["host", "child-process"]).default("host"),
|
|
16774
16802
|
host_engine_policy: _enum(["upgrade", "fallback"]).default("upgrade"),
|
|
@@ -16817,6 +16845,7 @@ var OmoTaskWarningsLayerSchema = object({
|
|
|
16817
16845
|
unavailable_categories: boolean2().optional()
|
|
16818
16846
|
}).strict();
|
|
16819
16847
|
var OmoTaskSettingsLayerSchema = object({
|
|
16848
|
+
isolation: OmoTaskIsolationLayerSchema.optional(),
|
|
16820
16849
|
default_execution_mode: _enum(["auto", "in-process", "process"]).optional(),
|
|
16821
16850
|
process_runner: _enum(["host", "child-process"]).optional(),
|
|
16822
16851
|
host_engine_policy: _enum(["upgrade", "fallback"]).optional(),
|
|
@@ -16948,6 +16977,7 @@ var OmoConfigProfileSchema = object({
|
|
|
16948
16977
|
telemetry: OmoTelemetrySettingsLayerSchema.optional(),
|
|
16949
16978
|
disabled_skills: OmoDisabledSkillsSchema.optional(),
|
|
16950
16979
|
"[opencode]": OmoOpenCodeHarnessConfigSchema.optional(),
|
|
16980
|
+
"[native]": OmoTypedHarnessConfigSchema.optional(),
|
|
16951
16981
|
"[senpi]": OmoTypedHarnessConfigSchema.optional(),
|
|
16952
16982
|
"[codex]": OmoTypedHarnessConfigSchema.optional()
|
|
16953
16983
|
}).strict();
|
|
@@ -16966,6 +16996,7 @@ var OmoConfigSchema = object({
|
|
|
16966
16996
|
telemetry: OmoTelemetrySettingsSchema.optional(),
|
|
16967
16997
|
disabled_skills: OmoDisabledSkillsSchema.optional(),
|
|
16968
16998
|
"[opencode]": OmoOpenCodeHarnessConfigSchema.optional(),
|
|
16999
|
+
"[native]": OmoTypedHarnessConfigSchema.optional(),
|
|
16969
17000
|
"[senpi]": OmoTypedHarnessConfigSchema.optional(),
|
|
16970
17001
|
"[codex]": OmoTypedHarnessConfigSchema.optional(),
|
|
16971
17002
|
profiles: record(string2(), OmoConfigProfileSchema).default({}),
|
|
@@ -16987,6 +17018,7 @@ var OmoConfigLayerSchema = object({
|
|
|
16987
17018
|
telemetry: OmoTelemetrySettingsLayerSchema.optional(),
|
|
16988
17019
|
disabled_skills: OmoDisabledSkillsSchema.optional(),
|
|
16989
17020
|
"[opencode]": OmoOpenCodeHarnessConfigSchema.optional(),
|
|
17021
|
+
"[native]": OmoTypedHarnessConfigSchema.optional(),
|
|
16990
17022
|
"[senpi]": OmoTypedHarnessConfigSchema.optional(),
|
|
16991
17023
|
"[codex]": OmoTypedHarnessConfigSchema.optional(),
|
|
16992
17024
|
profiles: record(string2(), OmoConfigProfileSchema).optional(),
|
|
@@ -17050,6 +17082,54 @@ function canonicalizeLegacyCategoryNames(document) {
|
|
|
17050
17082
|
return { document: canonicalized, renames };
|
|
17051
17083
|
}
|
|
17052
17084
|
|
|
17085
|
+
// packages/omo-config-core/src/schema/legacy-harness-names.ts
|
|
17086
|
+
function canonicalHarnessName(name) {
|
|
17087
|
+
return Object.hasOwn(OMO_CONFIG_LEGACY_HARNESS_ALIASES, name) ? OMO_CONFIG_LEGACY_HARNESS_ALIASES[name] : name;
|
|
17088
|
+
}
|
|
17089
|
+
function harnessBlockKey(harness) {
|
|
17090
|
+
return `[${harness}]`;
|
|
17091
|
+
}
|
|
17092
|
+
function legacyHarnessOfBlockKey(key) {
|
|
17093
|
+
if (!key.startsWith("[") || !key.endsWith("]"))
|
|
17094
|
+
return;
|
|
17095
|
+
const harness = key.slice(1, -1);
|
|
17096
|
+
return Object.hasOwn(OMO_CONFIG_LEGACY_HARNESS_ALIASES, harness) ? harness : undefined;
|
|
17097
|
+
}
|
|
17098
|
+
function isRecord7(value) {
|
|
17099
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17100
|
+
}
|
|
17101
|
+
function canonicalizeBlocksIn(container, path, renames) {
|
|
17102
|
+
const result = {};
|
|
17103
|
+
for (const [key, value] of Object.entries(container)) {
|
|
17104
|
+
const legacyHarness = legacyHarnessOfBlockKey(key);
|
|
17105
|
+
if (legacyHarness === undefined) {
|
|
17106
|
+
result[key] = value;
|
|
17107
|
+
continue;
|
|
17108
|
+
}
|
|
17109
|
+
const canonical = harnessBlockKey(canonicalHarnessName(legacyHarness));
|
|
17110
|
+
const dropped = Object.hasOwn(container, canonical);
|
|
17111
|
+
renames.push({ canonical, dropped, legacy: key, path: [...path, key].join(".") });
|
|
17112
|
+
if (!dropped)
|
|
17113
|
+
result[canonical] = value;
|
|
17114
|
+
}
|
|
17115
|
+
return result;
|
|
17116
|
+
}
|
|
17117
|
+
function canonicalizeLegacyHarnessBlocks(document) {
|
|
17118
|
+
if (!isRecord7(document))
|
|
17119
|
+
return { document: {}, renames: [] };
|
|
17120
|
+
const renames = [];
|
|
17121
|
+
const canonicalized = canonicalizeBlocksIn(document, [], renames);
|
|
17122
|
+
const profiles = canonicalized["profiles"];
|
|
17123
|
+
if (isRecord7(profiles)) {
|
|
17124
|
+
const canonicalProfiles = {};
|
|
17125
|
+
for (const [name, profile] of Object.entries(profiles)) {
|
|
17126
|
+
canonicalProfiles[name] = isRecord7(profile) ? canonicalizeBlocksIn(profile, ["profiles", name], renames) : profile;
|
|
17127
|
+
}
|
|
17128
|
+
canonicalized["profiles"] = canonicalProfiles;
|
|
17129
|
+
}
|
|
17130
|
+
return { document: canonicalized, renames };
|
|
17131
|
+
}
|
|
17132
|
+
|
|
17053
17133
|
// node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
17054
17134
|
function createScanner(text, ignoreTrivia = false) {
|
|
17055
17135
|
const len = text.length;
|
|
@@ -18025,7 +18105,7 @@ function resolveOmoConfigPaths(options) {
|
|
|
18025
18105
|
}
|
|
18026
18106
|
|
|
18027
18107
|
// packages/omo-config-core/src/loader/resolution.ts
|
|
18028
|
-
var HARNESS_KEYS = [...new Set([...HARNESS_IDS, ...OMO_CONFIG_HARNESS_IDS])].map((harness) =>
|
|
18108
|
+
var HARNESS_KEYS = [...new Set([...HARNESS_IDS, ...OMO_CONFIG_HARNESS_IDS, ...OMO_CONFIG_LEGACY_HARNESS_IDS])].map((harness) => harnessBlockKey(harness));
|
|
18029
18109
|
function profileName(value) {
|
|
18030
18110
|
return value === "" ? undefined : value;
|
|
18031
18111
|
}
|
|
@@ -18054,7 +18134,13 @@ function withoutControlKeys(config) {
|
|
|
18054
18134
|
function harnessLayer(config, harness) {
|
|
18055
18135
|
if (harness === undefined)
|
|
18056
18136
|
return {};
|
|
18057
|
-
|
|
18137
|
+
const canonical = canonicalHarnessName(harness);
|
|
18138
|
+
const legacyKeys = Object.entries(OMO_CONFIG_LEGACY_HARNESS_ALIASES).filter(([, target]) => target === canonical).map(([legacy]) => harnessBlockKey(legacy));
|
|
18139
|
+
let layer = {};
|
|
18140
|
+
for (const key of [...legacyKeys, harnessBlockKey(canonical)]) {
|
|
18141
|
+
layer = mergeOmoConfigRecords(layer, toRecord(config[key]) ?? {});
|
|
18142
|
+
}
|
|
18143
|
+
return layer;
|
|
18058
18144
|
}
|
|
18059
18145
|
function resolveOmoConfigView(options) {
|
|
18060
18146
|
const profiles = toRecord(options.config["profiles"]);
|
|
@@ -18105,6 +18191,7 @@ var DEFAULT_RAW_CONFIG = {
|
|
|
18105
18191
|
function stripResolutionControlKeys(config) {
|
|
18106
18192
|
const {
|
|
18107
18193
|
"[codex]": _codex,
|
|
18194
|
+
"[native]": _native,
|
|
18108
18195
|
"[opencode]": _opencode,
|
|
18109
18196
|
"[senpi]": _senpi,
|
|
18110
18197
|
profiles: _profiles,
|
|
@@ -18130,21 +18217,21 @@ function hasUnsafeUnrecognizedKey(issues) {
|
|
|
18130
18217
|
function hasTamperedPrototype(value) {
|
|
18131
18218
|
if (Array.isArray(value))
|
|
18132
18219
|
return value.some((entry) => hasTamperedPrototype(entry));
|
|
18133
|
-
if (!
|
|
18220
|
+
if (!isRecord8(value))
|
|
18134
18221
|
return false;
|
|
18135
18222
|
const prototype = Object.getPrototypeOf(value);
|
|
18136
18223
|
if (prototype !== Object.prototype && prototype !== null)
|
|
18137
18224
|
return true;
|
|
18138
18225
|
return Object.values(value).some((entry) => hasTamperedPrototype(entry));
|
|
18139
18226
|
}
|
|
18140
|
-
function
|
|
18227
|
+
function isRecord8(value) {
|
|
18141
18228
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18142
18229
|
}
|
|
18143
18230
|
function containerAt(record, path) {
|
|
18144
18231
|
let container = record;
|
|
18145
18232
|
for (const segment of path) {
|
|
18146
18233
|
const next = container[segment];
|
|
18147
|
-
if (!
|
|
18234
|
+
if (!isRecord8(next))
|
|
18148
18235
|
return null;
|
|
18149
18236
|
container = next;
|
|
18150
18237
|
}
|
|
@@ -18255,6 +18342,15 @@ function legacyCategoryDiagnostic(path, renames) {
|
|
|
18255
18342
|
issuePaths: renames.map((rename) => rename.path)
|
|
18256
18343
|
};
|
|
18257
18344
|
}
|
|
18345
|
+
function legacyHarnessDiagnostic(path, renames) {
|
|
18346
|
+
const detail = renames.map((rename) => rename.dropped ? `${rename.path} ignored because ${rename.canonical} is also configured` : `${rename.path} renamed to ${rename.canonical}`).join(", ");
|
|
18347
|
+
return {
|
|
18348
|
+
kind: "deprecated-keys",
|
|
18349
|
+
message: `Deprecated harness block in ${path}: ${detail}. Rename it; the alias is removed in a future release.`,
|
|
18350
|
+
path,
|
|
18351
|
+
issuePaths: renames.map((rename) => rename.path)
|
|
18352
|
+
};
|
|
18353
|
+
}
|
|
18258
18354
|
function loadOmoConfig(options = {}) {
|
|
18259
18355
|
const fileSystem = options.fileSystem ?? DEFAULT_READ_FILE_SYSTEM;
|
|
18260
18356
|
const cwd = options.cwd ?? process.cwd();
|
|
@@ -18277,8 +18373,12 @@ function loadOmoConfig(options = {}) {
|
|
|
18277
18373
|
if (canonicalized.renames.length > 0) {
|
|
18278
18374
|
diagnostics.push(legacyCategoryDiagnostic(candidate.path, canonicalized.renames));
|
|
18279
18375
|
}
|
|
18280
|
-
|
|
18281
|
-
|
|
18376
|
+
const harnessCanonicalized = canonicalizeLegacyHarnessBlocks(canonicalized.document);
|
|
18377
|
+
if (harnessCanonicalized.renames.length > 0) {
|
|
18378
|
+
diagnostics.push(legacyHarnessDiagnostic(candidate.path, harnessCanonicalized.renames));
|
|
18379
|
+
}
|
|
18380
|
+
layers.push({ config: harnessCanonicalized.document, source: loaded.source });
|
|
18381
|
+
merged = mergeOmoConfigRecords(merged, harnessCanonicalized.document);
|
|
18282
18382
|
}
|
|
18283
18383
|
}
|
|
18284
18384
|
const requestedProfile = resolveOmoProfileName({
|
|
@@ -20878,10 +20978,10 @@ function readCatalogMultiAgentVersion(model, cachePath) {
|
|
|
20878
20978
|
} catch {
|
|
20879
20979
|
return null;
|
|
20880
20980
|
}
|
|
20881
|
-
if (!
|
|
20981
|
+
if (!isRecord9(cache) || !Array.isArray(cache.models))
|
|
20882
20982
|
return null;
|
|
20883
20983
|
for (const entry of cache.models) {
|
|
20884
|
-
if (!
|
|
20984
|
+
if (!isRecord9(entry))
|
|
20885
20985
|
continue;
|
|
20886
20986
|
if (entry.slug !== model && entry.id !== model)
|
|
20887
20987
|
continue;
|
|
@@ -20906,7 +21006,7 @@ function readRootModelCatalogPath(config) {
|
|
|
20906
21006
|
const single = config.match(/^\s*model_catalog_json\s*=\s*'([^']+)'/m);
|
|
20907
21007
|
return single?.[1] ?? null;
|
|
20908
21008
|
}
|
|
20909
|
-
function
|
|
21009
|
+
function isRecord9(value) {
|
|
20910
21010
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20911
21011
|
}
|
|
20912
21012
|
function removeFeatureFlagSetting(config, featureName) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# ATTRIBUTION / NOTICE
|
|
2
|
+
|
|
3
|
+
This skill (`browser`, part of `@oh-my-opencode/shared-skills`) is project-original documentation.
|
|
4
|
+
It drives a third-party tool that it does **not** redistribute.
|
|
5
|
+
|
|
6
|
+
## BrowserSkill — driven, not vendored
|
|
7
|
+
|
|
8
|
+
The attached engine this skill documents is **BrowserSkill** by Tencent.
|
|
9
|
+
|
|
10
|
+
- Upstream: https://github.com/Tencent/BrowserSkill
|
|
11
|
+
- License: MIT
|
|
12
|
+
- What ships here: documentation and two local helper scripts, authored by this project.
|
|
13
|
+
- What does NOT ship here: the `bsk` CLI, the daemon, the browser extension, or any upstream
|
|
14
|
+
source. The user installs those from upstream's own installer and from the Chrome Web Store /
|
|
15
|
+
Edge Add-ons listings. This package never bundles a browser binary or an extension payload.
|
|
16
|
+
|
|
17
|
+
MIT permits redistribution; we simply have no reason to, because upstream publishes signed
|
|
18
|
+
per-platform releases and store builds that stay current on their own.
|
|
19
|
+
|
|
20
|
+
## Owned-engine references
|
|
21
|
+
|
|
22
|
+
`references/owned-engine/` documents a *contract* for a code-driven browser — the escalation
|
|
23
|
+
ladder, viewport pinning, reading the network instead of the DOM, overlay and cross-origin
|
|
24
|
+
handling — not any particular package. The techniques are generic CDP practice. No third-party
|
|
25
|
+
source is reproduced.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: browser
|
|
3
|
+
description: "Drives a real browser: sites the user is already signed into, forms and clicks, JS-rendered pages, screenshots, web QA, extension popups, and a human handoff for login, CAPTCHA or OTP. Works through the BrowserSkill extension and its bsk CLI, inside the user's own browser, in a separate Agent Window. Use for any interactive browser task; not for a plain search or an unblocked static fetch."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Browser
|
|
7
|
+
|
|
8
|
+
Two engines live behind this skill. Choose before you act:
|
|
9
|
+
|
|
10
|
+
| You need | Engine | Where |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| A site the user is signed into, a form, a click-through, a screenshot, web QA, an extension popup | **attached** — the user's own browser | this file |
|
|
13
|
+
| A throwaway profile, bot-scoring evasion, a CAPTCHA, network interception, a QA flight trace, coordinate control | **owned** — a browser your code launches | [references/owned-engine/README.md](references/owned-engine/README.md) |
|
|
14
|
+
| Text out of a URL, a 403 bypass, a platform that blocks fetchers | neither | the `ultimate-browsing` skill |
|
|
15
|
+
|
|
16
|
+
**Attached is the default,** because it is the only engine carrying the user's logins and the only
|
|
17
|
+
one where a human is a single command away. The owned engine is an opt-in local install, not part
|
|
18
|
+
of this package.
|
|
19
|
+
|
|
20
|
+
## Step 0 — prove the stack before you drive it
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
node "<skill-root>/scripts/browser-doctor.mjs"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
It reports one of four states and what to do next:
|
|
27
|
+
|
|
28
|
+
| State | Meaning | Next |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| `ready` | CLI, daemon and a connected browser | start a session |
|
|
31
|
+
| `no-extension` | CLI works, no browser is connected | give the user the store link the doctor printed, wait, re-run |
|
|
32
|
+
| `no-cli` | `bsk` is not installed | `node "<skill-root>/scripts/browser-install.mjs"`, then re-run |
|
|
33
|
+
| `no-browser-support` | the platform has no supported browser | say so and stop |
|
|
34
|
+
|
|
35
|
+
**Never substitute another browser for a missing one.** A headless browser you launch yourself has
|
|
36
|
+
none of the user's sessions, so every login turns into a ladder you should not be climbing. If the
|
|
37
|
+
attached engine is unavailable, say which state you hit and ask the user.
|
|
38
|
+
|
|
39
|
+
## The loop
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
bsk session start --json --no-focus --name "<task>" # keep session_id
|
|
43
|
+
bsk navigate https://example.com --session <id> --json
|
|
44
|
+
bsk observe --session <id> # @eN refs live here
|
|
45
|
+
bsk click @e1 --session <id> --json
|
|
46
|
+
bsk screenshot --session <id> --out ./shot.png --json
|
|
47
|
+
bsk session stop <id> --json # success AND failure
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
1. **Observe before every action.** `observe` returns a semantic tree whose `@eN` refs are reissued
|
|
51
|
+
on each call. Read a ref and use it in the same cycle; a ref from two calls ago points somewhere
|
|
52
|
+
else now.
|
|
53
|
+
2. **Navigation and large DOM changes stale every ref.** Observe again rather than reusing.
|
|
54
|
+
3. **Two identical failures mean change approach, not retry.** A third identical attempt is a defect.
|
|
55
|
+
4. **Borrow a user tab explicitly** (`tab list --scope user`, `tab borrow <id>`, `tab return <id>`).
|
|
56
|
+
Borrowing prompts the user; never invent tab ids and never repeat a denied borrow.
|
|
57
|
+
5. **Always stop the session,** on success and on failure. Stopping also returns borrowed tabs.
|
|
58
|
+
|
|
59
|
+
Command semantics, the flags that behave differently than they read, and the failure table are in
|
|
60
|
+
[references/commands.md](references/commands.md).
|
|
61
|
+
|
|
62
|
+
## When a human is the only way through
|
|
63
|
+
|
|
64
|
+
Login, CAPTCHA, OTP, a payment confirmation, a consent dialog:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
bsk request-help --session <id> --prompt "<what you need done>" [--target @eN]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Then observe again. Respect a `cancelled` or `timed_out` answer; do not work around it by changing
|
|
71
|
+
the extension's automation settings.
|
|
72
|
+
|
|
73
|
+
## Rules
|
|
74
|
+
|
|
75
|
+
- **Never read credentials through the page.** No `evaluate` that extracts a password, token, cookie
|
|
76
|
+
or recovery code. The value of this engine is that the browser is already signed in.
|
|
77
|
+
- **Never clear cookies, cache or site data.** It is the user's real profile; clearing it logs them
|
|
78
|
+
out everywhere. No flow here needs it.
|
|
79
|
+
- **`--no-focus` by default.** The browser belongs to someone who is probably using it.
|
|
80
|
+
- **One short, named session per task,** always stopped.
|
|
81
|
+
- Do not toggle the extension's automation settings, and do not restart the browser to fix a state.
|
|
82
|
+
|
|
83
|
+
## More
|
|
84
|
+
|
|
85
|
+
- [references/install.md](references/install.md) — installing the CLI and the extension, per OS
|
|
86
|
+
- [references/commands.md](references/commands.md) — command semantics, refs, failure table
|
|
87
|
+
- [references/remote.md](references/remote.md) — agent on one machine, browser on another
|
|
88
|
+
- [references/recipes/1password.md](references/recipes/1password.md) — reading a vault the user has unlocked
|
|
89
|
+
- [references/owned-engine/README.md](references/owned-engine/README.md) — the code-driven engine
|