@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,54 @@
1
+ /**
2
+ * Workflow Block: SaveFile
3
+ *
4
+ * 保存文件到磁盘
5
+ */
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ /**
9
+ * 保存文件
10
+ *
11
+ * @param input - 输入参数
12
+ * @returns Promise<SaveFileOutput>
13
+ */
14
+ export async function execute(input) {
15
+ const { content, path: filePath, encoding = 'utf-8' } = input;
16
+ if (!content) {
17
+ return {
18
+ saved: false,
19
+ path: filePath,
20
+ size: 0,
21
+ error: 'Empty content'
22
+ };
23
+ }
24
+ if (!filePath) {
25
+ return {
26
+ saved: false,
27
+ path: '',
28
+ size: 0,
29
+ error: 'Missing file path'
30
+ };
31
+ }
32
+ try {
33
+ const dir = path.dirname(filePath);
34
+ if (!fs.existsSync(dir)) {
35
+ fs.mkdirSync(dir, { recursive: true });
36
+ }
37
+ fs.writeFileSync(filePath, content, encoding);
38
+ const stats = fs.statSync(filePath);
39
+ return {
40
+ saved: true,
41
+ path: filePath,
42
+ size: stats.size
43
+ };
44
+ }
45
+ catch (error) {
46
+ return {
47
+ saved: false,
48
+ path: filePath,
49
+ size: 0,
50
+ error: `Save error: ${error.message}`
51
+ };
52
+ }
53
+ }
54
+ //# sourceMappingURL=SaveFile.js.map
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Workflow Block: ScrollNextBatch
3
+ *
4
+ * 执行一次滚动并等待稳定
5
+ */
6
+ /**
7
+ * 执行下一批滚动
8
+ *
9
+ * @param input - 输入参数
10
+ * @returns Promise<ScrollNextBatchOutput>
11
+ */
12
+ export async function execute(input) {
13
+ const { sessionId, distance = 800, serviceUrl = 'http://127.0.0.1:7704' } = input;
14
+ const commandUrl = `${serviceUrl}/command`;
15
+ try {
16
+ const beforeRes = await fetch(commandUrl, {
17
+ method: 'POST',
18
+ headers: { 'Content-Type': 'application/json' },
19
+ body: JSON.stringify({
20
+ action: 'evaluate',
21
+ args: {
22
+ profileId: sessionId,
23
+ script: 'window.scrollY || 0',
24
+ },
25
+ }),
26
+ });
27
+ const beforeData = await beforeRes.json().catch(() => ({}));
28
+ const previousPosition = Number(beforeData?.data?.result ?? beforeData?.body?.result ?? beforeData?.result ?? 0) || 0;
29
+ const wheelRes = await fetch(commandUrl, {
30
+ method: 'POST',
31
+ headers: { 'Content-Type': 'application/json' },
32
+ body: JSON.stringify({
33
+ action: 'mouse:wheel',
34
+ args: {
35
+ profileId: sessionId,
36
+ deltaX: 0,
37
+ deltaY: Math.max(-800, Math.min(800, Number(distance) || 0)),
38
+ },
39
+ }),
40
+ });
41
+ const wheelData = await wheelRes.json().catch(() => ({}));
42
+ if (wheelData?.ok === false || wheelData?.success === false) {
43
+ return {
44
+ scrolled: false,
45
+ previousPosition,
46
+ newPosition: previousPosition,
47
+ error: wheelData?.error || 'mouse_wheel_failed',
48
+ };
49
+ }
50
+ await new Promise((resolve) => setTimeout(resolve, 800));
51
+ const afterRes = await fetch(commandUrl, {
52
+ method: 'POST',
53
+ headers: { 'Content-Type': 'application/json' },
54
+ body: JSON.stringify({
55
+ action: 'evaluate',
56
+ args: { profileId: sessionId, script: 'window.scrollY || 0' },
57
+ }),
58
+ });
59
+ const afterData = await afterRes.json().catch(() => ({}));
60
+ const newPosition = Number(afterData?.data?.result ?? afterData?.body?.result ?? afterData?.result ?? previousPosition) || previousPosition;
61
+ return { scrolled: true, previousPosition, newPosition };
62
+ }
63
+ catch (error) {
64
+ return {
65
+ scrolled: false,
66
+ previousPosition: 0,
67
+ newPosition: 0,
68
+ error: `Scroll error: ${error.message}`
69
+ };
70
+ }
71
+ }
72
+ //# sourceMappingURL=ScrollNextBatch.js.map
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Workflow Block: SessionHealthBlock
3
+ *
4
+ * 职责:
5
+ * - 检查当前会话健康状态(浏览器响应、页面可访问、容器匹配正常)
6
+ * - 提供轻量级健康检查,不干扰现有会话
7
+ * - 用于长时间运行任务中的定期健康监控
8
+ */
9
+ import { logControllerActionError, logControllerActionResult, logControllerActionStart, } from './helpers/operationLogger.js';
10
+ export async function execute(input) {
11
+ const { sessionId, serviceUrl = 'http://127.0.0.1:7701', timeoutMs = 10000 } = input;
12
+ const controllerUrl = `${serviceUrl}/v1/controller/action`;
13
+ async function controllerAction(action, payload = {}) {
14
+ const opId = logControllerActionStart(action, payload, { source: 'SessionHealthBlock' });
15
+ try {
16
+ const res = await fetch(controllerUrl, {
17
+ method: 'POST',
18
+ headers: { 'Content-Type': 'application/json' },
19
+ body: JSON.stringify({ action, payload }),
20
+ signal: AbortSignal.timeout ? AbortSignal.timeout(timeoutMs) : undefined
21
+ });
22
+ if (!res.ok) {
23
+ throw new Error(`HTTP ${res.status}: ${await res.text()}`);
24
+ }
25
+ const data = await res.json();
26
+ const result = data.data || data;
27
+ logControllerActionResult(opId, action, result, { source: 'SessionHealthBlock' });
28
+ return result;
29
+ }
30
+ catch (error) {
31
+ logControllerActionError(opId, action, error, payload, { source: 'SessionHealthBlock' });
32
+ throw error;
33
+ }
34
+ }
35
+ const checks = {
36
+ browserResponsive: false,
37
+ pageAccessible: false,
38
+ containersMatchable: false
39
+ };
40
+ let currentUrl;
41
+ try {
42
+ // 1. 检查浏览器是否响应
43
+ const urlData = await controllerAction('browser:execute', {
44
+ profile: sessionId,
45
+ script: 'location.href'
46
+ });
47
+ currentUrl = urlData?.result || urlData?.data?.result;
48
+ if (typeof currentUrl === 'string' && currentUrl.includes('xiaohongshu.com')) {
49
+ checks.browserResponsive = true;
50
+ checks.pageAccessible = true;
51
+ }
52
+ }
53
+ catch (err) {
54
+ return {
55
+ success: false,
56
+ healthy: false,
57
+ checks,
58
+ error: `Browser not responsive: ${err.message}`
59
+ };
60
+ }
61
+ // 2. 容器层健康:出于稳定性考虑,这里不再强依赖 containers:match,
62
+ // 仅以浏览器可响应 + 页面可访问 作为“健康”判定的硬条件。
63
+ // containersMatchable 字段保留用于诊断,但不作为失败条件。
64
+ checks.containersMatchable = true;
65
+ const healthy = checks.browserResponsive && checks.pageAccessible;
66
+ return {
67
+ success: true,
68
+ healthy,
69
+ checks,
70
+ currentUrl
71
+ };
72
+ }
73
+ //# sourceMappingURL=SessionHealthBlock.js.map
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Workflow Block: StartBrowserService
3
+ *
4
+ * 确保浏览器服务可用
5
+ */
6
+ /**
7
+ * 确保浏览器服务可用
8
+ *
9
+ * @param input - 输入参数
10
+ * @returns Promise<StartBrowserServiceOutput>
11
+ */
12
+ export async function execute(input) {
13
+ const { host = '127.0.0.1', port = 7704, wsPort = 8765 } = input;
14
+ const healthUrl = `http://${host}:${port}/health`;
15
+ try {
16
+ const response = await fetch(healthUrl);
17
+ if (!response.ok) {
18
+ throw new Error(`Browser Service returned ${response.status}`);
19
+ }
20
+ const data = await response.json();
21
+ if (!data.ok) {
22
+ throw new Error('Browser Service health check failed');
23
+ }
24
+ return {
25
+ status: 'connected',
26
+ host,
27
+ port,
28
+ wsPort,
29
+ service: 'browser-service',
30
+ timestamp: new Date().toISOString()
31
+ };
32
+ }
33
+ catch (error) {
34
+ return {
35
+ status: 'error',
36
+ host,
37
+ port,
38
+ wsPort,
39
+ service: 'browser-service',
40
+ timestamp: new Date().toISOString(),
41
+ error: `Browser Service not available at ${healthUrl}: ${error.message}`
42
+ };
43
+ }
44
+ }
45
+ //# sourceMappingURL=StartBrowserService.js.map
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Workflow Block: ValidateContainerDefinition
3
+ *
4
+ * 验证容器定义的格式完整性
5
+ */
6
+ /**
7
+ * 验证容器定义
8
+ *
9
+ * @param input - 输入参数
10
+ * @returns ValidateContainerDefinitionOutput
11
+ */
12
+ export async function execute(input) {
13
+ const { definition } = input;
14
+ if (!definition) {
15
+ return {
16
+ definition: null,
17
+ validation: {
18
+ isValid: false,
19
+ errors: ['缺少容器定义']
20
+ },
21
+ error: '缺少容器定义'
22
+ };
23
+ }
24
+ const errors = [];
25
+ if (!definition.id) {
26
+ errors.push('缺少 id 字段');
27
+ }
28
+ if (!definition.name) {
29
+ errors.push('缺少 name 字段');
30
+ }
31
+ if (!definition.type) {
32
+ errors.push('缺少 type 字段');
33
+ }
34
+ if (definition.selectors) {
35
+ if (!Array.isArray(definition.selectors)) {
36
+ errors.push('selectors 不是数组');
37
+ }
38
+ else {
39
+ definition.selectors.forEach((sel, idx) => {
40
+ if (!sel.css) {
41
+ errors.push(`selectors[${idx}] 缺少 css 字段`);
42
+ }
43
+ if (!sel.variant) {
44
+ errors.push(`selectors[${idx}] 缺少 variant 字段`);
45
+ }
46
+ if (!sel.score) {
47
+ errors.push(`selectors[${idx}] 缺少 score 字段`);
48
+ }
49
+ });
50
+ }
51
+ }
52
+ else {
53
+ errors.push('缺少 selectors 字段');
54
+ }
55
+ if (definition.operations && !Array.isArray(definition.operations)) {
56
+ errors.push('operations 不是数组');
57
+ }
58
+ const isValid = errors.length === 0;
59
+ return {
60
+ definition: isValid ? definition : null,
61
+ validation: {
62
+ isValid,
63
+ errors: errors.length > 0 ? errors : undefined
64
+ }
65
+ };
66
+ }
67
+ //# sourceMappingURL=ValidateContainerDefinition.js.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Workflow Block: ValidateExtract
3
+ *
4
+ * 校验提取数据的有效性
5
+ */
6
+ /**
7
+ * 校验提取数据
8
+ *
9
+ * @param input - 输入参数
10
+ * @returns ValidateExtractOutput
11
+ */
12
+ export async function execute(input) {
13
+ const { fields, requiredFields = ['author', 'content'] } = input;
14
+ if (!fields || typeof fields !== 'object') {
15
+ return {
16
+ isValid: false,
17
+ missingFields: requiredFields,
18
+ validatedFields: {},
19
+ error: '缺少 fields 数据'
20
+ };
21
+ }
22
+ const missingFields = [];
23
+ for (const field of requiredFields) {
24
+ if (!fields[field] || (typeof fields[field] === 'string' && fields[field].trim() === '')) {
25
+ missingFields.push(field);
26
+ }
27
+ }
28
+ const isValid = missingFields.length === 0;
29
+ return {
30
+ isValid,
31
+ missingFields,
32
+ validatedFields: isValid ? fields : {}
33
+ };
34
+ }
35
+ //# sourceMappingURL=ValidateExtract.js.map
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Workflow Block: WaitSearchPermitBlock
3
+ *
4
+ * 职责:
5
+ * 1. 向 SearchGate 申请搜索许可
6
+ * 2. 如果未获许可,自动等待并重试
7
+ * 3. 只有拿到许可后才成功返回
8
+ */
9
+ export async function execute(input) {
10
+ const { sessionId, keyword, gateUrl = process.env.WEBAUTO_SEARCH_GATE_URL || 'http://127.0.0.1:7790', serviceUrl = 'http://127.0.0.1:7701', maxWaitMs = 300_000 } = input;
11
+ // Gate errors are not actionable by waiting; fail fast instead of retry loops.
12
+ const failFastOnGateError = String(process.env.WEBAUTO_SEARCH_GATE_FAIL_FAST || '1') !== '0';
13
+ const skipIfAlreadyOnSearchResult = typeof input.skipIfAlreadyOnSearchResult === 'boolean' ? input.skipIfAlreadyOnSearchResult : true;
14
+ const dev = typeof input.dev === 'boolean'
15
+ ? input.dev
16
+ : (process.env.DEBUG === '1');
17
+ const devTag = typeof input.devTag === 'string' && input.devTag.trim()
18
+ ? String(input.devTag).trim()
19
+ : (dev ? 'dev' : '');
20
+ // 若已经在正确的搜索结果页,直接跳过(避免重复申请 permit 造成“看起来像连续搜索”)
21
+ if (skipIfAlreadyOnSearchResult && typeof keyword === 'string' && keyword.trim()) {
22
+ try {
23
+ const { urlKeywordEquals } = await import('./helpers/searchPageState.js');
24
+ const controllerUrl = `${serviceUrl.replace(/\/$/, '')}/v1/controller/action`;
25
+ const resp = await fetch(controllerUrl, {
26
+ method: 'POST',
27
+ headers: { 'Content-Type': 'application/json' },
28
+ body: JSON.stringify({
29
+ action: 'browser:execute',
30
+ payload: { profile: sessionId, script: 'location.href' },
31
+ }),
32
+ signal: AbortSignal.timeout ? AbortSignal.timeout(5000) : undefined,
33
+ });
34
+ const data = await resp.json().catch(() => ({}));
35
+ const url = data?.data?.result || data?.result || '';
36
+ if (typeof url === 'string' && url.includes('/search_result') && urlKeywordEquals(url, keyword)) {
37
+ console.log(`[WaitSearchPermit] skip: already on search_result for "${keyword}"`);
38
+ return { success: true, granted: true, waitedMs: 0, skipped: true };
39
+ }
40
+ }
41
+ catch {
42
+ // ignore
43
+ }
44
+ }
45
+ const permitEndpoint = `${gateUrl.replace(/\/$/, '')}/permit`;
46
+ const start = Date.now();
47
+ async function requestPermit() {
48
+ try {
49
+ const response = await fetch(permitEndpoint, {
50
+ method: 'POST',
51
+ headers: { 'Content-Type': 'application/json' },
52
+ body: JSON.stringify({
53
+ key: sessionId,
54
+ ...(typeof keyword === 'string' && keyword.trim() ? { keyword: keyword.trim() } : {}),
55
+ ...(dev ? { dev: true } : {}),
56
+ ...(devTag ? { devTag } : {}),
57
+ windowMs: 60_000,
58
+ maxCount: 2
59
+ }),
60
+ signal: AbortSignal.timeout ? AbortSignal.timeout(5000) : undefined
61
+ });
62
+ if (!response.ok) {
63
+ const text = await response.text().catch(() => '');
64
+ return { ok: false, retry: true, error: `HTTP ${response.status}${text ? `: ${text}` : ''}` };
65
+ }
66
+ const data = await response.json().catch(() => ({}));
67
+ return {
68
+ ok: true,
69
+ allowed: Boolean(data.allowed),
70
+ waitMs: Number(data.waitMs || 0),
71
+ retryAfterMs: typeof data.retryAfterMs === 'number' ? Number(data.retryAfterMs) : null,
72
+ reason: typeof data.reason === 'string' ? data.reason : null,
73
+ keyword: typeof data.keyword === 'string' ? data.keyword : null,
74
+ consecutive: typeof data.consecutive === 'number' ? data.consecutive : null,
75
+ deny: data.deny && typeof data.deny === 'object'
76
+ ? {
77
+ code: String(data.deny.code || 'unknown'),
78
+ message: String(data.deny.message || 'denied'),
79
+ retryAfterMs: typeof data.deny.retryAfterMs === 'number' ? Number(data.deny.retryAfterMs) : null,
80
+ details: data.deny.details ?? null,
81
+ suggestedActions: Array.isArray(data.deny.suggestedActions)
82
+ ? data.deny.suggestedActions.map((s) => String(s))
83
+ : [],
84
+ }
85
+ : null,
86
+ retry: false
87
+ };
88
+ }
89
+ catch (err) {
90
+ return { ok: false, retry: true, error: err.message };
91
+ }
92
+ }
93
+ console.log(`[WaitSearchPermit] Requesting permit for ${sessionId}...${typeof keyword === 'string' && keyword.trim() ? ` keyword="${keyword.trim()}"` : ''}`);
94
+ while (Date.now() - start < maxWaitMs) {
95
+ const result = await requestPermit();
96
+ if (result.ok && result.allowed) {
97
+ console.log(`[WaitSearchPermit] ✅ Permit granted (waited ${(Date.now() - start) / 1000}s)`);
98
+ return { success: true, granted: true, waitedMs: Date.now() - start, reason: result.reason ?? null };
99
+ }
100
+ if (result.ok && !result.allowed) {
101
+ // 开发阶段:禁止连续三次同 keyword 搜索,直接失败(不要无脑重试)
102
+ if (result.reason === 'dev_consecutive_keyword_limit' || result.deny?.code === 'dev_consecutive_keyword_limit') {
103
+ const denyMsg = result.deny?.message || '';
104
+ const actions = (result.deny?.suggestedActions || []).length > 0
105
+ ? (result.deny?.suggestedActions || [])
106
+ : [
107
+ 'Stop and inspect logs/screenshots; do not spam search retries.',
108
+ 'If this is a dev-only rerun and you must search the same keyword again, restart SearchGate to clear in-memory dev keyword history.',
109
+ 'Alternatively, wait until the dev keyword history expires (default keeps 24h).',
110
+ ];
111
+ console.error(`[WaitSearchPermit] ❌ SearchGate denied: dev_consecutive_keyword_limit (keyword="${String(result.keyword || keyword || '')}", consecutive=${String(result.consecutive ?? '')})${denyMsg ? ` | ${denyMsg}` : ''}`);
112
+ for (const action of actions) {
113
+ console.error(`[WaitSearchPermit] - ${action}`);
114
+ }
115
+ return {
116
+ success: false,
117
+ granted: false,
118
+ waitedMs: Date.now() - start,
119
+ reason: result.reason ?? null,
120
+ retryAfterMs: result.retryAfterMs ?? result.deny?.retryAfterMs ?? null,
121
+ deny: result.deny ?? null,
122
+ error: `SearchGate denied: dev_consecutive_keyword_limit (keyword="${String(result.keyword || keyword || '')}", consecutive=${String(result.consecutive ?? '')})`,
123
+ };
124
+ }
125
+ // 只在服务端真正计算出需要等待时才等待
126
+ const waitMs = Math.max(0, Number(result.retryAfterMs ?? result.waitMs ?? 0));
127
+ if (waitMs > 0) {
128
+ console.log(`[WaitSearchPermit] ⏳ Throttled${result.reason ? ` (${result.reason})` : ''}, waiting ${Math.ceil(waitMs / 1000)}s...`);
129
+ await new Promise(resolve => setTimeout(resolve, waitMs));
130
+ continue;
131
+ }
132
+ else {
133
+ // waitMs=0:可能是服务端拒绝但未给出等待时间;避免 busy-loop,稍等再试
134
+ console.warn(`[WaitSearchPermit] ⚠️ Gate denied but waitMs=0${result.reason ? ` (reason=${result.reason})` : ''}, retrying in 1s...`);
135
+ await new Promise(resolve => setTimeout(resolve, 1000));
136
+ continue;
137
+ }
138
+ }
139
+ if (!result.ok && result.retry) {
140
+ const errMsg = String(result.error || 'unknown error');
141
+ if (failFastOnGateError) {
142
+ return {
143
+ success: false,
144
+ granted: false,
145
+ waitedMs: Date.now() - start,
146
+ error: `SearchGate error: ${errMsg}`,
147
+ };
148
+ }
149
+ console.warn(`[WaitSearchPermit] ⚠️ Gate error (${errMsg}), retrying in 5s...`);
150
+ await new Promise(resolve => setTimeout(resolve, 5000));
151
+ continue;
152
+ }
153
+ break;
154
+ }
155
+ return {
156
+ success: false,
157
+ granted: false,
158
+ waitedMs: Date.now() - start,
159
+ error: `WaitSearchPermit timeout after ${maxWaitMs / 1000}s`
160
+ };
161
+ }
162
+ //# sourceMappingURL=WaitSearchPermitBlock.js.map
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Workflow Block: WaitStable
3
+ *
4
+ * 等待页面稳定信号
5
+ */
6
+ /**
7
+ * 等待页面稳定
8
+ *
9
+ * @param input - 输入参数
10
+ * @returns Promise<WaitStableOutput>
11
+ */
12
+ export async function execute(input) {
13
+ const { sessionId, checkInterval = 500, maxWait = 10000, stableThreshold = 3, serviceUrl = 'http://127.0.0.1:7704' } = input;
14
+ const commandUrl = `${serviceUrl}/command`;
15
+ const startTime = Date.now();
16
+ let checks = 0;
17
+ let lastHeight = 0;
18
+ let stableCount = 0;
19
+ try {
20
+ while (Date.now() - startTime < maxWait) {
21
+ checks++;
22
+ const evalRes = await fetch(commandUrl, {
23
+ method: 'POST',
24
+ headers: { 'Content-Type': 'application/json' },
25
+ body: JSON.stringify({
26
+ action: 'evaluate',
27
+ args: {
28
+ profileId: sessionId,
29
+ script: `
30
+ (() => {
31
+ return document.body.scrollHeight;
32
+ })()
33
+ `
34
+ }
35
+ })
36
+ });
37
+ const evalData = await evalRes.json();
38
+ if (evalData.success && evalData.data !== undefined) {
39
+ const currentHeight = evalData.data;
40
+ if (currentHeight === lastHeight) {
41
+ stableCount++;
42
+ if (stableCount >= stableThreshold) {
43
+ const waitTime = Date.now() - startTime;
44
+ return {
45
+ isStable: true,
46
+ waitTime,
47
+ checks
48
+ };
49
+ }
50
+ }
51
+ else {
52
+ stableCount = 0;
53
+ }
54
+ lastHeight = currentHeight;
55
+ }
56
+ await new Promise(resolve => setTimeout(resolve, checkInterval));
57
+ }
58
+ return {
59
+ isStable: false,
60
+ waitTime: maxWait,
61
+ checks,
62
+ error: 'Timeout waiting for page stability'
63
+ };
64
+ }
65
+ catch (error) {
66
+ return {
67
+ isStable: false,
68
+ waitTime: Date.now() - startTime,
69
+ checks,
70
+ error: `WaitStable error: ${error.message}`
71
+ };
72
+ }
73
+ }
74
+ //# sourceMappingURL=WaitStable.js.map