@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
@@ -1,486 +0,0 @@
1
- import { createEl, labeledInput, section } from '../ui-components.mts';
2
- import { resolveWebautoRoot } from '../path-helpers.mts';
3
-
4
- function buildArgs(parts: string[]) {
5
- return parts.filter((x) => x != null && String(x).trim() !== '');
6
- }
7
-
8
- const XHS_NAV_TARGET_KEY = 'webauto.xhs.navTarget.v1';
9
-
10
- export function renderPreflight(root: HTMLElement, ctx: any) {
11
- const filterInput = createEl('input', { value: '', placeholder: '过滤:profileId / alias / platform' }) as HTMLInputElement;
12
- const selectAllBox = createEl('input', { type: 'checkbox' }) as HTMLInputElement;
13
- const selectionHint = createEl('div', { className: 'muted' }, ['selected=0']);
14
- const onlyMissingFp = createEl('input', { type: 'checkbox' }) as HTMLInputElement;
15
- const regenPlatform = createEl('select') as HTMLSelectElement;
16
- [
17
- { value: 'random', label: 'random(win/mac)' },
18
- { value: 'windows', label: 'windows' },
19
- { value: 'macos', label: 'macos' },
20
- ].forEach((x) => regenPlatform.appendChild(createEl('option', { value: x.value }, [x.label])));
21
- regenPlatform.value = 'random';
22
-
23
- const statusBox = createEl('div', { className: 'muted' }, ['']);
24
- const listBox = createEl('div', { className: 'list' });
25
- const batchDeleteBtn = createEl('button', { className: 'danger' }, ['批量删除选中 profile']) as HTMLButtonElement;
26
- const batchDeleteFp = createEl('input', { type: 'checkbox' }) as HTMLInputElement;
27
-
28
- const onboardingSummary = createEl('div', { className: 'muted' }, ['正在加载 profile 信息...']) as HTMLDivElement;
29
- const onboardingTips = createEl('div', { className: 'muted', style: 'font-size:12px; margin-top:6px;' }, [
30
- '首次使用建议:输入账号名后,系统自动按 <账号名>-batch-1/2/3 命名;留空默认 xiaohongshu-batch-1/2/3。登录后可设置 alias(账号名)用于区分,默认会自动获取用户名。',
31
- ]) as HTMLDivElement;
32
- const gotoXhsBtn = createEl('button', { className: 'secondary', type: 'button' }, ['去小红书首页']) as HTMLButtonElement;
33
- const browserStatus = createEl('div', { className: 'muted' }, ['浏览器状态:未检查']) as HTMLDivElement;
34
- const browserCheckBtn = createEl('button', { className: 'secondary', type: 'button' }, ['检查浏览器/依赖']) as HTMLButtonElement;
35
- const browserDownloadBtn = createEl('button', { type: 'button' }, ['下载 Camoufox']) as HTMLButtonElement;
36
-
37
- let cachedScan: any = null;
38
- const webautoRoot = resolveWebautoRoot(ctx.settings?.downloadRoot || '', window.api);
39
-
40
- function getAliasMap(): Record<string, string> {
41
- const m = ctx.settings?.profileAliases;
42
- return m && typeof m === 'object' ? m : {};
43
- }
44
-
45
- async function saveAlias(profileId: string, alias: string) {
46
- const nextAliases = { ...getAliasMap() };
47
- const key = String(profileId || '').trim();
48
- const val = String(alias || '').trim();
49
- if (!key) return;
50
- if (!val) delete nextAliases[key];
51
- else nextAliases[key] = val;
52
- const next = await window.api.settingsSet({ profileAliases: nextAliases });
53
- ctx.settings = next;
54
- // main process broadcasts settings:changed; other tabs will refresh automatically.
55
- }
56
-
57
- function toLower(x: any) {
58
- return String(x || '').toLowerCase();
59
- }
60
-
61
- function renderList() {
62
- listBox.textContent = '';
63
- const entries: any[] = cachedScan?.entries || [];
64
- const q = toLower(filterInput.value.trim());
65
- const aliases = getAliasMap();
66
-
67
- const filtered = entries.filter((e) => {
68
- if (onlyMissingFp.checked && e.fingerprint) return false;
69
- if (!q) return true;
70
- const hay = [
71
- e.profileId,
72
- aliases[e.profileId] || '',
73
- e.fingerprint?.platform || '',
74
- e.fingerprint?.originalPlatform || '',
75
- e.fingerprint?.osVersion || '',
76
- e.fingerprint?.userAgent || '',
77
- ]
78
- .map(toLower)
79
- .join(' ');
80
- return hay.includes(q);
81
- });
82
-
83
- const header = createEl('div', {
84
- className: 'item',
85
- // One-row-per-profile, keep actions on a single line; avoid horizontal scroll.
86
- style: 'display:grid; grid-template-columns: 32px 180px 180px 120px minmax(0,1fr) 360px; gap:8px; font-weight:700; align-items:center; min-width:0;',
87
- });
88
- header.appendChild(createEl('div', {}, ['sel']));
89
- header.appendChild(createEl('div', {}, ['profileId']));
90
- header.appendChild(createEl('div', {}, ['alias']));
91
- header.appendChild(createEl('div', {}, ['fingerprint']));
92
- header.appendChild(createEl('div', {}, ['userAgent']));
93
- header.appendChild(createEl('div', {}, ['actions']));
94
- listBox.appendChild(header);
95
-
96
- for (const e of filtered) {
97
- const fp = e.fingerprint;
98
- const fpLabel = fp
99
- ? `${fp.originalPlatform || fp.platform || 'unknown'}${fp.osVersion ? ` ${fp.osVersion}` : ''}`
100
- : '(missing)';
101
-
102
- const aliasInput = createEl('input', {
103
- value: String(aliases[e.profileId] || ''),
104
- placeholder: '账号名(alias,用于区分账号,默认登录后获取用户名)',
105
- }) as HTMLInputElement;
106
-
107
- const row = createEl('div', {
108
- className: 'item',
109
- style: 'display:grid; grid-template-columns: 32px 180px 180px 120px minmax(0,1fr) 360px; gap:8px; align-items:center; min-width:0;',
110
- });
111
- const rowSelect = createEl('input', { type: 'checkbox' }) as HTMLInputElement;
112
- rowSelect.dataset.profileId = String(e.profileId || '');
113
- rowSelect.onchange = () => updateSelectionHint();
114
- row.appendChild(rowSelect);
115
- row.appendChild(createEl('div', {}, [String(e.profileId)]));
116
- row.appendChild(createEl('div', { style: 'min-width:0;' }, [aliasInput]));
117
- row.appendChild(createEl('div', { className: 'muted' }, [fpLabel]));
118
- row.appendChild(
119
- createEl(
120
- 'div',
121
- { className: 'muted', style: 'overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0;', title: String(fp?.userAgent || '') },
122
- [String(fp?.userAgent || '')],
123
- ),
124
- );
125
-
126
- const actions = createEl('div', { style: 'display:flex; gap:6px; flex-wrap:nowrap; align-items:center; overflow:hidden; justify-content:flex-end;' });
127
- const btnOpenProfile = createEl('button', { className: 'secondary' }, ['打开']);
128
- const btnOpenFp = createEl('button', { className: 'secondary' }, ['指纹']);
129
- const btnSaveAlias = createEl('button', { className: 'secondary' }, ['保存']);
130
- // Reduce width for the frequently-used action.
131
- const btnRegenFp = createEl('button', {}, ['重生']);
132
- const btnDelFp = createEl('button', { className: 'secondary' }, ['删指']);
133
- const btnDelProfile = createEl('button', { className: 'danger' }, ['删档']);
134
-
135
- btnOpenProfile.onclick = () => void window.api.osOpenPath(e.profileDir);
136
- btnOpenFp.onclick = () => void window.api.osOpenPath(e.fingerprintPath);
137
- let lastSavedAlias = String(aliases[e.profileId] || '').trim();
138
- const commitAlias = async () => {
139
- const nextAlias = String(aliasInput.value || '').trim();
140
- if (nextAlias === lastSavedAlias) return;
141
- await saveAlias(e.profileId, nextAlias);
142
- lastSavedAlias = nextAlias;
143
- aliasInput.style.borderColor = '';
144
- };
145
- aliasInput.oninput = () => {
146
- const dirty = String(aliasInput.value || '').trim() !== lastSavedAlias;
147
- aliasInput.style.borderColor = dirty ? '#2b67ff' : '';
148
- };
149
- btnSaveAlias.onclick = () => void commitAlias();
150
- aliasInput.onkeydown = (ev) => {
151
- if (ev.key === 'Enter') void commitAlias();
152
- };
153
- aliasInput.onblur = () => void commitAlias();
154
- btnRegenFp.onclick = async () => {
155
- ctx.clearLog();
156
- const platform = String(regenPlatform.value || 'random');
157
- const out = await window.api.fingerprintRegenerate({ profileId: e.profileId, platform });
158
- ctx.appendLog(JSON.stringify(out, null, 2));
159
- await refreshScan();
160
- };
161
- btnDelFp.onclick = async () => {
162
- if (!confirm(`删除 fingerprint: ${e.profileId}?`)) return;
163
- ctx.clearLog();
164
- const out = await window.api.fingerprintDelete({ profileId: e.profileId });
165
- ctx.appendLog(JSON.stringify(out, null, 2));
166
- await refreshScan();
167
- };
168
- btnDelProfile.onclick = async () => {
169
- if (!confirm(`删除 profile 目录: ${e.profileId}?\n(可选:同时删除指纹文件)`)) return;
170
- const alsoFp = confirm(`同时删除 ${e.profileId} 的 fingerprint 文件?`);
171
- ctx.clearLog();
172
- const out = await window.api.profileDelete({ profileId: e.profileId, deleteFingerprint: alsoFp });
173
- ctx.appendLog(JSON.stringify(out, null, 2));
174
- await refreshScan();
175
- };
176
-
177
- actions.appendChild(btnOpenProfile);
178
- actions.appendChild(btnOpenFp);
179
- actions.appendChild(btnSaveAlias);
180
- actions.appendChild(btnRegenFp);
181
- actions.appendChild(btnDelFp);
182
- actions.appendChild(btnDelProfile);
183
- row.appendChild(actions);
184
-
185
- listBox.appendChild(row);
186
- }
187
- updateSelectionHint();
188
- }
189
-
190
- function updateSelectionHint() {
191
- const selected = listBox.querySelectorAll('input[type="checkbox"][data-profile-id]:checked').length;
192
- selectionHint.textContent = `selected=${selected}`;
193
- }
194
-
195
- async function batchDeleteSelectedProfiles() {
196
- const selected: string[] = [];
197
- listBox.querySelectorAll('input[type="checkbox"][data-profile-id]').forEach((el) => {
198
- const cb = el as HTMLInputElement;
199
- if (!cb.checked) return;
200
- const id = String(cb.dataset.profileId || '').trim();
201
- if (id) selected.push(id);
202
- });
203
- if (selected.length === 0) return;
204
-
205
- if (!confirm(`批量删除 ${selected.length} 个 profile?`)) return;
206
- const deleteFp = batchDeleteFp.checked && confirm(`同时删除这 ${selected.length} 个 profile 的 fingerprint 文件?`);
207
-
208
- ctx.clearLog();
209
- for (const profileId of selected) {
210
- try {
211
- const out = await window.api.profileDelete({ profileId, deleteFingerprint: deleteFp });
212
- ctx.appendLog(JSON.stringify(out, null, 2));
213
- } catch (err: any) {
214
- ctx.appendLog(`[batch-delete] ${profileId} failed: ${err?.message || String(err)}`);
215
- }
216
- }
217
- await refreshScan();
218
- }
219
-
220
- async function refreshScan() {
221
- const out = await window.api.profilesScan();
222
- cachedScan = out;
223
- statusBox.textContent = `profiles=${out?.entries?.length || 0} profilesRoot=${out?.profilesRoot || ''} fingerprintsRoot=${out?.fingerprintsRoot || ''}`;
224
-
225
- const entries: any[] = out?.entries || [];
226
- const aliases = getAliasMap();
227
- const aliasedCount = entries.filter((e) => String(aliases[String(e?.profileId || '')] || '').trim()).length;
228
- onboardingSummary.textContent = `profile=${entries.length},已设置账号名=${aliasedCount}`;
229
- if (entries.length === 0) {
230
- onboardingTips.textContent = '当前没有可用 profile:请先在下方“批量账号池”里新增账号。';
231
- } else if (aliasedCount < entries.length) {
232
- onboardingTips.textContent = `仍有 ${entries.length - aliasedCount} 个 profile 未设置账号名(alias)。alias 用于区分账号,默认登录后会自动获取用户名。`;
233
- } else {
234
- onboardingTips.textContent = '很好:所有 profile 都有账号名(alias),在小红书首页会按“账号名 (profileId)”显示。';
235
- }
236
-
237
- renderList();
238
- }
239
-
240
- const toolbar = createEl('div', { className: 'row' }, [
241
- labeledInput('filter', filterInput),
242
- createEl('div', { style: 'display:flex; flex-direction:column; gap:6px;' }, [
243
- createEl('label', {}, ['select all']),
244
- selectAllBox,
245
- ]),
246
- createEl('div', { style: 'display:flex; flex-direction:column; gap:6px;' }, [
247
- createEl('label', {}, ['del fingerprint']),
248
- batchDeleteFp,
249
- ]),
250
- createEl('div', { style: 'display:flex; flex-direction:column; gap:6px;' }, [
251
- createEl('label', {}, ['only missing fingerprint']),
252
- onlyMissingFp,
253
- ]),
254
- labeledInput('regen platform', regenPlatform),
255
- createEl('button', { className: 'secondary' }, ['刷新列表']),
256
- createEl('button', {}, ['批量补齐缺失指纹(脚本)']),
257
- batchDeleteBtn,
258
- ]);
259
- (toolbar.children[5] as HTMLButtonElement).onclick = () => void refreshScan();
260
- (toolbar.children[6] as HTMLButtonElement).onclick = async () => {
261
- ctx.clearLog();
262
- const args = buildArgs([window.api.pathJoin('apps', 'webauto', 'entry', 'profilepool.mjs'), 'migrate-fingerprints']);
263
- await window.api.cmdSpawn({ title: 'migrate fingerprints', cwd: '', args, groupKey: 'profilepool' });
264
- setTimeout(() => void refreshScan(), 1000);
265
- };
266
- batchDeleteBtn.onclick = () => void batchDeleteSelectedProfiles();
267
-
268
- filterInput.oninput = () => renderList();
269
- onlyMissingFp.onchange = () => renderList();
270
- selectAllBox.onchange = () => {
271
- const checked = selectAllBox.checked;
272
- listBox.querySelectorAll('input[type="checkbox"][data-profile-id]').forEach((el) => {
273
- (el as HTMLInputElement).checked = checked;
274
- });
275
- updateSelectionHint();
276
- };
277
-
278
- const runBrowserCheck = async (opts: { download?: boolean; source?: 'auto' | 'manual' } = {}) => {
279
- const download = opts.download === true;
280
- const source = opts.source || 'manual';
281
- const script = window.api.pathJoin('apps', 'webauto', 'entry', 'xhs-install.mjs');
282
- const args = buildArgs([script, '--check-browser-only', ...(download ? ['--download-browser'] : [])]);
283
-
284
- browserStatus.textContent = download ? '浏览器状态:下载+检查中...' : '浏览器状态:检查中...';
285
- browserStatus.style.color = '#8b93a6';
286
-
287
- if (typeof window.api?.cmdRunJson === 'function') {
288
- const out = await window.api.cmdRunJson({
289
- title: download ? 'xhs install download' : 'xhs install check',
290
- cwd: '',
291
- args,
292
- timeoutMs: download ? 240000 : 120000,
293
- }).catch((err: any) => ({ ok: false, error: err?.message || String(err) }));
294
-
295
- const mergedOutput = String(out?.stdout || out?.stderr || out?.error || '').replace(/\x1b\[[0-9;]*m/g, '');
296
- if (out?.ok) {
297
- browserStatus.textContent = download ? '浏览器状态:下载并检查通过' : '浏览器状态:检查通过';
298
- browserStatus.style.color = '#22c55e';
299
- } else if (/Camoufox 未安装/i.test(mergedOutput)) {
300
- browserStatus.textContent = '浏览器状态:未安装 Camoufox(可点“下载 Camoufox”)';
301
- browserStatus.style.color = '#f59e0b';
302
- } else {
303
- browserStatus.textContent = `浏览器状态:检查失败(code=${out?.code ?? 'n/a'})`;
304
- browserStatus.style.color = '#ef4444';
305
- }
306
- if (source === 'manual' && mergedOutput) {
307
- ctx.appendLog(`[preflight] install output\n${mergedOutput}`);
308
- }
309
- return;
310
- }
311
-
312
- if (typeof window.api?.cmdSpawn === 'function') {
313
- await window.api.cmdSpawn({ title: download ? 'xhs install download' : 'xhs install check', cwd: '', args, groupKey: 'install' });
314
- browserStatus.textContent = '浏览器状态:已触发检查(查看日志)';
315
- browserStatus.style.color = '#22c55e';
316
- return;
317
- }
318
-
319
- browserStatus.textContent = '浏览器状态:检查能力不可用';
320
- browserStatus.style.color = '#ef4444';
321
- };
322
-
323
- gotoXhsBtn.onclick = () => {
324
- try {
325
- window.localStorage.setItem(XHS_NAV_TARGET_KEY, 'account');
326
- } catch {
327
- // ignore storage failures
328
- }
329
- if (typeof ctx?.setActiveTab === 'function') ctx.setActiveTab('xiaohongshu');
330
- };
331
-
332
- browserCheckBtn.onclick = async () => {
333
- ctx.clearLog();
334
- await runBrowserCheck({ source: 'manual' });
335
- };
336
-
337
- browserDownloadBtn.onclick = async () => {
338
- ctx.clearLog();
339
- await runBrowserCheck({ download: true, source: 'manual' });
340
- };
341
-
342
- root.appendChild(
343
- section('首次引导(账号视角)', [
344
- onboardingSummary,
345
- onboardingTips,
346
- createEl('div', { className: 'row' }, [gotoXhsBtn]),
347
- ]),
348
- );
349
-
350
- root.appendChild(
351
- section('浏览器检查与下载', [
352
- browserStatus,
353
- createEl('div', { className: 'row' }, [browserCheckBtn, browserDownloadBtn]),
354
- createEl('div', { className: 'muted', style: 'font-size:12px;' }, ['说明:检查/下载的详细输出请查看日志页。']),
355
- ]),
356
- );
357
-
358
- root.appendChild(
359
- section('Profiles + Fingerprints (CRUD)', [
360
- toolbar,
361
- statusBox,
362
- selectionHint,
363
- listBox,
364
- createEl('div', { className: 'muted' }, [`提示:profile 与 fingerprint 的真实路径均在 ${webautoRoot} 下;alias 只影响 UI 显示,不影响 profileId。`]),
365
- ]),
366
- );
367
-
368
- // keep: ProfilePool helper (create profiles + bulk login)
369
- const keywordInput = createEl('input', { value: 'xiaohongshu', placeholder: '账号名(可选),系统自动拼接为 <账号名>-batch-1/2/3;留空默认 xiaohongshu-batch' }) as HTMLInputElement;
370
- const ensureCountInput = createEl('input', { value: '0', type: 'number', min: '0' }) as HTMLInputElement;
371
- const timeoutInput = createEl('input', { value: String(ctx.settings?.timeouts?.loginTimeoutSec || 900), type: 'number', min: '30' }) as HTMLInputElement;
372
- const keepSession = createEl('input', { type: 'checkbox' }) as HTMLInputElement;
373
- const poolListBox = createEl('div', { className: 'list' });
374
- const poolStatus = createEl('div', { className: 'muted' }, ['']);
375
-
376
-
377
- function resolveBatchPrefix() {
378
- const base = String(keywordInput.value || '').trim() || 'xiaohongshu';
379
- return `${base}-batch`;
380
- }
381
-
382
- async function poolList() {
383
- ctx.clearLog();
384
- const kw = resolveBatchPrefix();
385
- const out = await window.api.cmdRunJson({
386
- title: 'profilepool list',
387
- cwd: '',
388
- args: buildArgs([window.api.pathJoin('apps', 'webauto', 'entry', 'profilepool.mjs'), 'list', kw, '--json']),
389
- });
390
- poolListBox.textContent = '';
391
- if (!out?.ok || !out?.json) {
392
- poolListBox.appendChild(createEl('div', { className: 'item' }, ['(failed)']));
393
- return;
394
- }
395
- const profiles = out.json.profiles || [];
396
- profiles.forEach((p: string) => poolListBox.appendChild(createEl('div', { className: 'item' }, [p])));
397
- poolStatus.textContent = `count=${profiles.length} root=${out.json.root}`;
398
- await refreshScan();
399
- }
400
-
401
- async function poolAdd() {
402
- ctx.clearLog();
403
- const kw = resolveBatchPrefix();
404
- const out = await window.api.cmdRunJson({
405
- title: 'profilepool add',
406
- cwd: '',
407
- args: buildArgs([window.api.pathJoin('apps', 'webauto', 'entry', 'profilepool.mjs'), 'add', kw, '--json']),
408
- });
409
- ctx.appendLog(JSON.stringify(out?.json || out, null, 2));
410
- const createdProfileId = String(out?.json?.profileId || '').trim();
411
- await poolList();
412
-
413
- if (!createdProfileId) return;
414
- if (typeof window.api?.cmdSpawn !== 'function') return;
415
-
416
- const timeoutSec = Math.max(30, Math.floor(Number(timeoutInput.value || '900')));
417
- const loginArgs = buildArgs([
418
- window.api.pathJoin('apps', 'webauto', 'entry', 'profilepool.mjs'),
419
- 'login-profile',
420
- createdProfileId,
421
- '--timeout-sec',
422
- String(timeoutSec),
423
- '--check-interval-sec',
424
- '2',
425
- '--keep-session',
426
- ...(ctx.settings?.unifiedApiUrl ? ['--unified-api', String(ctx.settings.unifiedApiUrl)] : []),
427
- ...(ctx.settings?.browserServiceUrl ? ['--browser-service', String(ctx.settings.browserServiceUrl)] : []),
428
- ]);
429
- await window.api.cmdSpawn({
430
- title: `profilepool login-profile ${createdProfileId}`,
431
- cwd: '',
432
- args: loginArgs,
433
- groupKey: 'profilepool',
434
- env: { WEBAUTO_DAEMON: '1' },
435
- });
436
- ctx.appendLog(`[preflight] 已创建并启动登录: ${createdProfileId}`);
437
- }
438
-
439
- async function poolLogin() {
440
- ctx.clearLog();
441
- const kw = resolveBatchPrefix();
442
- const ensureCount = Math.max(0, Math.floor(Number(ensureCountInput.value || '0')));
443
- const timeoutSec = Math.max(30, Math.floor(Number(timeoutInput.value || '900')));
444
- const args = buildArgs([
445
- window.api.pathJoin('apps', 'webauto', 'entry', 'profilepool.mjs'),
446
- 'login',
447
- kw,
448
- ...(ctx.settings?.unifiedApiUrl ? ['--unified-api', String(ctx.settings.unifiedApiUrl)] : []),
449
- ...(ctx.settings?.browserServiceUrl ? ['--browser-service', String(ctx.settings.browserServiceUrl)] : []),
450
- '--timeout-sec',
451
- String(timeoutSec),
452
- ...(ensureCount > 0 ? ['--ensure-count', String(ensureCount)] : []),
453
- ...(keepSession.checked ? ['--keep-session'] : []),
454
- ]);
455
- await window.api.cmdSpawn({ title: `profilepool login ${kw}`, cwd: '', args, groupKey: 'profilepool' });
456
- }
457
-
458
- const poolActions = createEl('div', { className: 'row' }, [
459
- createEl('button', { className: 'secondary' }, ['扫描池']),
460
- createEl('button', { className: 'secondary' }, ['新增一个并登录']),
461
- createEl('button', {}, ['批量登录/补登录']),
462
- ]);
463
- (poolActions.children[0] as HTMLButtonElement).onclick = () => void poolList();
464
- (poolActions.children[1] as HTMLButtonElement).onclick = () => void poolAdd();
465
- (poolActions.children[2] as HTMLButtonElement).onclick = () => void poolLogin();
466
-
467
- root.appendChild(
468
- section('批量账号池(自动序号)', [
469
- createEl('div', { className: 'row' }, [
470
- labeledInput('账号名(默认 xiaohongshu)', keywordInput),
471
- labeledInput('ensure-count (可选)', ensureCountInput),
472
- labeledInput('login timeout (sec)', timeoutInput),
473
- createEl('div', { style: 'display:flex; flex-direction:column; gap:6px;' }, [
474
- createEl('label', {}, ['keep-session']),
475
- keepSession,
476
- ]),
477
- ]),
478
- poolActions,
479
- poolStatus,
480
- poolListBox,
481
- ]),
482
- );
483
-
484
- void refreshScan();
485
- void runBrowserCheck({ source: 'auto' });
486
- }
@@ -1,33 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { test } from 'node:test';
4
- import assert from 'node:assert/strict';
5
- import { fileURLToPath } from 'node:url';
6
-
7
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
- const tabPath = path.join(__dirname, 'preflight.mts');
9
-
10
- async function getSrc() {
11
- return readFile(tabPath, 'utf8');
12
- }
13
-
14
- test('preflight includes onboarding and profilepool in same tab', async () => {
15
- const src = await getSrc();
16
- assert.match(src, /section\('首次引导(账号视角)'/);
17
- assert.match(src, /section\('批量账号池(自动序号)'/);
18
- assert.match(src, /section\('浏览器检查与下载'/);
19
- assert.match(src, /去小红书首页/);
20
- assert.match(src, /ctx\.setActiveTab\('xiaohongshu'\)/);
21
- assert.match(src, /localStorage\.setItem\(XHS_NAV_TARGET_KEY, 'account'\)/);
22
- assert.match(src, /账号名(alias,用于区分账号,默认登录后获取用户名)/);
23
- assert.match(src, /runBrowserCheck/);
24
- assert.match(src, /const args = buildArgs\(\[script, '--check-browser-only'/);
25
- assert.match(src, /\.\.\.\(download \? \['--download-browser'\] : \[]\)/);
26
- assert.match(src, /toolbar\.children\[5\]/);
27
- assert.match(src, /toolbar\.children\[6\]/);
28
- assert.match(src, /login-profile/);
29
- assert.match(src, /新增一个并登录/);
30
- assert.match(src, /const commitAlias = async \(\) =>/);
31
- assert.match(src, /aliasInput\.onblur = \(\) => void commitAlias\(\);/);
32
- assert.match(src, /source: 'auto'/);
33
- });