lasso-mcp 1.18.1 → 1.18.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/.dedao-extract/.qc-v3/fk-14.png +0 -0
- package/.dedao-extract/.qc-v3/fkp2-02.png +0 -0
- package/.dedao-extract/.qc-v3/l001-6.png +0 -0
- package/.dedao-extract/.qc-v3/l001-7.png +0 -0
- package/.dedao-extract/.qc-v3/l002-4.png +0 -0
- package/.dedao-extract/analyze.mjs +169 -0
- package/.dedao-extract/dbg-fixscreen.mjs +43 -0
- package/.dedao-extract/dbg-text.mjs +25 -0
- package/.dedao-extract/dbg-text2.mjs +20 -0
- package/.dedao-extract/dbg-text3.mjs +18 -0
- package/.dedao-extract/dbg-text4.mjs +27 -0
- package/.dedao-extract/dbg-text5.mjs +31 -0
- package/.dedao-extract/extract-v2.mjs +539 -0
- package/.dedao-extract/extract-v3.mjs +745 -0
- package/.dedao-extract/gapfill.mjs +154 -0
- package/.dedao-extract/probe-frag.mjs +125 -0
- package/.dedao-extract/prod-chapters-dry.json +2516 -0
- package/.dedao-extract/prod-enumeration.json +1682 -0
- package/.dedao-extract/produce-all.mjs +555 -0
- package/.dedao-extract/qc-final.mjs +65 -0
- package/.dedao-extract/qc-v3.mjs +91 -0
- package/.dedao-extract/r2-01-navigate.json +14 -0
- package/.dedao-extract/r2-98-results.json +697 -0
- package/.dedao-extract/r2-99-log.json +15 -0
- package/.dedao-extract/r2-analyze.mjs +96 -0
- package/.dedao-extract/r2-fk-dump.json +139 -0
- package/.dedao-extract/r2-fk-figattr.json +62 -0
- package/.dedao-extract/r2-fk-pagemap.json +64 -0
- package/.dedao-extract/r2-l001-dump.json +129 -0
- package/.dedao-extract/r2-l001-figattr.json +53 -0
- package/.dedao-extract/r2-l001-pagemap.json +55 -0
- package/.dedao-extract/r2-l002-dump.json +109 -0
- package/.dedao-extract/r2-l002-figattr.json +35 -0
- package/.dedao-extract/r2-l002-pagemap.json +37 -0
- package/.dedao-extract/s8-01-navigate.json +14 -0
- package/.dedao-extract/s8-98-results.json +43 -0
- package/.dedao-extract/s8-99-log.json +24 -0
- package/.dedao-extract/s8-fk-fix.json +15 -0
- package/.dedao-extract/s8-fk-pagemap-post.json +58 -0
- package/.dedao-extract/s8-fk-pagemap-pre.json +68 -0
- package/.dedao-extract/s8-fk-promo.json +11 -0
- package/.dedao-extract/s8-ink.mjs +49 -0
- package/.dedao-extract/s8-l003-fix.json +21 -0
- package/.dedao-extract/s8-l003-pagemap-post.json +38 -0
- package/.dedao-extract/s8-l003-pagemap-pre.json +48 -0
- package/.dedao-extract/s8-l003-promo.json +11 -0
- package/.dedao-extract/s9-sikao.json +394 -0
- package/.dedao-extract/scout7-round2.mjs +386 -0
- package/.dedao-extract/scout7b.mjs +121 -0
- package/.dedao-extract/scout7c.mjs +99 -0
- package/.dedao-extract/scout8.mjs +334 -0
- package/.dedao-extract/scout9.mjs +121 -0
- package/.dedao-extract/scratch/fk-01.pgm +75 -0
- package/.dedao-extract/scratch/fk-02.pgm +4 -0
- package/.dedao-extract/scratch/fk-03.pgm +207 -0
- package/.dedao-extract/scratch/fk-04.pgm +986 -0
- package/.dedao-extract/scratch/fk-05.pgm +4 -0
- package/.dedao-extract/scratch/fk-06.pgm +4 -0
- package/.dedao-extract/scratch/fk-07.pgm +4 -0
- package/.dedao-extract/scratch/fk-08.pgm +4 -0
- package/.dedao-extract/scratch/fk-09.pgm +4 -0
- package/.dedao-extract/scratch/fk-10.pgm +4 -0
- package/.dedao-extract/scratch/fk-11.pgm +4 -0
- package/.dedao-extract/scratch/fk-12.pgm +4 -0
- package/.dedao-extract/scratch/fk-13.pgm +4 -0
- package/.dedao-extract/scratch/fk-14.pgm +107 -0
- package/.dedao-extract/scratch/fk-analysis.json +47 -0
- package/.dedao-extract/scratch/fk-before.pdf +0 -0
- package/.dedao-extract/scratch/fk-clean-inner.txt +42 -0
- package/.dedao-extract/scratch/fk-dom-inner.txt +381 -0
- package/.dedao-extract/scratch/fk-fix-inner.txt +42 -0
- package/.dedao-extract/scratch/fk-pdftotext.txt +66 -0
- package/.dedao-extract/scratch/fk-r3-base.pdf +0 -0
- package/.dedao-extract/scratch/fk-r3-base.txt +66 -0
- package/.dedao-extract/scratch/fk-r3-fix.pdf +0 -0
- package/.dedao-extract/scratch/fk-r3-fix.txt +66 -0
- package/.dedao-extract/scratch/fk-r3-s09.pdf +0 -0
- package/.dedao-extract/scratch/l001-1.pgm +6 -0
- package/.dedao-extract/scratch/l001-2.pgm +38 -0
- package/.dedao-extract/scratch/l001-3.pgm +38 -0
- package/.dedao-extract/scratch/l001-4.pgm +4 -0
- package/.dedao-extract/scratch/l001-5.pgm +179 -0
- package/.dedao-extract/scratch/l001-6.pgm +43 -1
- package/.dedao-extract/scratch/l001-7.pgm +4 -0
- package/.dedao-extract/scratch/l001-8.pgm +107 -0
- package/.dedao-extract/scratch/l001-analysis.json +23 -0
- package/.dedao-extract/scratch/l001-before.pdf +0 -0
- package/.dedao-extract/scratch/l001-dom-inner.txt +444 -0
- package/.dedao-extract/scratch/l001-pdftotext.txt +146 -0
- package/.dedao-extract/scratch/l002-1.pgm +6 -0
- package/.dedao-extract/scratch/l002-2.pgm +4 -0
- package/.dedao-extract/scratch/l002-3.pgm +4 -0
- package/.dedao-extract/scratch/l002-4.pgm +4 -0
- package/.dedao-extract/scratch/l002-5.pgm +106 -0
- package/.dedao-extract/scratch/l002-analysis.json +17 -0
- package/.dedao-extract/scratch/l002-before.pdf +0 -0
- package/.dedao-extract/scratch/l002-dom-inner.txt +392 -0
- package/.dedao-extract/scratch/l002-pdftotext.txt +82 -0
- package/.dedao-extract/scratch/l003-clean-inner.txt +74 -0
- package/.dedao-extract/scratch/l003-fix-inner.txt +74 -0
- package/.dedao-extract/scratch/l003-r3-base.pdf +0 -0
- package/.dedao-extract/scratch/l003-r3-base.txt +109 -0
- package/.dedao-extract/scratch/l003-r3-fix.pdf +0 -0
- package/.dedao-extract/scratch/l003-r3-fix.txt +108 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-01.pgm +32 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-02.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-03.pgm +119 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-04.pgm +496 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-05.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-06.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-07.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-08.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-09.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-10.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-11.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-12.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-13.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-base-14.pgm +58 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-01.pgm +32 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-02.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-03.pgm +119 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-04.pgm +496 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-05.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-06.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-07.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-08.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-09.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-10.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-11.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-12.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-13.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-fix-14.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-01.pgm +15 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-02.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-03.pgm +27 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-04.pgm +128 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-05.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-06.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-07.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-08.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-09.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-10.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-11.pgm +4 -0
- package/.dedao-extract/scratch/pp-fk-r3-s09-12.pgm +18 -0
- package/.dedao-extract/scratch/pp-l003-r3-base-1.pgm +7 -0
- package/.dedao-extract/scratch/pp-l003-r3-base-2.pgm +114 -0
- package/.dedao-extract/scratch/pp-l003-r3-base-3.pgm +4 -0
- package/.dedao-extract/scratch/pp-l003-r3-base-4.pgm +30 -0
- package/.dedao-extract/scratch/pp-l003-r3-base-5.pgm +4 -0
- package/.dedao-extract/scratch/pp-l003-r3-base-6.pgm +64 -0
- package/.dedao-extract/scratch/pp-l003-r3-fix-1.pgm +7 -0
- package/.dedao-extract/scratch/pp-l003-r3-fix-2.pgm +114 -0
- package/.dedao-extract/scratch/pp-l003-r3-fix-3.pgm +4 -0
- package/.dedao-extract/scratch/pp-l003-r3-fix-4.pgm +31 -0
- package/.dedao-extract/scratch/pp-l003-r3-fix-5.pgm +4 -0
- package/.dedao-extract/scratch/promo-fk-datauri.txt +1 -0
- package/.dedao-extract/scratch/promo-fk.jpg +0 -0
- package/.dedao-extract/scratch/promo-l001.jpg +0 -0
- package/.dedao-extract/scratch/promo-l002.jpg +0 -0
- package/.dedao-extract/scratch/s8-ink-report.json +447 -0
- package/.dedao-extract/scratch/v2-fk-clean-inner.txt +42 -0
- package/.dedao-extract/scratch/v2-fk-it1.pdf +0 -0
- package/.dedao-extract/scratch/v2-fk-it2.pdf +0 -0
- package/.dedao-extract/scratch/v2-fk-it3.pdf +0 -0
- package/.dedao-extract/scratch/v2-l001-clean-inner.txt +99 -0
- package/.dedao-extract/scratch/v2-l001-it1.pdf +0 -0
- package/.dedao-extract/scratch/v2-l001-it2.pdf +0 -0
- package/.dedao-extract/scratch/v2-l002-clean-inner.txt +53 -0
- package/.dedao-extract/scratch/v2-l002-it1.pdf +0 -0
- package/.dedao-extract/scratch/v2-l002-it2.pdf +0 -0
- package/.dedao-extract/scratch/v3-fk-clean-inner.txt +42 -0
- package/.dedao-extract/scratch/v3-fk-it1.pdf +0 -0
- package/.dedao-extract/scratch/v3-fk-it2.pdf +0 -0
- package/.dedao-extract/scratch/v3-fk-it3.pdf +0 -0
- package/.dedao-extract/scratch/v3-l001-clean-inner.txt +93 -0
- package/.dedao-extract/scratch/v3-l001-it1.pdf +0 -0
- package/.dedao-extract/scratch/v3-l001-it2.pdf +0 -0
- package/.dedao-extract/scratch/v3-l002-clean-inner.txt +49 -0
- package/.dedao-extract/scratch/v3-l002-it1.pdf +0 -0
- package/.dedao-extract/scratch/v3-l002-it2.pdf +0 -0
- package/.dedao-extract/v2-01-navigate.json +14 -0
- package/.dedao-extract/v2-98-results.json +128 -0
- package/.dedao-extract/v2-99-log.json +20 -0
- package/.dedao-extract/v2-fk-figs-it1.json +76 -0
- package/.dedao-extract/v2-fk-figs-it2.json +76 -0
- package/.dedao-extract/v2-fk-fix-screen.json +20 -0
- package/.dedao-extract/v2-fk-meta.json +145 -0
- package/.dedao-extract/v2-fk-promo-audit.json +12 -0
- package/.dedao-extract/v2-fk-targets-it1.json +94 -0
- package/.dedao-extract/v2-fk-targets-it2.json +94 -0
- package/.dedao-extract/v2-l001-figs-it1.json +62 -0
- package/.dedao-extract/v2-l001-fix-screen.json +20 -0
- package/.dedao-extract/v2-l001-meta.json +147 -0
- package/.dedao-extract/v2-l001-promo-audit.json +12 -0
- package/.dedao-extract/v2-l001-targets-it1.json +84 -0
- package/.dedao-extract/v2-l002-figs-it1.json +34 -0
- package/.dedao-extract/v2-l002-fix-screen.json +13 -0
- package/.dedao-extract/v2-l002-meta.json +126 -0
- package/.dedao-extract/v2-l002-promo-audit.json +12 -0
- package/.dedao-extract/v2-l002-targets-it1.json +46 -0
- package/.dedao-extract/v2-qc-final.json +60 -0
- package/.dedao-extract/v3-01-navigate.json +14 -0
- package/.dedao-extract/v3-98-results.json +530 -0
- package/.dedao-extract/v3-99-log.json +60 -0
- package/.dedao-extract/v3-fk-figs-it1.json +66 -0
- package/.dedao-extract/v3-fk-figs-it2.json +66 -0
- package/.dedao-extract/v3-fk-fix-screen.json +20 -0
- package/.dedao-extract/v3-fk-meta.json +164 -0
- package/.dedao-extract/v3-fk-promo-audit.json +12 -0
- package/.dedao-extract/v3-fk-sikao.json +6 -0
- package/.dedao-extract/v3-fk-targets-it1.json +84 -0
- package/.dedao-extract/v3-fk-targets-it2.json +84 -0
- package/.dedao-extract/v3-l001-figs-it1.json +54 -0
- package/.dedao-extract/v3-l001-fix-screen.json +19 -0
- package/.dedao-extract/v3-l001-meta.json +192 -0
- package/.dedao-extract/v3-l001-promo-audit.json +12 -0
- package/.dedao-extract/v3-l001-sikao.json +41 -0
- package/.dedao-extract/v3-l001-targets-it1.json +76 -0
- package/.dedao-extract/v3-l002-figs-it1.json +30 -0
- package/.dedao-extract/v3-l002-fix-screen.json +12 -0
- package/.dedao-extract/v3-l002-meta.json +172 -0
- package/.dedao-extract/v3-l002-promo-audit.json +12 -0
- package/.dedao-extract/v3-l002-sikao.json +32 -0
- package/.dedao-extract/v3-l002-targets-it1.json +42 -0
- package/.dedao-extract/v3-qc-final.json +77 -0
- package/.dedao-extract/write-version-record.py +43 -0
- package/ARCHITECTURE.md +11 -0
- package/dist/browse/StepEngine.d.ts +1 -1
- package/dist/browse/StepEngine.d.ts.map +1 -1
- package/dist/browse/StepEngine.js +28 -4
- package/dist/browse/StepEngine.js.map +1 -1
- package/dist/browse/steps-types.d.ts +2 -2
- package/dist/browse/steps-types.d.ts.map +1 -1
- package/dist/channels/BrowseChannel.d.ts +3 -1
- package/dist/channels/BrowseChannel.d.ts.map +1 -1
- package/dist/channels/BrowseChannel.js +32 -9
- package/dist/channels/BrowseChannel.js.map +1 -1
- package/dist/desktop/AppleScriptProvider.d.ts +1 -1
- package/dist/desktop/AppleScriptProvider.d.ts.map +1 -1
- package/dist/desktop/AppleScriptProvider.js +6 -2
- package/dist/desktop/AppleScriptProvider.js.map +1 -1
- package/dist/desktop/AxProvider.d.ts +6 -3
- package/dist/desktop/AxProvider.d.ts.map +1 -1
- package/dist/desktop/AxProvider.js +6 -2
- package/dist/desktop/AxProvider.js.map +1 -1
- package/dist/desktop/ScreenshotVlmProvider.d.ts.map +1 -1
- package/dist/desktop/ScreenshotVlmProvider.js +4 -3
- package/dist/desktop/ScreenshotVlmProvider.js.map +1 -1
- package/dist/doctor/doctor.d.ts +1 -1
- package/dist/doctor/doctor.js +1 -1
- package/dist/fallback/BudgetTracker.d.ts +8 -0
- package/dist/fallback/BudgetTracker.d.ts.map +1 -1
- package/dist/fallback/BudgetTracker.js +13 -0
- package/dist/fallback/BudgetTracker.js.map +1 -1
- package/dist/fallback/FallbackDecider.d.ts.map +1 -1
- package/dist/fallback/FallbackDecider.js +5 -2
- package/dist/fallback/FallbackDecider.js.map +1 -1
- package/dist/fallback/LongCircuitBreaker.d.ts +40 -10
- package/dist/fallback/LongCircuitBreaker.d.ts.map +1 -1
- package/dist/fallback/LongCircuitBreaker.js +41 -5
- package/dist/fallback/LongCircuitBreaker.js.map +1 -1
- package/dist/fallback/outcome.d.ts +1 -0
- package/dist/fallback/outcome.d.ts.map +1 -1
- package/dist/fallback/outcome.js +48 -4
- package/dist/fallback/outcome.js.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/runtime/CallerTierTracker.d.ts +11 -6
- package/dist/runtime/CallerTierTracker.d.ts.map +1 -1
- package/dist/runtime/CallerTierTracker.js +11 -6
- package/dist/runtime/CallerTierTracker.js.map +1 -1
- package/dist/ssrf/ssrf-guard.d.ts +23 -0
- package/dist/ssrf/ssrf-guard.d.ts.map +1 -1
- package/dist/ssrf/ssrf-guard.js +37 -0
- package/dist/ssrf/ssrf-guard.js.map +1 -1
- package/dist/tools/admin.d.ts.map +1 -1
- package/dist/tools/admin.js +24 -3
- package/dist/tools/admin.js.map +1 -1
- package/dist/tools/browse.d.ts.map +1 -1
- package/dist/tools/browse.js +10 -4
- package/dist/tools/browse.js.map +1 -1
- package/dist/tools/browserbase.d.ts.map +1 -1
- package/dist/tools/browserbase.js +7 -4
- package/dist/tools/browserbase.js.map +1 -1
- package/dist/tools/fetch-feed.d.ts.map +1 -1
- package/dist/tools/fetch-feed.js +7 -4
- package/dist/tools/fetch-feed.js.map +1 -1
- package/dist/tools/fetch-url.d.ts.map +1 -1
- package/dist/tools/fetch-url.js +27 -13
- package/dist/tools/fetch-url.js.map +1 -1
- package/dist/tools/network.d.ts.map +1 -1
- package/dist/tools/network.js +17 -8
- package/dist/tools/network.js.map +1 -1
- package/dist/tools/pdf.d.ts.map +1 -1
- package/dist/tools/pdf.js +18 -9
- package/dist/tools/pdf.js.map +1 -1
- package/dist/tools/screenshot.d.ts.map +1 -1
- package/dist/tools/screenshot.js +7 -4
- package/dist/tools/screenshot.js.map +1 -1
- package/dist/tools/steel.d.ts.map +1 -1
- package/dist/tools/steel.js +7 -4
- package/dist/tools/steel.js.map +1 -1
- package/dist/tools/wayback.d.ts.map +1 -1
- package/dist/tools/wayback.js +7 -4
- package/dist/tools/wayback.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/util/output-envelope.d.ts +4 -1
- package/dist/util/output-envelope.d.ts.map +1 -1
- package/dist/util/output-envelope.js +51 -9
- package/dist/util/output-envelope.js.map +1 -1
- package/doc/29-/351/224/231/351/205/215/346/234/272/345/210/266/345/256/241/350/256/241/enumerate.md +139 -0
- package/doc/29-/351/224/231/351/205/215/346/234/272/345/210/266/345/256/241/350/256/241/fixes.md +132 -0
- package/doc/29-/351/224/231/351/205/215/346/234/272/345/210/266/345/256/241/350/256/241/verdict.md +104 -0
- package/doc/KEY-GUIDE.md +1 -0
- package/package.json +1 -1
- package/src/browse/StepEngine.ts +32 -5
- package/src/browse/steps-types.ts +2 -2
- package/src/channels/BrowseChannel.ts +40 -9
- package/src/desktop/AppleScriptProvider.ts +7 -3
- package/src/desktop/AxProvider.ts +12 -5
- package/src/desktop/ScreenshotVlmProvider.ts +3 -2
- package/src/doctor/doctor.ts +1 -1
- package/src/fallback/BudgetTracker.ts +15 -0
- package/src/fallback/FallbackDecider.ts +5 -2
- package/src/fallback/LongCircuitBreaker.ts +48 -9
- package/src/fallback/outcome.ts +49 -4
- package/src/index.ts +13 -2
- package/src/runtime/CallerTierTracker.ts +11 -6
- package/src/ssrf/ssrf-guard.ts +43 -0
- package/src/tools/admin.ts +26 -3
- package/src/tools/browse.ts +10 -4
- package/src/tools/browserbase.ts +7 -4
- package/src/tools/fetch-feed.ts +8 -5
- package/src/tools/fetch-url.ts +30 -15
- package/src/tools/network.ts +18 -9
- package/src/tools/pdf.ts +19 -10
- package/src/tools/screenshot.ts +8 -5
- package/src/tools/steel.ts +7 -4
- package/src/tools/wayback.ts +8 -5
- package/src/types.ts +7 -0
- package/src/util/output-envelope.ts +54 -8
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// analyze.mjs — v2 管线共享分析器(零光栅快测 + 墨迹终检 + 文字零丢失)
|
|
3
|
+
// 白盒依据:P14-探察-二轮 §3(S-A' 闭环:pdfimages 0.1s + pdftotext -bbox 0.07s/页;
|
|
4
|
+
// pdftoppm 对含课程表 PDF 约 2min/份,只作出厂终检,禁入主管线)
|
|
5
|
+
import { execFileSync } from "node:child_process";
|
|
6
|
+
import * as fs from "node:fs";
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
import * as os from "node:os";
|
|
9
|
+
|
|
10
|
+
// 打印参数(extract-batch3 同款):A4、四边 0.4in → pt 域
|
|
11
|
+
export const PT_PER_IN = 72;
|
|
12
|
+
export const PAGE_W_IN = 8.268, PAGE_H_IN = 11.693, MARGIN_IN = 0.4;
|
|
13
|
+
export const CONTENT_TOP = MARGIN_IN * 72; // 28.8pt
|
|
14
|
+
export const PAGE_H_PT = PAGE_H_IN * 72; // 841.92
|
|
15
|
+
export const CONTENT_BOTTOM = PAGE_H_PT - MARGIN_IN * 72; // 813.12
|
|
16
|
+
export const CONTENT_H_PT = CONTENT_BOTTOM - CONTENT_TOP; // 784.32
|
|
17
|
+
export const PAGE_CSS = Math.round((PAGE_H_IN - 2 * MARGIN_IN) * 96); // 1046 css px/页
|
|
18
|
+
export const PROMO_NAT = { w: 1080, h: 607 }; // P14 §1.1 尾部宣传图自然尺寸指纹
|
|
19
|
+
|
|
20
|
+
function tmp(pdf) {
|
|
21
|
+
return path.join(os.tmpdir(), `dz-ana-${process.pid}-${path.basename(pdf)}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ---- pdfimages -list 解析 ----
|
|
25
|
+
export function pdfImages(pdf) {
|
|
26
|
+
const out = execFileSync("pdfimages", ["-list", pdf], { maxBuffer: 64 << 20 }).toString();
|
|
27
|
+
const rows = [];
|
|
28
|
+
for (const line of out.split("\n").slice(2)) {
|
|
29
|
+
const t = line.trim().split(/\s+/);
|
|
30
|
+
if (t.length < 14 || !/^\d+$/.test(t[0])) continue;
|
|
31
|
+
rows.push({
|
|
32
|
+
page: +t[0], num: +t[1], type: t[2], w: +t[3], h: +t[4],
|
|
33
|
+
enc: t[8], xppi: +t[t.length - 4], yppi: +t[t.length - 3],
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return rows.filter((r) => r.type === "image"); // smask=同对象 alpha 通道,不计
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ---- pdftotext -bbox 解析(词级坐标) ----
|
|
40
|
+
export function bboxWords(pdf) {
|
|
41
|
+
const out = execFileSync("pdftotext", ["-bbox", pdf, "-"], { maxBuffer: 128 << 20 }).toString();
|
|
42
|
+
const pages = [];
|
|
43
|
+
let page = null;
|
|
44
|
+
const re = /<page width="([\d.]+)" height="([\d.]+)">|<word xMin="([\d.-]+)" yMin="([\d.-]+)" xMax="([\d.-]+)" yMax="([\d.-]+)">([\s\S]*?)<\/word>/g;
|
|
45
|
+
let m;
|
|
46
|
+
while ((m = re.exec(out))) {
|
|
47
|
+
if (m[1]) { page = { w: +m[1], h: +m[2], words: [] }; pages.push(page); }
|
|
48
|
+
else if (page) {
|
|
49
|
+
page.words.push({ x0: +m[3], y0: +m[4], x1: +m[5], y1: +m[6], text: m[7] });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return pages;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ---- 快测洞报告(S-A' 闭环核心) ----
|
|
56
|
+
// 判定:非末页 ∧ 文本尾空 >12% ∧ 版面充满度 <0.88(文本跨距 + 图显示高 + 图间隙)
|
|
57
|
+
// 课程表切片页(全页图)被充满度豁免;图片收尾页被充满度豁免(bbox 只见文字的假洞)
|
|
58
|
+
// P23 修复:页脚页码(displayHeaderFooter,y≈821-827 > CONTENT_BOTTOM=813.12)必须排除——
|
|
59
|
+
// 路线b 合并 PDF 带页码页脚,计入会把 textBottom 钉死在页脚 → tailPct 恒 0 → 洞检测全盲。
|
|
60
|
+
// 单章管线(engine)无页脚,此过滤为无操作,行为不变。
|
|
61
|
+
export function holeReport(pdf, { tailPct = 12, fullFloor = 0.88, gapPt = 24 } = {}) {
|
|
62
|
+
const imgs = pdfImages(pdf);
|
|
63
|
+
const pages = bboxWords(pdf);
|
|
64
|
+
const n = pages.length;
|
|
65
|
+
const per = pages.map((pg, i) => {
|
|
66
|
+
const contentWords = pg.words.filter((w) => w.y1 <= CONTENT_BOTTOM + 0.75); // 页脚词排除
|
|
67
|
+
const ys = contentWords.map((w) => w.y1);
|
|
68
|
+
const textBottom = ys.length ? Math.max(...ys) : null;
|
|
69
|
+
const textTop = contentWords.length ? Math.min(...contentWords.map((w) => w.y0)) : null;
|
|
70
|
+
const imgsOnPage = imgs.filter((r) => r.page === i + 1);
|
|
71
|
+
const imgPt = Math.min(
|
|
72
|
+
CONTENT_H_PT,
|
|
73
|
+
imgsOnPage.reduce((s, r) => s + (r.yppi > 0 ? (r.h / r.yppi) * PT_PER_IN : 0), 0),
|
|
74
|
+
);
|
|
75
|
+
const textSpan = textBottom !== null ? textBottom - CONTENT_TOP : 0;
|
|
76
|
+
const used = Math.max(textSpan, 0) + imgPt + imgsOnPage.length * gapPt;
|
|
77
|
+
const fullness = +(used / CONTENT_H_PT).toFixed(3);
|
|
78
|
+
const tailPt = textBottom !== null ? CONTENT_BOTTOM - textBottom : CONTENT_H_PT;
|
|
79
|
+
const tailPctV = +(Math.max(0, tailPt) / CONTENT_H_PT * 100).toFixed(1);
|
|
80
|
+
const isLast = i === n - 1;
|
|
81
|
+
const hole = !isLast && tailPctV > tailPct && fullness < fullFloor;
|
|
82
|
+
const freePt = +Math.max(0, CONTENT_H_PT - used).toFixed(1); // 版面自由空间(保守:文本跨距+图高+图间隙的加性模型)
|
|
83
|
+
const freePct = +(freePt / CONTENT_H_PT * 100).toFixed(1);
|
|
84
|
+
return { page: i + 1, textBottom, textTop, imgCount: imgsOnPage.length, imgPt: Math.round(imgPt), fullness, tailPt: +tailPt.toFixed(1), tailPct: tailPctV, freePt, freePct, isLast, hole };
|
|
85
|
+
});
|
|
86
|
+
return { pdf, pages: n, holes: per.filter((p) => p.hole), per };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ---- 宣传图断言:PDF 内不得存在 1080×607 图 ----
|
|
90
|
+
export function promoInPdf(pdf) {
|
|
91
|
+
return pdfImages(pdf).filter((r) => r.w === PROMO_NAT.w && r.h === PROMO_NAT.h);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ---- 文字零丢失(P14 §3 定案:cleanup 态 innerText vs pdftotext,missing 必须为空) ----
|
|
95
|
+
export function textZeroLoss(pdf, innerTxt) {
|
|
96
|
+
const pdftxt = execFileSync("pdftotext", [pdf, "-"], { maxBuffer: 128 << 20 }).toString();
|
|
97
|
+
const norm = (s) => s.normalize("NFC").replace(/[\s]/g, "");
|
|
98
|
+
const a = norm(pdftxt), b = norm(innerTxt); // a=PDF 侧,b=DOM 侧
|
|
99
|
+
// 多重集 diff(字符级,CJK 字≈词;PDF 侧多出字符=良性:CSS 列表序号等)
|
|
100
|
+
const cnt = new Map();
|
|
101
|
+
for (const ch of a) cnt.set(ch, (cnt.get(ch) || 0) + 1);
|
|
102
|
+
const missCnt = new Map();
|
|
103
|
+
for (const ch of b) {
|
|
104
|
+
const left = cnt.get(ch) || 0;
|
|
105
|
+
if (left > 0) cnt.set(ch, left - 1);
|
|
106
|
+
else missCnt.set(ch, (missCnt.get(ch) || 0) + 1);
|
|
107
|
+
}
|
|
108
|
+
const missing = [...missCnt.entries()].map(([ch, c]) => `${ch}x${c}`);
|
|
109
|
+
// 保序检查:b 必须是 a 的子序列
|
|
110
|
+
let j = 0;
|
|
111
|
+
for (let i = 0; i < a.length && j < b.length; i++) if (a[i] === b[j]) j++;
|
|
112
|
+
return { missing, missingEmpty: missing.length === 0, inOrder: j === b.length, pdfChars: a.length, domChars: b.length };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ---- 墨迹终检(慢:pdftoppm PGM,仅出厂抽检/3 章对比证据) ----
|
|
116
|
+
export function inkReport(pdf, { first = 1, last = null, tailInkTh = 242, dpi = 36 } = {}) {
|
|
117
|
+
const dir = tmp(pdf);
|
|
118
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
119
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
120
|
+
const npages = last ?? bboxWords(pdf).length;
|
|
121
|
+
const args = ["-f", String(first), "-l", String(last ?? npages), "-r", String(dpi), "-gray", pdf, path.join(dir, "p")];
|
|
122
|
+
execFileSync("pdftoppm", args, { maxBuffer: 64 << 20, timeout: 570000 });
|
|
123
|
+
const files = fs.readdirSync(dir).filter((f) => f.endsWith(".pgm")).sort();
|
|
124
|
+
const out = [];
|
|
125
|
+
for (const f of files) {
|
|
126
|
+
const buf = fs.readFileSync(path.join(dir, f));
|
|
127
|
+
let p = 0;
|
|
128
|
+
const tok = () => {
|
|
129
|
+
while (p < buf.length && (buf[p] === 0x20 || buf[p] === 0x0a || buf[p] === 0x0d || buf[p] === 0x09)) p++;
|
|
130
|
+
if (buf[p] === 0x23) { while (p < buf.length && buf[p] !== 0x0a) p++; return tok(); }
|
|
131
|
+
const s = p;
|
|
132
|
+
while (p < buf.length && !(buf[p] === 0x20 || buf[p] === 0x0a || buf[p] === 0x0d || buf[p] === 0x09)) p++;
|
|
133
|
+
return buf.toString("latin1", s, p);
|
|
134
|
+
};
|
|
135
|
+
if (tok() !== "P5") continue;
|
|
136
|
+
const w = +tok(), h = +tok(); tok(); p++;
|
|
137
|
+
const data = buf.subarray(p, p + w * h);
|
|
138
|
+
let lastInk = -1, firstInk = -1;
|
|
139
|
+
for (let y = 0; y < h && firstInk < 0; y++)
|
|
140
|
+
for (let x = 0; x < w; x++) if (data[y * w + x] < tailInkTh) { firstInk = y; break; }
|
|
141
|
+
for (let y = h - 1; y >= 0; y--) {
|
|
142
|
+
let ink = false;
|
|
143
|
+
for (let x = 0; x < w; x++) if (data[y * w + x] < tailInkTh) { ink = true; break; }
|
|
144
|
+
if (ink) { lastInk = y; break; }
|
|
145
|
+
}
|
|
146
|
+
out.push({ page: +f.match(/(\d+)\.pgm$/)[1], tailBlankPct: +(((h - 1 - lastInk) / h) * 100).toFixed(1), headBlankPct: firstInk < 0 ? 100 : +((firstInk / h) * 100).toFixed(1) });
|
|
147
|
+
}
|
|
148
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ---- Chrome 可见性守卫(P16:PID 定向,禁进程名全量) ----
|
|
153
|
+
export function chromeGuard() {
|
|
154
|
+
try {
|
|
155
|
+
const pid = execFileSync("zsh", ["-c", "lsof -nP -iTCP:9226 -sTCP:LISTEN | awk 'NR>1{print $2}' | sort -u | head -1"])
|
|
156
|
+
.toString().trim();
|
|
157
|
+
if (!pid || !/^\d+$/.test(pid)) return { ok: false, err: "no-pid" };
|
|
158
|
+
const vis = execFileSync("osascript", ["-e",
|
|
159
|
+
`tell application "System Events" to get visible of (first process whose unix id is ${pid})`]).toString().trim();
|
|
160
|
+
if (vis === "true") {
|
|
161
|
+
execFileSync("osascript", ["-e",
|
|
162
|
+
`tell application "System Events" to set visible of (first process whose unix id is ${pid}) to false`]);
|
|
163
|
+
return { ok: true, pid, was: "visible", action: "rehidden" };
|
|
164
|
+
}
|
|
165
|
+
return { ok: true, pid, was: "hidden", action: "none" };
|
|
166
|
+
} catch (e) {
|
|
167
|
+
return { ok: false, err: String(e).slice(0, 120) };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// dbg-fixscreen.mjs — 捕获 JS_FIX_SCREEN 的原始 evaluate 返回(定位 dropped=undefined 根因)
|
|
3
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
4
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
import * as fs from "node:fs";
|
|
7
|
+
|
|
8
|
+
const ROOT = "/Users/wangdong/Documents/Project/cc-control-all/lasso";
|
|
9
|
+
const OUT = path.join(ROOT, ".dedao-extract");
|
|
10
|
+
const TARGET = "https://www.dedao.cn/course/article?id=6EBOqDNZ27YlVdg8oKm4bQ1odMAkgz";
|
|
11
|
+
|
|
12
|
+
// 从 extract-v2.mjs 源码原样抽取 JS_FIX_SCREEN(保证测的就是产线代码)
|
|
13
|
+
const src = fs.readFileSync(path.join(OUT, "extract-v2.mjs"), "utf8");
|
|
14
|
+
const m = src.match(/const JS_FIX_SCREEN = `([\s\S]*?)`;/);
|
|
15
|
+
if (!m) { console.error("extract failed"); process.exit(1); }
|
|
16
|
+
const PAGE_CSS = 1046;
|
|
17
|
+
const JS_FIX_SCREEN = m[1].replace("${PAGE_CSS}", String(PAGE_CSS));
|
|
18
|
+
|
|
19
|
+
const client = new Client({ name: "dedao-dbg-fs", version: "1.0.0" });
|
|
20
|
+
const transport = new StdioClientTransport({
|
|
21
|
+
command: "/bin/zsh",
|
|
22
|
+
args: ["-c", `exec node dist/index.js 2>>${JSON.stringify(path.join(OUT, "server-dbg-stderr.log"))}`],
|
|
23
|
+
cwd: ROOT, env: { ...process.env, LASSO_CDP_PORT: "9226" },
|
|
24
|
+
});
|
|
25
|
+
await client.connect(transport);
|
|
26
|
+
async function browse(action, options = {}, timeoutMs = 180000) {
|
|
27
|
+
const res = await client.callTool({ name: "browse_logged_in", arguments: { url: TARGET, action, options } }, undefined, { timeout: timeoutMs });
|
|
28
|
+
return JSON.parse(res.content[0].text);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// navigate 先行(P6:新 server 会话需先绑定 page)
|
|
32
|
+
const nav = await browse("navigate", {});
|
|
33
|
+
console.log("[nav]", JSON.stringify(nav).slice(0, 120));
|
|
34
|
+
await new Promise((r) => setTimeout(r, 2500));
|
|
35
|
+
const t = await browse("evaluate", { js: `return JSON.stringify({title:(document.querySelector('div.article-body-wrap .article-title')||{textContent:''}).textContent.trim().slice(0,30),figs:document.querySelectorAll('div.article-body-wrap figure').length});` });
|
|
36
|
+
console.log("[state]", t.data?.preview ?? JSON.stringify(t).slice(0, 200));
|
|
37
|
+
|
|
38
|
+
const r = await browse("evaluate", { js: JS_FIX_SCREEN }, undefined, { timeout: 120000 });
|
|
39
|
+
console.log("[outcome]", r.outcome, "| [error]", r.error ?? null);
|
|
40
|
+
console.log("[preview]", (r.data?.preview ?? "").slice(0, 1500));
|
|
41
|
+
await transport.close();
|
|
42
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
43
|
+
process.exit(0);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// debug text fetch — 看 evaluate 原始返回
|
|
3
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
4
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
5
|
+
const ROOT = "/Users/wangdong/Documents/Project/cc-control-all/lasso";
|
|
6
|
+
const client = new Client({ name: "dbg", version: "1" });
|
|
7
|
+
const transport = new StdioClientTransport({
|
|
8
|
+
command: "/bin/zsh",
|
|
9
|
+
args: ["-c", `exec node dist/index.js 2>>/tmp/dbg-stderr.log`],
|
|
10
|
+
cwd: ROOT,
|
|
11
|
+
env: { ...process.env, LASSO_CDP_PORT: "9226" },
|
|
12
|
+
});
|
|
13
|
+
await client.connect(transport);
|
|
14
|
+
const call = (js) =>
|
|
15
|
+
client
|
|
16
|
+
.callTool(
|
|
17
|
+
{ name: "browse_logged_in", arguments: { url: "https://www.dedao.cn/course/article?id=1", action: "evaluate", options: { js } } },
|
|
18
|
+
undefined,
|
|
19
|
+
{ timeout: 60000 },
|
|
20
|
+
)
|
|
21
|
+
.then((r) => r.content[0].text);
|
|
22
|
+
console.log("A:", await call(`return JSON.stringify((document.body.innerText).slice(0,60));`));
|
|
23
|
+
console.log("B:", await call(`return (document.body.innerText||'').length;`));
|
|
24
|
+
await transport.close();
|
|
25
|
+
setTimeout(() => process.exit(0), 300);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3
|
+
const ROOT = "/Users/wangdong/Documents/Project/cc-control-all/lasso";
|
|
4
|
+
const client = new Client({ name: "dbg2", version: "1" });
|
|
5
|
+
const transport = new StdioClientTransport({
|
|
6
|
+
command: "/bin/zsh",
|
|
7
|
+
args: ["-c", `exec node dist/index.js 2>>/tmp/dbg2-stderr.log`],
|
|
8
|
+
cwd: ROOT,
|
|
9
|
+
env: { ...process.env, LASSO_CDP_PORT: "9226" },
|
|
10
|
+
});
|
|
11
|
+
await client.connect(transport);
|
|
12
|
+
const call = (action, options) =>
|
|
13
|
+
client.callTool({ name: "browse_logged_in", arguments: { url: "https://www.dedao.cn/course/article?id=6EBOqDNZ27YlVdg8oKm4bQ1odMAkgz", action, options } }, undefined, { timeout: 90000 }).then((r) => r.content[0].text);
|
|
14
|
+
console.log("nav:", (await call("navigate", {})).slice(0, 120));
|
|
15
|
+
await new Promise(r => setTimeout(r, 4000));
|
|
16
|
+
console.log("A body.innerText len:", await call("evaluate", { js: `return (document.body.innerText||'').length + ' | head=' + (document.body.innerText||'').slice(0,30);` }));
|
|
17
|
+
console.log("B wrap innerText len:", await call("evaluate", { js: `return (document.querySelector('div.article-body-wrap').innerText||'').length;` }));
|
|
18
|
+
console.log("C textContent len:", await call("evaluate", { js: `return (document.querySelector('div.article-body-wrap').textContent||'').length;` }));
|
|
19
|
+
await transport.close();
|
|
20
|
+
setTimeout(() => process.exit(0), 300);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3
|
+
const ROOT = "/Users/wangdong/Documents/Project/cc-control-all/lasso";
|
|
4
|
+
const client = new Client({ name: "dbg3", version: "1" });
|
|
5
|
+
const transport = new StdioClientTransport({
|
|
6
|
+
command: "/bin/zsh",
|
|
7
|
+
args: ["-c", `exec node dist/index.js 2>>/tmp/dbg3-stderr.log`],
|
|
8
|
+
cwd: ROOT,
|
|
9
|
+
env: { ...process.env, LASSO_CDP_PORT: "9226" },
|
|
10
|
+
});
|
|
11
|
+
await client.connect(transport);
|
|
12
|
+
const call = (action, options) =>
|
|
13
|
+
client.callTool({ name: "browse_logged_in", arguments: { url: "https://www.dedao.cn/course/article?id=6EBOqDNZ27YlVdg8oKm4bQ1odMAkgz", action, options } }, undefined, { timeout: 90000 }).then((r) => r.content[0].text);
|
|
14
|
+
console.log("nav FULL:", await call("navigate", {}));
|
|
15
|
+
await new Promise(r => setTimeout(r, 5000));
|
|
16
|
+
console.log("A:", await call("evaluate", { js: `return (document.body.innerText||'').length;` }));
|
|
17
|
+
await transport.close();
|
|
18
|
+
setTimeout(() => process.exit(0), 300);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3
|
+
const ROOT = "/Users/wangdong/Documents/Project/cc-control-all/lasso";
|
|
4
|
+
const client = new Client({ name: "dbg4", version: "1" });
|
|
5
|
+
const transport = new StdioClientTransport({
|
|
6
|
+
command: "/bin/zsh",
|
|
7
|
+
args: ["-c", `exec node dist/index.js 2>>/tmp/dbg4-stderr.log`],
|
|
8
|
+
cwd: ROOT,
|
|
9
|
+
env: { ...process.env, LASSO_CDP_PORT: "9226" },
|
|
10
|
+
});
|
|
11
|
+
await client.connect(transport);
|
|
12
|
+
const call = (action, options) =>
|
|
13
|
+
client.callTool({ name: "browse_logged_in", arguments: { url: "https://www.dedao.cn/course/article?id=6EBOqDNZ27YlVdg8oKm4bQ1odMAkgz", action, options } }, undefined, { timeout: 90000 }).then((r) => r.content[0].text);
|
|
14
|
+
console.log("nav:", (await call("navigate", {})).slice(0, 80));
|
|
15
|
+
for (let i = 0; i < 10; i++) {
|
|
16
|
+
await new Promise(r => setTimeout(r, 1200));
|
|
17
|
+
const j = JSON.parse(await call("evaluate", { js: `return JSON.stringify({rs:document.readyState,t:!!document.querySelector('.article-title'),len:(document.body.innerText||'').length});` }));
|
|
18
|
+
const p = j?.data?.preview;
|
|
19
|
+
console.log(i, p);
|
|
20
|
+
if (p && p.includes('"t":true')) break;
|
|
21
|
+
}
|
|
22
|
+
// 精确复刻 evText 第一片
|
|
23
|
+
const raw = await call("evaluate", { js: `return JSON.stringify((document.body.innerText).slice(0,1800));` });
|
|
24
|
+
const rj = JSON.parse(raw);
|
|
25
|
+
console.log("outcome:", rj.outcome, "| preview len:", (rj.data?.preview ?? "").length, "| preview head:", JSON.stringify((rj.data?.preview ?? "").slice(0, 80)));
|
|
26
|
+
await transport.close();
|
|
27
|
+
setTimeout(() => process.exit(0), 300);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
const ROOT = "/Users/wangdong/Documents/Project/cc-control-all/lasso";
|
|
5
|
+
const client = new Client({ name: "dbg5", version: "1" });
|
|
6
|
+
const transport = new StdioClientTransport({
|
|
7
|
+
command: "/bin/zsh",
|
|
8
|
+
args: ["-c", `exec node dist/index.js 2>>/tmp/dbg5-stderr.log`],
|
|
9
|
+
cwd: ROOT,
|
|
10
|
+
env: { ...process.env, LASSO_CDP_PORT: "9226" },
|
|
11
|
+
});
|
|
12
|
+
await client.connect(transport);
|
|
13
|
+
const call = (action, options) =>
|
|
14
|
+
client.callTool({ name: "browse_logged_in", arguments: { url: "https://www.dedao.cn/course/article?id=6EBOqDNZ27YlVdg8oKm4bQ1odMAkgz", action, options } }, undefined, { timeout: 90000 }).then((r) => r.content[0].text);
|
|
15
|
+
console.log("nav ok:", JSON.parse(await call("navigate", {})).outcome);
|
|
16
|
+
await new Promise(r => setTimeout(r, 4000));
|
|
17
|
+
// b3 JS_CLEANUP 原样(从 scout7 文件抽取,保证一字不差)
|
|
18
|
+
const src = fs.readFileSync(".dedao-extract/scout7-round2.mjs", "utf8");
|
|
19
|
+
const m = src.match(/const JS_CLEANUP = `return \(\(\)=>\{[\s\S]*?\}\)\(\)`;/);
|
|
20
|
+
await call("evaluate", { js: m[0].replace("const JS_CLEANUP = ", "").replace(/;$/, "") });
|
|
21
|
+
const raw = await call("evaluate", { js: `return JSON.stringify((document.body.innerText).slice(0,1800));` });
|
|
22
|
+
const rj = JSON.parse(raw);
|
|
23
|
+
const p = rj?.data?.preview ?? "";
|
|
24
|
+
console.log("outcome:", rj.outcome, "| preview len:", p.length);
|
|
25
|
+
console.log("preview head:", JSON.stringify(p.slice(0, 120)));
|
|
26
|
+
console.log("preview tail:", JSON.stringify(p.slice(-120)));
|
|
27
|
+
try { const s = JSON.parse(p); console.log("parse OK, string len:", s.length, "| head:", JSON.stringify(s.slice(0, 40))); } catch (e) { console.log("parse FAIL:", e.message); }
|
|
28
|
+
const raw2 = await call("evaluate", { js: `return JSON.stringify((document.body.innerText||'').length);` });
|
|
29
|
+
console.log("innerText len direct:", JSON.parse(raw2)?.data?.preview);
|
|
30
|
+
await transport.close();
|
|
31
|
+
setTimeout(() => process.exit(0), 300);
|