lasso-mcp 1.17.0 → 1.17.2
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/ARCHITECTURE.md +202 -82
- package/README.md +18 -2
- package/dist/browse/HighRiskGate.d.ts.map +1 -1
- package/dist/browse/HighRiskGate.js +10 -12
- package/dist/browse/HighRiskGate.js.map +1 -1
- package/dist/channels/BrowseChannel.d.ts.map +1 -1
- package/dist/channels/BrowseChannel.js +15 -1
- package/dist/channels/BrowseChannel.js.map +1 -1
- package/dist/channels/LoggedInChannel.d.ts +44 -0
- package/dist/channels/LoggedInChannel.d.ts.map +1 -1
- package/dist/channels/LoggedInChannel.js +143 -2
- package/dist/channels/LoggedInChannel.js.map +1 -1
- package/dist/config/config.d.ts +9 -0
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +12 -3
- package/dist/config/config.js.map +1 -1
- package/dist/config/provider-registry.d.ts.map +1 -1
- package/dist/config/provider-registry.js +9 -2
- package/dist/config/provider-registry.js.map +1 -1
- package/dist/doctor/doctor.d.ts +7 -1
- package/dist/doctor/doctor.d.ts.map +1 -1
- package/dist/doctor/doctor.js +2 -2
- package/dist/doctor/doctor.js.map +1 -1
- package/dist/index.js +23 -3
- package/dist/index.js.map +1 -1
- package/dist/logged-in/TabRegistry.d.ts +69 -17
- package/dist/logged-in/TabRegistry.d.ts.map +1 -1
- package/dist/logged-in/TabRegistry.js +111 -47
- package/dist/logged-in/TabRegistry.js.map +1 -1
- package/dist/logged-in/TabSession.d.ts +7 -6
- package/dist/logged-in/TabSession.d.ts.map +1 -1
- package/dist/logged-in/TabSession.js +18 -15
- package/dist/logged-in/TabSession.js.map +1 -1
- package/dist/ssrf/ssrf-guard.d.ts.map +1 -1
- package/dist/ssrf/ssrf-guard.js +8 -1
- package/dist/ssrf/ssrf-guard.js.map +1 -1
- package/doc/08-media-interact-/345/212/237/350/203/275/346/236/266/346/236/204.md +13 -0
- package/doc/09-media-interact-/345/256/236/346/226/275/346/216/222/346/234/237.md +19 -1
- package/doc/17-/345/212/237/350/203/275/346/265/213/350/257/225/346/270/205/345/215/225.md +494 -83
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-00-/346/200/273/347/273/223.md +134 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-admin-flow.json +174 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-admin-flow.mjs +169 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-cli-badcmd.err +25 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-cli-badcmd.out +0 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-cli-h.out +23 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-cli-help.err +0 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-cli-help.out +23 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-cli-v.out +1 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-cli-version.err +0 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-cli-version.exit +1 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-cli-version.out +2 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-doctor-cli.json +186 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-doctor-mcp.json +8 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-doctor-stealth.json +187 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-doctor-stealth2.json +187 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-forest-flow.json +51 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-forest-flow.mjs +107 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-http-fixture.mjs +39 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-meter.mjs +89 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-a1.json +9 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-a2.json +9 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-browse-out.json +1762 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-browse.mjs +166 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-cost-out.json +245 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-cost.mjs +56 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-e1.json +9 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-e2.mjs +64 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-e3.mjs +74 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-l1-launch.json +7 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-l2-launch.json +16 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-l5-launch.json +9 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-life-loggedin.mjs +43 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-life-reaper-watch.mjs +62 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-life-res-after.json +1 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-life-res-before.json +1 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-life.sh +60 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-life2-res-after.json +1 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-life2-res-before.json +1 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-life2.sh +61 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-meter.mjs +53 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-probe2-out.json +534 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-probe2.mjs +91 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-r11-verify.mjs +73 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-read-flow.json +55 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-read-flow.mjs +131 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-replay-strict.out +70 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-replay.out +70 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-browse.md +210 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-infra.md +246 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-perf-lib.mjs +74 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-perf-probe.mjs +18 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-perf-probe2.mjs +26 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-perf-runA.mjs +63 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-perf-runA2.mjs +41 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-perf-runB.mjs +73 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-perf-runC.mjs +80 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-perf-runC2.mjs +58 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-perf-runD.mjs +68 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-perf.md +229 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-search.md +273 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-round1-verdict.md +124 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-sighup-flow.json +24 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-sighup-flow.mjs +91 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-sighup-flow2.json +24 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-ssrf-fall.json +98 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft-ssrf-fall.mjs +87 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-run.mjs +118 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s1.json +30 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s1.jsonl +26 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s10.json +11 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s10.jsonl +7 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s1b.json +14 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s1b.jsonl +10 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s2.json +13 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s2.jsonl +9 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s2b.json +8 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s2b.jsonl +4 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s3.json +17 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s3.jsonl +13 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s4.json +15 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s4.jsonl +11 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s5.json +11 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s5.jsonl +7 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s6.json +8 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s6.jsonl +3 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s7rec.json +7 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s7rec.jsonl +3 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s7rep.json +8 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s7rep.jsonl +4 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s7rep2.json +8 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s7rep2.jsonl +4 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s7stale.json +8 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s7stale.jsonl +4 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s9.json +9 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s9.jsonl +4 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s9b.json +7 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s9b.jsonl +3 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s9c.json +8 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/ft1-s9c.jsonl +4 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-acceptance.md +147 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/gate-output.txt +13 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts01-02-result.json +155 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts01-02.mjs +103 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts03-result.json +373 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts03.mjs +131 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts04-result.json +40 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts04.mjs +75 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts05-result.json +73 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts05.mjs +144 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts05b-result.json +257 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts05b.mjs +150 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts06-result.json +339 -0
- package/doc/17-/346/211/247/350/241/214/350/256/260/345/275/225/silence-data/ts06.mjs +136 -0
- package/doc/26-/346/226/207/346/241/243/346/237/245/347/274/272/350/241/245/346/274/217/gap-matrix.md +283 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/audit.md +195 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/fix.md +61 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/review-03.md +68 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/probe.mjs +128 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/s7fix-l3-result.json +54 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/s7fix-l3.mjs +224 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t1-network.mjs +89 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t1-result.json +259 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t2-asn-poll.jsonl +25 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t2-headless.mjs +149 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t2-result.json +144 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t2b-asn-type.mjs +37 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t2b-lsappinfo-during.txt +567 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t3-hidden.mjs +74 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t3-result.json +67 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4a-hidden-loggedin.mjs +75 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4a-result.json +195 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4b-focus.mjs +167 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4b-result.json +382 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4c-gaps.mjs +134 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4c-result.json +282 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4c-snapshot-ddg.txt +399 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4c-snapshot-example.txt +6 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4d-final.mjs +118 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4d-result.json +202 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4d-snapshot.txt +4 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4e-clickfill.mjs +89 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4e-result.json +105 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4e-snapshot-ddg-full.txt +357 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4e-snapshot-example-full.txt +6 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4e2-fill.mjs +66 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify-data/t4e2-result.json +30 -0
- package/doc/27-/351/235/231/351/273/230/346/200/247/345/205/250/351/235/242/345/256/241/350/256/241/verify.md +188 -0
- package/doc/KEY-GUIDE.md +3 -1
- package/doc/README.md +60 -0
- package/doc/TROUBLESHOOTING.md +6 -0
- package/package.json +1 -1
- package/src/browse/HighRiskGate.ts +13 -17
- package/src/channels/BrowseChannel.ts +15 -1
- package/src/channels/LoggedInChannel.ts +142 -2
- package/src/config/config.ts +15 -3
- package/src/config/provider-registry.ts +9 -2
- package/src/doctor/doctor.ts +13 -2
- package/src/index.ts +25 -4
- package/src/invariants/check-invariants.mjs +49 -10
- package/src/logged-in/TabRegistry.ts +142 -53
- package/src/logged-in/TabSession.ts +21 -17
- package/src/ssrf/ssrf-guard.ts +8 -1
package/ARCHITECTURE.md
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
# Lasso 架构
|
|
2
2
|
|
|
3
|
-
> 本文是 Lasso v1.
|
|
3
|
+
> 本文是 Lasso **v1.17.2** 的架构概览(user-first;深度架构基线见 [`doc/08`](./doc/08-media-interact-功能架构.md)(冻结于 2026-07-21,头部有现状对齐横幅);实施排期与决策记录见 [`doc/09`](./doc/09-media-interact-实施排期.md);doc/ 目录导读见 [`doc/README.md`](./doc/README.md))。
|
|
4
4
|
|
|
5
5
|
## 1. 项目定位
|
|
6
6
|
|
|
7
|
-
Lasso 是 Claude Code 的**全交互**对外抓手 MCP(浏览器 +
|
|
7
|
+
Lasso 是 Claude Code 的**全交互**对外抓手 MCP(浏览器 + 桌面 + 本地私有数据)。与 [media-gen-mcp](https://github.com/wangdong233/media-gen-mcp)(图像抓手)双子星:
|
|
8
8
|
|
|
9
9
|
- media-gen-mcp:「所有图像操作归一个 MCP」(生成 + 识别)
|
|
10
|
-
- **Lasso**:「所有外部交互归一个 MCP」(浏览器 +
|
|
10
|
+
- **Lasso**:「所有外部交互归一个 MCP」(浏览器 + 桌面 + 搜自己的机器)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
**工具面(17 个 MCP 工具,`tools/list` 实跑核)**:`search / browse_headless / browse_logged_in / desktop / fetch_url / screenshot / pdf / network / read_text / search_local / wayback_lookup / fetch_feed / doctor / interact_roots / interact_observe / interact_act / admin`(另有 `browserbase` / `steel` 两个云通道工具按环境条件解锁,不在默认清单;对应 channel 名 `browse_cloud_browserbase` / `browse_cloud_steel`)。
|
|
13
|
+
|
|
14
|
+
四条交互通道:`search` / `browse_headless` / `browse_logged_in` / `desktop`,加 **`search_local` 本地私有搜索**(doc/24 裁决 B1「第四通道」:Chrome 历史 / Spotlight 文件,纯本地只读)与条件解锁的 `browse_cloud_steel` 云通道。所有通道共享同一套 fallback 范式 / 状态模型 / 工具风格(R-CI-02 红线:禁第二套做法);`search_local` 是唯一例外——纯本地只读查询无网络面、无 fallback 语义,走「工具直连」范式(照 `read_text` / `doctor-tool` 先例,不建 Channel 子类,防空壳对称 R-ABS-01)。
|
|
13
15
|
|
|
14
16
|
## 2. 整体分层
|
|
15
17
|
|
|
@@ -23,18 +25,22 @@ Lasso 是 Claude Code 的**全交互**对外抓手 MCP(浏览器 + 桌面)
|
|
|
23
25
|
│ Lasso(单进程 Node.js) │
|
|
24
26
|
│ │
|
|
25
27
|
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
26
|
-
│ │ Tool Layer(src/tools
|
|
27
|
-
│ │ search / browse_headless / browse_logged_in
|
|
28
|
-
│ │
|
|
29
|
-
│ │
|
|
28
|
+
│ │ Tool Layer(src/tools/,17 工具) │ │
|
|
29
|
+
│ │ search / browse_headless / browse_logged_in / desktop │ │
|
|
30
|
+
│ │ search_local / fetch_url / fetch_feed / wayback_lookup │ │
|
|
31
|
+
│ │ screenshot / pdf / network / read_text / interact_* │ │
|
|
32
|
+
│ │ doctor / admin — 每工具 Zod schema + ToolAnnotations │ │
|
|
30
33
|
│ └────────────────────────┬─────────────────────────────────┘ │
|
|
31
34
|
│ │ typed call │
|
|
32
35
|
│ ┌────────────────────────▼─────────────────────────────────┐ │
|
|
33
36
|
│ │ Channel Layer(src/channels/ + src/browse/ + src/desktop/│ │
|
|
34
|
-
│ │ + src/search/ + src/logged-in/)
|
|
35
|
-
│ │ BaseChannel ←
|
|
36
|
-
│ │
|
|
37
|
-
│ │ ←
|
|
37
|
+
│ │ + src/search/ + src/search-local/ + src/logged-in/) │ │
|
|
38
|
+
│ │ BaseChannel ← MachineMcpSearchChannel / BraveChannel │ │
|
|
39
|
+
│ │ BaseChannel ← UiChannel │ │
|
|
40
|
+
│ │ ← BrowseChannel(abstract) │ │
|
|
41
|
+
│ │ ← HeadlessChannel / LoggedInChannel │ │
|
|
42
|
+
│ │ / SteelChannel / BrowserbaseChannel │ │
|
|
43
|
+
│ │ ← StagehandChannel / DesktopChannel │ │
|
|
38
44
|
│ └────────────────────────┬─────────────────────────────────┘ │
|
|
39
45
|
│ │ FallbackDecider + tri-state │
|
|
40
46
|
│ ┌────────────────────────▼─────────────────────────────────┐ │
|
|
@@ -47,16 +53,18 @@ Lasso 是 Claude Code 的**全交互**对外抓手 MCP(浏览器 + 桌面)
|
|
|
47
53
|
│ │ SubprocessManager + RustBridge │ │
|
|
48
54
|
│ │ chrome-devtools-mcp@1.7.0(headless / logged_in / │ │
|
|
49
55
|
│ │ Steel / browserbase 各自 registerSpec) │ │
|
|
50
|
-
│ │ lasso-rust-helper(AXAPI/UIA/AT-SPI + cgEvent
|
|
56
|
+
│ │ lasso-rust-helper(AXAPI/UIA/AT-SPI + cgEvent │ │
|
|
51
57
|
│ │ + screenshot + TCC) │ │
|
|
52
58
|
│ └──────────────────────────────────────────────────────────┘ │
|
|
53
59
|
└──────────────────────────────┬─────────────────────────────────┘
|
|
54
60
|
┌───────────────────────┼───────────────────────┐
|
|
55
61
|
▼ ▼ ▼
|
|
56
|
-
chrome-devtools-mcp
|
|
57
|
-
@1.7.0(--headless /
|
|
58
|
-
--browser-url / Steel
|
|
59
|
-
CDP / --wsEndpoint)
|
|
62
|
+
chrome-devtools-mcp search 多源链(HTTP): lasso-rust-helper
|
|
63
|
+
@1.7.0(--headless / machine_mcp → brave → (macOS AXAPI +
|
|
64
|
+
--browser-url / Steel serp_http 快探 → cgEvent;Windows UIA;
|
|
65
|
+
CDP / --wsEndpoint) browse_headless 实搜 Linux AT-SPI)
|
|
66
|
+
→ recording replay
|
|
67
|
+
(+ search_local 纯本地源)
|
|
60
68
|
```
|
|
61
69
|
|
|
62
70
|
### 2.1 浏览器驱动契约锁:chrome-devtools-mcp 1.7.0(v1.11 迁移)
|
|
@@ -77,16 +85,19 @@ Lasso 是 Claude Code 的**全交互**对外抓手 MCP(浏览器 + 桌面)
|
|
|
77
85
|
|
|
78
86
|
```
|
|
79
87
|
BaseChannel (src/channels/BaseChannel.ts)
|
|
80
|
-
├──
|
|
88
|
+
├── MachineMcpSearchChannel (机器 MCP 复用;只通用层,不进 UI)
|
|
89
|
+
├── BraveChannel (Brave API 源;只通用层,不进 UI)
|
|
81
90
|
└── UiChannel (src/channels/UiChannel.ts)
|
|
82
|
-
├── BrowseChannel (browse_headless + browse_logged_in + cloud 复用)
|
|
83
|
-
├── HeadlessChannel
|
|
84
|
-
├── LoggedInChannel
|
|
85
|
-
├── SteelChannel
|
|
91
|
+
├── BrowseChannel (abstract;browse_headless + browse_logged_in + cloud 复用)
|
|
92
|
+
│ ├── HeadlessChannel
|
|
93
|
+
│ ├── LoggedInChannel
|
|
94
|
+
│ ├── SteelChannel (v1.6 自托管云浏览器;extends BrowseChannel 平级兄弟)
|
|
95
|
+
│ └── BrowserbaseChannel (v1.11 --wsEndpoint 契约)
|
|
96
|
+
├── StagehandChannel (程序化实验通道,无 MCP 工具入口)
|
|
86
97
|
└── DesktopChannel (desktop 4 档 fallback:ax → appleScript → cgEvent → screenshotVlm)
|
|
87
98
|
```
|
|
88
99
|
|
|
89
|
-
UI 通道共享 UiChannel 的状态写盘 / LRU / output envelope 机制;Search 只走通用层(无 UI
|
|
100
|
+
UI 通道共享 UiChannel 的状态写盘 / LRU / output envelope 机制;Search 只走通用层(无 UI 状态概念,`MachineMcpSearchChannel` / `BraveChannel` 直接 extends BaseChannel;v1.17 A3 后 `channels/SearchChannel.ts`〔zhipu 直连〕已删,INV-80 墓碑)。`search_local` 不进 Channel 层(见 §1)。**INV-2 守:所有 XxxChannel 必须 extends BaseChannel**(不绕过)。
|
|
90
101
|
|
|
91
102
|
### 3.2 CapabilityBag(运行时动态启停)
|
|
92
103
|
|
|
@@ -110,7 +121,7 @@ outcome = worked | didnt | unknown
|
|
|
110
121
|
|
|
111
122
|
### 3.4 StateStore LRU(128)
|
|
112
123
|
|
|
113
|
-
页面 DOM / 桌面 OutlineNode 不灌 CC 上下文,而是写本地磁盘(`~/.cache/lasso/state
|
|
124
|
+
页面 DOM / 桌面 OutlineNode 不灌 CC 上下文,而是写本地磁盘(`~/.cache/lasso/<run_id>/<channel>-<stateId>.json`,`src/util/state-store.ts`),返回 `state_id`。CC 后续 `act` / `find` 经 `state_id` 引用 → **4× token 效率**。LRU(128) 自动淘汰旧状态。desktop 侧另有 `skeleton:true` 树剪枝(v1.11:被 max_depth 剪掉的子树折叠为边界节点 + childrenCount)与顶层 `truncated:true` 诚实信号(v1.12:仅真剪掉子树时出现)。
|
|
114
125
|
|
|
115
126
|
### 3.5 stealth 体系(v1.5 → v1.13 演进)
|
|
116
127
|
|
|
@@ -125,7 +136,7 @@ outcome = worked | didnt | unknown
|
|
|
125
136
|
### 3.6 生命周期与稳定性(v1.9 → v1.13)
|
|
126
137
|
|
|
127
138
|
- **无头浏览器**:空闲 5 分钟自动回收(`LASSO_HEADLESS_IDLE_MS`,v1.9;touchKeepalive 防误杀)
|
|
128
|
-
- **launch-chrome**:台账(`launched-chromes.json`)+ `lasso chrome-stop`(只杀 cmdline 验证归属的 pid,防 pid 复用误杀,v1.9);hidden 档默认 + 最后使用后 ~60s 自动关(`LASSO_LAUNCH_MODE` / `LASSO_LAUNCH_IDLE_MS`,v1.10);`admin tab_restore` 恢复用户原 tab(红线:不关用户原有 tab
|
|
139
|
+
- **launch-chrome**:台账(`launched-chromes.json`)+ `lasso chrome-stop`(只杀 cmdline 验证归属的 pid,防 pid 复用误杀,v1.9);hidden 档默认 + 最后使用后 ~60s 自动关(`LASSO_LAUNCH_MODE` / `LASSO_LAUNCH_IDLE_MS`,v1.10);`admin tab_restore` 恢复用户原 tab(红线:不关用户原有 tab;v1.17.1 修复恒 no-op 缺陷,双 targetId 守卫)
|
|
129
140
|
- **stdin-EOF 收尾**(v1.12):CC 异常退出 → 父进程死 → stdin EOF → 复用幂等 shutdown;受管子进程不再孤儿到 zombie reaper 1h 阈值(上游 SDK #2002 的进程侧缓解)
|
|
130
141
|
- **停机链全路径有界**(v1.13):Steel 会话释放双层 3s 上界(停机链 race 3s + fetch `AbortSignal.timeout(3s)`)——自托管 Steel 停摆/endpoint 悬挂(实测可挂 ~301s)不再拖死退出
|
|
131
142
|
- **`LASSO_PROXY` 出口代理**(v1.11):headless 经 `--proxy-server`、Steel 经 session `proxyUrl`;**`browse_logged_in` 永不读取**(用户真实 Chrome 出口原样,铁律);doctor `proxy_config` 回显
|
|
@@ -174,15 +185,16 @@ AxBackend interface(三平台同构 OutlineNode 契约)
|
|
|
174
185
|
|
|
175
186
|
## 5. 设计原则(08 §0)
|
|
176
187
|
|
|
177
|
-
1. **能力导向命名**:search / browse_* / desktop(不按后端命名)
|
|
188
|
+
1. **能力导向命名**:search / browse_* / desktop / search_local(不按后端命名)
|
|
178
189
|
2. **页面/界面状态写磁盘**:4× token 效率
|
|
179
190
|
3. **减少推理调用**:多步链式(如 search → click → extract)一次工具调用完成
|
|
180
191
|
4. **fallback 对 CC 透明**:CC 只看到 `worked / didnt`,不感知降级细节
|
|
181
|
-
5. **诚实三态交付**:`worked / didnt / unknown`(unknown 是 fallback 触发器);假成功零容忍(expect 稳定性采样 / VLM 链尾诚实化 / find 拒纯 ref
|
|
192
|
+
5. **诚实三态交付**:`worked / didnt / unknown`(unknown 是 fallback 触发器);假成功零容忍(expect 稳定性采样 / VLM 链尾诚实化 / find 拒纯 ref / content_blocks 失败标注 / ref 失效诚实报错同族)
|
|
182
193
|
6. **零侵入跟随上游**:chrome-devtools-mcp 升级时 Lasso 不改业务(契约锁版本,当前 1.7.0)
|
|
183
194
|
7. **第二套做法红线**(R-CI-02):横切关注点变体只允许一套(fallback 范式 / state 模型 / dispatch Map / provider registry 等)
|
|
184
|
-
8. **不变量脚本化**(CI 守门):**
|
|
195
|
+
8. **不变量脚本化**(CI 守门):**81 条 INV** 静态 grep + 形状测,防 refactor 回退;另有 `inv-selftest` 20 样本「注入违规 → 必红」复证(见 §10)
|
|
185
196
|
9. **平台差异隔离在 backend 内部**:AxBackend 三平台同构 OutlineNode 契约;TS 层零平台字面量
|
|
197
|
+
10. **质量轴静态映射**(v1.17 A1):`quality`(api/scrape/stale)按 `served_by` 静态映射,零启发式——宁缺毋假(查不到就不标)
|
|
186
198
|
|
|
187
199
|
## 6. 边界(08 §7)
|
|
188
200
|
|
|
@@ -190,73 +202,174 @@ Lasso 明确**不做**以下事情:
|
|
|
190
202
|
|
|
191
203
|
- **不解 2FA**:站点要求 2FA 时返 `NEEDS_MANUAL_2FA`(red line;不让 CC 尝试绕过)
|
|
192
204
|
- **不做「全坐标 grounding」方案**:desktop 以语义 AX tree 为主路径(tier-1);坐标形态 `{x,y}`(取 snapshot rect 中心)只是 tier-3 cgEvent 的**兜底**,服务 canvas / Electron 自绘 UI 与 VLM 链尾(v1.11 T7)——不采用「截图 + 坐标识别」为主路径的脆弱方案
|
|
193
|
-
- **不做 RRF 融合 / corpus 持久化**:search 是 hit +
|
|
205
|
+
- **不做 RRF 融合 / corpus 持久化**:search 是 hit + 独立 wayback_lookup 工具,不是 RAG
|
|
206
|
+
- **search 主路径不调 Wayback**(INV-58):死链恢复是独立工具 `wayback_lookup`,由 CC 显式调用
|
|
194
207
|
- **不导出 cookie**:`browse_logged_in` 的 cookie 留本机 Chrome(除用户显式 opt-in `admin` action 且经 AES-256-GCM 加密)
|
|
208
|
+
- **search_local 隐私红线**(INV-81,v1.17):只读(源库禁写,唯一写面 mkdtemp 临时目录)/ 无全文导出字段(只返 title/url/时间/标题片段)/ limit 硬顶 50(无 dump 面板)/ 模块零网络 / 日志只记 query_len——浏览历史是高敏数据,工具暴露面即风险面
|
|
195
209
|
- **托管型云浏览器默认关**:cloud 通道必经 `LASSO_ALLOW_CLOUD_BROWSER=true` manual-switch + 端点/key 双重解锁(INV-25/74 守)。其中 **Steel 是自托管**(Apache-2.0 开源、本地 Docker、零 per-session 费、cookie 不出本地,v1.6)——与托管型(browserbase / stagehand,付费)区分;stagehand 是程序化实验通道(无 MCP 工具入口,doctor #39 探测 REST 契约)
|
|
196
210
|
- **macOS 先行**:Win/Linux backend 编译可证(cfg-gate + `cargo check --target`),真机执行待社区反馈(不伪造)
|
|
197
211
|
|
|
198
|
-
|
|
212
|
+
### 6.1 简单架构清单对齐(doc/17 §6 终判)
|
|
213
|
+
|
|
214
|
+
对照「简单架构清单」38 条(架构思想录 02/03 体系)逐行判定,ft-round1 全量测试轮终判(2026-08-18,R1 独立裁决官):**✅27 / ⚠️11(全部有处置:修 1 + watch 6 + 接受理由 4)/ ❌0 / ⏸1**。三条 🔴 硬不变量全过:R-FF-01(import 图 467 边实跑零非法边)/ R-FF-02(值级 0 环)/ R-DEP-03(别名清除后 AST 扫 0 命中)。阈值均为起点值未校准。逐条格内裁决见 `doc/17-功能测试清单.md` §6。
|
|
215
|
+
|
|
216
|
+
## 7. 搜索域终态(v1.14 → v1.17.1)
|
|
217
|
+
|
|
218
|
+
v1.13 后搜索域经历四次结构性修订(doc/21 重审 → doc/22 死层清除 → doc/24 颠覆性调研 → doc/25 五项裁决),终态如下。
|
|
219
|
+
|
|
220
|
+
### 7.1 终态链与扇出(v1.17 A3 后)
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
engine=auto(默认)→ 多源扇出(machine_mcp + brave 两 API 源)
|
|
224
|
+
单源耗尽 / 零 API 源 → 串行 fallback 链:
|
|
225
|
+
machine_mcp → brave → serp_http(快探)→ browse_headless(实搜)→ recording replay
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
- **machine_mcp**(v1.4):零配置复用本机 `~/.claude.json` 已配的 search MCP(只读不写、永不 log Authorization,INV-72)——v1.17 A3 后是智谱能力的**唯一载体**(直连档已删)
|
|
229
|
+
- **brave**:结构化 API 源。运营事实(doc/21 实核):Brave 免费档 2026-02 取消,现口径 $5/月赠送额度(≈1000 次/月量级);Bing API 已于 2025-08-11 退役——**BingChannel 已代码级删除**(v1.15 Phase A,INV-54 墓碑,存量配置静默忽略)
|
|
230
|
+
- **serp_http**(v1.15):brave 之前的 ~1s 裸 HTTP 快探(见 §7.2)
|
|
231
|
+
- **browse_headless 实搜兜底**:query 语言分流(CJK→百度,非 CJK→DDG 纯 HTML 端点,零 Key;v1.14 起 DDG 被挡时级联 Brave SERP HTML)
|
|
232
|
+
- **recording replay**:全源熔断时的最后兜底(过去录过的同 query fixture;v1.16 起加新鲜度门,见 §7.7)
|
|
233
|
+
- **zhipu 直连档已删**(v1.17 A3,INV-80 墓碑):SearchChannel 类不存在、engine enum 无 "zhipu"、config 不消费 ZHIPU_API_KEY、doctor 报 `zhipu_keys_retired`
|
|
234
|
+
- **wayback 不在链内**(INV-58):死链恢复是独立工具,CC 显式调用
|
|
235
|
+
|
|
236
|
+
**quality 轴**(v1.17 A1):每条 search 结果带 `quality: "api" | "scrape" | "stale"`——`search.machine_mcp` / `search.brave` → api;`serp_http:*` / `browse_*` → scrape;`recording_replay` → stale;其他不标(静态映射零启发式,`src/search/QualityTag.ts` 单一真源)。
|
|
237
|
+
|
|
238
|
+
### 7.2 serp_http 快探层(v1.15 Phase B)
|
|
239
|
+
|
|
240
|
+
`src/serp/http-serp.ts`:browse_headless 之前的裸 HTTP SERP 探针(注入时 fallbacks 从 `[browse_headless]` 变 `[serp_http, browse_headless]`)。复用 browse_headless 的**同一 selector 集**(`selectors.ts` 三引擎:BAIDU / DDG / BRAVE_SERP)+ bot 探测,不起浏览器。真机对照(doc/22):serp_http 1.9s / 20 条 vs 浏览器 5.3s / 0 条。真机坑有维护记录(brave 字体 CSS 垃圾结果、百度软挡终态 URL 校验),见 `doc/SELECTOR-MAINTENANCE.md`。
|
|
241
|
+
|
|
242
|
+
### 7.3 content_blocks 第二跳(v1.17 A2′ 自研)
|
|
243
|
+
|
|
244
|
+
`src/search/ContentSecondHop.ts`:search 第一跳(蓝链)之后的 **opt-in** 正文富化(`content_blocks: 1..5`)。拿 top N 结果并发裸 HTTP 抓正文(defuddle 抽取 + 查询相关裁剪),零付费依赖、**不起浏览器**(重站/JS 渲染页如实 `fetch_failed`,留给 CC 自己 browse——不自动升级)。红线:
|
|
245
|
+
|
|
246
|
+
- **enrichment 不是 fallback**:第二跳任何失败不改变主结果 outcome / served_by / quality / fallback_used;失败条目保留蓝链字段 + `content_status`(ok / fetch_failed / not_html / extract_failed 四态)如实标注
|
|
247
|
+
- **护栏**:单条 timeout 5s / 256KB 两段式截断(content-length 预检 + 流式读硬顶)/ 每条裁剪预算 ~6k 字符 / 并发 3 / 整体 wall-clock 软上限 15s
|
|
248
|
+
- **SSRF 必过 ssrfGuard**(与 fetch_url 同函数同 config)+ `redirect:"manual"`(3xx 不跟随,防重定向绕过);连接池单一真源(不 new Agent)
|
|
249
|
+
- **cache 零污染**:content_blocks 不入 cache key——蓝链照常缓存 7 天,正文每次实抓
|
|
250
|
+
|
|
251
|
+
### 7.4 search_local 第四通道(v1.17 B1)
|
|
252
|
+
|
|
253
|
+
`src/search-local/`(doc/24 裁决 B1 + doc/25 裁决④):**本地私有搜索**——「我上周看过的那篇文章在哪」「我机器上哪些文件提到 X」。三源分阶段:
|
|
254
|
+
|
|
255
|
+
- `history`(默认):Chrome History 多 profile 只读 SQLite 查询(`chrome-history.ts`;`profile` 参数可选)
|
|
256
|
+
- `files`:`mdfind` / Spotlight(`mdfind.ts`)
|
|
257
|
+
- `notes`:本版明确推迟——enum 保值但返 `didnt` + `reason:"notes_deferred_v2"`(诚实不装不知道;ZBODY zlib+protobuf 全文解析是独立工程,v2 再议)
|
|
258
|
+
|
|
259
|
+
隐私红线 = INV-81(见 §6);四处联动防「写好没装配」(注册器 + index.ts 注册 + V5_TOOL_TO_CHANNEL + descriptions)。
|
|
260
|
+
|
|
261
|
+
### 7.5 fetch_feed(v1.16 D-GO-2)
|
|
262
|
+
|
|
263
|
+
`src/tools/fetch-feed.ts`:拉一个 feed URL → 结构化条目列表(RSS 2.0 / Atom / JSON Feed 1.1,零依赖正则解析——只认完整 `<item>`/`<entry>` 块,截断尾部天然丢弃不产半条假条目)。设计立场:**无状态纯原语 + 独立 tool 不进 search 降级链**(与 wayback_lookup 同范式)——RSS 是推模型零索引滞后,「最新动态」类查询 CC 显式直调;必经 ssrfGuard + doFetchUrl(不自造第二套 fetch);bounded output 48KiB / 16KiB preview + `truncated_input` 标记。
|
|
264
|
+
|
|
265
|
+
### 7.6 freshness 与缓存语义
|
|
266
|
+
|
|
267
|
+
- **TTL × freshness 耦合**(v1.16 ZB-3):有效 TTL = min(7 天, freshness 窗口)——`freshness=day` 的缓存最多存 24h,第 2 天起必须重搜;freshness 全档入 cache key(不同时效不互相污染,v1.11 起)
|
|
268
|
+
- **replay 新鲜度门**(v1.16):replay 键只有 (engine, query) 不含 freshness——门规则 = fixture 年龄 > freshness 窗口 → `replay_miss`(返原结果,诚实 didnt/unknown;`freshness=day` 不再命中陈年录制)
|
|
269
|
+
|
|
270
|
+
### 7.7 doctor 与运营事实探测
|
|
271
|
+
|
|
272
|
+
`doctor --deep`(v1.14,显式 opt-in,默认零网络副作用):#11b `brave_deep_probe` 对 Brave API 发一次最小真实请求,四分类——**200** key+计划均健康 / **401** key 无效 / **403**(或响应体含 plan 语义)计划层级失效 / **429** 限流(key 本身有效)——把「用户注册撞付费墙才发现」变成「doctor --deep 一跑就知道」。搜索供应商的运营事实漂移由 KEY-GUIDE 90 天重核制度对账(doc/21 建制)。
|
|
273
|
+
|
|
274
|
+
## 8. 交互升级:elicitation 与 refs(v1.17 C1/C2)
|
|
275
|
+
|
|
276
|
+
### 8.1 elicitation 高风险回合内确认(C1)
|
|
277
|
+
|
|
278
|
+
`src/interact/ElicitationPort.ts`:HighRiskGate 命中高风险 pattern 时,向 CC 用户弹结构化确认(continue/skip/abort 三选一),替代「直接 blocked 中断」。安全模型(doc/25 裁决⑤):
|
|
279
|
+
|
|
280
|
+
- 三值决议:`accept`(本次放行)/ `decline`(维持 blocked)/ `unavailable`(能力未声明或任何异常——**fail-closed**,落回现行 didnt 路径 byte-identical)
|
|
281
|
+
- **能力预检前置**:客户端未声明 `elicitation.form` 能力 → 连请求都不发,100% 降级 didnt(测试钉死;升级客户端即得);单次确认 wall-clock 上限 120s
|
|
282
|
+
- **accept 无记忆**:每次命中独立确认(INV-14 anti-gaming 延伸);pattern 表仍代码级 const,不从 config/env 读
|
|
283
|
+
- 本模块永不 throw(StepEngine 对 assessStep 异常的兜底是放行——端口 throw 会意外放行高风险操作)
|
|
284
|
+
|
|
285
|
+
### 8.2 include_refs 交互句柄(C2)
|
|
286
|
+
|
|
287
|
+
`src/browse/extract-refs.ts`:browse extract 的 `include_refs` opt-in 三件套——① extract 顺带给交互元素注入 `data-lasso-uid="r1"..`(cap 50);② markdown 末尾追加 `## Interactive refs` 附录表(正文零内嵌标记);③ `click`/`fill` 接 ref 句柄(`^r\d+$`)。**ref 失效诚实语义**:页面变了 querySelector miss → `ref_stale_re_snapshot` → didnt(不猜不自动重试,重新 extract 即得新句柄)。raw 档运行时忽略该参数 + `ignored_include_refs:true` 标注。
|
|
288
|
+
|
|
289
|
+
## 9. 安全面(持续加固记录)
|
|
290
|
+
|
|
291
|
+
- **SSRF**(INV-31,fetch_url / wayback / fetch_feed / serp_http / content_blocks 同函数同 config):默认拒私网 IP;fake-ip(198.18.0.0/15)内置放行;`redirect:"manual"` 防 302→169.254 绕过。**v1.17.1 加固**:IPv6 字面量 URL 剥括号后再 DNS lookup——此前 `[::1]` 带括号串在 TUN fake-ip 环境被当域名解析成 fake-ip,IPv6 loopback/ULA/IPv4-mapped 全部绕过(ft-round1 🔴FT-DEF-3,`src/ssrf/ssrf-guard.ts`)
|
|
292
|
+
- **HighRiskGate**:同 v1.17.1 修复裸 `JSON.parse` 解析围栏响应(异常 → gate_error 保守放行,C1 红线端到端失效)——改经 upstream-response 适配器 + INV-76(m) 防复发(ft-round1 🔴FT-DEF-1′)
|
|
293
|
+
- **静默性(v1.17.2,doc/27-静默性全面审计)**:六维打扰面(①OS 焦点 ②窗口 ③Dock/cmd-tab ④音频 ⑤通知 ⑥资源)逐通道白盒 + 真机审计后修复两个缺陷、固化全部边界——
|
|
294
|
+
- **S-7 修复(tab 内容劫持)**:上游 1.7.0 连接即 `selectPage(pages[0])`,v1.17.1 及之前 lasso 的 navigate 会改写用户第一个 tab(两轮真机复现)。现 `LoggedInChannel.ensureOwnPageSelected`(非台账 Chrome 路径):`CdpClient.createBackgroundTarget`(`Target.createTarget {background:true}`,E7 实证零抢焦)自建后台 tab → 上游 `list_pages` 前后 **id-diff 唯一归因**(上游 id 是进程内单调计数器;不取最大 id,防与用户同刻开 tab 竞态误归因)→ `select_page {pageId}` **不带 bringToFront**(上游激活严格 opt-in,省略 = 纯上下文指针切换,真机实测零 OS 焦点/零 tab 激活)。自建 tab 晚于 TabSession 快照 → 会话收尾 restore 关它(用户 tab 栏零残留)。任何失败(解析/归因/CDP/select 拒绝)warn 降级维持旧行为,永不阻断 browse。
|
|
295
|
+
- **S-10 修复(close_page 契约 + 所有权)**:旧 `close_page {url}` 在 1.7.0 wire 级必被 zod 拒(-32602,实测);且旧 reconcile 把全部列出 URL 入册(用户 tab 也是候选)。现 `TabRegistry` 按 `{pageId}` 关 + **登记制所有权**(`noteOwnPage` 只由 ensureOwnPageSelected 成功路径登记;用户 tab 无登记路径,close 淘汰在集合定义层面不可能落在用户 tab 上——红线机械化范式)。
|
|
296
|
+
- **诚实边界固化**(不可修,见 KEY-GUIDE/README 矩阵):desktop 物理键鼠设计占用;launch-chrome hidden 的 Dock 图标(有头 Chrome 注册 Foreground ASN,LSUIElement 不可控;headless 无此问题——真机实证无 Foreground ASN);visible 档语义即「看着干」;用户 Chrome 不静音(零注入铁律)+ 操作 tab 的 hasFocus 仿真(不抢 OS 焦点)。
|
|
297
|
+
- **守卫**:INV-78(d) 精化——`bringToFront` token 级零命中(作用域内任何 select_page 都不可能带激活开关)+ `"new_page"` 禁令新增 + S-7 实装锚(select_page 调用形 + 护栏日志事件 grep)。
|
|
298
|
+
- 其余安全 INV 面(cloud 双重解锁 / appleScript 白名单 / stealth profiles / 连接池)见 §11 分类表
|
|
299
|
+
|
|
300
|
+
## 10. 测试策略
|
|
199
301
|
|
|
200
|
-
| 层 | 工具 | 覆盖 | 规模(v1.
|
|
302
|
+
| 层 | 工具 | 覆盖 | 规模(v1.17.2 终态) |
|
|
201
303
|
|---|---|---|---|
|
|
202
|
-
| 架构不变量 | `check-invariants.mjs`(自写) | INV-1..
|
|
203
|
-
| INV 自测 | `inv-selftest.mjs`(`npm run inv-selftest`) | 抽样 INV 做「注入违规 →
|
|
204
|
-
| TS 单测 | vitest | channel / fallback / forest / doctor / launcher / outline-contract / replay-baseline / stealth / lifecycle / cdp-actions | **
|
|
205
|
-
| Rust 单测 | cargo test | ax / applescript / cgevent(+keymap) / screenshot / tcc / windows / protocol / role-map | **207
|
|
304
|
+
| 架构不变量 | `check-invariants.mjs`(自写) | INV-1..81 静态 grep + 形状测 | **81 条** |
|
|
305
|
+
| INV 自测 | `inv-selftest.mjs`(`npm run inv-selftest`) | 抽样 INV 做「注入违规 → 必红」复证 | **20 样本**(外部契约类全覆盖;未验证 pin 显性化报告) |
|
|
306
|
+
| TS 单测 | vitest | channel / fallback / forest / doctor / launcher / outline-contract / replay-baseline / stealth / lifecycle / cdp-actions / search-local / content-second-hop / elicitation / extract-refs / quality / http-serp / fetch-feed 等 | **2253 测试**(135 文件;doc/17 ft-round1 门禁两轮独立复跑在档 + doc/27 静默性审计补测) |
|
|
307
|
+
| Rust 单测 | cargo test | ax / applescript / cgevent(+keymap) / screenshot / tcc / windows / protocol / role-map | **207 测试**(cargo test 实跑;rust-helper 自 v1.13 起零改) |
|
|
206
308
|
| 跨平台编译 | cargo check --target | Windows (x86_64-pc-windows-msvc) + Linux (x86_64-unknown-linux-gnu) | CI Linux runner |
|
|
207
309
|
| 录制回放回归 | npm run replay-baseline | fixtures/serp-baseline/ × 三引擎 × 多 query | 12+ fixtures |
|
|
208
310
|
| 故障注入 | vitest | fallback 链 / 限流 / 政策 gate / SERP 改版 | ~20 场景 |
|
|
311
|
+
| 全量功能测试 | doc/17 清单 + ft 执行记录 | 四面板(search / browse / infra / perf)~170 用例真机 | ft-round1 **ALL-CLEAN**(2026-08-18) |
|
|
209
312
|
| 契约锁 | chrome-devtools-mcp@**1.7.0** version pin(`LOCKED_CDP_MCP_VERSION` 单一真源) | 上游小版本升级不破 Lasso;迁移要点见 §2.1 | SubprocessManager.ts |
|
|
210
313
|
|
|
211
|
-
##
|
|
314
|
+
## 11. 不变量(81 条)分类
|
|
212
315
|
|
|
213
316
|
| 范畴 | INV 编号 | 守的是什么 |
|
|
214
317
|
|---|---|---|
|
|
215
318
|
| 单一真源(grep 守 class / type 只在一处定义) | INV-3 / 9 / 24 / 60 | ProviderConfig / ProviderRegistry / RootRegistry / AxBackendFactory |
|
|
216
319
|
| 禁第二套(横切关注点变体只允许一套) | INV-4 / 6 / 23 / 33 | FallbackDecider / dispatch Map / 跨 surface fallback / pdf dispatch |
|
|
217
320
|
| 平台隔离(src/**/*.ts 无平台字面量) | INV-21 / 60 / 61 | TS 层无 AXUIElement/CGEvent/UIAutomationClient |
|
|
218
|
-
| 隐私红线 | INV-15 / 43 / 48..53 / 57 / 62 | output envelope 0o600 / 零遥测 / cookie AES-256-GCM / 录制 opt-in / 禁录 logged_in |
|
|
321
|
+
| 隐私红线 | INV-15 / 43 / 48..53 / 57 / 62 / **81** | output envelope 0o600 / 零遥测 / cookie AES-256-GCM / 录制 opt-in / 禁录 logged_in / **search_local 只读+无全文导出+limit≤50+零网络** |
|
|
219
322
|
| 安全红线 | INV-14 / 25 / 27 / 30 / 31 / 32 | HIGH_RISK_PATTERNS / cloud 双重解锁 / appleScript 白名单 / stealth profiles / SSRF / 连接池 |
|
|
220
323
|
| 诚实交付 | INV-13 / 19 | expect failed 必须 didnt + 终止 / OutlineNode 同形异源 |
|
|
221
324
|
| v1.0 release polish | INV-63 / 64 / 65 | version 三处一致 / launcher 不引新 npm dep / README+ARCHITECTURE 必引用 08+09 |
|
|
222
325
|
| v1.1 LLM 友好抽取 | INV-66..69 | raw 默认 byte-identical / extractor 内部件封装 / markdown 引擎禁第三运行期 / 引用角标零 crawl4ai 依赖 |
|
|
223
326
|
| v1.2-v1.4 配置与复用 | INV-70 / 71 / 72 | interactiveOnly opt-in 剪枝 byte-identical / config 文件机制(扁平 JSON + env 覆盖)/ 机器 MCP 复用安全(只读不写、永不 log Authorization) |
|
|
224
327
|
| v1.5-v1.7 反检测与云通道 | INV-73 / 74 / 75 | stealth 16 路一致性 + Headless 接线 / Steel 通道零回归(单独导出 + 双重解锁 + mutex)/ creepjs 门禁纯 doctor 侧零回归 |
|
|
225
|
-
| v1.8 wave 修复守护 | INV-76 |
|
|
226
|
-
| v1.9 浏览器生命周期 | INV-77 | 台账 + chrome-stop 归属验证 / tab 快照恢复三守卫 /
|
|
227
|
-
| v1.10 静默启动与回收 | INV-78 | hidden 档 flag 集不漂移 / idle reaper 零第二 kill 原语 / 激活路径禁令 |
|
|
328
|
+
| v1.8 wave 修复守护 | INV-76 | 上游契约适配与接线回归(v1.17.1 扩 (m):HighRiskGate 解析必经 upstream-response) |
|
|
329
|
+
| v1.9-v1.10 浏览器生命周期 | INV-77 / 78 | 台账 + chrome-stop 归属验证 / tab 快照恢复三守卫 / hidden 档 flag 集不漂移 / idle reaper 零第二 kill 原语 |
|
|
228
330
|
| v1.11 1.7.0 迁移守护 | INV-79 | 版本锁 1.7.0 / 遥测关 / --wsEndpoint / launch 级 stealth / 零哑 flag 形态 |
|
|
331
|
+
| v1.14-v1.17 运营事实与死层清除 | INV-54 / 80 | 死层墓碑:Bing(BingChannel 全链删、配置静默忽略)/ zhipu 直连(无 SearchChannel 类 / engine enum 无 "zhipu" / config 键容忍不消费 / doctor 报 retired) |
|
|
229
332
|
|
|
230
333
|
完整 INV 列表 + 释义见 `src/invariants/check-invariants.mjs` 顶部注释。
|
|
231
334
|
|
|
232
|
-
##
|
|
335
|
+
## 12. 数据流(典型场景)
|
|
233
336
|
|
|
234
|
-
###
|
|
337
|
+
### 12.1 search(v1.17 A3 后终态链)
|
|
235
338
|
|
|
236
339
|
```
|
|
237
|
-
CC → search("rust async 最新动态", freshness="week")
|
|
238
|
-
→
|
|
239
|
-
|
|
240
|
-
→
|
|
241
|
-
→
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
340
|
+
CC → search("rust async 最新动态", freshness="week", content_blocks=3)
|
|
341
|
+
→ engine=auto → fanout(machine_mcp + brave 两 API 源,配额/可用性裁决)
|
|
342
|
+
→ 零 API 源或扇出失败 → 串行链:
|
|
343
|
+
machine_mcp → brave → serp_http(~1s 裸 HTTP 快探)
|
|
344
|
+
→ browse_headless(真 Chrome 实搜:CJK→百度,非 CJK→DDG→Brave SERP 级联)
|
|
345
|
+
→ recording replay(新鲜度门:fixture 年龄 > freshness 窗口 → replay_miss)
|
|
346
|
+
→ quality 打标(machine_mcp/brave→api;serp_http/browse→scrape;replay→stale)
|
|
347
|
+
→ 蓝链入缓存(TTL = min(7d, freshness 窗口))→ 第二跳富化 top 3 正文
|
|
348
|
+
(并发 3 / 单条 5s / 256KB / 裁剪 ~6k;失败条目 content_status 如实标注,
|
|
349
|
+
主结果零改动)
|
|
350
|
+
→ 返 { outcome, entries, served_by, quality, ... }
|
|
246
351
|
```
|
|
247
352
|
|
|
248
|
-
###
|
|
353
|
+
### 12.2 browse_logged_in(2FA 场景)
|
|
249
354
|
|
|
250
355
|
```
|
|
251
356
|
CC → browse_logged_in("https://app.example.com", action="snapshot")
|
|
252
357
|
→ LoggedInChannel.run() → chrome-devtools-mcp@1.7.0 (:9222 CDP)
|
|
358
|
+
→ getMcpClient 装配链(v1.17.2 全序):
|
|
359
|
+
ensureRunning → onChromeUse(reaper touch)
|
|
360
|
+
→ precreateBackgroundTabIfHidden(仅台账 hidden + 零 page)
|
|
361
|
+
→ TabSession.takeSnapshotIfAbsent(用户 tab 基线,先于建塔)
|
|
362
|
+
→ _detect2FA(attach 时读选中页)
|
|
363
|
+
→ ensureOwnPageSelected(仅非台账 Chrome:建后台塔 → id-diff →
|
|
364
|
+
select_page{pageId} 无 bringToFront;失败 warn 降级)→ noteOwnPage
|
|
365
|
+
→ TabRegistry.reconcile(只触达已登记 own 页;close_page{pageId})
|
|
253
366
|
→ 站点返 302 to /login/2fa
|
|
254
367
|
→ outcome="didnt" + error="NEEDS_MANUAL_2FA"
|
|
255
368
|
→ 链止(不 fallback;2FA 是红线)
|
|
256
369
|
→ CC 提示用户本机 Chrome 完成 2FA
|
|
257
370
|
```
|
|
258
371
|
|
|
259
|
-
###
|
|
372
|
+
### 12.3 desktop(macOS 四档:语义优先、坐标兜底)
|
|
260
373
|
|
|
261
374
|
```
|
|
262
375
|
CC → desktop(action="act", actions=[{ref:"@e7", type:"click"}])
|
|
@@ -271,7 +384,7 @@ CC → desktop(action="act", actions=[{ref:"@e7", type:"click"}])
|
|
|
271
384
|
→ 返 { outcome, provider: "desktop.ax"|"desktop.appleScript"|"desktop.cgEvent"|"desktop.vlm" }
|
|
272
385
|
```
|
|
273
386
|
|
|
274
|
-
###
|
|
387
|
+
### 12.4 launch-chrome(跨平台子命令)
|
|
275
388
|
|
|
276
389
|
```
|
|
277
390
|
$ lasso launch-chrome
|
|
@@ -283,55 +396,62 @@ $ lasso launch-chrome
|
|
|
283
396
|
→ 探活 CDP /json/version → 台账登记 → server 运行期最后使用后 ~60s 自动关
|
|
284
397
|
```
|
|
285
398
|
|
|
286
|
-
##
|
|
399
|
+
## 13. 关键路径文件索引
|
|
287
400
|
|
|
288
|
-
| 模块 | 主文件 |
|
|
401
|
+
| 模块 | 主文件 | 备注 |
|
|
289
402
|
|---|---|---|
|
|
290
|
-
| Tool 注册 / 生命周期 | src/index.ts(stdin-EOF 收尾 / reaper / Steel 3s
|
|
291
|
-
| Tool handler | src/tools/{search,browse,desktop,admin,doctor,network,fetch-url}.ts | — |
|
|
403
|
+
| Tool 注册 / 生命周期 | src/index.ts(stdin-EOF 收尾 / reaper / Steel 3s 上界 / V5_TOOL_TO_CHANNEL 18 键 = 16 默认工具 + browserbase/steel;admin 是虚拟 channel 经 toolManager 直注册,不入表) | ~1470 |
|
|
404
|
+
| Tool handler | src/tools/{search,browse,desktop,admin,doctor,network,fetch-url,fetch-feed,wayback,screenshot,pdf,read-text,interact}.ts + descriptions.ts(描述单一真源) | — |
|
|
292
405
|
| Channel 层 | src/channels/{BaseChannel,UiChannel}.ts | — |
|
|
293
406
|
| BrowseChannel 族 | src/browse/BrowseChannel.ts;HeadlessChannel(launch 级 stealth + 宿主对齐 profile);SteelChannel(session mutex + proxyUrl) | — |
|
|
294
407
|
| stealth | src/browse/{StealthEngine,stealth-profiles}.ts(16 路 + 4 profile + 值域 2026-07) | — |
|
|
295
|
-
| markdown 抽取 | src/browse/markdown-extractor.ts(defuddle 双激活 + turndown
|
|
408
|
+
| markdown 抽取 | src/browse/markdown-extractor.ts(defuddle 双激活 + turndown 降级保底);extract-refs.ts(include_refs 三件套,v1.17) | — |
|
|
409
|
+
| 搜索域 | src/search/{FallbackChain,SearchCache,MultiSourceFanout,FreeTierRouter,AttributedSearch,QualityTag,ContentSecondHop,MachineMcpDetector}.ts;src/channels/{MachineMcpSearchChannel,BraveChannel}.ts(BingChannel / SearchChannel〔zhipu 直连〕均已删,INV-54/80 墓碑) | QualityTag/ContentSecondHop = v1.17 |
|
|
410
|
+
| serp_http 快探 | src/serp/http-serp.ts(v1.15,brave 前 ~1s;复用 selectors.ts 三引擎) | — |
|
|
411
|
+
| SERP | src/serp/{selectors,extract,SerpHealthMonitor,RecordingStore,replay-baseline}.ts(百度 / DDG / Brave SERP 三引擎 + 语言分流 + 改版检测 + 回放) | — |
|
|
412
|
+
| search_local | src/search-local/{register-search-local-tool,chrome-history,mdfind}.ts(v1.17 B1,INV-81) | — |
|
|
413
|
+
| 交互升级 | src/interact/ElicitationPort.ts(C1);src/browse/{HighRiskGate,extract-refs}.ts | — |
|
|
296
414
|
| desktop 四档 | src/desktop/{AxProvider,AxBackend,AxBackendFactory,OutlineMapper,CGEventProvider,ScreenshotVlmProvider}.ts | AxProvider ~330 |
|
|
297
|
-
| FallbackDecider | src/fallback/FallbackDecider.ts | ~
|
|
298
|
-
|
|
|
299
|
-
|
|
|
300
|
-
|
|
|
301
|
-
|
|
|
302
|
-
| INV 自测 | scripts/inv-selftest.mjs(14 样本红转复证) | ~280 |
|
|
415
|
+
| FallbackDecider | src/fallback/FallbackDecider.ts | ~350 |
|
|
416
|
+
| Launcher | src/launcher/{launch-chrome,chrome-paths,chrome-stop,chrome-idle-reaper,chrome-ledger,chrome-hide}.ts(INV-64 不引新 npm dep) | 共 ~1540 |
|
|
417
|
+
| Doctor | src/doctor/doctor.ts(40 项 check 量级,以实跑为准;#21 event-synthesis / #36 machine_mcp / #37 steel / #38 creepjs / #39 stagehand / #11b brave_deep_probe(--deep)/ zhipu_keys_retired) | ~3100 |
|
|
418
|
+
| Invariants | src/invariants/check-invariants.mjs(81 条 INV) | ~4450 |
|
|
419
|
+
| INV 自测 | scripts/inv-selftest.mjs(20 样本红转复证) | ~330 |
|
|
303
420
|
| Subprocess | src/subprocess/SubprocessManager.ts(`LOCKED_CDP_MCP_VERSION = "1.7.0"`) | ~730 |
|
|
304
|
-
| Rust helper | rust-helper/src/{ax,uia,atspi,applescript,cgevent,cgevent_keymap,screenshot,tcc,windows,protocol,main,ax_role_map,app_bundle_map}.rs | ~5000 |
|
|
421
|
+
| Rust helper | rust-helper/src/{ax,uia,atspi,applescript,cgevent,cgevent_keymap,screenshot,tcc,windows,protocol,main,ax_role_map,app_bundle_map}.rs | ~5000;自 v1.13 零改 |
|
|
305
422
|
|
|
306
|
-
##
|
|
423
|
+
## 14. 版本与发布
|
|
307
424
|
|
|
308
|
-
- **当前版本**:`1.
|
|
425
|
+
- **当前版本**:`1.17.2`(doc/27 静默性全面审计落地:S-7 自建后台 tab + S-10 close_page 契约与所有权修复、INV-78(d) 精化;2026-08-19)
|
|
309
426
|
- **version 真源**:`package.json` + `src/index.ts:LASSO_SERVER_VERSION` + `src/doctor/doctor.ts:LASSO_VERSION`(INV-63 守:三处必字面量一致)
|
|
310
|
-
- **doctor readiness
|
|
427
|
+
- **doctor readiness**:全量 check pass → `ready: true`(检查项随版本增长,以实跑输出为准)
|
|
311
428
|
- **跨平台 backend**:macOS 本机全证;Win/Linux 编译可证 + 契约可证,真机执行待社区反馈
|
|
312
|
-
- **门禁四链**:`npm run build` / `npm test`(
|
|
429
|
+
- **门禁四链**:`npm run build` / `npm test`(2253)/ `npm run check-invariants`(81)/ `npm run inv-selftest`(20)+ `cargo test`(207)
|
|
313
430
|
|
|
314
|
-
##
|
|
431
|
+
## 15. 质量与决策主线(doc/19 → doc/25 → doc/17)
|
|
315
432
|
|
|
316
|
-
2026-08-15
|
|
433
|
+
2026-08-15 起的三段质量主线,决策记录全部在档(索引见 [`doc/README.md`](./doc/README.md)「决策时间线」):
|
|
317
434
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
435
|
+
1. **五轮最优性审查**(doc/19,v1.10 → v1.13):四域白盒复审 → 裁决 → 实施 → 独立审查循环,候选 16 → 14 → 7 → 1 → 0 单调收敛(round5 终裁 ROUND-CLEAN);四维结论选型 / 架构 / 范围 / 实施全最优。
|
|
436
|
+
2. **搜索重审与死层清偿**(doc/21 → doc/22,v1.14 / v1.15):运营事实对账(Brave 免费档 2026-02 取消、Bing API 2025-08-11 退役)暴露「机制达标、运行时诚实度未达标」→ free_only 路由接线 + DDG→Brave SERP 级联 + `doctor --deep` + KEY-GUIDE 90 天重核制度(v1.14);Bing 死层代码级清除(INV-54)+ serp_http 快探层(v1.15)。
|
|
437
|
+
3. **方法论检讨与颠覆性调研**(doc/23 / 23a → doc/24,v1.16):零基视角制度化(「搜索优化失效」根因 = 只在既有方案内比较);颠覆性扫描按 D-GO / D-DECISION / D-WATCH / D-NOGO 分级裁决 → 落地 D-GO 三项:freshness TTL 耦合 / fetch_feed / README 生态段(v1.16)。
|
|
438
|
+
4. **五项用户裁决**(doc/25,v1.17):A1 quality 轴 / A3 删 zhipu 直连(INV-80)/ A2′ content_blocks 第二跳 / B1 search_local(INV-81)/ C1 elicitation + C2 include_refs。
|
|
439
|
+
5. **全量功能测试轮**(doc/17,v1.17.1):四面板 ~170 用例真机执行,抓出并修复 6 缺陷(🔴IPv6 字面量 SSRF 绕过 / 🔴HighRiskGate 裸 JSON.parse / doWait 假成功 / tab_restore no-op / doctor file 键 / SIGHUP),R1 独立裁决 **ALL-CLEAN**;§6 简单架构 38 条终判见 §6.1。
|
|
322
440
|
|
|
323
|
-
|
|
441
|
+
方法学沉淀(供复用):裁决官不采信文档(关键声称白盒双源亲验);证据阶梯 L0-L3;mutation 即验收;「先拿事实再加参数」;收敛协议前置;零基视角才可见方案级盲区;决策分级(GO/DECISION/WATCH/NOGO)交用户裁决而非默认全做。
|
|
324
442
|
|
|
325
|
-
##
|
|
443
|
+
## 16. 相关文档
|
|
326
444
|
|
|
327
445
|
- [README.md](./README.md) — 用户手册(安装 / 配置 / 工具列表 / 隐私 / 故障排查)
|
|
328
|
-
- [doc/
|
|
329
|
-
- [doc/
|
|
446
|
+
- [doc/README.md](./doc/README.md) — doc/ 目录导读(用户向 / 维护手册 / 决策档案三分法 + 决策时间线 + 新鲜度表)
|
|
447
|
+
- [doc/08 功能架构](./doc/08-media-interact-功能架构.md) — 权威架构基线(F 编号;冻结于 2026-07-21,头部含 v1.17.1 现状对齐横幅 + F 编号 ↔ 现实映射)
|
|
448
|
+
- [doc/09 实施排期](./doc/09-media-interact-实施排期.md) — v0.1 → v1.17.1 能力跃升全路径与决策记录
|
|
330
449
|
- [doc/19 最优性审查轮次](./doc/19-最优性审查轮次/00-总结.md) — 五轮审查全记录(v1.10 → v1.13 质量主线)
|
|
331
|
-
- [doc/
|
|
450
|
+
- [doc/17 功能测试清单](./doc/17-功能测试清单.md) — 全量功能测试(ft-round1 ALL-CLEAN + §6 简单架构终判)
|
|
332
451
|
- [doc/TROUBLESHOOTING.md](./doc/TROUBLESHOOTING.md) — FAQ + error_kind 释义
|
|
333
452
|
- [doc/SELECTOR-MAINTENANCE.md](./doc/SELECTOR-MAINTENANCE.md) — selector 债维护手册
|
|
453
|
+
- [doc/26 文档查缺补漏](./doc/26-文档查缺补漏/gap-matrix.md) — 文档盘点矩阵(新鲜度档位 + F 编号映射真源)
|
|
334
454
|
|
|
335
455
|
---
|
|
336
456
|
|
|
337
|
-
本文档是 Lasso v1.
|
|
457
|
+
本文档是 Lasso v1.17.1 架构概览(user-first;2026-08-18 同步,事实基准 = HEAD `1432bd4` 源码实核 + `tools/list` / `cargo test` / `check-invariants` 实跑)。深度架构基线(含 F 编号 / 不变量推导链 / 测试策略)见 [`doc/08`](./doc/08-media-interact-功能架构.md);v0.1 → v1.17.1 实施排期(含每 phase 决策记录)见 [`doc/09`](./doc/09-media-interact-实施排期.md)。
|
package/README.md
CHANGED
|
@@ -228,8 +228,9 @@ claude mcp add lasso -- npx -y lasso-mcp
|
|
|
228
228
|
**macOS 想控桌面**:跑一次 `lasso doctor`,按提示给 `lasso-rust-helper` 勾上「辅助功能」和「屏幕录制」权限即可,doctor 会一步步引导。
|
|
229
229
|
|
|
230
230
|
<details>
|
|
231
|
-
<summary>📋 更新日志(v1.8 → v1.17,点开看每版改了什么)</summary>
|
|
231
|
+
<summary>📋 更新日志(v1.8 → v1.17.2,点开看每版改了什么)</summary>
|
|
232
232
|
|
|
233
|
+
- **v1.17.2**:静默性全面审计落地(真机六维实测:焦点/窗口/Dock/音频/通知/资源)——① 修复「连你自己开的可见 Chrome」时 lasso 会**改写你第一个 tab 内容**的缺陷:现在 lasso 在你的 Chrome 里自建一个后台 tab 干活(不抢焦点、不激活),会话结束自动关掉,你的 tab 一律不动;② 修复 tab 管理的契约错配(`close_page` 参数形态),且关 tab 现在只可能落在 lasso 自己开的 tab 上(登记制,类型层面保证);③ 隐私文档新增**静默性矩阵**(每条通道×每维打扰的实测结论,见「隐私与安全」)。
|
|
233
234
|
- **v1.17**:五项升级——① 智谱直连 key 退役(`ZHIPU_API_KEY` 不再消费;智谱能力由机器 web-search-prime MCP 复用唯一承载,搜索默认零配置)② `search` 新增 `content_blocks` 第二跳(搜完并发抓 top N 正文、查询相关裁剪 ~6k 字符,失败条目如实标注,零付费依赖)③ 新工具 `search_local`(Chrome 浏览历史 + Spotlight 本地私有搜索,隐私红线:只返标题/链接/时间,禁全文导出)④ 高风险操作支持回合内 elicitation 确认(老客户端零影响)⑤ `browse extract` 新增 `include_refs` 交互句柄(`[r1]` 式附录 + 按句柄点击/填写,页面变了诚实失效)。搜索结果统一带 `quality` 质量轴标注(api / scrape / stale)。
|
|
234
235
|
|
|
235
236
|
- **v1.16**:新增 `fetch_feed` 工具(RSS / Atom / JSON Feed → 结构化条目;追版本号、退役时间线、官方公告这类「要新」的问题直接问源,不再等搜索索引)+ 修复搜索缓存新鲜度缺陷(`freshness=day` 的结果此前可能被缓存成最多 7 天的陈货,现在 day 档 24 小时即过期;全源熔断时的录制回放也会按 freshness 窗口拒掉过期 fixture,不再拿陈年录像充数)。
|
|
@@ -304,7 +305,7 @@ lasso launch-chrome
|
|
|
304
305
|
- 启动后自动探活调试端口,Chrome 没起来 / 端口被占会明确报错,不假报成功。
|
|
305
306
|
- 自动关阈值:`LASSO_LAUNCH_IDLE_MS`(默认 60000;`300000` 回退 5 分钟;`0` 禁用)。单次长任务放行:`--idle-ms 3600000`。
|
|
306
307
|
- 无头浏览器空闲 5 分钟自动回收(`LASSO_HEADLESS_IDLE_MS` 可调/禁用)。
|
|
307
|
-
- 诚实边界:单独跑 `lasso launch-chrome`(不经 server)没有 idle 自动关,出口是 `chrome-stop`;`browse_logged_in` 连**你自己开的可见 Chrome**
|
|
308
|
+
- 诚实边界:单独跑 `lasso launch-chrome`(不经 server)没有 idle 自动关,出口是 `chrome-stop`;它起的 Chrome 在 Dock / 任务栏会多一个图标(浏览器有头进程的注册行为,lasso 控制不了),要零图标用 `browse_headless`;`browse_logged_in` 连**你自己开的可见 Chrome** 时会在你的 Chrome 里临时开一个后台 tab 干活(不抢焦点不发声,结束自动关,v1.17.2 起你的 tab 一律不被改写)——但你的 Chrome 本身不静音(lasso 不改写你的浏览器参数),浏览到自动播放页面会真出声;`desktop` 模拟真人键鼠,设计上就占用物理键鼠,没有静默形态。
|
|
308
309
|
- chrome-stop 只关 Lasso 自己起的、验证过归属的 Chrome,不会误伤你手动开的浏览器。
|
|
309
310
|
|
|
310
311
|
</details>
|
|
@@ -373,6 +374,21 @@ lasso launch-chrome
|
|
|
373
374
|
- **不让陌生人随便碰你的内网服务**——访问内网默认被拒,保护你的内部服务不被随意触达;Surge / Clash 等 TUN 代理网络已内置放行,无需额外配置。
|
|
374
375
|
- **搜索结果默认不落盘**,只有你主动开启录制模式才会存一份快照(用于回归测试)。
|
|
375
376
|
|
|
377
|
+
### 静默性矩阵(v1.17.2 真机实测)
|
|
378
|
+
|
|
379
|
+
「静默」= 干活时你不被打扰。下表是六维打扰面(抢焦点 / 弹窗口 / Dock 图标 / 出声 / 系统通知 / 资源占用)逐格真机实测的结论(macOS 12 + Chrome 150,2026-08):
|
|
380
|
+
|
|
381
|
+
| 你用的能力 | 抢焦点 | 弹窗口 | Dock 图标 | 出声 | 通知 | 资源 |
|
|
382
|
+
|---|---|---|---|---|---|---|
|
|
383
|
+
| `search` / `fetch_url` / `fetch_feed` / `search_local` | 无 | 无 | 无 | 无 | 无 | 极低(纯网络/本地查询,CPU 峰 <3 秒即落) |
|
|
384
|
+
| `browse_headless`(无头浏览) | 无 | 无 | 无 | 无(恒静音) | 无 | 中(存活期约 400MB,闲置 5 分钟自动回收) |
|
|
385
|
+
| `launch-chrome`(默认 hidden 档) | 无 | 无 | **多一个 Chrome 图标**(清不掉,见下方边界) | 无(恒静音) | 无 | 中(server 里约 60 秒不用自动关) |
|
|
386
|
+
| `launch-chrome --mode visible` | **会**(弹出窗口,你主动选的) | 会 | 会 | 无(也恒静音) | 无 | 中 |
|
|
387
|
+
| `browse_logged_in` 连**你自己开的 Chrome** | 无(逐操作实测) | 无 | 无新增 | **你的 Chrome 不静音**(lasso 不改写你的浏览器) | 无 | 低 |
|
|
388
|
+
| `desktop` 控桌面 | **设计上占用键鼠** | — | — | — | 首次配置授权弹窗 | 极低 |
|
|
389
|
+
|
|
390
|
+
连你自己 Chrome 的三条边界(v1.17.2 起):① lasso 在你的 Chrome 里自建**后台 tab** 干活,不抢焦点、不激活窗口,会话结束自动关——你的 tab 一律不被改写(旧版会改写第一个 tab 的内容,已修复);② 你的 Chrome 不静音——lasso 浏览到自动播放页面会真出声(要静音自己启动 Chrome 时加 `--mute-audio`);③ lasso 操作期间那个后台 tab 会「自认为有焦点」(浏览器调试协议的仿真,不影响你正在用的前台应用)。
|
|
391
|
+
|
|
376
392
|
---
|
|
377
393
|
|
|
378
394
|
## 故障排查
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HighRiskGate.d.ts","sourceRoot":"","sources":["../../src/browse/HighRiskGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"HighRiskGate.d.ts","sourceRoot":"","sources":["../../src/browse/HighRiskGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAWtE,gEAAgE;AAChE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,kBAAkB,EAAE,aAAa,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAMC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAO/C,CAAC;AAKH;;;;;;;GAOG;AACH,qBAAa,YAAY;IAQrB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe;IARlC;;;;;OAKG;gBAEgB,cAAc,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,EACxC,eAAe,GAAE,eAAe,GAAG,IAAW;IAGjE;;;;;;;;;;;;;;;;OAgBG;IACG,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAuG1D;AAKD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAyCtD"}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { logger } from "../util/logger.js";
|
|
2
|
+
// FT-DEF-1(ft-round1 R11 真机抓出,2026-08-18):evaluate_script 响应必须经
|
|
3
|
+
// upstream-response 单一权威解析(```json 围栏 + 双层编码)。此前本模块自带
|
|
4
|
+
// 裸 firstText+JSON.parse(W1-DEF-1b 统一 7 消费点时的漏网第 8 点),真机
|
|
5
|
+
// 1.7.0 围栏形状下 JSON.parse("Script ran...") 必炸 → gate_error 保守放行
|
|
6
|
+
// → C1 高风险确认红线真机全失效(2227 单测全绿放过的 V-1 同型缺陷)。
|
|
7
|
+
import { parseEvalResult } from "./upstream-response.js";
|
|
2
8
|
// ============================================================
|
|
3
9
|
// HIGH_RISK_PATTERNS —— 模块顶级 const(INV-14 anti-gaming)
|
|
4
10
|
// ============================================================
|
|
@@ -123,11 +129,12 @@ export class HighRiskGate {
|
|
|
123
129
|
const r = (await client.callTool("evaluate_script", {
|
|
124
130
|
function: expr,
|
|
125
131
|
}));
|
|
126
|
-
|
|
127
|
-
|
|
132
|
+
// FT-DEF-1:改经 parseEvalResult(围栏剥除 + 双层 JSON 解码;无围栏/解析失败
|
|
133
|
+
// 返 undefined → 走 empty_eval 保守分支,与旧 firstText 空文本语义对齐)。
|
|
134
|
+
const verdict = parseEvalResult(r);
|
|
135
|
+
if (!verdict) {
|
|
128
136
|
return { blocked: false, reason: "gate_error:empty_eval" };
|
|
129
137
|
}
|
|
130
|
-
const verdict = JSON.parse(text);
|
|
131
138
|
if (verdict.kind) {
|
|
132
139
|
// v1.17 Phase E(parse24 §6.1):port 注入时先回合内人确认。
|
|
133
140
|
// accept → blocked=false + reason="high_risk_elicited:<kind>"(审计可见);
|
|
@@ -242,13 +249,4 @@ export function buildAssessExpr(target) {
|
|
|
242
249
|
}
|
|
243
250
|
}`;
|
|
244
251
|
}
|
|
245
|
-
function firstText(r) {
|
|
246
|
-
if (!r?.content)
|
|
247
|
-
return undefined;
|
|
248
|
-
for (const b of r.content) {
|
|
249
|
-
if (b.type === "text" && b.text)
|
|
250
|
-
return b.text;
|
|
251
|
-
}
|
|
252
|
-
return undefined;
|
|
253
|
-
}
|
|
254
252
|
//# sourceMappingURL=HighRiskGate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HighRiskGate.js","sourceRoot":"","sources":["../../src/browse/HighRiskGate.ts"],"names":[],"mappings":"AAuCA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"HighRiskGate.js","sourceRoot":"","sources":["../../src/browse/HighRiskGate.ts"],"names":[],"mappings":"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"}
|