@web-auto/webauto 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +247 -12
  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 +37 -9
  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,146 +0,0 @@
1
- import { createEl, labeledInput, section } from '../ui-components.mts';
2
- import { resolveConfigPath } from '../path-helpers.mts';
3
- import { renderDebug } from './debug.mts';
4
-
5
- export function renderSettings(root: HTMLElement, ctx: any) {
6
- const coreDaemon = createEl('input', { value: ctx.settings?.coreDaemonUrl || 'http://127.0.0.1:7700' }) as HTMLInputElement;
7
- const download = createEl('input', { value: ctx.settings?.downloadRoot || '' }) as HTMLInputElement;
8
- const env = createEl('select') as HTMLSelectElement;
9
- ['debug', 'prod'].forEach((x) => env.appendChild(createEl('option', { value: x }, [x])));
10
- env.value = ctx.settings?.defaultEnv || 'debug';
11
- const keyword = createEl('input', { value: ctx.settings?.defaultKeyword || '' }) as HTMLInputElement;
12
- const loginTimeout = createEl('input', { value: String(ctx.settings?.timeouts?.loginTimeoutSec || 900), type: 'number', min: '30' }) as HTMLInputElement;
13
- const cmdTimeout = createEl('input', { value: String(ctx.settings?.timeouts?.cmdTimeoutSec || 0), type: 'number', min: '0' }) as HTMLInputElement;
14
- // AI Reply Configuration
15
- const aiEnabled = createEl('input', { type: 'checkbox', checked: ctx.settings?.aiReply?.enabled ?? false }) as HTMLInputElement;
16
- const aiBaseUrl = createEl('input', { value: ctx.settings?.aiReply?.baseUrl || 'http://127.0.0.1:5520', placeholder: 'http://127.0.0.1:5520' }) as HTMLInputElement;
17
- const aiApiKey = createEl('input', { value: ctx.settings?.aiReply?.apiKey || '', type: 'password', placeholder: 'sk-...' }) as HTMLInputElement;
18
- const aiModel = createEl('input', { value: ctx.settings?.aiReply?.model || 'iflow.glm-5', placeholder: 'iflow.glm-5' }) as HTMLInputElement;
19
- const aiTemperature = createEl('input', { value: String(ctx.settings?.aiReply?.temperature ?? 0.7), type: 'number', min: '0', max: '2', step: '0.1' }) as HTMLInputElement;
20
- const aiMaxChars = createEl('input', { value: String(ctx.settings?.aiReply?.maxChars ?? 20), type: 'number', min: '5', max: '500' }) as HTMLInputElement;
21
- const aiTimeout = createEl('input', { value: String(ctx.settings?.aiReply?.timeoutMs ?? 25000), type: 'number', min: '5000', step: '1000' }) as HTMLInputElement;
22
- const aiStyle = createEl('select') as HTMLSelectElement;
23
- ['friendly', 'professional', 'humorous', 'concise', 'custom'].forEach((x) => aiStyle.appendChild(createEl('option', { value: x }, [x])));
24
- aiStyle.value = ctx.settings?.aiReply?.stylePreset || 'friendly';
25
- const aiStyleCustom = createEl('input', { value: ctx.settings?.aiReply?.styleCustom || '', placeholder: '自定义风格描述(可选)' }) as HTMLInputElement;
26
- const aiTestResult = createEl('div', { className: 'muted', style: 'min-height:1.5em;' }) as HTMLDivElement;
27
-
28
- async function fetchModels() {
29
- try {
30
- aiTestResult.textContent = '获取模型列表中...';
31
- const result = await (window as any).api.invoke('ai:listModels', {
32
- baseUrl: aiBaseUrl.value.trim(),
33
- apiKey: aiApiKey.value.trim(),
34
- });
35
- if (result.ok && result.models?.length > 0) {
36
- aiTestResult.textContent = '找到 ' + result.models.length + ' 个模型: ' + result.models.slice(0, 3).join(', ') + (result.models.length > 3 ? '...' : '');
37
- if (!aiModel.value && result.models[0]) {
38
- aiModel.value = result.models[0];
39
- }
40
- } else {
41
- aiTestResult.textContent = result.error ? '错误: ' + result.error : '未找到模型';
42
- }
43
- } catch (e: any) {
44
- aiTestResult.textContent = '错误: ' + (e?.message || String(e));
45
- }
46
- }
47
-
48
- async function testConnection() {
49
- try {
50
- aiTestResult.textContent = '测试连通性...';
51
- const result = await (window as any).api.invoke('ai:testChatCompletion', {
52
- baseUrl: aiBaseUrl.value.trim(),
53
- apiKey: aiApiKey.value.trim(),
54
- model: aiModel.value.trim() || 'iflow.glm-5',
55
- timeoutMs: Number(aiTimeout.value) || 25000,
56
- });
57
- if (result.ok) {
58
- aiTestResult.textContent = '连通成功 (' + result.latencyMs + 'ms)';
59
- } else {
60
- aiTestResult.textContent = result.error ? '错误: ' + result.error : '测试失败';
61
- }
62
- } catch (e: any) {
63
- aiTestResult.textContent = '错误: ' + (e?.message || String(e));
64
- }
65
- }
66
- const configPath = resolveConfigPath(ctx.settings?.downloadRoot || '', window.api);
67
- const debugHost = createEl('div') as HTMLDivElement;
68
-
69
- async function save() {
70
- const next = await window.api.settingsSet({
71
- coreDaemonUrl: coreDaemon.value.trim(),
72
- downloadRoot: download.value.trim(),
73
- defaultEnv: env.value,
74
- defaultKeyword: keyword.value,
75
- timeouts: {
76
- loginTimeoutSec: Number(loginTimeout.value || '900'),
77
- cmdTimeoutSec: Number(cmdTimeout.value || '0'),
78
- },
79
- aiReply: {
80
- enabled: aiEnabled.checked,
81
- baseUrl: aiBaseUrl.value.trim(),
82
- apiKey: aiApiKey.value.trim(),
83
- model: aiModel.value.trim(),
84
- temperature: Number(aiTemperature.value) || 0.7,
85
- maxChars: Number(aiMaxChars.value) || 20,
86
- timeoutMs: Number(aiTimeout.value) || 25000,
87
- stylePreset: aiStyle.value as any,
88
- styleCustom: aiStyleCustom.value.trim(),
89
- },
90
- });
91
- ctx.settings = next;
92
- ctx.appendLog('[settings] saved');
93
- }
94
-
95
- root.appendChild(
96
- section('设置', [
97
- createEl('div', { className: 'row' }, [
98
- labeledInput('Core Daemon', coreDaemon),
99
- ]),
100
- createEl('div', { className: 'row' }, [
101
-
102
- labeledInput('downloadRoot', download),
103
- labeledInput('defaultEnv', env),
104
- labeledInput('defaultKeyword', keyword),
105
- ]),
106
- createEl('div', { className: 'row' }, [
107
- labeledInput('loginTimeoutSec', loginTimeout),
108
- labeledInput('cmdTimeoutSec', cmdTimeout),
109
- ]),
110
- createEl('div', { className: 'row' }, [
111
- createEl('button', {}, ['保存']),
112
- ]),
113
- createEl('div', { className: 'muted' }, [`保存到 ${configPath} 的 desktopConsole 配置块(若 dist/modules/config 不可用则 fallback 到 legacy settings 文件)`]),
114
- section('AI 智能回复', [
115
- createEl('div', { className: 'row' }, [
116
- labeledInput('启用智能回复', aiEnabled),
117
- ]),
118
- createEl('div', { className: 'row' }, [
119
- labeledInput('API Base URL', aiBaseUrl),
120
- labeledInput('API Key', aiApiKey),
121
- ]),
122
- createEl('div', { className: 'row' }, [
123
- labeledInput('模型', aiModel),
124
- createEl('button', { style: 'margin-left:8px;' }, ['获取模型列表']),
125
- createEl('button', { style: 'margin-left:8px;' }, ['测试连通']),
126
- ]),
127
- createEl('div', { className: 'row' }, [
128
- labeledInput('Temperature', aiTemperature),
129
- labeledInput('最大字数', aiMaxChars),
130
- labeledInput('超时(ms)', aiTimeout),
131
- ]),
132
- createEl('div', { className: 'row' }, [
133
- labeledInput('回复风格', aiStyle),
134
- labeledInput('自定义风格', aiStyleCustom),
135
- ]),
136
- aiTestResult,
137
- ]),
138
- section('调试(已并入设置)', [debugHost]),
139
- ]),
140
- );
141
- (root.querySelector('button') as HTMLButtonElement).onclick = () => void save();
142
- const buttons = root.querySelectorAll('button');
143
- if (buttons[1]) (buttons[1] as HTMLButtonElement).onclick = () => void fetchModels();
144
- if (buttons[2]) (buttons[2] as HTMLButtonElement).onclick = () => void testConnection();
145
- renderDebug(debugHost, ctx);
146
- }
@@ -1,486 +0,0 @@
1
- import { createEl } from '../../ui-components.mjs';
2
- import {
3
- XHS_DEFAULT_BATCH_KEY,
4
- readBatchKey,
5
- sanitizeBatchKey,
6
- writeBatchKey,
7
- } from './helpers.mjs';
8
- export function extractBatchBase(_profileId: string): string {
9
- return XHS_DEFAULT_BATCH_KEY;
10
- }
11
- export function inferDefaultBatchBase(_currentProfileId: string, _latestProfiles: string[]): string {
12
- return XHS_DEFAULT_BATCH_KEY;
13
- }
14
- type AccountFlowOptions = {
15
- api: any;
16
- profilePickSel: HTMLSelectElement;
17
- accountModeSelect: HTMLSelectElement;
18
- singleProfileHint: HTMLDivElement;
19
- shardProfilesBox: HTMLDivElement;
20
- shardProfilesHint: HTMLDivElement;
21
- shardResolvedHint: HTMLDivElement;
22
- accountAuditSummary: HTMLDivElement;
23
- accountAuditList: HTMLDivElement;
24
- accountRefreshBtn: HTMLButtonElement;
25
- accountLiveProbeBtn: HTMLButtonElement;
26
- addAccountCountInput: HTMLInputElement;
27
- addBatchNameInput: HTMLInputElement;
28
- accountAddBtn: HTMLButtonElement;
29
- batchKeyValue: HTMLDivElement;
30
- batchNextBtn: HTMLButtonElement;
31
- onboardingSummary: HTMLDivElement;
32
- onboardingCard: HTMLDivElement;
33
- onboardingTips: HTMLDivElement;
34
- persistedSingleProfile: string;
35
- persistedShardProfiles: Set<string>;
36
- setActiveTile: (tileId: string) => void;
37
- saveGuideState: (state: any) => void;
38
- applyGuideLock: () => void;
39
- getGuideState: () => any;
40
- setNavHint: (text: string) => void;
41
- runBrowserStatusCheck: (profileId: string, reason?: string) => Promise<boolean>;
42
- };
43
- type AccountFlowController = {
44
- refreshProfileChoices: (preferredProfileId?: string) => Promise<void>;
45
- startAccountAutoRefresh: (reason: string) => void;
46
- stopAccountAutoRefresh: () => void;
47
- getSelectedShardProfiles: () => string[];
48
- renderSingleProfileHint: () => void;
49
- renderShardHints: () => void;
50
- resolveAddBatchPrefix: () => string;
51
- syncAddBatchPlaceholder: () => void;
52
- };
53
- export function createAccountFlowController(opts: AccountFlowOptions): AccountFlowController {
54
- const {
55
- api,
56
- profilePickSel,
57
- accountModeSelect,
58
- singleProfileHint,
59
- shardProfilesBox,
60
- shardProfilesHint,
61
- shardResolvedHint,
62
- accountAuditSummary,
63
- accountAuditList,
64
- accountRefreshBtn,
65
- accountLiveProbeBtn,
66
- addAccountCountInput,
67
- addBatchNameInput,
68
- accountAddBtn,
69
- batchKeyValue,
70
- batchNextBtn,
71
- onboardingSummary,
72
- onboardingCard,
73
- onboardingTips,
74
- persistedSingleProfile,
75
- persistedShardProfiles,
76
- setActiveTile,
77
- saveGuideState,
78
- applyGuideLock,
79
- getGuideState,
80
- setNavHint,
81
- runBrowserStatusCheck,
82
- } = opts;
83
- let latestProfiles: string[] = [];
84
- let accountAutoRefreshTimer: ReturnType<typeof setInterval> | null = null;
85
- let accountAutoRefreshUntil = 0;
86
- let refreshSeq = 0;
87
- let batchKey = readBatchKey();
88
- if (!batchKey || /^batch-\d{8}-\d{4}$/.test(batchKey)) {
89
- batchKey = XHS_DEFAULT_BATCH_KEY;
90
- }
91
- const updateBatchKey = (next?: string) => {
92
- const candidate = sanitizeBatchKey(String(next || '').trim());
93
- batchKey = candidate === XHS_DEFAULT_BATCH_KEY ? candidate : XHS_DEFAULT_BATCH_KEY;
94
- writeBatchKey(batchKey);
95
- batchKeyValue.textContent = batchKey;
96
- addBatchNameInput.value = batchKey;
97
- };
98
- const openPreflightAccountTab = () => { if (typeof api?.setActiveTab === 'function') api.setActiveTab('preflight'); };
99
- const aliasesMap = () => {
100
- const aliases = api?.settings?.profileAliases;
101
- return aliases && typeof aliases === 'object' ? aliases : {};
102
- };
103
- const getSelectedShardProfiles = () => {
104
- const selected: string[] = [];
105
- shardProfilesBox.querySelectorAll('input[type="checkbox"][data-profile-id]').forEach((node) => {
106
- const cb = node as HTMLInputElement;
107
- if (!cb.checked) return;
108
- const id = String(cb.dataset.profileId || '').trim();
109
- if (id) selected.push(id);
110
- });
111
- return selected;
112
- };
113
- const uniqueProfileIds = (items: string[]) => {
114
- const seen = new Set<string>();
115
- const out: string[] = [];
116
- for (const raw of items) {
117
- const id = String(raw || '').trim();
118
- if (!id || seen.has(id)) continue;
119
- seen.add(id);
120
- out.push(id);
121
- }
122
- return out;
123
- };
124
- const isNewFormatProfileId = (id: string) => /.+-batch-\d+$/.test(String(id || '').trim());
125
- const renderSingleProfileHint = () => {
126
- const current = String(profilePickSel.value || '').trim();
127
- if (!current) {
128
- singleProfileHint.textContent = '当前实际使用:(未选择账号)';
129
- return;
130
- }
131
- const label = String(profilePickSel.selectedOptions?.[0]?.textContent || current).trim();
132
- singleProfileHint.textContent = `当前实际使用:${label}`;
133
- };
134
- const renderShardHints = () => {
135
- const selected = getSelectedShardProfiles();
136
- shardProfilesHint.textContent = `selected=${selected.length}`;
137
- shardResolvedHint.textContent = selected.length > 0 ? `resolved: --profiles ${selected.join(',')}` : '';
138
- };
139
- const resolveAddBatchPrefix = (): string => {
140
- return XHS_DEFAULT_BATCH_KEY;
141
- };
142
- const syncAddBatchPlaceholder = () => {
143
- addBatchNameInput.placeholder = `Account prefix (fixed ${XHS_DEFAULT_BATCH_KEY})`;
144
- };
145
- const deriveCookieCandidates = (profileDir: string, profileId: string) => {
146
- const candidates = new Set<string>();
147
- const normalized = String(profileDir || '').replace(/\\/g, '/');
148
- const marker = '/profiles/';
149
- const at = normalized.lastIndexOf(marker);
150
- if (at > 0) {
151
- const rootDir = normalized.slice(0, at);
152
- candidates.add(rootDir + '/cookies/' + profileId + '.json');
153
- }
154
- if (typeof window.api?.osHomedir === 'function') {
155
- const homeDir = String(window.api.osHomedir() || '').trim();
156
- if (homeDir) {
157
- candidates.add(window.api.pathJoin(homeDir, '.webauto', 'cookies', `${profileId}.json`));
158
- }
159
- }
160
- return Array.from(candidates).map((p) => (window.api?.pathNormalize ? window.api.pathNormalize(p) : p));
161
- };
162
- let startAddAccountFlow: (() => Promise<void>) | null = null;
163
- const refreshAccountAudit = async (
164
- profiles: string[],
165
- aliases: Record<string, string>,
166
- profileDirs: Map<string, string>,
167
- seq: number,
168
- ) => {
169
- const appendAction = (label: string, onClick: () => void) => {
170
- const row = createEl('div', { className: 'xhs-account-row' });
171
- const btn = createEl('button', { type: 'button', className: 'secondary', style: 'padding:2px 8px; font-size:11px;' }, [label]) as HTMLButtonElement;
172
- btn.onclick = (evt) => {
173
- evt.preventDefault();
174
- onClick();
175
- };
176
- row.appendChild(createEl('div', { className: 'muted', style: 'font-size:12px;' }, ['需要补充账号操作']));
177
- row.appendChild(btn);
178
- accountAuditList.appendChild(row);
179
- };
180
- const sessions = await window.api.runtimeListSessions().catch(() => []);
181
- const activeProfiles = new Set(
182
- Array.isArray(sessions)
183
- ? sessions.map((s: any) => String(s?.profileId || '').trim()).filter(Boolean)
184
- : [],
185
- );
186
- const uniqueProfiles = uniqueProfileIds(profiles);
187
- const rows = await Promise.all(
188
- uniqueProfiles.map(async (profileId) => {
189
- const profileDir = String(profileDirs.get(profileId) || '').trim();
190
- const cookieCandidates = deriveCookieCandidates(profileDir, profileId);
191
- let cookieReady = false;
192
- for (const cookiePath of cookieCandidates) {
193
- const cookieRet = await window.api.fsReadTextPreview({ path: cookiePath, maxBytes: 160, maxLines: 2 }).catch(() => null);
194
- if (cookieRet?.ok && String(cookieRet?.text || '').trim()) {
195
- cookieReady = true;
196
- break;
197
- }
198
- }
199
- const active = activeProfiles.has(profileId);
200
- return {
201
- profileId,
202
- alias: String((aliases as any)[profileId] || '').trim(),
203
- cookieReady,
204
- active,
205
- };
206
- }),
207
- );
208
- if (seq !== refreshSeq) return;
209
- accountAuditList.innerHTML = '';
210
- if (rows.length === 0) {
211
- accountAuditList.appendChild(createEl('div', { className: 'xhs-account-row muted' }, ['暂无账号,请先新增账号。']));
212
- accountAuditSummary.textContent = '账号检查:0 个账号';
213
- const state = getGuideState();
214
- state.accountReady = false;
215
- saveGuideState(state);
216
- applyGuideLock();
217
- appendAction('去新增账号', () => {
218
- openPreflightAccountTab();
219
- if (startAddAccountFlow) void startAddAccountFlow();
220
- });
221
- return;
222
- }
223
- const cookieReadyCount = rows.filter((x) => x.cookieReady).length;
224
- const activeCount = rows.filter((x) => x.active).length;
225
- accountAuditSummary.textContent = `账号检查:总数=${rows.length},cookie就绪=${cookieReadyCount},当前在线=${activeCount}`;
226
- const state = getGuideState();
227
- state.accountReady = cookieReadyCount > 0 || activeCount > 0;
228
- saveGuideState(state);
229
- applyGuideLock();
230
- if (cookieReadyCount === 0 && activeCount === 0) {
231
- appendAction('去登录账号', () => {
232
- openPreflightAccountTab();
233
- if (startAddAccountFlow) void startAddAccountFlow();
234
- });
235
- }
236
- rows.forEach((entry) => {
237
- const label = entry.alias ? `${entry.alias} (${entry.profileId})` : entry.profileId;
238
- const status = entry.active ? '在线' : entry.cookieReady ? 'cookie就绪' : '待登录';
239
- const statusColor = entry.active ? '#22c55e' : entry.cookieReady ? '#f59e0b' : '#ef4444';
240
- const row = createEl('div', { className: 'xhs-account-row' });
241
- row.appendChild(createEl('div', { className: 'muted', style: 'font-size:12px;' }, [label]));
242
- row.appendChild(createEl('div', { style: `font-size:12px; color:${statusColor};` }, [status]));
243
- const aliasBtn = createEl('button', { type: 'button', className: 'secondary', style: 'padding:2px 6px; font-size:11px;' }, ['设置别名']) as HTMLButtonElement;
244
- aliasBtn.onclick = async () => {
245
- const currentAlias = String(entry.alias || '').trim();
246
- const nextAlias = window.prompt('账号别名(仅用于区分账号显示名)', currentAlias || '');
247
- if (nextAlias == null) return;
248
- const aliasesNext: Record<string, string> = { ...aliases };
249
- const cleaned = String(nextAlias || '').trim();
250
- if (cleaned) aliasesNext[entry.profileId] = cleaned;
251
- else delete aliasesNext[entry.profileId];
252
- try {
253
- const updated = await window.api.settingsSet({ profileAliases: aliasesNext });
254
- api.settings = updated;
255
- void refreshProfileChoices();
256
- } catch {
257
- alert('别名保存失败,请稍后再试');
258
- }
259
- };
260
- row.appendChild(aliasBtn);
261
- accountAuditList.appendChild(row);
262
- });
263
- };
264
- const refreshProfileChoices = async (preferredProfileId = '') => {
265
- const seq = ++refreshSeq;
266
- accountAuditSummary.textContent = '账号检查:刷新中...';
267
- const selectedNow = getSelectedShardProfiles();
268
- const prevSingle = String(profilePickSel.value || persistedSingleProfile || '').trim();
269
- const preferredSingle = String(preferredProfileId || '').trim();
270
- const prevSelected = selectedNow.length > 0 ? new Set(selectedNow) : new Set(persistedShardProfiles);
271
- const scan = await window.api.profilesScan().catch(() => null);
272
- const entries: any[] = Array.isArray(scan?.entries) ? scan.entries : [];
273
- const profiles: string[] = uniqueProfileIds(entries.map((e: any) => String(e?.profileId || '').trim())).filter(isNewFormatProfileId);
274
- const profileDirs = new Map<string, string>();
275
- entries.forEach((e: any) => {
276
- const pid = String(e?.profileId || '').trim();
277
- if (!pid || !isNewFormatProfileId(pid)) return;
278
- if (!profileDirs.has(pid)) profileDirs.set(pid, String(e?.profileDir || '').trim());
279
- });
280
- if (seq !== refreshSeq) return;
281
- latestProfiles = profiles.slice();
282
- syncAddBatchPlaceholder();
283
- const aliases = aliasesMap();
284
- const aliasedProfiles = profiles.filter((profileId) => String((aliases as any)[profileId] || '').trim()).length;
285
- onboardingSummary.textContent = `profile=${profiles.length},已设置账号名=${aliasedProfiles}`;
286
- if (profiles.length === 0) {
287
- onboardingCard.style.display = '';
288
- onboardingTips.textContent = '当前没有可用 profile:请前往预处理页创建/登录 profile,再返回此页。';
289
- } else {
290
- onboardingCard.style.display = 'none';
291
- }
292
- profilePickSel.textContent = '';
293
- profilePickSel.appendChild(createEl('option', { value: '' }, ['(请选择账号:alias / profile)']));
294
- for (const profileId of profiles) {
295
- const alias = String((aliases as any)[profileId] || '').trim();
296
- const label = alias ? `${alias} (${profileId})` : profileId;
297
- profilePickSel.appendChild(createEl('option', { value: profileId }, [label]));
298
- }
299
- if (preferredSingle && profiles.includes(preferredSingle)) {
300
- profilePickSel.value = preferredSingle;
301
- } else if (prevSingle && profiles.includes(prevSingle)) {
302
- profilePickSel.value = prevSingle;
303
- } else if (profiles.length > 0) {
304
- profilePickSel.value = profiles[0];
305
- }
306
- renderSingleProfileHint();
307
- shardProfilesBox.innerHTML = '';
308
- for (const profileId of profiles) {
309
- const alias = String((aliases as any)[profileId] || '').trim();
310
- const label = alias ? `${alias} (${profileId})` : profileId;
311
- const id = `xh-profile-${profileId.replace(/[^a-zA-Z0-9_-]/g, '-')}`;
312
- const cb = createEl('input', { type: 'checkbox', id }) as HTMLInputElement;
313
- cb.dataset.profileId = profileId;
314
- cb.checked = prevSelected.has(profileId) || (profiles.length === 1 && prevSelected.size === 0);
315
- cb.onchange = () => {
316
- persistedShardProfiles.clear();
317
- getSelectedShardProfiles().forEach((pid) => persistedShardProfiles.add(pid));
318
- renderShardHints();
319
- };
320
- const row = createEl('div', { className: 'row', style: 'align-items:center; gap:8px; margin-bottom:4px;' }, [
321
- cb,
322
- createEl('label', { for: id, style: 'cursor:pointer;' }, [label]),
323
- ]);
324
- shardProfilesBox.appendChild(row);
325
- }
326
- if (shardProfilesBox.childElementCount === 0) {
327
- shardProfilesBox.appendChild(createEl('div', { className: 'muted' }, ['暂无可用账号,请先在预处理页新增账号']));
328
- }
329
- persistedShardProfiles.clear();
330
- getSelectedShardProfiles().forEach((pid) => persistedShardProfiles.add(pid));
331
- renderShardHints();
332
- await refreshAccountAudit(profiles, aliases as Record<string, string>, profileDirs, seq);
333
- };
334
- const stopAccountAutoRefresh = () => {
335
- if (accountAutoRefreshTimer) {
336
- clearInterval(accountAutoRefreshTimer);
337
- accountAutoRefreshTimer = null;
338
- }
339
- };
340
- const startAccountAutoRefresh = (reason: string) => {
341
- stopAccountAutoRefresh();
342
- accountAutoRefreshUntil = Date.now() + 10 * 60 * 1000;
343
- api?.appendLog?.(`[ui] account auto refresh start (${reason})`);
344
- const tick = async () => {
345
- if (Date.now() > accountAutoRefreshUntil) {
346
- stopAccountAutoRefresh();
347
- return;
348
- }
349
- await refreshProfileChoices().catch(() => null);
350
- if (getGuideState().accountReady) {
351
- api?.appendLog?.('[ui] account auto refresh done (account ready)');
352
- stopAccountAutoRefresh();
353
- }
354
- };
355
- void tick();
356
- accountAutoRefreshTimer = setInterval(() => {
357
- void tick();
358
- }, 15000);
359
- };
360
- startAddAccountFlow = async () => {
361
- if (typeof window.api?.cmdSpawn !== 'function' || typeof window.api?.cmdRunJson !== 'function') {
362
- api?.appendLog?.('[error] cmdSpawn/cmdRunJson API unavailable in renderer');
363
- alert('启动失败:cmdSpawn/cmdRunJson API 不可用');
364
- return;
365
- }
366
- const kw = resolveAddBatchPrefix();
367
- if (!kw) {
368
- api?.appendLog?.('[ui] add-account blocked: empty batch');
369
- alert('批次名称不能为空,请先填写批次名称或使用默认 xiaohongshu');
370
- return;
371
- }
372
- const addCount = Math.max(1, Math.floor(Number(addAccountCountInput.value || '1')));
373
- const timeoutSec = Math.max(30, Math.floor(Number(api?.settings?.timeouts?.loginTimeoutSec || 900)));
374
- const createdProfiles: string[] = [];
375
- api?.appendLog?.(`[ui] add-account start batch=${kw} count=${addCount}`);
376
- setNavHint(`正在创建新账号(批次=${kw}, count=${addCount})...`);
377
- for (let i = 0; i < addCount; i += 1) {
378
- const out = await window.api.cmdRunJson({
379
- title: `profilepool add ${kw}`,
380
- cwd: '',
381
- args: [window.api.pathJoin('apps', 'webauto', 'entry', 'profilepool.mjs'), 'add', kw, '--json'],
382
- }).catch((err: any) => ({ ok: false, error: err?.message || String(err) }));
383
- if (!out?.ok || !out?.json?.profileId) {
384
- const reason = String(out?.error || out?.stderr || out?.stdout || 'unknown_error');
385
- api?.appendLog?.(`[ui] profilepool add failed: ${reason}`);
386
- alert(`新增账号失败(创建 profile 失败):${reason}`);
387
- return;
388
- }
389
- const createdProfileId = String(out.json.profileId || '').trim();
390
- if (!createdProfileId) {
391
- alert('新增账号失败:未返回 profileId');
392
- return;
393
- }
394
- createdProfiles.push(createdProfileId);
395
- api?.appendLog?.(`[ui] profile created: ${createdProfileId}`);
396
- }
397
- const targetProfile = createdProfiles[0] || '';
398
- if (!targetProfile) {
399
- alert('新增账号失败:未创建任何 profile');
400
- return;
401
- }
402
- const loginArgs = [
403
- window.api.pathJoin('apps', 'webauto', 'entry', 'profilepool.mjs'),
404
- 'login-profile',
405
- targetProfile,
406
- '--timeout-sec',
407
- String(timeoutSec),
408
- '--keep-session',
409
- ...(api?.settings?.unifiedApiUrl ? ['--unified-api', String(api.settings.unifiedApiUrl)] : []),
410
- ...(api?.settings?.browserServiceUrl ? ['--browser-service', String(api.settings.browserServiceUrl)] : []),
411
- ];
412
- api?.appendLog?.(`[ui] spawn profilepool login-profile profile=${targetProfile} timeout=${timeoutSec}s`);
413
- try {
414
- const ret = await window.api.cmdSpawn({
415
- title: `profilepool login-profile ${targetProfile} (headful)`,
416
- cwd: '',
417
- args: loginArgs,
418
- groupKey: 'profilepool',
419
- env: { WEBAUTO_DAEMON: '1' },
420
- });
421
- if (!ret || !ret.runId) {
422
- api?.appendLog?.('[ui] spawn returned empty runId');
423
- alert('新增账号启动失败:未获取 runId,请查看日志');
424
- return;
425
- }
426
- api?.appendLog?.(`[ui] spawn ok runId=${ret.runId}`);
427
- setNavHint(`已创建账号:${createdProfiles.join(', ')};已打开登录窗口:${targetProfile},请完成登录后点“检查账号状态”。`);
428
- await refreshProfileChoices(targetProfile);
429
- startAccountAutoRefresh('add-account');
430
- } catch (err: any) {
431
- api?.appendLog?.(`[ui] spawn exception: ${err?.message || String(err)}`);
432
- alert(`新增账号启动失败:${err?.message || String(err)}`);
433
- }
434
- };
435
- accountRefreshBtn.onclick = async () => {
436
- const profileId = String(profilePickSel.value || '').trim();
437
- if (!profileId) {
438
- setActiveTile('account');
439
- setNavHint('请先新增账号,然后再做账号检查。');
440
- alert('请先新增账号,然后再做账号检查。');
441
- return;
442
- }
443
- await runBrowserStatusCheck(profileId, 'refresh');
444
- void refreshProfileChoices(profileId);
445
- };
446
- accountLiveProbeBtn.onclick = async () => {
447
- const accountMode = String(accountModeSelect.value || 'single').trim();
448
- const shardSelected = accountMode === 'shards' ? getSelectedShardProfiles() : [];
449
- const profileId = String((shardSelected[0] || profilePickSel.value || '')).trim();
450
- if (!profileId) {
451
- alert('请先选择一个账号后再执行实时探测');
452
- return;
453
- }
454
- await runBrowserStatusCheck(profileId, 'live-probe');
455
- setTimeout(() => {
456
- void refreshProfileChoices();
457
- }, 1500);
458
- };
459
- batchNextBtn.onclick = () => {
460
- updateBatchKey(XHS_DEFAULT_BATCH_KEY);
461
- setNavHint(`Naming reset: ${XHS_DEFAULT_BATCH_KEY}`);
462
- };
463
- addBatchNameInput.addEventListener('change', () => {
464
- updateBatchKey(XHS_DEFAULT_BATCH_KEY);
465
- setNavHint(`Account IDs use fixed pattern: ${XHS_DEFAULT_BATCH_KEY}-N`);
466
- });
467
- accountAddBtn.addEventListener('pointerdown', (evt) => {
468
- evt.stopPropagation();
469
- });
470
- accountAddBtn.addEventListener('click', (evt) => {
471
- evt.preventDefault();
472
- evt.stopPropagation();
473
- if (startAddAccountFlow) void startAddAccountFlow();
474
- });
475
- updateBatchKey(batchKey || XHS_DEFAULT_BATCH_KEY);
476
- return {
477
- refreshProfileChoices,
478
- startAccountAutoRefresh,
479
- stopAccountAutoRefresh,
480
- getSelectedShardProfiles,
481
- renderSingleProfileHint,
482
- renderShardHints,
483
- resolveAddBatchPrefix,
484
- syncAddBatchPlaceholder,
485
- };
486
- }
@@ -1,56 +0,0 @@
1
- export const XHS_NAV_TARGET_KEY = 'webauto.xhs.navTarget.v1';
2
-
3
- export function consumeNavTarget(focusTile: (id: string) => void) {
4
- let target = '';
5
- try {
6
- target = String(window.localStorage.getItem(XHS_NAV_TARGET_KEY) || '').trim();
7
- if (target) window.localStorage.removeItem(XHS_NAV_TARGET_KEY);
8
- } catch {
9
- target = '';
10
- }
11
- if (target === 'account') {
12
- focusTile('account');
13
- }
14
- }
15
-
16
- export async function runGuideBrowserCheck(
17
- api: any,
18
- guideState: any,
19
- browserStatus: HTMLSpanElement | HTMLDivElement,
20
- saveGuideState: (state: any) => void,
21
- ) {
22
- const script = window.api.pathJoin('apps', 'webauto', 'entry', 'xhs-install.mjs');
23
- const args = [script, '--check-browser-only'];
24
-
25
- browserStatus.textContent = '⏳ 浏览器检查中...';
26
- browserStatus.style.color = '#f59e0b';
27
-
28
- if (typeof window.api?.cmdRunJson === 'function') {
29
- const out = await window.api
30
- .cmdRunJson({ title: 'xhs install check', cwd: '', args, timeoutMs: 120000 })
31
- .catch(() => ({ ok: false }));
32
- const merged = String(out?.stdout || out?.stderr || '').replace(/\x1b\[[0-9;]*m/g, '');
33
- if (out?.ok) {
34
- guideState.browserReady = true;
35
- browserStatus.textContent = '✅ 浏览器检查通过';
36
- browserStatus.style.color = '#22c55e';
37
- } else if (/Camoufox 未安装/i.test(merged)) {
38
- guideState.browserReady = false;
39
- browserStatus.textContent = '⚠️ 未安装 Camoufox';
40
- browserStatus.style.color = '#f59e0b';
41
- if (merged) api?.appendLog?.(`[xhs-guide] install check\n${merged}`);
42
- } else {
43
- guideState.browserReady = false;
44
- browserStatus.textContent = '❌ 浏览器检查失败';
45
- browserStatus.style.color = '#ef4444';
46
- if (merged) api?.appendLog?.(`[xhs-guide] install check\n${merged}`);
47
- }
48
- saveGuideState(guideState);
49
- return;
50
- }
51
-
52
- guideState.browserReady = false;
53
- browserStatus.textContent = '❌ 浏览器检查能力不可用';
54
- browserStatus.style.color = '#ef4444';
55
- saveGuideState(guideState);
56
- }