@web-auto/webauto 0.1.1 → 0.1.3
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/apps/desktop-console/default-settings.json +1 -0
- package/apps/desktop-console/dist/main/index.mjs +1618 -0
- package/apps/desktop-console/{src → dist}/main/preload.mjs +10 -0
- package/apps/desktop-console/dist/renderer/index.js +3063 -0
- package/apps/desktop-console/entry/ui-console.mjs +299 -0
- package/apps/webauto/entry/account.mjs +356 -0
- package/apps/webauto/entry/lib/account-detect.mjs +160 -0
- package/apps/webauto/entry/lib/account-store.mjs +587 -0
- package/apps/webauto/entry/lib/profilepool.mjs +1 -1
- package/apps/webauto/entry/xhs-install.mjs +27 -3
- package/apps/webauto/entry/xhs-status.mjs +152 -0
- package/apps/webauto/entry/xhs-unified.mjs +595 -17
- package/bin/webauto.mjs +263 -15
- package/dist/apps/webauto/server.js +66 -0
- package/dist/modules/camo-backend/src/index.js +575 -0
- package/dist/modules/camo-backend/src/internal/BrowserSession.js +817 -0
- package/dist/modules/camo-backend/src/internal/ElementRegistry.js +61 -0
- package/dist/modules/camo-backend/src/internal/ProfileLock.js +85 -0
- package/dist/modules/camo-backend/src/internal/SessionManager.js +172 -0
- package/dist/modules/camo-backend/src/internal/container-matcher.js +852 -0
- package/dist/modules/camo-backend/src/internal/engine-manager.js +258 -0
- package/dist/modules/camo-backend/src/internal/fingerprint.js +203 -0
- package/dist/modules/camo-backend/src/internal/pageRuntime.js +29 -0
- package/dist/modules/camo-backend/src/internal/runtimeInjector.js +30 -0
- package/dist/modules/camo-backend/src/internal/state-bus.js +46 -0
- package/dist/modules/camo-backend/src/internal/storage-paths.js +36 -0
- package/dist/modules/camo-backend/src/internal/ws-server.js +1202 -0
- package/dist/modules/camo-runtime/src/utils/browser-service.mjs +423 -0
- package/dist/modules/camo-runtime/src/utils/config.mjs +77 -0
- package/dist/modules/container-registry/src/index.js +184 -0
- package/dist/modules/logging/src/index.js +92 -0
- package/dist/modules/operations/src/builtin.js +27 -0
- package/dist/modules/operations/src/container-binding.js +75 -0
- package/dist/modules/operations/src/executor.js +146 -0
- package/dist/modules/operations/src/operations/click.js +167 -0
- package/dist/modules/operations/src/operations/extract.js +204 -0
- package/dist/modules/operations/src/operations/find-child.js +17 -0
- package/dist/modules/operations/src/operations/highlight.js +138 -0
- package/dist/modules/operations/src/operations/key.js +61 -0
- package/dist/modules/operations/src/operations/navigate.js +148 -0
- package/dist/modules/operations/src/operations/scroll.js +126 -0
- package/dist/modules/operations/src/operations/type.js +190 -0
- package/dist/modules/operations/src/queue.js +100 -0
- package/dist/modules/operations/src/registry.js +11 -0
- package/dist/modules/operations/src/system/mouse.js +33 -0
- package/dist/modules/state/src/atomic-json.js +33 -0
- package/dist/modules/workflow/blocks/AnchorVerificationBlock.js +71 -0
- package/dist/modules/workflow/blocks/BehaviorRandomizer.js +26 -0
- package/dist/modules/workflow/blocks/CallWorkflowBlock.js +38 -0
- package/dist/modules/workflow/blocks/CloseDetailBlock.js +209 -0
- package/dist/modules/workflow/blocks/CollectBatch.js +137 -0
- package/dist/modules/workflow/blocks/CollectCommentsBlock.js +415 -0
- package/dist/modules/workflow/blocks/CollectSearchListBlock.js +599 -0
- package/dist/modules/workflow/blocks/CollectWeiboPosts.js +229 -0
- package/dist/modules/workflow/blocks/DetectPageStateBlock.js +259 -0
- package/dist/modules/workflow/blocks/EnsureLoginBlock.js +162 -0
- package/dist/modules/workflow/blocks/EnsureSession.js +426 -0
- package/dist/modules/workflow/blocks/ErrorClassifier.js +164 -0
- package/dist/modules/workflow/blocks/ErrorRecoveryBlock.js +319 -0
- package/dist/modules/workflow/blocks/ExpandCommentsBlock.js +1032 -0
- package/dist/modules/workflow/blocks/ExtractDetailBlock.js +310 -0
- package/dist/modules/workflow/blocks/ExtractPostFields.js +88 -0
- package/dist/modules/workflow/blocks/GenerateSmartReplyBlock.js +68 -0
- package/dist/modules/workflow/blocks/GoToSearchBlock.js +497 -0
- package/dist/modules/workflow/blocks/GracefulFallbackBlock.js +104 -0
- package/dist/modules/workflow/blocks/HighlightBlock.js +66 -0
- package/dist/modules/workflow/blocks/InitAutoScroll.js +65 -0
- package/dist/modules/workflow/blocks/LoadContainerDefinition.js +50 -0
- package/dist/modules/workflow/blocks/LoadContainerIndex.js +43 -0
- package/dist/modules/workflow/blocks/LocateAndGuardBlock.js +176 -0
- package/dist/modules/workflow/blocks/LoginRecoveryBlock.js +242 -0
- package/dist/modules/workflow/blocks/MatchContainers.js +64 -0
- package/dist/modules/workflow/blocks/MonitoringBlock.js +190 -0
- package/dist/modules/workflow/blocks/OpenDetailBlock.js +1240 -0
- package/dist/modules/workflow/blocks/OrganizeXhsNotesBlock.js +117 -0
- package/dist/modules/workflow/blocks/PersistXhsNoteBlock.js +270 -0
- package/dist/modules/workflow/blocks/PickSinglePost.js +69 -0
- package/dist/modules/workflow/blocks/ProgressTracker.js +125 -0
- package/dist/modules/workflow/blocks/RecordFixtureBlock.js +44 -0
- package/dist/modules/workflow/blocks/RenderMarkdown.js +48 -0
- package/dist/modules/workflow/blocks/SaveFile.js +54 -0
- package/dist/modules/workflow/blocks/ScrollNextBatch.js +72 -0
- package/dist/modules/workflow/blocks/SessionHealthBlock.js +73 -0
- package/dist/modules/workflow/blocks/StartBrowserService.js +45 -0
- package/dist/modules/workflow/blocks/ValidateContainerDefinition.js +67 -0
- package/dist/modules/workflow/blocks/ValidateExtract.js +35 -0
- package/dist/modules/workflow/blocks/WaitSearchPermitBlock.js +162 -0
- package/dist/modules/workflow/blocks/WaitStable.js +74 -0
- package/dist/modules/workflow/blocks/WarmupCommentsBlock.js +120 -0
- package/dist/modules/workflow/blocks/WorkflowExecutor.js +156 -0
- package/dist/modules/workflow/blocks/XiaohongshuCollectFromLinksBlock.js +1004 -0
- package/dist/modules/workflow/blocks/XiaohongshuCollectLinksBlock.js +1049 -0
- package/dist/modules/workflow/blocks/XiaohongshuFullCollectBlock.js +782 -0
- package/dist/modules/workflow/blocks/helpers/anchorVerify.js +198 -0
- package/dist/modules/workflow/blocks/helpers/asyncWorkQueue.js +53 -0
- package/dist/modules/workflow/blocks/helpers/commentScroller.js +334 -0
- package/dist/modules/workflow/blocks/helpers/commentSectionLocator.js +126 -0
- package/dist/modules/workflow/blocks/helpers/containerAnchors.js +301 -0
- package/dist/modules/workflow/blocks/helpers/debugArtifacts.js +6 -0
- package/dist/modules/workflow/blocks/helpers/downloadPaths.js +29 -0
- package/dist/modules/workflow/blocks/helpers/expandCommentsController.js +53 -0
- package/dist/modules/workflow/blocks/helpers/expandCommentsExtractor.js +129 -0
- package/dist/modules/workflow/blocks/helpers/macosVisionOcrPlugin.js +116 -0
- package/dist/modules/workflow/blocks/helpers/mergeXhsMarkdown.js +109 -0
- package/dist/modules/workflow/blocks/helpers/openDetailController.js +56 -0
- package/dist/modules/workflow/blocks/helpers/openDetailTypes.js +7 -0
- package/dist/modules/workflow/blocks/helpers/openDetailViewport.js +474 -0
- package/dist/modules/workflow/blocks/helpers/openDetailWaiter.js +104 -0
- package/dist/modules/workflow/blocks/helpers/operationLogger.js +195 -0
- package/dist/modules/workflow/blocks/helpers/persistedNotes.js +107 -0
- package/dist/modules/workflow/blocks/helpers/replyExpander.js +260 -0
- package/dist/modules/workflow/blocks/helpers/scrollIntoView.js +138 -0
- package/dist/modules/workflow/blocks/helpers/searchExecutor.js +328 -0
- package/dist/modules/workflow/blocks/helpers/searchGate.js +46 -0
- package/dist/modules/workflow/blocks/helpers/searchPageState.js +164 -0
- package/dist/modules/workflow/blocks/helpers/searchResultWaiter.js +64 -0
- package/dist/modules/workflow/blocks/helpers/simpleAnchor.js +134 -0
- package/dist/modules/workflow/blocks/helpers/smartReply.js +40 -0
- package/dist/modules/workflow/blocks/helpers/systemInput.js +635 -0
- package/dist/modules/workflow/blocks/helpers/targetCountMode.js +9 -0
- package/dist/modules/workflow/blocks/helpers/xhsCliArgs.js +80 -0
- package/dist/modules/workflow/blocks/helpers/xhsCommentDom.js +805 -0
- package/dist/modules/workflow/blocks/helpers/xhsNoteOrganizer.js +140 -0
- package/dist/modules/workflow/blocks/restore/RestorePhaseBlock.js +204 -0
- package/dist/modules/workflow/config/workflowRegistry.js +32 -0
- package/dist/modules/workflow/definitions/batch-collect-workflow.js +63 -0
- package/dist/modules/workflow/definitions/scroll-extract-workflow.js +74 -0
- package/dist/modules/workflow/definitions/xiaohongshu-collect-workflow-v2.js +81 -0
- package/dist/modules/workflow/definitions/xiaohongshu-collect-workflow.js +57 -0
- package/dist/modules/workflow/definitions/xiaohongshu-full-collect-workflow-v3.js +68 -0
- package/dist/modules/workflow/definitions/xiaohongshu-note-collect.js +49 -0
- package/dist/modules/workflow/definitions/xiaohongshu-phase1-workflow-v3.js +30 -0
- package/dist/modules/workflow/definitions/xiaohongshu-phase2-links-workflow-v3.js +40 -0
- package/dist/modules/workflow/definitions/xiaohongshu-phase3-collect-workflow-v1.js +54 -0
- package/dist/modules/workflow/definitions/xiaohongshu-phase34-from-links-workflow-v3.js +25 -0
- package/dist/modules/workflow/src/WeiboEventDrivenWorkflowRunner.js +308 -0
- package/dist/modules/workflow/src/context.js +70 -0
- package/dist/modules/workflow/src/index.js +5 -0
- package/dist/modules/workflow/src/orchestrator.js +230 -0
- package/dist/modules/workflow/src/runner.js +55 -0
- package/dist/modules/workflow/src/runtime.js +70 -0
- package/dist/modules/workflow/workflows/WeiboFeedExtractionWorkflow.js +359 -0
- package/dist/modules/workflow/workflows/XiaohongshuLoginWorkflow.js +110 -0
- package/dist/modules/xiaohongshu/app/src/blocks/MatchCommentsBlock.js +139 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase1EnsureServicesBlock.js +36 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase1MonitorCookieBlock.js +213 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase1StartProfileBlock.js +121 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase2CollectLinksBlock.js +1249 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase2SearchBlock.js +703 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase34CloseDetailBlock.js +41 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase34CloseTabsBlock.js +44 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase34CollectCommentsBlock.js +150 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase34ExtractDetailBlock.js +117 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase34OpenDetailBlock.js +102 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase34OpenTabsBlock.js +109 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase34PersistDetailBlock.js +117 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase34ProcessSingleNoteBlock.js +114 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase34ValidateLinksBlock.js +90 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase3InteractBlock.js +1009 -0
- package/dist/modules/xiaohongshu/app/src/blocks/Phase4MultiTabHarvestBlock.js +233 -0
- package/dist/modules/xiaohongshu/app/src/blocks/ReplyInteractBlock.js +291 -0
- package/dist/modules/xiaohongshu/app/src/blocks/XhsDiscoverFallbackBlock.js +240 -0
- package/dist/modules/xiaohongshu/app/src/blocks/helpers/commentMatchDsl.js +126 -0
- package/dist/modules/xiaohongshu/app/src/blocks/helpers/commentMatcher.js +99 -0
- package/dist/modules/xiaohongshu/app/src/blocks/helpers/evidence.js +27 -0
- package/dist/modules/xiaohongshu/app/src/blocks/helpers/sharding.js +42 -0
- package/dist/modules/xiaohongshu/app/src/blocks/helpers/xhsComments.js +270 -0
- package/dist/modules/xiaohongshu/app/src/index.js +9 -0
- package/dist/modules/xiaohongshu/app/src/utils/checkpoints.js +222 -0
- package/dist/modules/xiaohongshu/app/src/utils/controllerAction.js +43 -0
- package/dist/services/controller/src/controller.js +1476 -0
- package/dist/services/controller/src/index.js +2 -0
- package/dist/services/controller/src/payload-normalizer.js +129 -0
- package/dist/services/shared/heartbeat.js +120 -0
- package/dist/services/shared/lib/errorHandler.js +2 -0
- package/dist/services/shared/serviceProcessLogger.js +139 -0
- package/dist/services/unified-api/RemoteBrowserSession.js +176 -0
- package/dist/services/unified-api/RemoteSessionManager.js +148 -0
- package/dist/services/unified-api/container-operations-handler.js +115 -0
- package/dist/services/unified-api/server.js +652 -0
- package/dist/services/unified-api/state-registry.js +274 -0
- package/dist/services/unified-api/task-persistence.js +66 -0
- package/dist/services/unified-api/task-state.js +130 -0
- package/modules/camo-runtime/src/autoscript/action-providers/xhs/search.mjs +12 -5
- package/modules/xiaohongshu/app/pnpm-lock.yaml +24 -0
- package/package.json +38 -10
- package/.beads/README.md +0 -81
- package/.beads/config.yaml +0 -67
- package/.beads/interactions.jsonl +0 -0
- package/.beads/issues.jsonl +0 -180
- package/.beads/metadata.json +0 -4
- package/.claude/settings.local.json +0 -10
- package/.github/workflows/ci.yml +0 -55
- package/AGENTS.md +0 -253
- package/apps/desktop-console/README.md +0 -27
- package/apps/desktop-console/package-lock.json +0 -897
- package/apps/desktop-console/package.json +0 -20
- package/apps/desktop-console/scripts/build-and-install.mjs +0 -19
- package/apps/desktop-console/scripts/build.mjs +0 -45
- package/apps/desktop-console/scripts/test-preload.mjs +0 -13
- package/apps/desktop-console/src/main/config.mts +0 -26
- package/apps/desktop-console/src/main/core-daemon-manager.mts +0 -131
- package/apps/desktop-console/src/main/desktop-settings.mts +0 -267
- package/apps/desktop-console/src/main/heartbeat-watchdog.mts +0 -50
- package/apps/desktop-console/src/main/heartbeat-watchdog.test.mts +0 -68
- package/apps/desktop-console/src/main/index-streaming.test.mts +0 -20
- package/apps/desktop-console/src/main/index.mts +0 -980
- package/apps/desktop-console/src/main/profile-store.mts +0 -239
- package/apps/desktop-console/src/main/profile-store.test.mts +0 -54
- package/apps/desktop-console/src/main/state-bridge.mts +0 -114
- package/apps/desktop-console/src/main/task-state-types.ts +0 -32
- package/apps/desktop-console/src/renderer/hooks/use-task-state.mts +0 -120
- package/apps/desktop-console/src/renderer/index.mts +0 -133
- package/apps/desktop-console/src/renderer/index.test.mts +0 -34
- package/apps/desktop-console/src/renderer/path-helpers.mts +0 -46
- package/apps/desktop-console/src/renderer/path-helpers.test.mts +0 -14
- package/apps/desktop-console/src/renderer/tabs/debug.mts +0 -48
- package/apps/desktop-console/src/renderer/tabs/debug.test.mts +0 -22
- package/apps/desktop-console/src/renderer/tabs/logs.mts +0 -421
- package/apps/desktop-console/src/renderer/tabs/logs.test.mts +0 -27
- package/apps/desktop-console/src/renderer/tabs/preflight.mts +0 -486
- package/apps/desktop-console/src/renderer/tabs/preflight.test.mts +0 -33
- package/apps/desktop-console/src/renderer/tabs/profile-pool.mts +0 -213
- package/apps/desktop-console/src/renderer/tabs/results.mts +0 -171
- package/apps/desktop-console/src/renderer/tabs/run.test.mts +0 -63
- package/apps/desktop-console/src/renderer/tabs/runtime.mts +0 -151
- package/apps/desktop-console/src/renderer/tabs/settings.mts +0 -146
- package/apps/desktop-console/src/renderer/tabs/xiaohongshu/account-flow.mts +0 -486
- package/apps/desktop-console/src/renderer/tabs/xiaohongshu/guide-browser-check.mts +0 -56
- package/apps/desktop-console/src/renderer/tabs/xiaohongshu/helpers.mts +0 -262
- package/apps/desktop-console/src/renderer/tabs/xiaohongshu/layout-block.mts +0 -430
- package/apps/desktop-console/src/renderer/tabs/xiaohongshu/live-stats.mts +0 -847
- package/apps/desktop-console/src/renderer/tabs/xiaohongshu/run-flow.mts +0 -443
- package/apps/desktop-console/src/renderer/tabs/xiaohongshu-state.mts +0 -425
- package/apps/desktop-console/src/renderer/tabs/xiaohongshu.mts +0 -497
- package/apps/desktop-console/src/renderer/tabs/xiaohongshu.test.mts +0 -291
- package/apps/desktop-console/src/renderer/ui-components.mts +0 -31
- package/docs/README_camoufox_chinese.md +0 -141
- package/docs/USAGE_V3.md +0 -163
- package/docs/arch/OCR_MACOS_PLUGIN.md +0 -39
- package/docs/arch/PORTS.md +0 -40
- package/docs/arch/REGRESSION_CHECKLIST.md +0 -121
- package/docs/arch/SEARCH_GATE.md +0 -224
- package/docs/arch/VIEWPORT_SAFETY.md +0 -182
- package/docs/arch/XIAOHONGSHU_OFFLINE_MOCK_DESIGN.md +0 -267
- package/docs/xiaohongshu-container-driven-summary.md +0 -221
- package/docs/xiaohongshu-full-collect-runbook.md +0 -134
- package/docs/xiaohongshu-next-steps.md +0 -228
- package/docs/xiaohongshu-quickstart.md +0 -73
- package/docs/xiaohongshu-workflow-summary.md +0 -227
- package/modules/container-registry/tests/container-registry.test.ts +0 -16
- package/modules/logging/tests/logging.test.ts +0 -38
- package/modules/operations/tests/operations.test.ts +0 -22
- package/modules/operations/tests/viewport-filter.test.ts +0 -161
- package/modules/operations/tests/visible-only.test.ts +0 -250
- package/modules/session-manager/tests/session-manager.test.ts +0 -23
- package/modules/state/src/atomic-json.test.ts +0 -30
- package/modules/state/src/paths.test.ts +0 -59
- package/modules/state/src/xiaohongshu-collect-state.test.ts +0 -259
- package/modules/workflow/blocks/AnchorVerificationBlock.d.ts.map +0 -1
- package/modules/workflow/blocks/AnchorVerificationBlock.js.map +0 -1
- package/modules/workflow/blocks/DetectPageStateBlock.d.ts.map +0 -1
- package/modules/workflow/blocks/DetectPageStateBlock.js.map +0 -1
- package/modules/workflow/blocks/ErrorRecoveryBlock.d.ts.map +0 -1
- package/modules/workflow/blocks/ErrorRecoveryBlock.js.map +0 -1
- package/modules/workflow/blocks/WaitSearchPermitBlock.d.ts.map +0 -1
- package/modules/workflow/blocks/WaitSearchPermitBlock.js.map +0 -1
- package/modules/workflow/blocks/helpers/containerAnchors.d.ts.map +0 -1
- package/modules/workflow/blocks/helpers/containerAnchors.js.map +0 -1
- package/modules/workflow/blocks/helpers/downloadPaths.test.ts +0 -62
- package/modules/workflow/blocks/helpers/mergeXhsMarkdown.test.ts +0 -121
- package/modules/workflow/blocks/helpers/operationLogger.d.ts.map +0 -1
- package/modules/workflow/blocks/helpers/operationLogger.js.map +0 -1
- package/modules/workflow/blocks/helpers/persistedNotes.test.ts +0 -268
- package/modules/workflow/blocks/helpers/searchPageState.d.ts.map +0 -1
- package/modules/workflow/blocks/helpers/searchPageState.js.map +0 -1
- package/modules/workflow/blocks/helpers/targetCountMode.test.ts +0 -29
- package/modules/workflow/blocks/helpers/xhsCliArgs.test.ts +0 -75
- package/modules/workflow/tests/smartReply.test.ts +0 -32
- package/modules/xiaohongshu/app/src/blocks/Phase3Interact.matcher.test.ts +0 -33
- package/modules/xiaohongshu/app/src/utils/__tests__/checkpoints.test.ts +0 -141
- package/modules/xiaohongshu/app/tests/commentMatchDsl.test.ts +0 -50
- package/modules/xiaohongshu/app/tests/commentMatcher.test.ts +0 -46
- package/modules/xiaohongshu/app/tests/sharding.test.ts +0 -31
- package/package-scripts.json +0 -8
- package/runtime/infra/utils/README.md +0 -13
- package/runtime/infra/utils/scripts/README.md +0 -0
- package/runtime/infra/utils/scripts/development/eval-in-session.mjs +0 -40
- package/runtime/infra/utils/scripts/development/highlight-search-containers.mjs +0 -35
- package/runtime/infra/utils/scripts/service/kill-port.mjs +0 -24
- package/runtime/infra/utils/scripts/service/start-api.mjs +0 -39
- package/runtime/infra/utils/scripts/service/start-browser-service.mjs +0 -106
- package/runtime/infra/utils/scripts/service/stop-api.mjs +0 -18
- package/runtime/infra/utils/scripts/service/stop-browser-service.mjs +0 -104
- package/runtime/infra/utils/scripts/test-services.mjs +0 -94
- package/services/shared/heartbeat.test.ts +0 -102
- package/services/unified-api/__tests__/task-state.test.ts +0 -95
- package/sitecustomize.py +0 -19
- package/tests/README.md +0 -194
- package/tests/e2e/workflows/weibo-feed-extraction.test.ts +0 -171
- package/tests/fixtures/data/container-definitions.json +0 -67
- package/tests/fixtures/pages/simple-page.html +0 -69
- package/tests/integration/01-test-container-match.mjs +0 -188
- package/tests/integration/02-test-dom-branch.mjs +0 -161
- package/tests/integration/03-test-container-operation-system.mjs +0 -91
- package/tests/integration/05-test-container-lifecycle-events.mjs +0 -224
- package/tests/integration/05-test-container-lifecycle-with-events.mjs +0 -250
- package/tests/integration/06-test-container-dom-tree-drawing.mjs +0 -256
- package/tests/integration/07-test-weibo-container-lifecycle.mjs +0 -355
- package/tests/integration/08-test-weibo-feed-workflow.test.mjs +0 -164
- package/tests/integration/10-test-visual-analyzer.mjs +0 -312
- package/tests/integration/11-test-visual-loop.mjs +0 -284
- package/tests/integration/12-test-simple-visual-loop.mjs +0 -242
- package/tests/integration/13-test-visual-robust.mjs +0 -185
- package/tests/integration/14-test-visual-highlight-loop.mjs +0 -271
- package/tests/integration/inspect-page.mjs +0 -50
- package/tests/integration/run-all-tests.mjs +0 -95
- package/tests/patch_verification/CODEX_PATCH_TEST.md +0 -103
- package/tests/patch_verification/PHASE2_ANALYSIS.md +0 -179
- package/tests/patch_verification/PHASE2_OPTIMIZATION_REPORT.md +0 -55
- package/tests/patch_verification/PHASE2_TO_PHASE4_SUMMARY.md +0 -126
- package/tests/patch_verification/QUICK_TEST_SEQUENCE.md +0 -262
- package/tests/patch_verification/README.md +0 -143
- package/tests/patch_verification/RUN_TESTS.md +0 -60
- package/tests/patch_verification/TEST_EXECUTION.md +0 -99
- package/tests/patch_verification/TEST_PLAN.md +0 -328
- package/tests/patch_verification/TEST_RESULTS.md +0 -34
- package/tests/patch_verification/TOOL_TEST_PLAN.md +0 -48
- package/tests/patch_verification/run-tool-test.mjs +0 -121
- package/tests/patch_verification/temp_test_files/test01.txt +0 -1
- package/tests/patch_verification/temp_test_files/test02.txt +0 -3
- package/tests/patch_verification/temp_test_files/test02_gnu.txt +0 -3
- package/tests/patch_verification/temp_test_files/test03.txt +0 -1
- package/tests/patch_verification/temp_test_files/test03_multiline.txt +0 -5
- package/tests/patch_verification/temp_test_files/test04_function.ts +0 -5
- package/tests/patch_verification/temp_test_files/test05_import.ts +0 -4
- package/tests/patch_verification/temp_test_files/test06_special_chars.txt +0 -4
- package/tests/patch_verification/temp_test_files/test07_indentation.ts +0 -5
- package/tests/patch_verification/temp_test_files/test08_mismatch.txt +0 -1
- package/tests/patch_verification/temp_test_files/test_add_02.txt +0 -3
- package/tests/patch_verification/temp_test_files/test_simple.txt +0 -1
- package/tests/runner/TestReporter.mjs +0 -57
- package/tests/runner/TestRunner.mjs +0 -244
- package/tests/unit/commands/profile.test.mjs +0 -10
- package/tests/unit/container/change-notifier.test.mjs +0 -181
- package/tests/unit/lifecycle/session-registry.test.mjs +0 -135
- package/tests/unit/operations/registry.test.ts +0 -73
- package/tests/unit/utils/browser-service.test.mjs +0 -153
- package/tests/unit/utils/config.test.mjs +0 -166
- package/tests/unit/utils/fingerprint.test.mjs +0 -166
- package/tsconfig.json +0 -31
- package/tsconfig.services.json +0 -26
- /package/apps/desktop-console/{src → dist}/renderer/index.html +0 -0
- /package/apps/desktop-console/{src/renderer/tabs → dist/renderer}/run.mts +0 -0
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* 使用 weibo_fresh profile 的容器生命周期完整闭环测试
|
|
4
|
-
*
|
|
5
|
-
* 测试流程:
|
|
6
|
-
* 1. 连接 WebSocket
|
|
7
|
-
* 2. 使用 weibo_fresh profile 检查/创建会话
|
|
8
|
-
* 3. 订阅容器状态
|
|
9
|
-
* 4. 执行容器匹配(触发容器发现)
|
|
10
|
-
* 5. 等待容器发现事件
|
|
11
|
-
* 6. 获取容器树并绘制 DOM Tree
|
|
12
|
-
* 7. 验证完整的事件流
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { WebSocket } from 'ws';
|
|
16
|
-
import http from 'node:http';
|
|
17
|
-
|
|
18
|
-
const HOST = '127.0.0.1';
|
|
19
|
-
const UNIFIED_API_PORT = 7701;
|
|
20
|
-
const WS_URL = `ws://${HOST}:${UNIFIED_API_PORT}/ws`;
|
|
21
|
-
const API_HOST = `http://${HOST}:${UNIFIED_API_PORT}`;
|
|
22
|
-
const PROFILE_ID = 'weibo_fresh';
|
|
23
|
-
|
|
24
|
-
const events = [];
|
|
25
|
-
let ws = null;
|
|
26
|
-
let sessionId = null;
|
|
27
|
-
|
|
28
|
-
function log(msg) {
|
|
29
|
-
console.log(`[WEIBO-LIFECYCLE] ${msg}`);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function httpPost(path, data) {
|
|
33
|
-
return new Promise((resolve, reject) => {
|
|
34
|
-
const payload = JSON.stringify(data || {});
|
|
35
|
-
const req = http.request(
|
|
36
|
-
`${API_HOST}${path}`,
|
|
37
|
-
{
|
|
38
|
-
method: 'POST',
|
|
39
|
-
headers: {
|
|
40
|
-
'Content-Type': 'application/json',
|
|
41
|
-
'Content-Length': Buffer.byteLength(payload)
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
(res) => {
|
|
45
|
-
let body = '';
|
|
46
|
-
res.on('data', (chunk) => body += chunk);
|
|
47
|
-
res.on('end', () => {
|
|
48
|
-
try {
|
|
49
|
-
resolve(JSON.parse(body));
|
|
50
|
-
} catch (err) {
|
|
51
|
-
resolve({ body, statusCode: res.statusCode });
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
);
|
|
56
|
-
req.on('error', reject);
|
|
57
|
-
req.write(payload);
|
|
58
|
-
req.end();
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function httpGet(path) {
|
|
63
|
-
return new Promise((resolve, reject) => {
|
|
64
|
-
http.get(`${API_HOST}${path}`, (res) => {
|
|
65
|
-
let body = '';
|
|
66
|
-
res.on('data', (chunk) => body += chunk);
|
|
67
|
-
res.on('end', () => {
|
|
68
|
-
try {
|
|
69
|
-
resolve(JSON.parse(body));
|
|
70
|
-
} catch (err) {
|
|
71
|
-
resolve({ body, statusCode: res.statusCode });
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
}).on('error', reject);
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async function connectWebSocket() {
|
|
79
|
-
return new Promise((resolve, reject) => {
|
|
80
|
-
ws = new WebSocket(WS_URL);
|
|
81
|
-
|
|
82
|
-
ws.on('open', () => {
|
|
83
|
-
log('WebSocket 连接成功');
|
|
84
|
-
resolve();
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
ws.on('message', (data) => {
|
|
88
|
-
const msg = JSON.parse(data.toString());
|
|
89
|
-
events.push(msg);
|
|
90
|
-
|
|
91
|
-
// 打印容器相关事件
|
|
92
|
-
if (msg.type === 'event' && msg.topic && msg.topic.includes('container')) {
|
|
93
|
-
log(`收到容器事件: ${msg.topic}`);
|
|
94
|
-
if (msg.payload) {
|
|
95
|
-
const preview = JSON.stringify(msg.payload).substring(0, 150);
|
|
96
|
-
log(` 数据: ${preview}...`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
ws.on('error', reject);
|
|
102
|
-
|
|
103
|
-
setTimeout(() => reject(new Error('WebSocket 连接超时')), 5000);
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async function checkHealth() {
|
|
108
|
-
log('检查服务健康状态...');
|
|
109
|
-
const health = await httpGet('/health');
|
|
110
|
-
if (!health.ok) {
|
|
111
|
-
throw new Error('服务不健康');
|
|
112
|
-
}
|
|
113
|
-
log('✓ 服务健康');
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
async function getSessions() {
|
|
117
|
-
log('获取当前会话列表...');
|
|
118
|
-
const result = await httpPost('/v1/controller/action', {
|
|
119
|
-
action: 'session:list',
|
|
120
|
-
payload: {}
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
if (!result.success) {
|
|
124
|
-
throw new Error('获取会话列表失败');
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const sessions = result.data?.sessions || result.data?.data?.sessions || [];
|
|
128
|
-
log(`✓ 找到 ${sessions.length} 个会话`);
|
|
129
|
-
|
|
130
|
-
// 查找 weibo_fresh profile 的会话
|
|
131
|
-
const weiboSession = sessions.find(s => s.profileId === PROFILE_ID || s.session_id === PROFILE_ID);
|
|
132
|
-
|
|
133
|
-
if (weiboSession) {
|
|
134
|
-
sessionId = weiboSession.session_id;
|
|
135
|
-
log(`✓ 找到 weibo_fresh 会话: ${sessionId}`);
|
|
136
|
-
log(` 当前 URL: ${weiboSession.current_url}`);
|
|
137
|
-
} else {
|
|
138
|
-
log(`⚠ 未找到 ${PROFILE_ID} 会话`);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return { sessions, weiboSession };
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async function subscribeToContainer(containerId) {
|
|
145
|
-
log(`订阅容器: ${containerId}`);
|
|
146
|
-
const result = await httpPost(`/v1/container/${containerId}/subscribe`, {});
|
|
147
|
-
|
|
148
|
-
if (!result.success) {
|
|
149
|
-
throw new Error(`订阅失败: ${result.error || '未知错误'}`);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
log(`✓ 容器订阅成功: ${containerId}`);
|
|
153
|
-
return result;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
async function executeContainerMatch(url) {
|
|
157
|
-
log('执行容器匹配...');
|
|
158
|
-
const result = await httpPost('/v1/controller/action', {
|
|
159
|
-
action: 'containers:match',
|
|
160
|
-
payload: { sessionId, url }
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
log(`✓ 容器匹配完成,返回: ${result.success ? '成功' : '失败'}`);
|
|
164
|
-
return result;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async function inspectContainerTree(url) {
|
|
168
|
-
log('获取容器树结构...');
|
|
169
|
-
const result = await httpPost('/v1/controller/action', {
|
|
170
|
-
action: 'inspect_tree',
|
|
171
|
-
payload: { sessionId, url, maxDepth: 3 }
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
log(`✓ 容器树获取完成,返回: ${result.success ? '成功' : '失败'}`);
|
|
175
|
-
return result;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function printContainerTree(data, indent = 0) {
|
|
179
|
-
const prefix = ' '.repeat(indent);
|
|
180
|
-
|
|
181
|
-
if (!data) {
|
|
182
|
-
console.log(`${prefix}[空]`);
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// 处理不同的返回格式
|
|
187
|
-
const tree = data.snapshot || data.tree || data.data || data;
|
|
188
|
-
|
|
189
|
-
if (!tree) {
|
|
190
|
-
log(`无法解析容器树,直接显示原始数据`);
|
|
191
|
-
console.log(prefix, JSON.stringify(data).substring(0, 200));
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (Array.isArray(tree)) {
|
|
196
|
-
tree.forEach(node => printNode(node, indent + 1));
|
|
197
|
-
} else if (tree.containerId || tree.id) {
|
|
198
|
-
printNode(tree, indent);
|
|
199
|
-
} else if (typeof tree === 'object') {
|
|
200
|
-
Object.values(tree).forEach(val => {
|
|
201
|
-
if (Array.isArray(val)) {
|
|
202
|
-
val.forEach(node => printNode(node, indent + 1));
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function printNode(node, indent) {
|
|
209
|
-
const prefix = ' '.repeat(indent);
|
|
210
|
-
const id = node.containerId || node.id || node.defId || 'unknown';
|
|
211
|
-
const type = node.type || node.containerType || 'container';
|
|
212
|
-
const children = node.children || node.nodes || [];
|
|
213
|
-
const selectors = node.selectors || node.selector || [];
|
|
214
|
-
|
|
215
|
-
console.log(`${prefix}├─ [${type}] ${id}`);
|
|
216
|
-
|
|
217
|
-
if (selectors.length > 0) {
|
|
218
|
-
const selStr = Array.isArray(selectors) ? selectors.join(', ') : selectors;
|
|
219
|
-
console.log(`${prefix}│ selectors: ${selStr}`);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (Array.isArray(children) && children.length > 0) {
|
|
223
|
-
children.forEach(child => printNode(child, indent + 1));
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
async function drawAsciiTree() {
|
|
228
|
-
log('\n=== 预期 DOM Tree (ASCII) ===');
|
|
229
|
-
console.log(`
|
|
230
|
-
┌─ [HTML]
|
|
231
|
-
│ └─ [BODY]
|
|
232
|
-
│ └─ [container] WB_main_frame
|
|
233
|
-
│ ├─ [container] WB_webapp
|
|
234
|
-
│ │ ├─ [container] WB_textarea
|
|
235
|
-
│ │ └─ [container] WB_feed
|
|
236
|
-
│ │ ├─ [container] feed_content
|
|
237
|
-
│ │ │ └─ [list-item] feed_item
|
|
238
|
-
│ │ └─ [container] feed_tools
|
|
239
|
-
│ │ ├─ [button] publish
|
|
240
|
-
│ │ └─ [button] refresh
|
|
241
|
-
`);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
async function analyzeEvents() {
|
|
245
|
-
log('\n=== 事件流分析 ===');
|
|
246
|
-
log(`总共收到 ${events.length} 个事件`);
|
|
247
|
-
|
|
248
|
-
// 分类事件
|
|
249
|
-
const containerEvents = events.filter(e =>
|
|
250
|
-
e.type === 'event' && e.topic && e.topic.includes('container')
|
|
251
|
-
);
|
|
252
|
-
const readyEvents = events.filter(e => e.type === 'ready');
|
|
253
|
-
const pongEvents = events.filter(e => e.type === 'pong');
|
|
254
|
-
const responseEvents = events.filter(e => e.type === 'response');
|
|
255
|
-
|
|
256
|
-
log(`容器相关事件: ${containerEvents.length} 个`);
|
|
257
|
-
log(`ready 事件: ${readyEvents.length} 个`);
|
|
258
|
-
log(`pong 事件: ${pongEvents.length} 个`);
|
|
259
|
-
log(`response 事件: ${responseEvents.length} 个`);
|
|
260
|
-
|
|
261
|
-
// 打印容器事件详情
|
|
262
|
-
if (containerEvents.length > 0) {
|
|
263
|
-
log('\n容器事件详情:');
|
|
264
|
-
containerEvents.forEach((event, index) => {
|
|
265
|
-
log(`[${index + 1}] ${event.topic}`);
|
|
266
|
-
if (event.payload) {
|
|
267
|
-
const keys = Object.keys(event.payload);
|
|
268
|
-
log(` 字段: ${keys.join(', ')}`);
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
} else {
|
|
272
|
-
log('⚠ 未收到容器相关事件');
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
return { containerEvents, readyEvents, pongEvents, responseEvents };
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
async function main() {
|
|
279
|
-
try {
|
|
280
|
-
// Step 1: 检查服务健康
|
|
281
|
-
await checkHealth();
|
|
282
|
-
|
|
283
|
-
// Step 2: 连接 WebSocket
|
|
284
|
-
await connectWebSocket();
|
|
285
|
-
|
|
286
|
-
// Step 3: 获取会话列表
|
|
287
|
-
const { sessions, weiboSession } = await getSessions();
|
|
288
|
-
|
|
289
|
-
if (!weiboSession) {
|
|
290
|
-
log('⚠ 未找到 weibo_fresh 会话,尝试使用第一个可用会话');
|
|
291
|
-
if (sessions.length > 0) {
|
|
292
|
-
sessionId = sessions[0].session_id;
|
|
293
|
-
log(`使用会话: ${sessionId}`);
|
|
294
|
-
} else {
|
|
295
|
-
log('⚠ 没有可用会话,跳过容器操作测试');
|
|
296
|
-
await analyzeEvents();
|
|
297
|
-
log('\n✅ 基础 WebSocket 和健康检查通过');
|
|
298
|
-
ws.close();
|
|
299
|
-
process.exit(0);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// Step 4: 绘制预期的 DOM Tree
|
|
304
|
-
await drawAsciiTree();
|
|
305
|
-
|
|
306
|
-
// Step 5: 订阅容器
|
|
307
|
-
await subscribeToContainer('test-weibo-container');
|
|
308
|
-
|
|
309
|
-
// Step 6: 执行容器匹配(触发发现流程)
|
|
310
|
-
const matchResult = await executeContainerMatch(weiboSession?.current_url || 'https://weibo.com');
|
|
311
|
-
|
|
312
|
-
// Step 7: 获取容器树
|
|
313
|
-
const treeResult = await inspectContainerTree(weiboSession?.current_url || 'https://weibo.com');
|
|
314
|
-
|
|
315
|
-
// Step 8: 打印容器树
|
|
316
|
-
if (treeResult.success && treeResult.data) {
|
|
317
|
-
log('\n=== 容器树结构 ===');
|
|
318
|
-
printContainerTree(treeResult.data);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Step 9: 等待事件传播
|
|
322
|
-
log('等待事件传播...');
|
|
323
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
324
|
-
|
|
325
|
-
// Step 10: 分析事件
|
|
326
|
-
const analysis = await analyzeEvents();
|
|
327
|
-
|
|
328
|
-
// Step 11: 总结
|
|
329
|
-
log('\n=== 测试总结 ===');
|
|
330
|
-
log('✓ WebSocket 连接: 通过');
|
|
331
|
-
log('✓ 会话获取: 通过');
|
|
332
|
-
log(`✓ 容器匹配: ${matchResult.success ? '通过' : '失败'}`);
|
|
333
|
-
log(`✓ 容器树获取: ${treeResult.success ? '通过' : '失败'}`);
|
|
334
|
-
log(`✓ 事件接收: 通过 (${events.length} 个事件)`);
|
|
335
|
-
|
|
336
|
-
if (analysis.containerEvents.length > 0) {
|
|
337
|
-
log('✓ 容器事件跟踪: 通过');
|
|
338
|
-
} else {
|
|
339
|
-
log('⚠ 容器事件跟踪: 未收到(可能需要实际容器发现)');
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
log('\n✅ 容器生命周期完整闭环测试完成!');
|
|
343
|
-
|
|
344
|
-
ws.close();
|
|
345
|
-
process.exit(0);
|
|
346
|
-
|
|
347
|
-
} catch (error) {
|
|
348
|
-
console.error('\n❌ 测试失败:', error.message);
|
|
349
|
-
console.error(error.stack);
|
|
350
|
-
if (ws) ws.close();
|
|
351
|
-
process.exit(1);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
main();
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Weibo Feed Extraction Workflow Test
|
|
4
|
-
*
|
|
5
|
-
* Tests complete workflow:
|
|
6
|
-
* 1. Navigate to weibo.com with weibo_fresh profile
|
|
7
|
-
* 2. Match containers (page → feed_list → feed_posts)
|
|
8
|
-
* 3. Extract links from each post
|
|
9
|
-
* 4. Scroll to load more posts
|
|
10
|
-
* 5. Repeat extraction
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import assert from 'node:assert/strict';
|
|
14
|
-
import WebSocket from 'ws';
|
|
15
|
-
|
|
16
|
-
const UNIFIED_PORT = 7701;
|
|
17
|
-
const BROWSER_PORT = 7704;
|
|
18
|
-
const PROFILE_ID = 'weibo_fresh';
|
|
19
|
-
const TARGET_URL = 'https://weibo.com';
|
|
20
|
-
|
|
21
|
-
function log(msg) {
|
|
22
|
-
console.log(`[weibo-workflow-test] ${msg}`);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async function waitForHealth(url, timeout = 20000) {
|
|
26
|
-
const start = Date.now();
|
|
27
|
-
while (Date.now() - start < timeout) {
|
|
28
|
-
try {
|
|
29
|
-
const res = await fetch(url, { signal: AbortSignal.timeout(1200) });
|
|
30
|
-
if (res.ok) return true;
|
|
31
|
-
} catch {}
|
|
32
|
-
await new Promise(res => setTimeout(res, 500));
|
|
33
|
-
}
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function sendWsAction(action, payload = {}) {
|
|
38
|
-
return new Promise((resolve, reject) => {
|
|
39
|
-
const ws = new WebSocket(`ws://127.0.0.1:${UNIFIED_PORT}/ws`);
|
|
40
|
-
const timeout = setTimeout(() => {
|
|
41
|
-
ws.close();
|
|
42
|
-
reject(new Error('WebSocket action timeout'));
|
|
43
|
-
}, 30000);
|
|
44
|
-
|
|
45
|
-
ws.on('open', () => {
|
|
46
|
-
ws.send(JSON.stringify({
|
|
47
|
-
type: 'action',
|
|
48
|
-
action,
|
|
49
|
-
payload,
|
|
50
|
-
requestId: Date.now()
|
|
51
|
-
}));
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
ws.on('message', (data) => {
|
|
55
|
-
try {
|
|
56
|
-
const msg = JSON.parse(data.toString());
|
|
57
|
-
if (msg.type === 'response') {
|
|
58
|
-
clearTimeout(timeout);
|
|
59
|
-
ws.close();
|
|
60
|
-
resolve(msg);
|
|
61
|
-
}
|
|
62
|
-
} catch (err) {
|
|
63
|
-
clearTimeout(timeout);
|
|
64
|
-
ws.close();
|
|
65
|
-
reject(err);
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
ws.on('error', (err) => {
|
|
70
|
-
clearTimeout(timeout);
|
|
71
|
-
reject(err);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function main() {
|
|
77
|
-
try {
|
|
78
|
-
log('Step 1: Check services health');
|
|
79
|
-
const unifiedHealthy = await waitForHealth(`http://127.0.0.1:${UNIFIED_PORT}/health`);
|
|
80
|
-
const browserHealthy = await waitForHealth(`http://127.0.0.1:${BROWSER_PORT}/health`);
|
|
81
|
-
|
|
82
|
-
if (!unifiedHealthy || !browserHealthy) {
|
|
83
|
-
throw new Error('Services not healthy. Please start with: node scripts/start-headful.mjs');
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
log('Step 2: Match containers');
|
|
87
|
-
const matchResult = await sendWsAction('containers:match', {
|
|
88
|
-
profile: PROFILE_ID,
|
|
89
|
-
url: TARGET_URL,
|
|
90
|
-
maxDepth: 3,
|
|
91
|
-
maxChildren: 20
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
assert.equal(matchResult.success, true, 'Container match should succeed');
|
|
95
|
-
const snapshot = matchResult.data?.snapshot;
|
|
96
|
-
assert.ok(snapshot, 'Should have snapshot');
|
|
97
|
-
|
|
98
|
-
log(` ✓ Matched containers: ${snapshot.container_tree?.containers?.length || 0}`);
|
|
99
|
-
|
|
100
|
-
// Verify weibo_main_page
|
|
101
|
-
const rootContainer = snapshot.container_tree?.containers?.[0];
|
|
102
|
-
assert.ok(rootContainer?.id?.includes('weibo_main_page'), 'Should match weibo_main_page');
|
|
103
|
-
log(` ✓ Root container: ${rootContainer.id}`);
|
|
104
|
-
|
|
105
|
-
// Verify feed_list
|
|
106
|
-
const feedList = snapshot.container_tree?.containers?.find(c => c.id?.includes('feed_list'));
|
|
107
|
-
assert.ok(feedList, 'Should find feed_list container');
|
|
108
|
-
log(` ✓ Feed list container: ${feedList.id}`);
|
|
109
|
-
|
|
110
|
-
// Verify feed_post containers
|
|
111
|
-
const feedPosts = snapshot.container_tree?.containers?.filter(c => c.id?.includes('feed_post'));
|
|
112
|
-
assert.ok(feedPosts.length > 0, 'Should find at least one feed_post');
|
|
113
|
-
log(` ✓ Found ${feedPosts.length} feed post containers`);
|
|
114
|
-
|
|
115
|
-
log('Step 3: Highlight first post');
|
|
116
|
-
if (feedPosts[0]) {
|
|
117
|
-
const highlightResult = await sendWsAction('browser:highlight', {
|
|
118
|
-
profile: PROFILE_ID,
|
|
119
|
-
selector: feedPosts[0].match?.nodes?.[0]?.selector,
|
|
120
|
-
options: {
|
|
121
|
-
style: '3px solid #00C853',
|
|
122
|
-
duration: 2000,
|
|
123
|
-
sticky: false
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
assert.equal(highlightResult.success, true, 'Highlight should succeed');
|
|
127
|
-
log(` ✓ Highlighted first post`);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
log('Step 4: Verify DOM structure');
|
|
131
|
-
// Check that containers have required properties
|
|
132
|
-
for (const container of [rootContainer, feedList, feedPosts[0]]) {
|
|
133
|
-
assert.ok(container?.id, 'Container should have id');
|
|
134
|
-
assert.ok(container?.match?.nodes, 'Container should have matched nodes');
|
|
135
|
-
assert.ok(container?.match?.nodes?.length > 0, 'Container should have at least one matched node');
|
|
136
|
-
log(` ✓ Container ${container.id} has ${container.match.nodes.length} matched nodes`);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
log('✅ Workflow test completed successfully');
|
|
140
|
-
log('📝 Verified components:');
|
|
141
|
-
log(' ✓ Unified API health');
|
|
142
|
-
log(' ✓ Browser Service health');
|
|
143
|
-
log(' ✓ Container matching');
|
|
144
|
-
log(' ✓ weibo_main_page container');
|
|
145
|
-
log(' ✓ weibo_main_page.feed_list container');
|
|
146
|
-
log(' ✓ weibo_main_page.feed_post containers');
|
|
147
|
-
log(' ✓ DOM node matching');
|
|
148
|
-
log(' ✓ Element highlighting');
|
|
149
|
-
|
|
150
|
-
log('\n📋 Next steps:');
|
|
151
|
-
log(' 1. Integrate operation execution with Unified API');
|
|
152
|
-
log(' 2. Add scroll-to-load operation binding');
|
|
153
|
-
log(' 3. Implement link extraction and storage');
|
|
154
|
-
log(' 4. Add event-driven operation triggers');
|
|
155
|
-
process.exit(0);
|
|
156
|
-
|
|
157
|
-
} catch (error) {
|
|
158
|
-
console.error('❌ Workflow test failed:', error.message);
|
|
159
|
-
if (error.stack) console.error(error.stack);
|
|
160
|
-
process.exit(1);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
main();
|