规范化后的skill
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
# Login and Browser Harness
|
||||
|
||||
Use this reference only when live E10 access is required.
|
||||
|
||||
## Safety requirements
|
||||
|
||||
- Use an isolated Chrome instance, never the user's daily browser profile.
|
||||
- Do not store credentials in files, memory, shell history notes, examples, or final documentation.
|
||||
- Keep all E10 activity read-only.
|
||||
- Clean up the isolated browser process when finished.
|
||||
|
||||
## Cross-platform placeholders
|
||||
|
||||
| Placeholder | Linux | macOS | Windows |
|
||||
|---|---|---|---|
|
||||
| `<CHROME>` | `google-chrome` | `/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome` | `"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"` |
|
||||
| `<TEMP_DIR>` | `/tmp/bh-e10` | `/tmp/bh-e10` | `%TEMP%\\bh-e10` |
|
||||
| `<SCREENSHOT_DIR>` | `/tmp` | `/tmp` | `%TEMP%` |
|
||||
|
||||
## Start isolated Chrome
|
||||
|
||||
Clean stale browser-harness daemons first. Then start Chrome with a dedicated remote debugging port and profile directory.
|
||||
|
||||
Linux/macOS pattern:
|
||||
|
||||
```bash
|
||||
pkill -f browser_harness.daemon 2>/dev/null; rm -f /tmp/bu-*.sock /tmp/bu-*.pid 2>/dev/null
|
||||
<CHROME> --headless=new --remote-debugging-port=9223 --user-data-dir=<TEMP_DIR> --no-first-run --no-default-browser-check --window-size=1920,1080
|
||||
sleep 3 && curl -s http://127.0.0.1:9223/json/version | grep webSocketDebuggerUrl
|
||||
```
|
||||
|
||||
Every browser-harness command must set `BU_CDP_URL` in the same shell command:
|
||||
|
||||
```bash
|
||||
export BU_CDP_URL=http://127.0.0.1:9223 && browser-harness <<'PY'
|
||||
# commands
|
||||
PY
|
||||
```
|
||||
|
||||
Do not run `export BU_CDP_URL=...` on a separate line and then invoke `browser-harness`; the daemon may not inherit the later shell environment.
|
||||
|
||||
Windows pattern:
|
||||
|
||||
```bat
|
||||
set BU_CDP_URL=http://127.0.0.1:9223 && browser-harness
|
||||
```
|
||||
|
||||
## Navigate and detect session state
|
||||
|
||||
```python
|
||||
new_tab("https://<E10_BASE>/login")
|
||||
wait_for_load()
|
||||
wait(3)
|
||||
capture_screenshot("<SCREENSHOT_DIR>/e10_login.png")
|
||||
print("URL:", js("window.location.href"))
|
||||
```
|
||||
|
||||
If the URL is not `/login`, an existing session may already be authenticated in the isolated profile. Continue only if the current page confirms a valid E10 session.
|
||||
|
||||
## Captcha handling
|
||||
|
||||
E10 captcha is expected to be a four-digit number. If visual recognition returns fewer than four digits, refresh the captcha image and capture again.
|
||||
|
||||
```python
|
||||
capture_screenshot("<SCREENSHOT_DIR>/e10_captcha.png")
|
||||
```
|
||||
|
||||
Use available visual inspection capability to read the four digits. If incomplete, click the captcha image center and retry.
|
||||
|
||||
## Fill login form reliably
|
||||
|
||||
E10 input fields may not respond to direct `element.value = ...`. Use the native input setter and dispatch events.
|
||||
|
||||
```python
|
||||
import json
|
||||
|
||||
info = json.loads(js('''
|
||||
var inputs = document.querySelectorAll("input");
|
||||
var result = [];
|
||||
for (var i = 0; i < inputs.length; i++) {
|
||||
var r = inputs[i].getBoundingClientRect();
|
||||
result.push({
|
||||
dataId: inputs[i].getAttribute("data-id"),
|
||||
x: Math.round(r.left + r.width/2),
|
||||
y: Math.round(r.top + r.height/2)
|
||||
});
|
||||
}
|
||||
var btn = document.querySelector("button");
|
||||
var br = btn ? btn.getBoundingClientRect() : null;
|
||||
return JSON.stringify({inputs: result, btn: br ? {x: Math.round(br.left+br.width/2), y: Math.round(br.top+br.height/2)} : null});
|
||||
'''))
|
||||
|
||||
js('''
|
||||
var ns = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
|
||||
window.__fi = function(dataId, value) {
|
||||
var el = document.querySelector("[data-id='" + dataId + "']");
|
||||
el.focus();
|
||||
el.value = "";
|
||||
ns.call(el, value);
|
||||
el.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
el.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
el.dispatchEvent(new Event("blur", { bubbles: true }));
|
||||
};
|
||||
''')
|
||||
|
||||
u = info["inputs"][0]
|
||||
p = info["inputs"][1]
|
||||
c = info["inputs"][2]
|
||||
b = info["btn"]
|
||||
|
||||
click_at_xy(u["x"], u["y"]); wait(0.2)
|
||||
js('window.__fi("' + u["dataId"] + '", "<USERNAME>")')
|
||||
click_at_xy(p["x"], p["y"]); wait(0.2)
|
||||
js('window.__fi("' + p["dataId"] + '", "<PASSWORD>")')
|
||||
click_at_xy(c["x"], c["y"]); wait(0.2)
|
||||
js('window.__fi("' + c["dataId"] + '", "<CAPTCHA>")')
|
||||
|
||||
print(js('''
|
||||
var vals = [];
|
||||
document.querySelectorAll("input").forEach(function(el){ vals.push(el.value ? "set" : "empty"); });
|
||||
JSON.stringify(vals);
|
||||
'''))
|
||||
|
||||
click_at_xy(b["x"], b["y"])
|
||||
wait(5)
|
||||
wait_for_load()
|
||||
print("After login:", js("window.location.href"))
|
||||
```
|
||||
|
||||
If still on `/login`, assume captcha or credentials failed. Refresh captcha and retry rather than proceeding.
|
||||
|
||||
## Cleanup
|
||||
|
||||
Linux/macOS:
|
||||
|
||||
```bash
|
||||
pkill -f "chrome.*9223" 2>/dev/null
|
||||
```
|
||||
|
||||
Windows:
|
||||
|
||||
```bat
|
||||
taskkill /F /IM chrome.exe 2>nul
|
||||
```
|
||||
Reference in New Issue
Block a user