@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.
Files changed (354) hide show
  1. package/apps/desktop-console/default-settings.json +1 -0
  2. package/apps/desktop-console/dist/main/index.mjs +1618 -0
  3. package/apps/desktop-console/{src → dist}/main/preload.mjs +10 -0
  4. package/apps/desktop-console/dist/renderer/index.js +3063 -0
  5. package/apps/desktop-console/entry/ui-console.mjs +299 -0
  6. package/apps/webauto/entry/account.mjs +356 -0
  7. package/apps/webauto/entry/lib/account-detect.mjs +160 -0
  8. package/apps/webauto/entry/lib/account-store.mjs +587 -0
  9. package/apps/webauto/entry/lib/profilepool.mjs +1 -1
  10. package/apps/webauto/entry/xhs-install.mjs +27 -3
  11. package/apps/webauto/entry/xhs-status.mjs +152 -0
  12. package/apps/webauto/entry/xhs-unified.mjs +595 -17
  13. package/bin/webauto.mjs +263 -15
  14. package/dist/apps/webauto/server.js +66 -0
  15. package/dist/modules/camo-backend/src/index.js +575 -0
  16. package/dist/modules/camo-backend/src/internal/BrowserSession.js +817 -0
  17. package/dist/modules/camo-backend/src/internal/ElementRegistry.js +61 -0
  18. package/dist/modules/camo-backend/src/internal/ProfileLock.js +85 -0
  19. package/dist/modules/camo-backend/src/internal/SessionManager.js +172 -0
  20. package/dist/modules/camo-backend/src/internal/container-matcher.js +852 -0
  21. package/dist/modules/camo-backend/src/internal/engine-manager.js +258 -0
  22. package/dist/modules/camo-backend/src/internal/fingerprint.js +203 -0
  23. package/dist/modules/camo-backend/src/internal/pageRuntime.js +29 -0
  24. package/dist/modules/camo-backend/src/internal/runtimeInjector.js +30 -0
  25. package/dist/modules/camo-backend/src/internal/state-bus.js +46 -0
  26. package/dist/modules/camo-backend/src/internal/storage-paths.js +36 -0
  27. package/dist/modules/camo-backend/src/internal/ws-server.js +1202 -0
  28. package/dist/modules/camo-runtime/src/utils/browser-service.mjs +423 -0
  29. package/dist/modules/camo-runtime/src/utils/config.mjs +77 -0
  30. package/dist/modules/container-registry/src/index.js +184 -0
  31. package/dist/modules/logging/src/index.js +92 -0
  32. package/dist/modules/operations/src/builtin.js +27 -0
  33. package/dist/modules/operations/src/container-binding.js +75 -0
  34. package/dist/modules/operations/src/executor.js +146 -0
  35. package/dist/modules/operations/src/operations/click.js +167 -0
  36. package/dist/modules/operations/src/operations/extract.js +204 -0
  37. package/dist/modules/operations/src/operations/find-child.js +17 -0
  38. package/dist/modules/operations/src/operations/highlight.js +138 -0
  39. package/dist/modules/operations/src/operations/key.js +61 -0
  40. package/dist/modules/operations/src/operations/navigate.js +148 -0
  41. package/dist/modules/operations/src/operations/scroll.js +126 -0
  42. package/dist/modules/operations/src/operations/type.js +190 -0
  43. package/dist/modules/operations/src/queue.js +100 -0
  44. package/dist/modules/operations/src/registry.js +11 -0
  45. package/dist/modules/operations/src/system/mouse.js +33 -0
  46. package/dist/modules/state/src/atomic-json.js +33 -0
  47. package/dist/modules/workflow/blocks/AnchorVerificationBlock.js +71 -0
  48. package/dist/modules/workflow/blocks/BehaviorRandomizer.js +26 -0
  49. package/dist/modules/workflow/blocks/CallWorkflowBlock.js +38 -0
  50. package/dist/modules/workflow/blocks/CloseDetailBlock.js +209 -0
  51. package/dist/modules/workflow/blocks/CollectBatch.js +137 -0
  52. package/dist/modules/workflow/blocks/CollectCommentsBlock.js +415 -0
  53. package/dist/modules/workflow/blocks/CollectSearchListBlock.js +599 -0
  54. package/dist/modules/workflow/blocks/CollectWeiboPosts.js +229 -0
  55. package/dist/modules/workflow/blocks/DetectPageStateBlock.js +259 -0
  56. package/dist/modules/workflow/blocks/EnsureLoginBlock.js +162 -0
  57. package/dist/modules/workflow/blocks/EnsureSession.js +426 -0
  58. package/dist/modules/workflow/blocks/ErrorClassifier.js +164 -0
  59. package/dist/modules/workflow/blocks/ErrorRecoveryBlock.js +319 -0
  60. package/dist/modules/workflow/blocks/ExpandCommentsBlock.js +1032 -0
  61. package/dist/modules/workflow/blocks/ExtractDetailBlock.js +310 -0
  62. package/dist/modules/workflow/blocks/ExtractPostFields.js +88 -0
  63. package/dist/modules/workflow/blocks/GenerateSmartReplyBlock.js +68 -0
  64. package/dist/modules/workflow/blocks/GoToSearchBlock.js +497 -0
  65. package/dist/modules/workflow/blocks/GracefulFallbackBlock.js +104 -0
  66. package/dist/modules/workflow/blocks/HighlightBlock.js +66 -0
  67. package/dist/modules/workflow/blocks/InitAutoScroll.js +65 -0
  68. package/dist/modules/workflow/blocks/LoadContainerDefinition.js +50 -0
  69. package/dist/modules/workflow/blocks/LoadContainerIndex.js +43 -0
  70. package/dist/modules/workflow/blocks/LocateAndGuardBlock.js +176 -0
  71. package/dist/modules/workflow/blocks/LoginRecoveryBlock.js +242 -0
  72. package/dist/modules/workflow/blocks/MatchContainers.js +64 -0
  73. package/dist/modules/workflow/blocks/MonitoringBlock.js +190 -0
  74. package/dist/modules/workflow/blocks/OpenDetailBlock.js +1240 -0
  75. package/dist/modules/workflow/blocks/OrganizeXhsNotesBlock.js +117 -0
  76. package/dist/modules/workflow/blocks/PersistXhsNoteBlock.js +270 -0
  77. package/dist/modules/workflow/blocks/PickSinglePost.js +69 -0
  78. package/dist/modules/workflow/blocks/ProgressTracker.js +125 -0
  79. package/dist/modules/workflow/blocks/RecordFixtureBlock.js +44 -0
  80. package/dist/modules/workflow/blocks/RenderMarkdown.js +48 -0
  81. package/dist/modules/workflow/blocks/SaveFile.js +54 -0
  82. package/dist/modules/workflow/blocks/ScrollNextBatch.js +72 -0
  83. package/dist/modules/workflow/blocks/SessionHealthBlock.js +73 -0
  84. package/dist/modules/workflow/blocks/StartBrowserService.js +45 -0
  85. package/dist/modules/workflow/blocks/ValidateContainerDefinition.js +67 -0
  86. package/dist/modules/workflow/blocks/ValidateExtract.js +35 -0
  87. package/dist/modules/workflow/blocks/WaitSearchPermitBlock.js +162 -0
  88. package/dist/modules/workflow/blocks/WaitStable.js +74 -0
  89. package/dist/modules/workflow/blocks/WarmupCommentsBlock.js +120 -0
  90. package/dist/modules/workflow/blocks/WorkflowExecutor.js +156 -0
  91. package/dist/modules/workflow/blocks/XiaohongshuCollectFromLinksBlock.js +1004 -0
  92. package/dist/modules/workflow/blocks/XiaohongshuCollectLinksBlock.js +1049 -0
  93. package/dist/modules/workflow/blocks/XiaohongshuFullCollectBlock.js +782 -0
  94. package/dist/modules/workflow/blocks/helpers/anchorVerify.js +198 -0
  95. package/dist/modules/workflow/blocks/helpers/asyncWorkQueue.js +53 -0
  96. package/dist/modules/workflow/blocks/helpers/commentScroller.js +334 -0
  97. package/dist/modules/workflow/blocks/helpers/commentSectionLocator.js +126 -0
  98. package/dist/modules/workflow/blocks/helpers/containerAnchors.js +301 -0
  99. package/dist/modules/workflow/blocks/helpers/debugArtifacts.js +6 -0
  100. package/dist/modules/workflow/blocks/helpers/downloadPaths.js +29 -0
  101. package/dist/modules/workflow/blocks/helpers/expandCommentsController.js +53 -0
  102. package/dist/modules/workflow/blocks/helpers/expandCommentsExtractor.js +129 -0
  103. package/dist/modules/workflow/blocks/helpers/macosVisionOcrPlugin.js +116 -0
  104. package/dist/modules/workflow/blocks/helpers/mergeXhsMarkdown.js +109 -0
  105. package/dist/modules/workflow/blocks/helpers/openDetailController.js +56 -0
  106. package/dist/modules/workflow/blocks/helpers/openDetailTypes.js +7 -0
  107. package/dist/modules/workflow/blocks/helpers/openDetailViewport.js +474 -0
  108. package/dist/modules/workflow/blocks/helpers/openDetailWaiter.js +104 -0
  109. package/dist/modules/workflow/blocks/helpers/operationLogger.js +195 -0
  110. package/dist/modules/workflow/blocks/helpers/persistedNotes.js +107 -0
  111. package/dist/modules/workflow/blocks/helpers/replyExpander.js +260 -0
  112. package/dist/modules/workflow/blocks/helpers/scrollIntoView.js +138 -0
  113. package/dist/modules/workflow/blocks/helpers/searchExecutor.js +328 -0
  114. package/dist/modules/workflow/blocks/helpers/searchGate.js +46 -0
  115. package/dist/modules/workflow/blocks/helpers/searchPageState.js +164 -0
  116. package/dist/modules/workflow/blocks/helpers/searchResultWaiter.js +64 -0
  117. package/dist/modules/workflow/blocks/helpers/simpleAnchor.js +134 -0
  118. package/dist/modules/workflow/blocks/helpers/smartReply.js +40 -0
  119. package/dist/modules/workflow/blocks/helpers/systemInput.js +635 -0
  120. package/dist/modules/workflow/blocks/helpers/targetCountMode.js +9 -0
  121. package/dist/modules/workflow/blocks/helpers/xhsCliArgs.js +80 -0
  122. package/dist/modules/workflow/blocks/helpers/xhsCommentDom.js +805 -0
  123. package/dist/modules/workflow/blocks/helpers/xhsNoteOrganizer.js +140 -0
  124. package/dist/modules/workflow/blocks/restore/RestorePhaseBlock.js +204 -0
  125. package/dist/modules/workflow/config/workflowRegistry.js +32 -0
  126. package/dist/modules/workflow/definitions/batch-collect-workflow.js +63 -0
  127. package/dist/modules/workflow/definitions/scroll-extract-workflow.js +74 -0
  128. package/dist/modules/workflow/definitions/xiaohongshu-collect-workflow-v2.js +81 -0
  129. package/dist/modules/workflow/definitions/xiaohongshu-collect-workflow.js +57 -0
  130. package/dist/modules/workflow/definitions/xiaohongshu-full-collect-workflow-v3.js +68 -0
  131. package/dist/modules/workflow/definitions/xiaohongshu-note-collect.js +49 -0
  132. package/dist/modules/workflow/definitions/xiaohongshu-phase1-workflow-v3.js +30 -0
  133. package/dist/modules/workflow/definitions/xiaohongshu-phase2-links-workflow-v3.js +40 -0
  134. package/dist/modules/workflow/definitions/xiaohongshu-phase3-collect-workflow-v1.js +54 -0
  135. package/dist/modules/workflow/definitions/xiaohongshu-phase34-from-links-workflow-v3.js +25 -0
  136. package/dist/modules/workflow/src/WeiboEventDrivenWorkflowRunner.js +308 -0
  137. package/dist/modules/workflow/src/context.js +70 -0
  138. package/dist/modules/workflow/src/index.js +5 -0
  139. package/dist/modules/workflow/src/orchestrator.js +230 -0
  140. package/dist/modules/workflow/src/runner.js +55 -0
  141. package/dist/modules/workflow/src/runtime.js +70 -0
  142. package/dist/modules/workflow/workflows/WeiboFeedExtractionWorkflow.js +359 -0
  143. package/dist/modules/workflow/workflows/XiaohongshuLoginWorkflow.js +110 -0
  144. package/dist/modules/xiaohongshu/app/src/blocks/MatchCommentsBlock.js +139 -0
  145. package/dist/modules/xiaohongshu/app/src/blocks/Phase1EnsureServicesBlock.js +36 -0
  146. package/dist/modules/xiaohongshu/app/src/blocks/Phase1MonitorCookieBlock.js +213 -0
  147. package/dist/modules/xiaohongshu/app/src/blocks/Phase1StartProfileBlock.js +121 -0
  148. package/dist/modules/xiaohongshu/app/src/blocks/Phase2CollectLinksBlock.js +1249 -0
  149. package/dist/modules/xiaohongshu/app/src/blocks/Phase2SearchBlock.js +703 -0
  150. package/dist/modules/xiaohongshu/app/src/blocks/Phase34CloseDetailBlock.js +41 -0
  151. package/dist/modules/xiaohongshu/app/src/blocks/Phase34CloseTabsBlock.js +44 -0
  152. package/dist/modules/xiaohongshu/app/src/blocks/Phase34CollectCommentsBlock.js +150 -0
  153. package/dist/modules/xiaohongshu/app/src/blocks/Phase34ExtractDetailBlock.js +117 -0
  154. package/dist/modules/xiaohongshu/app/src/blocks/Phase34OpenDetailBlock.js +102 -0
  155. package/dist/modules/xiaohongshu/app/src/blocks/Phase34OpenTabsBlock.js +109 -0
  156. package/dist/modules/xiaohongshu/app/src/blocks/Phase34PersistDetailBlock.js +117 -0
  157. package/dist/modules/xiaohongshu/app/src/blocks/Phase34ProcessSingleNoteBlock.js +114 -0
  158. package/dist/modules/xiaohongshu/app/src/blocks/Phase34ValidateLinksBlock.js +90 -0
  159. package/dist/modules/xiaohongshu/app/src/blocks/Phase3InteractBlock.js +1009 -0
  160. package/dist/modules/xiaohongshu/app/src/blocks/Phase4MultiTabHarvestBlock.js +233 -0
  161. package/dist/modules/xiaohongshu/app/src/blocks/ReplyInteractBlock.js +291 -0
  162. package/dist/modules/xiaohongshu/app/src/blocks/XhsDiscoverFallbackBlock.js +240 -0
  163. package/dist/modules/xiaohongshu/app/src/blocks/helpers/commentMatchDsl.js +126 -0
  164. package/dist/modules/xiaohongshu/app/src/blocks/helpers/commentMatcher.js +99 -0
  165. package/dist/modules/xiaohongshu/app/src/blocks/helpers/evidence.js +27 -0
  166. package/dist/modules/xiaohongshu/app/src/blocks/helpers/sharding.js +42 -0
  167. package/dist/modules/xiaohongshu/app/src/blocks/helpers/xhsComments.js +270 -0
  168. package/dist/modules/xiaohongshu/app/src/index.js +9 -0
  169. package/dist/modules/xiaohongshu/app/src/utils/checkpoints.js +222 -0
  170. package/dist/modules/xiaohongshu/app/src/utils/controllerAction.js +43 -0
  171. package/dist/services/controller/src/controller.js +1476 -0
  172. package/dist/services/controller/src/index.js +2 -0
  173. package/dist/services/controller/src/payload-normalizer.js +129 -0
  174. package/dist/services/shared/heartbeat.js +120 -0
  175. package/dist/services/shared/lib/errorHandler.js +2 -0
  176. package/dist/services/shared/serviceProcessLogger.js +139 -0
  177. package/dist/services/unified-api/RemoteBrowserSession.js +176 -0
  178. package/dist/services/unified-api/RemoteSessionManager.js +148 -0
  179. package/dist/services/unified-api/container-operations-handler.js +115 -0
  180. package/dist/services/unified-api/server.js +652 -0
  181. package/dist/services/unified-api/state-registry.js +274 -0
  182. package/dist/services/unified-api/task-persistence.js +66 -0
  183. package/dist/services/unified-api/task-state.js +130 -0
  184. package/modules/camo-runtime/src/autoscript/action-providers/xhs/search.mjs +12 -5
  185. package/modules/xiaohongshu/app/pnpm-lock.yaml +24 -0
  186. package/package.json +38 -10
  187. package/.beads/README.md +0 -81
  188. package/.beads/config.yaml +0 -67
  189. package/.beads/interactions.jsonl +0 -0
  190. package/.beads/issues.jsonl +0 -180
  191. package/.beads/metadata.json +0 -4
  192. package/.claude/settings.local.json +0 -10
  193. package/.github/workflows/ci.yml +0 -55
  194. package/AGENTS.md +0 -253
  195. package/apps/desktop-console/README.md +0 -27
  196. package/apps/desktop-console/package-lock.json +0 -897
  197. package/apps/desktop-console/package.json +0 -20
  198. package/apps/desktop-console/scripts/build-and-install.mjs +0 -19
  199. package/apps/desktop-console/scripts/build.mjs +0 -45
  200. package/apps/desktop-console/scripts/test-preload.mjs +0 -13
  201. package/apps/desktop-console/src/main/config.mts +0 -26
  202. package/apps/desktop-console/src/main/core-daemon-manager.mts +0 -131
  203. package/apps/desktop-console/src/main/desktop-settings.mts +0 -267
  204. package/apps/desktop-console/src/main/heartbeat-watchdog.mts +0 -50
  205. package/apps/desktop-console/src/main/heartbeat-watchdog.test.mts +0 -68
  206. package/apps/desktop-console/src/main/index-streaming.test.mts +0 -20
  207. package/apps/desktop-console/src/main/index.mts +0 -980
  208. package/apps/desktop-console/src/main/profile-store.mts +0 -239
  209. package/apps/desktop-console/src/main/profile-store.test.mts +0 -54
  210. package/apps/desktop-console/src/main/state-bridge.mts +0 -114
  211. package/apps/desktop-console/src/main/task-state-types.ts +0 -32
  212. package/apps/desktop-console/src/renderer/hooks/use-task-state.mts +0 -120
  213. package/apps/desktop-console/src/renderer/index.mts +0 -133
  214. package/apps/desktop-console/src/renderer/index.test.mts +0 -34
  215. package/apps/desktop-console/src/renderer/path-helpers.mts +0 -46
  216. package/apps/desktop-console/src/renderer/path-helpers.test.mts +0 -14
  217. package/apps/desktop-console/src/renderer/tabs/debug.mts +0 -48
  218. package/apps/desktop-console/src/renderer/tabs/debug.test.mts +0 -22
  219. package/apps/desktop-console/src/renderer/tabs/logs.mts +0 -421
  220. package/apps/desktop-console/src/renderer/tabs/logs.test.mts +0 -27
  221. package/apps/desktop-console/src/renderer/tabs/preflight.mts +0 -486
  222. package/apps/desktop-console/src/renderer/tabs/preflight.test.mts +0 -33
  223. package/apps/desktop-console/src/renderer/tabs/profile-pool.mts +0 -213
  224. package/apps/desktop-console/src/renderer/tabs/results.mts +0 -171
  225. package/apps/desktop-console/src/renderer/tabs/run.test.mts +0 -63
  226. package/apps/desktop-console/src/renderer/tabs/runtime.mts +0 -151
  227. package/apps/desktop-console/src/renderer/tabs/settings.mts +0 -146
  228. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/account-flow.mts +0 -486
  229. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/guide-browser-check.mts +0 -56
  230. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/helpers.mts +0 -262
  231. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/layout-block.mts +0 -430
  232. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/live-stats.mts +0 -847
  233. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/run-flow.mts +0 -443
  234. package/apps/desktop-console/src/renderer/tabs/xiaohongshu-state.mts +0 -425
  235. package/apps/desktop-console/src/renderer/tabs/xiaohongshu.mts +0 -497
  236. package/apps/desktop-console/src/renderer/tabs/xiaohongshu.test.mts +0 -291
  237. package/apps/desktop-console/src/renderer/ui-components.mts +0 -31
  238. package/docs/README_camoufox_chinese.md +0 -141
  239. package/docs/USAGE_V3.md +0 -163
  240. package/docs/arch/OCR_MACOS_PLUGIN.md +0 -39
  241. package/docs/arch/PORTS.md +0 -40
  242. package/docs/arch/REGRESSION_CHECKLIST.md +0 -121
  243. package/docs/arch/SEARCH_GATE.md +0 -224
  244. package/docs/arch/VIEWPORT_SAFETY.md +0 -182
  245. package/docs/arch/XIAOHONGSHU_OFFLINE_MOCK_DESIGN.md +0 -267
  246. package/docs/xiaohongshu-container-driven-summary.md +0 -221
  247. package/docs/xiaohongshu-full-collect-runbook.md +0 -134
  248. package/docs/xiaohongshu-next-steps.md +0 -228
  249. package/docs/xiaohongshu-quickstart.md +0 -73
  250. package/docs/xiaohongshu-workflow-summary.md +0 -227
  251. package/modules/container-registry/tests/container-registry.test.ts +0 -16
  252. package/modules/logging/tests/logging.test.ts +0 -38
  253. package/modules/operations/tests/operations.test.ts +0 -22
  254. package/modules/operations/tests/viewport-filter.test.ts +0 -161
  255. package/modules/operations/tests/visible-only.test.ts +0 -250
  256. package/modules/session-manager/tests/session-manager.test.ts +0 -23
  257. package/modules/state/src/atomic-json.test.ts +0 -30
  258. package/modules/state/src/paths.test.ts +0 -59
  259. package/modules/state/src/xiaohongshu-collect-state.test.ts +0 -259
  260. package/modules/workflow/blocks/AnchorVerificationBlock.d.ts.map +0 -1
  261. package/modules/workflow/blocks/AnchorVerificationBlock.js.map +0 -1
  262. package/modules/workflow/blocks/DetectPageStateBlock.d.ts.map +0 -1
  263. package/modules/workflow/blocks/DetectPageStateBlock.js.map +0 -1
  264. package/modules/workflow/blocks/ErrorRecoveryBlock.d.ts.map +0 -1
  265. package/modules/workflow/blocks/ErrorRecoveryBlock.js.map +0 -1
  266. package/modules/workflow/blocks/WaitSearchPermitBlock.d.ts.map +0 -1
  267. package/modules/workflow/blocks/WaitSearchPermitBlock.js.map +0 -1
  268. package/modules/workflow/blocks/helpers/containerAnchors.d.ts.map +0 -1
  269. package/modules/workflow/blocks/helpers/containerAnchors.js.map +0 -1
  270. package/modules/workflow/blocks/helpers/downloadPaths.test.ts +0 -62
  271. package/modules/workflow/blocks/helpers/mergeXhsMarkdown.test.ts +0 -121
  272. package/modules/workflow/blocks/helpers/operationLogger.d.ts.map +0 -1
  273. package/modules/workflow/blocks/helpers/operationLogger.js.map +0 -1
  274. package/modules/workflow/blocks/helpers/persistedNotes.test.ts +0 -268
  275. package/modules/workflow/blocks/helpers/searchPageState.d.ts.map +0 -1
  276. package/modules/workflow/blocks/helpers/searchPageState.js.map +0 -1
  277. package/modules/workflow/blocks/helpers/targetCountMode.test.ts +0 -29
  278. package/modules/workflow/blocks/helpers/xhsCliArgs.test.ts +0 -75
  279. package/modules/workflow/tests/smartReply.test.ts +0 -32
  280. package/modules/xiaohongshu/app/src/blocks/Phase3Interact.matcher.test.ts +0 -33
  281. package/modules/xiaohongshu/app/src/utils/__tests__/checkpoints.test.ts +0 -141
  282. package/modules/xiaohongshu/app/tests/commentMatchDsl.test.ts +0 -50
  283. package/modules/xiaohongshu/app/tests/commentMatcher.test.ts +0 -46
  284. package/modules/xiaohongshu/app/tests/sharding.test.ts +0 -31
  285. package/package-scripts.json +0 -8
  286. package/runtime/infra/utils/README.md +0 -13
  287. package/runtime/infra/utils/scripts/README.md +0 -0
  288. package/runtime/infra/utils/scripts/development/eval-in-session.mjs +0 -40
  289. package/runtime/infra/utils/scripts/development/highlight-search-containers.mjs +0 -35
  290. package/runtime/infra/utils/scripts/service/kill-port.mjs +0 -24
  291. package/runtime/infra/utils/scripts/service/start-api.mjs +0 -39
  292. package/runtime/infra/utils/scripts/service/start-browser-service.mjs +0 -106
  293. package/runtime/infra/utils/scripts/service/stop-api.mjs +0 -18
  294. package/runtime/infra/utils/scripts/service/stop-browser-service.mjs +0 -104
  295. package/runtime/infra/utils/scripts/test-services.mjs +0 -94
  296. package/services/shared/heartbeat.test.ts +0 -102
  297. package/services/unified-api/__tests__/task-state.test.ts +0 -95
  298. package/sitecustomize.py +0 -19
  299. package/tests/README.md +0 -194
  300. package/tests/e2e/workflows/weibo-feed-extraction.test.ts +0 -171
  301. package/tests/fixtures/data/container-definitions.json +0 -67
  302. package/tests/fixtures/pages/simple-page.html +0 -69
  303. package/tests/integration/01-test-container-match.mjs +0 -188
  304. package/tests/integration/02-test-dom-branch.mjs +0 -161
  305. package/tests/integration/03-test-container-operation-system.mjs +0 -91
  306. package/tests/integration/05-test-container-lifecycle-events.mjs +0 -224
  307. package/tests/integration/05-test-container-lifecycle-with-events.mjs +0 -250
  308. package/tests/integration/06-test-container-dom-tree-drawing.mjs +0 -256
  309. package/tests/integration/07-test-weibo-container-lifecycle.mjs +0 -355
  310. package/tests/integration/08-test-weibo-feed-workflow.test.mjs +0 -164
  311. package/tests/integration/10-test-visual-analyzer.mjs +0 -312
  312. package/tests/integration/11-test-visual-loop.mjs +0 -284
  313. package/tests/integration/12-test-simple-visual-loop.mjs +0 -242
  314. package/tests/integration/13-test-visual-robust.mjs +0 -185
  315. package/tests/integration/14-test-visual-highlight-loop.mjs +0 -271
  316. package/tests/integration/inspect-page.mjs +0 -50
  317. package/tests/integration/run-all-tests.mjs +0 -95
  318. package/tests/patch_verification/CODEX_PATCH_TEST.md +0 -103
  319. package/tests/patch_verification/PHASE2_ANALYSIS.md +0 -179
  320. package/tests/patch_verification/PHASE2_OPTIMIZATION_REPORT.md +0 -55
  321. package/tests/patch_verification/PHASE2_TO_PHASE4_SUMMARY.md +0 -126
  322. package/tests/patch_verification/QUICK_TEST_SEQUENCE.md +0 -262
  323. package/tests/patch_verification/README.md +0 -143
  324. package/tests/patch_verification/RUN_TESTS.md +0 -60
  325. package/tests/patch_verification/TEST_EXECUTION.md +0 -99
  326. package/tests/patch_verification/TEST_PLAN.md +0 -328
  327. package/tests/patch_verification/TEST_RESULTS.md +0 -34
  328. package/tests/patch_verification/TOOL_TEST_PLAN.md +0 -48
  329. package/tests/patch_verification/run-tool-test.mjs +0 -121
  330. package/tests/patch_verification/temp_test_files/test01.txt +0 -1
  331. package/tests/patch_verification/temp_test_files/test02.txt +0 -3
  332. package/tests/patch_verification/temp_test_files/test02_gnu.txt +0 -3
  333. package/tests/patch_verification/temp_test_files/test03.txt +0 -1
  334. package/tests/patch_verification/temp_test_files/test03_multiline.txt +0 -5
  335. package/tests/patch_verification/temp_test_files/test04_function.ts +0 -5
  336. package/tests/patch_verification/temp_test_files/test05_import.ts +0 -4
  337. package/tests/patch_verification/temp_test_files/test06_special_chars.txt +0 -4
  338. package/tests/patch_verification/temp_test_files/test07_indentation.ts +0 -5
  339. package/tests/patch_verification/temp_test_files/test08_mismatch.txt +0 -1
  340. package/tests/patch_verification/temp_test_files/test_add_02.txt +0 -3
  341. package/tests/patch_verification/temp_test_files/test_simple.txt +0 -1
  342. package/tests/runner/TestReporter.mjs +0 -57
  343. package/tests/runner/TestRunner.mjs +0 -244
  344. package/tests/unit/commands/profile.test.mjs +0 -10
  345. package/tests/unit/container/change-notifier.test.mjs +0 -181
  346. package/tests/unit/lifecycle/session-registry.test.mjs +0 -135
  347. package/tests/unit/operations/registry.test.ts +0 -73
  348. package/tests/unit/utils/browser-service.test.mjs +0 -153
  349. package/tests/unit/utils/config.test.mjs +0 -166
  350. package/tests/unit/utils/fingerprint.test.mjs +0 -166
  351. package/tsconfig.json +0 -31
  352. package/tsconfig.services.json +0 -26
  353. /package/apps/desktop-console/{src → dist}/renderer/index.html +0 -0
  354. /package/apps/desktop-console/{src/renderer/tabs → dist/renderer}/run.mts +0 -0
@@ -0,0 +1,204 @@
1
+ async function runExtract(ctx, config) {
2
+ if (!config.selector) {
3
+ throw new Error('extract operation requires selector');
4
+ }
5
+ const maxItems = config.max_items ?? 32;
6
+ const includeText = config.include_text ?? false;
7
+ const index = Number.isFinite(config.index) ? Math.max(0, Math.floor(config.index)) : null;
8
+ const visibleOnly = config.visibleOnly === true;
9
+ return ctx.page.evaluate((data) => {
10
+ const isVisible = (el) => {
11
+ const r = el.getBoundingClientRect();
12
+ return (r.width > 0 &&
13
+ r.height > 0 &&
14
+ r.bottom > 0 &&
15
+ r.top < window.innerHeight &&
16
+ r.right > 0 &&
17
+ r.left < window.innerWidth);
18
+ };
19
+ const allNodes = Array.from(document.querySelectorAll(data.selector || ''));
20
+ if (!allNodes.length) {
21
+ return { success: false, error: 'no elements found', count: 0, extracted: [] };
22
+ }
23
+ const nodes = data.visibleOnly ? allNodes.filter((n) => isVisible(n)) : allNodes;
24
+ if (!nodes.length) {
25
+ return { success: false, error: data.visibleOnly ? 'no visible elements found' : 'no elements found', count: 0, extracted: [] };
26
+ }
27
+ const roots = typeof data.index === 'number'
28
+ ? (() => {
29
+ const el = nodes[data.index];
30
+ return el ? [el] : [];
31
+ })()
32
+ : nodes;
33
+ if (!roots.length) {
34
+ return { success: false, error: 'no elements found', count: 0, extracted: [] };
35
+ }
36
+ const extracted = [];
37
+ const limit = Math.min(roots.length, data.maxItems);
38
+ const getAttrValue = (node, attr) => {
39
+ if (!node)
40
+ return '';
41
+ if (!attr || attr === 'textContent')
42
+ return (node.textContent || '').trim();
43
+ if (attr === 'href') {
44
+ const href = node.href || (typeof node.getAttribute === 'function' ? node.getAttribute('href') : '') || '';
45
+ return String(href || '').trim();
46
+ }
47
+ if (attr === 'src') {
48
+ const src = node.currentSrc || node.src || (typeof node.getAttribute === 'function' ? node.getAttribute('src') : '') || '';
49
+ return String(src || '').trim();
50
+ }
51
+ if (typeof node.getAttribute === 'function') {
52
+ const v = node.getAttribute(attr);
53
+ return v ? String(v).trim() : '';
54
+ }
55
+ return '';
56
+ };
57
+ const containerExtractorMode = Array.isArray(data.fields) && data.fields.length > 0 && data.extractors && typeof data.extractors === 'object';
58
+ for (let i = 0; i < limit; i++) {
59
+ const el = roots[i];
60
+ const item = {};
61
+ if (containerExtractorMode) {
62
+ const extractorKeys = data.fields;
63
+ const extractors = data.extractors || {};
64
+ for (const key of extractorKeys) {
65
+ const def = extractors[key] || {};
66
+ const selectors = Array.isArray(def.selectors) ? def.selectors : [];
67
+ const attr = def.attr || 'textContent';
68
+ const multiple = !!def.multiple;
69
+ if (!selectors.length) {
70
+ item[key] = multiple ? [] : '';
71
+ continue;
72
+ }
73
+ if (multiple) {
74
+ const values = [];
75
+ for (const sel of selectors) {
76
+ try {
77
+ const nodes = Array.from(el.querySelectorAll(sel));
78
+ for (const n of nodes) {
79
+ const v = getAttrValue(n, attr);
80
+ if (v)
81
+ values.push(v);
82
+ }
83
+ }
84
+ catch {
85
+ // ignore selector errors
86
+ }
87
+ if (values.length)
88
+ break;
89
+ }
90
+ item[key] = values;
91
+ }
92
+ else {
93
+ let value = '';
94
+ for (const sel of selectors) {
95
+ try {
96
+ const n = el.querySelector(sel);
97
+ if (!n)
98
+ continue;
99
+ value = getAttrValue(n, attr);
100
+ if (value)
101
+ break;
102
+ }
103
+ catch {
104
+ // ignore selector errors
105
+ }
106
+ }
107
+ item[key] = value;
108
+ }
109
+ }
110
+ // Back-compat: common link field names
111
+ if (!item.href) {
112
+ const linkCandidate = item.link ||
113
+ item.detail_url ||
114
+ item.detailUrl ||
115
+ item.author_link ||
116
+ item.user_link ||
117
+ '';
118
+ if (typeof linkCandidate === 'string' && linkCandidate) {
119
+ item.href = linkCandidate;
120
+ }
121
+ }
122
+ }
123
+ else {
124
+ // Generic selector-based extraction (legacy)
125
+ if (el.tagName === 'A' && el instanceof HTMLAnchorElement) {
126
+ item.href = el.href;
127
+ }
128
+ else if (data.fields && typeof data.fields === 'object' && data.fields.href) {
129
+ const hrefSel = data.fields.href;
130
+ const linkEl = hrefSel ? el.querySelector(hrefSel) : null;
131
+ if (linkEl instanceof HTMLAnchorElement) {
132
+ item.href = linkEl.href;
133
+ }
134
+ }
135
+ if (data.includeText) {
136
+ item.text = (el.textContent || '').trim().substring(0, 200);
137
+ }
138
+ if (data.fields && typeof data.fields === 'object' && !Array.isArray(data.fields)) {
139
+ for (const [field, selector] of Object.entries(data.fields)) {
140
+ if (field === 'href')
141
+ continue;
142
+ try {
143
+ const fieldEl = selector ? el.querySelector(selector) : null;
144
+ if (!fieldEl)
145
+ continue;
146
+ if (fieldEl instanceof HTMLImageElement) {
147
+ item[field] = fieldEl.currentSrc || fieldEl.src;
148
+ }
149
+ else if (fieldEl instanceof HTMLAnchorElement) {
150
+ item[field] = fieldEl.href;
151
+ }
152
+ else {
153
+ item[field] = (fieldEl.textContent || '').trim().substring(0, 200);
154
+ }
155
+ }
156
+ catch {
157
+ // ignore selector errors
158
+ }
159
+ }
160
+ }
161
+ }
162
+ // Apply whitelist/blacklist filters
163
+ if (item.href) {
164
+ let skip = false;
165
+ // Check blacklist
166
+ if (data.blacklist?.contains) {
167
+ for (const term of data.blacklist.contains) {
168
+ if (item.href.includes(term)) {
169
+ skip = true;
170
+ break;
171
+ }
172
+ }
173
+ }
174
+ if (data.blacklist?.suffix) {
175
+ for (const suffix of data.blacklist.suffix) {
176
+ if (item.href.endsWith(suffix)) {
177
+ skip = true;
178
+ break;
179
+ }
180
+ }
181
+ }
182
+ // Check whitelist
183
+ if (!skip && data.whitelist?.prefix) {
184
+ skip = !data.whitelist.prefix.some((prefix) => item.href.startsWith(prefix));
185
+ }
186
+ if (!skip) {
187
+ extracted.push(item);
188
+ }
189
+ }
190
+ else {
191
+ // If no href filtering, just add the item
192
+ extracted.push(item);
193
+ }
194
+ }
195
+ return { success: true, count: extracted.length, extracted };
196
+ }, { ...config, maxItems, includeText, index, visibleOnly });
197
+ }
198
+ export const extractOperation = {
199
+ id: 'extract',
200
+ description: 'Extract structured data from elements',
201
+ requiredCapabilities: ['extract'],
202
+ run: runExtract,
203
+ };
204
+ //# sourceMappingURL=extract.js.map
@@ -0,0 +1,17 @@
1
+ export const findChildOperation = {
2
+ id: 'find-child',
3
+ description: 'Find child containers',
4
+ run: async (ctx, config) => {
5
+ // This is a placeholder operation.
6
+ // The actual find-child logic is handled by RuntimeController directly.
7
+ // However, to satisfy OperationExecutor, we provide this definition.
8
+ // In a full implementation, this could call discovery logic.
9
+ // Returning success to indicate the operation request was valid.
10
+ // The side effects (discovery events) are handled by the caller or container system.
11
+ return {
12
+ success: true,
13
+ message: 'find-child operation triggered'
14
+ };
15
+ }
16
+ };
17
+ //# sourceMappingURL=find-child.js.map
@@ -0,0 +1,138 @@
1
+ async function runHighlight(ctx, config) {
2
+ if (!config.selector) {
3
+ throw new Error('highlight operation requires selector');
4
+ }
5
+ const style = config.style || '2px solid #fbbc05';
6
+ const duration = config.duration ?? 1500;
7
+ const index = Number.isFinite(config.index) ? Math.max(0, Math.floor(config.index)) : null;
8
+ const target = typeof config.target === 'string' ? config.target.trim() : '';
9
+ const channel = typeof config.channel === 'string' && config.channel.trim() ? config.channel.trim() : 'container-op';
10
+ const sticky = config.sticky === true;
11
+ const visibleOnly = config.visibleOnly === true;
12
+ return ctx.page.evaluate((data) => {
13
+ const isVisible = (el) => {
14
+ const r = el.getBoundingClientRect();
15
+ return (r.width > 0 &&
16
+ r.height > 0 &&
17
+ r.bottom > 0 &&
18
+ r.top < window.innerHeight &&
19
+ r.right > 0 &&
20
+ r.left < window.innerWidth);
21
+ };
22
+ const allNodes = Array.from(document.querySelectorAll(data.selector));
23
+ if (!allNodes.length) {
24
+ return { success: false, error: 'element not found', count: 0 };
25
+ }
26
+ const nodes = data.visibleOnly ? allNodes.filter((n) => isVisible(n)) : allNodes;
27
+ if (!nodes.length) {
28
+ return { success: false, error: data.visibleOnly ? 'no visible elements found' : 'element not found', count: 0 };
29
+ }
30
+ const selected = typeof data.index === 'number'
31
+ ? (() => {
32
+ const root = nodes[data.index];
33
+ if (!root)
34
+ return [];
35
+ let el = root;
36
+ if (data.target) {
37
+ if (data.target === 'self') {
38
+ el = root;
39
+ }
40
+ else if (data.target === 'img') {
41
+ el = root.querySelector('img') || root;
42
+ }
43
+ else {
44
+ el = root.querySelector(data.target) || root;
45
+ }
46
+ }
47
+ return [el];
48
+ })()
49
+ : nodes;
50
+ if (!selected.length) {
51
+ return { success: false, error: 'element not found', count: 0 };
52
+ }
53
+ const first = selected[0];
54
+ const r = first.getBoundingClientRect();
55
+ const viewport = { w: window.innerWidth, h: window.innerHeight };
56
+ const inViewport = r.width > 0 &&
57
+ r.height > 0 &&
58
+ r.bottom > 0 &&
59
+ r.top < viewport.h &&
60
+ r.right > 0 &&
61
+ r.left < viewport.w;
62
+ // 优先使用 runtime overlay(截图可见,且不污染元素 style)
63
+ try {
64
+ // @ts-ignore
65
+ const rt = window.__webautoRuntime;
66
+ const api = rt?.highlight;
67
+ if (api && typeof api.highlightElements === 'function') {
68
+ api.highlightElements(selected, {
69
+ channel: data.channel,
70
+ style: data.style,
71
+ duration: data.duration,
72
+ sticky: Boolean(data.sticky),
73
+ });
74
+ return {
75
+ success: true,
76
+ count: selected.length,
77
+ rect: { x1: r.left, y1: r.top, x2: r.right, y2: r.bottom },
78
+ viewport,
79
+ inViewport,
80
+ mode: 'overlay',
81
+ channel: data.channel,
82
+ };
83
+ }
84
+ }
85
+ catch {
86
+ // fallback below
87
+ }
88
+ // fallback: element outline (not guaranteed in screenshots on some pages)
89
+ const cleanups = selected.map((el) => {
90
+ const originalOutline = el.style?.outline;
91
+ const originalOutlineOffset = el.style?.outlineOffset;
92
+ try {
93
+ el.style.outline = data.style;
94
+ el.style.outlineOffset = '2px';
95
+ }
96
+ catch {
97
+ // ignore
98
+ }
99
+ return () => {
100
+ try {
101
+ el.style.outline = originalOutline;
102
+ el.style.outlineOffset = originalOutlineOffset;
103
+ }
104
+ catch {
105
+ // ignore cleanup errors
106
+ }
107
+ };
108
+ });
109
+ const cleanup = () => {
110
+ cleanups.forEach((fn) => {
111
+ try {
112
+ fn();
113
+ }
114
+ catch {
115
+ // ignore cleanup errors
116
+ }
117
+ });
118
+ };
119
+ if (data.duration > 0 && !data.sticky) {
120
+ setTimeout(cleanup, data.duration);
121
+ }
122
+ return {
123
+ success: true,
124
+ count: selected.length,
125
+ rect: { x1: r.left, y1: r.top, x2: r.right, y2: r.bottom },
126
+ viewport,
127
+ inViewport,
128
+ mode: 'outline',
129
+ };
130
+ }, { selector: config.selector, style, duration, index, target, channel, sticky, visibleOnly });
131
+ }
132
+ export const highlightOperation = {
133
+ id: 'highlight',
134
+ description: 'Highlight element using outline',
135
+ requiredCapabilities: ['highlight'],
136
+ run: runHighlight,
137
+ };
138
+ //# sourceMappingURL=highlight.js.map
@@ -0,0 +1,61 @@
1
+ function delay(ms) {
2
+ return new Promise((r) => setTimeout(r, ms));
3
+ }
4
+ async function runKey(ctx, config) {
5
+ const key = String(config.key || '').trim();
6
+ if (!key) {
7
+ throw new Error('key operation requires key');
8
+ }
9
+ const selector = typeof config.selector === 'string' ? config.selector.trim() : '';
10
+ const waitAfter = typeof config.wait_after === 'number'
11
+ ? config.wait_after
12
+ : typeof config.waitAfter === 'number'
13
+ ? config.waitAfter
14
+ : 0;
15
+ const useSystemMouse = config.useSystemMouse !== false;
16
+ const protocolMouse = ctx.page?.mouse;
17
+ if (selector) {
18
+ const rect = await ctx.page.evaluate((sel) => {
19
+ const el = document.querySelector(sel);
20
+ if (!el)
21
+ return null;
22
+ const r = el.getBoundingClientRect();
23
+ const visible = r.width > 0 && r.height > 0 && r.y < window.innerHeight && r.y + r.height > 0;
24
+ return { x1: r.left, y1: r.top, x2: r.right, y2: r.bottom, visible };
25
+ }, selector);
26
+ if (!rect || !rect.visible) {
27
+ return { success: false, error: 'element not visible' };
28
+ }
29
+ const cx = Math.round((rect.x1 + rect.x2) / 2);
30
+ const cy = Math.round((rect.y1 + rect.y2) / 2);
31
+ if (useSystemMouse) {
32
+ if (!ctx.systemInput?.mouseClick) {
33
+ return { success: false, error: 'system mouse not available' };
34
+ }
35
+ await ctx.systemInput.mouseClick(cx, cy);
36
+ }
37
+ else {
38
+ if (!protocolMouse || typeof protocolMouse.click !== 'function') {
39
+ return { success: false, error: 'protocol mouse not available' };
40
+ }
41
+ await protocolMouse.click(cx, cy);
42
+ }
43
+ await delay(150);
44
+ }
45
+ const keyboard = ctx.page.keyboard;
46
+ if (!keyboard || typeof keyboard.press !== 'function') {
47
+ return { success: false, error: 'keyboard press not available' };
48
+ }
49
+ await keyboard.press(key);
50
+ if (waitAfter > 0) {
51
+ await delay(waitAfter);
52
+ }
53
+ return { success: true, inputMode: useSystemMouse ? 'system' : 'protocol' };
54
+ }
55
+ export const keyOperation = {
56
+ id: 'key',
57
+ description: 'Press a key using system-level keyboard',
58
+ requiredCapabilities: [],
59
+ run: runKey,
60
+ };
61
+ //# sourceMappingURL=key.js.map
@@ -0,0 +1,148 @@
1
+ function resolveWaitAfter(config) {
2
+ const wait = typeof config.waitAfterMs === 'number' ? config.waitAfterMs : config.wait_after_ms;
3
+ return Number.isFinite(wait) ? Math.max(0, wait) : 0;
4
+ }
5
+ function ensureAbsoluteUrl(raw, base) {
6
+ if (!raw)
7
+ return '';
8
+ if (/^https?:\/\//i.test(raw))
9
+ return raw;
10
+ if (base) {
11
+ try {
12
+ return new URL(raw, base).toString();
13
+ }
14
+ catch {
15
+ return raw;
16
+ }
17
+ }
18
+ return raw;
19
+ }
20
+ function normalizedIndex(config, ctxIndex) {
21
+ if (typeof config.match_index === 'number')
22
+ return Math.max(0, Math.floor(config.match_index));
23
+ if (typeof config.matchIndex === 'number')
24
+ return Math.max(0, Math.floor(config.matchIndex));
25
+ if (typeof ctxIndex === 'number')
26
+ return Math.max(0, Math.floor(ctxIndex));
27
+ return 0;
28
+ }
29
+ function parseNoteInfo(url) {
30
+ const noteMatch = url?.match(/\/explore\/([0-9a-z]+)/i);
31
+ const xsecMatch = url?.match(/[?&]xsec_token=([^&]+)/i);
32
+ return {
33
+ noteId: noteMatch ? noteMatch[1] : '',
34
+ xsecToken: xsecMatch ? decodeURIComponent(xsecMatch[1]) : '',
35
+ };
36
+ }
37
+ async function resolveTargetUrl(ctx, config) {
38
+ if (config.url) {
39
+ const absolute = ensureAbsoluteUrl(config.url, config.baseUrl || config.base_url);
40
+ return { url: absolute, ...parseNoteInfo(absolute) };
41
+ }
42
+ const scopeSelector = config.scopeSelector || config.scope_selector || config.selector || '';
43
+ const anchorSelector = config.anchorSelector || config.anchor_selector || '';
44
+ if (!scopeSelector && !anchorSelector && !config.selector) {
45
+ throw new Error('navigate operation requires url or selector');
46
+ }
47
+ const attr = config.attribute || 'href';
48
+ const matchIndex = normalizedIndex(config, ctx.node?.index);
49
+ const evaluation = await ctx.page.evaluate(({ scopeSelector, anchorSelector, attribute, matchIndex }) => {
50
+ const resolveFromElement = (el) => {
51
+ if (!el) {
52
+ return { url: '', noteId: '', xsecToken: '' };
53
+ }
54
+ const target = el;
55
+ let raw = '';
56
+ if (attribute === 'textContent') {
57
+ raw = (target.textContent || '').trim();
58
+ }
59
+ else if (attribute) {
60
+ raw = target.getAttribute(attribute) || '';
61
+ if (!raw && attribute === 'href' && target instanceof HTMLAnchorElement) {
62
+ raw = target.href;
63
+ }
64
+ }
65
+ const href = target instanceof HTMLAnchorElement && attribute === 'href' ? target.href : raw;
66
+ const url = href || raw || '';
67
+ const noteMatch = url.match(/\/explore\/([0-9a-z]+)/i);
68
+ const tokenMatch = url.match(/[?&]xsec_token=([^&]+)/i);
69
+ return {
70
+ url,
71
+ noteId: noteMatch ? noteMatch[1] : '',
72
+ xsecToken: tokenMatch ? decodeURIComponent(tokenMatch[1]) : '',
73
+ };
74
+ };
75
+ const index = Number.isFinite(matchIndex) ? Math.max(0, Number(matchIndex)) : 0;
76
+ const scopes = scopeSelector ? Array.from(document.querySelectorAll(scopeSelector)) : [];
77
+ let scope = scopes[index] || scopes[0] || null;
78
+ if (!scope && anchorSelector) {
79
+ scope = document.body;
80
+ }
81
+ if (!scope) {
82
+ return { url: '', noteId: '', xsecToken: '' };
83
+ }
84
+ if (anchorSelector) {
85
+ const anchor = scope.matches(anchorSelector)
86
+ ? scope
87
+ : scope.querySelector(anchorSelector);
88
+ return resolveFromElement(anchor);
89
+ }
90
+ return resolveFromElement(scope);
91
+ }, { scopeSelector, anchorSelector, attribute: attr, matchIndex });
92
+ const absoluteUrl = ensureAbsoluteUrl(evaluation.url, config.baseUrl || config.base_url);
93
+ if (!absoluteUrl) {
94
+ throw new Error('navigate: selector did not resolve to a URL');
95
+ }
96
+ const info = parseNoteInfo(absoluteUrl);
97
+ return { url: absoluteUrl, ...info };
98
+ }
99
+ function isXiaohongshuUrl(url) {
100
+ return /(^https?:\/\/)?(www\.)?xiaohongshu\.com/i.test(url || '');
101
+ }
102
+ function isAllowedXiaohongshuNavigate(url) {
103
+ // 小红书强规则:禁止通过代码构造/抽取链接进行导航(尤其是 /explore、/search_result)
104
+ // 仅允许回到站点主页,其他页面必须通过页面内点击/搜索流转生成带 token 的 URL。
105
+ try {
106
+ const u = new URL(url);
107
+ const p = u.pathname || '/';
108
+ if (p === '/' || p === '' || p === '/explore')
109
+ return true; // /explore 作为站点入口页允许
110
+ return false;
111
+ }
112
+ catch {
113
+ return false;
114
+ }
115
+ }
116
+ export async function runNavigateOperation(ctx, config) {
117
+ const target = await resolveTargetUrl(ctx, config);
118
+ if (!target.url) {
119
+ return { success: false, error: 'navigate: empty url' };
120
+ }
121
+ if (isXiaohongshuUrl(target.url) && !isAllowedXiaohongshuNavigate(target.url)) {
122
+ return { success: false, error: `navigate: disabled for xiaohongshu url=${target.url}` };
123
+ }
124
+ try {
125
+ await ctx.page.goto(target.url, { waitUntil: 'domcontentloaded' });
126
+ }
127
+ catch (e) {
128
+ return { success: false, error: `navigate: page.goto failed: ${e?.message || String(e)}` };
129
+ }
130
+ const waitAfter = resolveWaitAfter(config);
131
+ if (waitAfter > 0) {
132
+ await new Promise((resolve) => setTimeout(resolve, waitAfter));
133
+ }
134
+ return {
135
+ success: true,
136
+ url: target.url,
137
+ noteId: target.noteId,
138
+ xsecToken: target.xsecToken,
139
+ navigation: { success: true, href: target.url, via: 'page.goto' },
140
+ };
141
+ }
142
+ export const navigateOperation = {
143
+ id: 'navigate',
144
+ description: 'Navigate current page using selector-derived URL or explicit target',
145
+ requiredCapabilities: ['navigate'],
146
+ run: runNavigateOperation,
147
+ };
148
+ //# sourceMappingURL=navigate.js.map