@web-auto/webauto 0.1.4 → 0.1.7

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 (174) hide show
  1. package/apps/desktop-console/default-settings.json +2 -2
  2. package/apps/desktop-console/dist/main/index.mjs +983 -128
  3. package/apps/desktop-console/dist/main/preload.mjs +7 -0
  4. package/apps/desktop-console/dist/renderer/index.html +622 -50
  5. package/apps/desktop-console/dist/renderer/index.js +2423 -469
  6. package/apps/desktop-console/dist/renderer/run.mts +6 -5
  7. package/apps/desktop-console/entry/ui-cli.mjs +672 -0
  8. package/apps/desktop-console/entry/ui-console.mjs +416 -29
  9. package/apps/webauto/entry/account.mjs +89 -53
  10. package/apps/webauto/entry/browser-status.mjs +7 -10
  11. package/apps/webauto/entry/lib/account-detect.mjs +254 -28
  12. package/apps/webauto/entry/lib/account-store.mjs +219 -30
  13. package/apps/webauto/entry/lib/bus-publish.mjs +63 -0
  14. package/apps/webauto/entry/lib/camo-cli.mjs +93 -0
  15. package/apps/webauto/entry/lib/profilepool.mjs +14 -5
  16. package/apps/webauto/entry/lib/quota-status.mjs +23 -0
  17. package/apps/webauto/entry/lib/schedule-store.mjs +1068 -0
  18. package/apps/webauto/entry/profilepool.mjs +106 -17
  19. package/apps/webauto/entry/schedule.mjs +612 -0
  20. package/apps/webauto/entry/weibo-unified.mjs +134 -0
  21. package/apps/webauto/entry/xhs-install.mjs +256 -31
  22. package/apps/webauto/entry/xhs-status.mjs +5 -2
  23. package/apps/webauto/entry/xhs-unified.mjs +631 -98
  24. package/apps/webauto/resources/container-library/weibo/weibo_detail_page/comment_item/container.json +40 -0
  25. package/apps/webauto/resources/container-library/weibo/weibo_detail_page/reply_expand_button/container.json +38 -0
  26. package/apps/webauto/resources/container-library/weibo/weibo_detail_page/reply_list/container.json +37 -0
  27. package/apps/webauto/resources/container-library/weibo/weibo_search_page/container.json +8 -3
  28. package/apps/webauto/resources/container-library/weibo/weibo_search_page/login_anchor/container.json +30 -0
  29. package/apps/webauto/resources/container-library/weibo/weibo_search_page/search_bar/container.json +47 -0
  30. package/apps/webauto/resources/container-library/weibo/weibo_search_page/search_button/container.json +39 -0
  31. package/bin/camoufox-cli.mjs +61 -0
  32. package/bin/webauto.mjs +301 -54
  33. package/dist/modules/camo-backend/src/index.js +49 -1
  34. package/dist/modules/camo-backend/src/internal/BrowserSession.js +572 -3
  35. package/dist/modules/camo-backend/src/internal/SessionManager.js +13 -1
  36. package/dist/modules/camo-backend/src/internal/storage-paths.js +6 -0
  37. package/dist/modules/collection-manager/bloom-filter.js +91 -0
  38. package/dist/modules/collection-manager/date-utils.js +275 -0
  39. package/dist/modules/collection-manager/index.js +258 -0
  40. package/dist/modules/collection-manager/storage.js +195 -0
  41. package/dist/modules/collection-manager/types.js +47 -0
  42. package/dist/modules/logging/src/index.js +1 -1
  43. package/dist/modules/process-registry/index.js +230 -0
  44. package/dist/modules/rate-limiter/index.js +242 -0
  45. package/dist/modules/workflow/blocks/ExecuteWeiboSearchBlock.js +128 -0
  46. package/dist/modules/workflow/blocks/PersistXhsNoteBlock.js +7 -3
  47. package/dist/modules/workflow/blocks/RenderMarkdown.js +4 -1
  48. package/dist/modules/workflow/blocks/WeiboCollectCommentsBlock.js +282 -0
  49. package/dist/modules/workflow/blocks/WeiboCollectFromLinksBlock.js +283 -0
  50. package/dist/modules/workflow/blocks/WeiboCollectSearchLinksBlock.js +208 -0
  51. package/dist/modules/workflow/blocks/WeiboCollectTimelineListBlock.js +128 -0
  52. package/dist/modules/workflow/blocks/WeiboCollectUserPostsListBlock.js +127 -0
  53. package/dist/modules/workflow/blocks/helpers/downloadPaths.js +21 -0
  54. package/dist/modules/workflow/config/workflowRegistry.js +2 -0
  55. package/dist/modules/workflow/definitions/weibo-search-workflow-v1.js +47 -0
  56. package/dist/modules/workflow/src/runner.js +6 -0
  57. package/dist/modules/xiaohongshu/app/src/blocks/Phase34PersistDetailBlock.js +4 -0
  58. package/dist/modules/xiaohongshu/app/src/blocks/Phase3InteractBlock.js +2 -2
  59. package/dist/modules/xiaohongshu/app/src/blocks/helpers/sharding.js +123 -0
  60. package/dist/modules/xiaohongshu/app/src/container-registry/src/index.d.ts +37 -0
  61. package/dist/modules/xiaohongshu/app/src/container-registry/src/index.js +184 -0
  62. package/dist/modules/xiaohongshu/app/src/workflow/blocks/AnchorVerificationBlock.d.ts +31 -0
  63. package/dist/modules/xiaohongshu/app/src/workflow/blocks/AnchorVerificationBlock.js +71 -0
  64. package/dist/modules/xiaohongshu/app/src/workflow/blocks/DetectPageStateBlock.d.ts +48 -0
  65. package/dist/modules/xiaohongshu/app/src/workflow/blocks/DetectPageStateBlock.js +259 -0
  66. package/dist/modules/xiaohongshu/app/src/workflow/blocks/ErrorRecoveryBlock.d.ts +28 -0
  67. package/dist/modules/xiaohongshu/app/src/workflow/blocks/ErrorRecoveryBlock.js +319 -0
  68. package/dist/modules/xiaohongshu/app/src/workflow/blocks/WaitSearchPermitBlock.d.ts +36 -0
  69. package/dist/modules/xiaohongshu/app/src/workflow/blocks/WaitSearchPermitBlock.js +162 -0
  70. package/dist/modules/xiaohongshu/app/src/workflow/blocks/helpers/containerAnchors.d.ts +36 -0
  71. package/dist/modules/xiaohongshu/app/src/workflow/blocks/helpers/containerAnchors.js +301 -0
  72. package/dist/modules/xiaohongshu/app/src/workflow/blocks/helpers/operationLogger.d.ts +29 -0
  73. package/dist/modules/xiaohongshu/app/src/workflow/blocks/helpers/operationLogger.js +195 -0
  74. package/dist/modules/xiaohongshu/app/src/workflow/blocks/helpers/searchPageState.d.ts +25 -0
  75. package/dist/modules/xiaohongshu/app/src/workflow/blocks/helpers/searchPageState.js +164 -0
  76. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/MatchCommentsBlock.d.ts +66 -0
  77. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/MatchCommentsBlock.js +139 -0
  78. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase1EnsureServicesBlock.d.ts +16 -0
  79. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase1EnsureServicesBlock.js +36 -0
  80. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase1MonitorCookieBlock.d.ts +27 -0
  81. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase1MonitorCookieBlock.js +213 -0
  82. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase1StartProfileBlock.d.ts +18 -0
  83. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase1StartProfileBlock.js +121 -0
  84. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase2CollectLinksBlock.d.ts +34 -0
  85. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase2CollectLinksBlock.js +1249 -0
  86. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase2SearchBlock.d.ts +17 -0
  87. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase2SearchBlock.js +703 -0
  88. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34CloseDetailBlock.d.ts +15 -0
  89. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34CloseDetailBlock.js +41 -0
  90. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34CloseTabsBlock.d.ts +26 -0
  91. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34CloseTabsBlock.js +44 -0
  92. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34CollectCommentsBlock.d.ts +29 -0
  93. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34CollectCommentsBlock.js +150 -0
  94. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34ExtractDetailBlock.d.ts +38 -0
  95. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34ExtractDetailBlock.js +117 -0
  96. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34OpenDetailBlock.d.ts +30 -0
  97. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34OpenDetailBlock.js +102 -0
  98. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34OpenTabsBlock.d.ts +23 -0
  99. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34OpenTabsBlock.js +109 -0
  100. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34PersistDetailBlock.d.ts +32 -0
  101. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34PersistDetailBlock.js +117 -0
  102. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34ProcessSingleNoteBlock.d.ts +35 -0
  103. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34ProcessSingleNoteBlock.js +114 -0
  104. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34ValidateLinksBlock.d.ts +34 -0
  105. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase34ValidateLinksBlock.js +90 -0
  106. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase3InteractBlock.d.ts +111 -0
  107. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase3InteractBlock.js +1009 -0
  108. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase4MultiTabHarvestBlock.d.ts +20 -0
  109. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/Phase4MultiTabHarvestBlock.js +233 -0
  110. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/ReplyInteractBlock.d.ts +48 -0
  111. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/ReplyInteractBlock.js +291 -0
  112. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/XhsDiscoverFallbackBlock.d.ts +23 -0
  113. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/XhsDiscoverFallbackBlock.js +240 -0
  114. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/helpers/commentMatchDsl.d.ts +55 -0
  115. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/helpers/commentMatchDsl.js +126 -0
  116. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/helpers/commentMatcher.d.ts +21 -0
  117. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/helpers/commentMatcher.js +99 -0
  118. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/helpers/evidence.d.ts +5 -0
  119. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/helpers/evidence.js +27 -0
  120. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/helpers/sharding.d.ts +37 -0
  121. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/helpers/sharding.js +165 -0
  122. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/helpers/xhsComments.d.ts +33 -0
  123. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/blocks/helpers/xhsComments.js +270 -0
  124. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/index.d.ts +9 -0
  125. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/index.js +9 -0
  126. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/utils/checkpoints.d.ts +50 -0
  127. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/utils/checkpoints.js +222 -0
  128. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/utils/controllerAction.d.ts +10 -0
  129. package/dist/modules/xiaohongshu/app/src/xiaohongshu/app/src/utils/controllerAction.js +43 -0
  130. package/dist/services/shared/serviceProcessLogger.js +1 -1
  131. package/dist/services/unified-api/server.js +105 -11
  132. package/modules/camo-backend/src/index.ts +46 -1
  133. package/modules/camo-backend/src/internal/BrowserSession.ts +619 -3
  134. package/modules/camo-backend/src/internal/SessionManager.ts +12 -1
  135. package/modules/camo-backend/src/internal/storage-paths.ts +5 -0
  136. package/modules/camo-runtime/src/autoscript/action-providers/xhs/comments.mjs +38 -2
  137. package/modules/camo-runtime/src/autoscript/action-providers/xhs/interaction.mjs +47 -2
  138. package/modules/camo-runtime/src/autoscript/action-providers/xhs/search.mjs +94 -11
  139. package/modules/camo-runtime/src/autoscript/action-providers/xhs.mjs +208 -2
  140. package/modules/camo-runtime/src/autoscript/runtime.mjs +7 -1
  141. package/modules/camo-runtime/src/autoscript/xhs-unified-template.mjs +76 -43
  142. package/modules/camo-runtime/src/container/runtime-core/operations/index.mjs +75 -1
  143. package/modules/camo-runtime/src/container/runtime-core/operations/selector-scripts.mjs +71 -4
  144. package/modules/camo-runtime/src/container/runtime-core/operations/tab-pool.mjs +183 -27
  145. package/modules/collection-manager/bloom-filter.ts +112 -0
  146. package/modules/collection-manager/date-utils.ts +316 -0
  147. package/modules/collection-manager/index.ts +309 -0
  148. package/modules/collection-manager/package.json +10 -0
  149. package/modules/collection-manager/storage.ts +174 -0
  150. package/modules/collection-manager/types.ts +156 -0
  151. package/modules/logging/src/index.ts +1 -1
  152. package/modules/process-registry/index.ts +284 -0
  153. package/modules/rate-limiter/index.ts +322 -0
  154. package/modules/state/src/paths.ts +9 -1
  155. package/modules/task-scheduler/index.ts +293 -0
  156. package/modules/workflow/blocks/ExecuteWeiboSearchBlock.ts +167 -0
  157. package/modules/workflow/blocks/PersistXhsNoteBlock.ts +7 -3
  158. package/modules/workflow/blocks/RenderMarkdown.ts +4 -1
  159. package/modules/workflow/blocks/WeiboCollectCommentsBlock.ts +339 -0
  160. package/modules/workflow/blocks/WeiboCollectFromLinksBlock.ts +338 -0
  161. package/modules/workflow/blocks/helpers/downloadPaths.ts +16 -0
  162. package/modules/workflow/config/workflowRegistry.ts +2 -0
  163. package/modules/workflow/definitions/weibo-search-workflow-v1.ts +47 -0
  164. package/modules/workflow/src/runner.ts +6 -0
  165. package/modules/xiaohongshu/app/src/blocks/Phase1StartProfileBlock.ts +1 -1
  166. package/modules/xiaohongshu/app/src/blocks/Phase34PersistDetailBlock.ts +4 -0
  167. package/modules/xiaohongshu/app/src/blocks/Phase3InteractBlock.ts +2 -3
  168. package/modules/xiaohongshu/app/src/blocks/helpers/sharding.ts +152 -0
  169. package/package.json +13 -4
  170. package/scripts/postinstall-resources.mjs +62 -0
  171. package/scripts/test/run-coverage.mjs +76 -0
  172. package/scripts/weibo/search.ts +49 -0
  173. package/services/shared/serviceProcessLogger.ts +1 -1
  174. package/services/unified-api/server.ts +98 -12
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ /**
3
+ * File storage utilities for collection data
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.CollectionStorage = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ class CollectionStorage {
43
+ baseDir;
44
+ collectionDir;
45
+ platform;
46
+ env;
47
+ collectionId;
48
+ constructor(baseDir, platform, env, collectionId) {
49
+ this.baseDir = baseDir;
50
+ this.platform = platform;
51
+ this.env = env;
52
+ this.collectionId = collectionId;
53
+ // Directory structure: baseDir/platform/env/collectionId/
54
+ this.collectionDir = path.join(baseDir, platform, env, collectionId);
55
+ }
56
+ /**
57
+ * Initialize storage directories
58
+ */
59
+ async init() {
60
+ await fs.promises.mkdir(this.collectionDir, { recursive: true });
61
+ }
62
+ /**
63
+ * Get paths for different files
64
+ */
65
+ getMetaPath() {
66
+ return path.join(this.collectionDir, 'collection-meta.json');
67
+ }
68
+ getPostsPath() {
69
+ return path.join(this.collectionDir, 'posts.jsonl');
70
+ }
71
+ getCommentsPath() {
72
+ return path.join(this.collectionDir, 'comments.jsonl');
73
+ }
74
+ getLinksPath() {
75
+ return path.join(this.collectionDir, 'links.jsonl');
76
+ }
77
+ getRunLogPath() {
78
+ return path.join(this.collectionDir, 'run.log');
79
+ }
80
+ getEventsPath() {
81
+ return path.join(this.collectionDir, 'run-events.jsonl');
82
+ }
83
+ /**
84
+ * Read/write meta
85
+ */
86
+ async readMeta() {
87
+ const metaPath = this.getMetaPath();
88
+ try {
89
+ const data = await fs.promises.readFile(metaPath, 'utf-8');
90
+ return JSON.parse(data);
91
+ }
92
+ catch {
93
+ return null;
94
+ }
95
+ }
96
+ async writeMeta(meta) {
97
+ const metaPath = this.getMetaPath();
98
+ await fs.promises.writeFile(metaPath, JSON.stringify(meta, null, 2), 'utf-8');
99
+ }
100
+ /**
101
+ * Append post to JSONL
102
+ */
103
+ async appendPost(post) {
104
+ const line = JSON.stringify(post) + '\n';
105
+ await fs.promises.appendFile(this.getPostsPath(), line, 'utf-8');
106
+ }
107
+ /**
108
+ * Append comment to JSONL
109
+ */
110
+ async appendComment(comment) {
111
+ const line = JSON.stringify(comment) + '\n';
112
+ await fs.promises.appendFile(this.getCommentsPath(), line, 'utf-8');
113
+ }
114
+ /**
115
+ * Read all posts
116
+ */
117
+ async readPosts() {
118
+ try {
119
+ const data = await fs.promises.readFile(this.getPostsPath(), 'utf-8');
120
+ return data.trim().split('\n').map(line => JSON.parse(line));
121
+ }
122
+ catch {
123
+ return [];
124
+ }
125
+ }
126
+ /**
127
+ * Read all comments
128
+ */
129
+ async readComments() {
130
+ try {
131
+ const data = await fs.promises.readFile(this.getCommentsPath(), 'utf-8');
132
+ return data.trim().split('\n').map(line => JSON.parse(line));
133
+ }
134
+ catch {
135
+ return [];
136
+ }
137
+ }
138
+ /**
139
+ * Count lines in JSONL file
140
+ */
141
+ async countLines(filePath) {
142
+ try {
143
+ const data = await fs.promises.readFile(filePath, 'utf-8');
144
+ return data.trim().split('\n').filter(line => line.length > 0).length;
145
+ }
146
+ catch {
147
+ return 0;
148
+ }
149
+ }
150
+ /**
151
+ * Get collection stats
152
+ */
153
+ async getStats() {
154
+ return {
155
+ postCount: await this.countLines(this.getPostsPath()),
156
+ commentCount: await this.countLines(this.getCommentsPath())
157
+ };
158
+ }
159
+ /**
160
+ * Clear all collection data (for fresh mode)
161
+ */
162
+ async clear() {
163
+ const files = [
164
+ this.getPostsPath(),
165
+ this.getCommentsPath(),
166
+ this.getLinksPath(),
167
+ this.getEventsPath()
168
+ ];
169
+ for (const file of files) {
170
+ try {
171
+ await fs.promises.unlink(file);
172
+ }
173
+ catch {
174
+ // File might not exist
175
+ }
176
+ }
177
+ }
178
+ /**
179
+ * List all collections for a platform/env
180
+ */
181
+ static async listCollections(baseDir, platform, env) {
182
+ const dir = path.join(baseDir, platform, env);
183
+ try {
184
+ const entries = await fs.promises.readdir(dir, { withFileTypes: true });
185
+ return entries
186
+ .filter(e => e.isDirectory())
187
+ .map(e => e.name);
188
+ }
189
+ catch {
190
+ return [];
191
+ }
192
+ }
193
+ }
194
+ exports.CollectionStorage = CollectionStorage;
195
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ /** Collection types for unified data management across platforms */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.buildCollectionId = buildCollectionId;
5
+ exports.parseCollectionId = parseCollectionId;
6
+ /**
7
+ * Build collection ID from spec
8
+ */
9
+ function buildCollectionId(spec) {
10
+ switch (spec.source) {
11
+ case 'search':
12
+ return `search:${spec.keyword}`;
13
+ case 'timeline':
14
+ return `timeline:${spec.date}`;
15
+ case 'user':
16
+ const safeName = spec.userName?.replace(/[\/\\:*?"<>|]/g, '_') || 'unknown';
17
+ return `user:${spec.userId}:${safeName}`;
18
+ case 'note':
19
+ return `note:${spec.noteId}`;
20
+ case 'product':
21
+ return `product:${spec.keyword}`;
22
+ }
23
+ }
24
+ /**
25
+ * Parse collection ID back to spec
26
+ */
27
+ function parseCollectionId(id) {
28
+ const parts = id.split(':');
29
+ if (parts.length < 2)
30
+ return null;
31
+ const source = parts[0];
32
+ switch (source) {
33
+ case 'search':
34
+ return { source: 'search', keyword: parts.slice(1).join(':') };
35
+ case 'timeline':
36
+ return { source: 'timeline', date: parts[1] };
37
+ case 'user':
38
+ return { source: 'user', userId: parts[1], userName: parts[2] };
39
+ case 'note':
40
+ return { source: 'note', noteId: parts[1] };
41
+ case 'product':
42
+ return { source: 'product', keyword: parts.slice(1).join(':') };
43
+ default:
44
+ return null;
45
+ }
46
+ }
47
+ //# sourceMappingURL=types.js.map
@@ -36,7 +36,7 @@ export function logDebug(module, event, data = {}) {
36
36
  data,
37
37
  };
38
38
  try {
39
- fs.appendFileSync(DEBUG_LOG_FILE, `${JSON.stringify(entry)}\n`);
39
+ fs.appendFileSync(DEBUG_LOG_FILE, `${JSON.stringify(entry)}\n`, 'utf8');
40
40
  }
41
41
  catch {
42
42
  // ignore
@@ -0,0 +1,230 @@
1
+ /**
2
+ * ProcessRegistry - 进程生命周期管理
3
+ */
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { promises as fs } from 'node:fs';
7
+ import { execSync } from 'node:child_process';
8
+ const DEFAULT_CONFIG = {
9
+ heartbeatIntervalMs: 30000,
10
+ staleTimeoutMs: 120000,
11
+ cleanupIntervalMs: 60000,
12
+ };
13
+ function resolveRegistryPath() {
14
+ const home = process.env.HOME || process.env.USERPROFILE || os.homedir();
15
+ return path.join(home, '.webauto', 'process-registry.json');
16
+ }
17
+ export class ProcessRegistry {
18
+ static instance = null;
19
+ entries = new Map();
20
+ registryPath;
21
+ config;
22
+ ownPid;
23
+ heartbeatTimer = null;
24
+ cleanupTimer = null;
25
+ initialized = false;
26
+ shutdownHandlersRegistered = false;
27
+ constructor(config = {}) {
28
+ this.config = { ...DEFAULT_CONFIG, ...config };
29
+ this.registryPath = resolveRegistryPath();
30
+ this.ownPid = process.pid;
31
+ }
32
+ static getInstance(config) {
33
+ if (!ProcessRegistry.instance) {
34
+ ProcessRegistry.instance = new ProcessRegistry(config);
35
+ }
36
+ return ProcessRegistry.instance;
37
+ }
38
+ async init() {
39
+ if (this.initialized)
40
+ return;
41
+ try {
42
+ const content = await fs.readFile(this.registryPath, 'utf-8');
43
+ const data = JSON.parse(content);
44
+ for (const entry of Object.values(data)) {
45
+ this.entries.set(entry.pid, entry);
46
+ }
47
+ console.log('[ProcessRegistry] Loaded', this.entries.size, 'entries');
48
+ }
49
+ catch {
50
+ // 无记录
51
+ }
52
+ this.startCleanupTimer();
53
+ this.initialized = true;
54
+ }
55
+ async register(type, profileId, metadata) {
56
+ await this.init();
57
+ const entry = {
58
+ pid: this.ownPid,
59
+ type,
60
+ profileId,
61
+ keyword: metadata?.keyword,
62
+ startedAt: Date.now(),
63
+ lastHeartbeat: Date.now(),
64
+ status: 'running',
65
+ metadata,
66
+ };
67
+ this.entries.set(this.ownPid, entry);
68
+ await this.persist();
69
+ console.log(`[ProcessRegistry] Registered: pid=${this.ownPid} type=${type} profile=${profileId}`);
70
+ this.startHeartbeat();
71
+ // 注册一次 exit 处理器
72
+ if (!this.shutdownHandlersRegistered) {
73
+ this.registerShutdownHandlers();
74
+ this.shutdownHandlersRegistered = true;
75
+ }
76
+ return this.ownPid;
77
+ }
78
+ registerShutdownHandlers() {
79
+ const handler = async () => {
80
+ await this.unregister();
81
+ };
82
+ process.once('SIGINT', handler);
83
+ process.once('SIGTERM', handler);
84
+ process.once('beforeExit', handler);
85
+ }
86
+ heartbeat() {
87
+ const entry = this.entries.get(this.ownPid);
88
+ if (entry) {
89
+ entry.lastHeartbeat = Date.now();
90
+ entry.status = 'running';
91
+ this.persist().catch(() => { });
92
+ }
93
+ }
94
+ async unregister() {
95
+ if (!this.entries.has(this.ownPid))
96
+ return;
97
+ this.stopHeartbeat();
98
+ this.entries.delete(this.ownPid);
99
+ await this.persist();
100
+ console.log(`[ProcessRegistry] Unregistered: pid=${this.ownPid}`);
101
+ }
102
+ getAll() {
103
+ return Array.from(this.entries.values());
104
+ }
105
+ getRunning() {
106
+ return this.getAll().filter(e => e.status === 'running');
107
+ }
108
+ async cleanStale() {
109
+ await this.init();
110
+ const now = Date.now();
111
+ const cleaned = [];
112
+ for (const [pid, entry] of this.entries) {
113
+ if (pid === this.ownPid)
114
+ continue;
115
+ if (now - entry.lastHeartbeat > this.config.staleTimeoutMs) {
116
+ entry.status = 'stale';
117
+ const isAlive = this.isProcessAlive(pid);
118
+ if (!isAlive) {
119
+ this.entries.delete(pid);
120
+ cleaned.push(`pid=${pid} (dead)`);
121
+ await this.cleanupBrowserSession(entry.profileId);
122
+ }
123
+ else {
124
+ console.log(`[ProcessRegistry] Killing stale process: pid=${pid} type=${entry.type}`);
125
+ this.killProcess(pid);
126
+ this.entries.delete(pid);
127
+ cleaned.push(`pid=${pid} (killed)`);
128
+ await this.cleanupBrowserSession(entry.profileId);
129
+ }
130
+ }
131
+ }
132
+ if (cleaned.length > 0) {
133
+ await this.persist();
134
+ console.log(`[ProcessRegistry] Cleaned ${cleaned.length} stale entries`);
135
+ }
136
+ return { cleaned: cleaned.length, killed: cleaned };
137
+ }
138
+ getStatus() {
139
+ const entry = this.entries.get(this.ownPid);
140
+ if (!entry)
141
+ return null;
142
+ return {
143
+ pid: entry.pid,
144
+ type: entry.type,
145
+ profileId: entry.profileId,
146
+ uptime: Date.now() - entry.startedAt,
147
+ };
148
+ }
149
+ startHeartbeat() {
150
+ if (this.heartbeatTimer)
151
+ return;
152
+ this.heartbeatTimer = setInterval(() => {
153
+ this.heartbeat();
154
+ }, this.config.heartbeatIntervalMs);
155
+ this.heartbeatTimer.unref();
156
+ }
157
+ stopHeartbeat() {
158
+ if (this.heartbeatTimer) {
159
+ clearInterval(this.heartbeatTimer);
160
+ this.heartbeatTimer = null;
161
+ }
162
+ }
163
+ startCleanupTimer() {
164
+ if (this.cleanupTimer)
165
+ return;
166
+ this.cleanupTimer = setInterval(() => {
167
+ this.cleanStale().catch(() => { });
168
+ }, this.config.cleanupIntervalMs);
169
+ this.cleanupTimer.unref();
170
+ }
171
+ isProcessAlive(pid) {
172
+ try {
173
+ process.kill(pid, 0);
174
+ return true;
175
+ }
176
+ catch {
177
+ return false;
178
+ }
179
+ }
180
+ killProcess(pid) {
181
+ try {
182
+ if (process.platform === 'win32') {
183
+ execSync(`taskkill /PID ${pid} /T /F`, { stdio: 'ignore' });
184
+ }
185
+ else {
186
+ process.kill(pid, 'SIGTERM');
187
+ setTimeout(() => {
188
+ if (this.isProcessAlive(pid)) {
189
+ try {
190
+ process.kill(pid, 'SIGKILL');
191
+ }
192
+ catch { }
193
+ }
194
+ }, 5000);
195
+ }
196
+ }
197
+ catch { }
198
+ }
199
+ async cleanupBrowserSession(profileId) {
200
+ try {
201
+ execSync(`camo stop ${profileId}`, { stdio: 'ignore', timeout: 10000 });
202
+ console.log(`[ProcessRegistry] Cleaned browser: ${profileId}`);
203
+ }
204
+ catch { }
205
+ }
206
+ async persist() {
207
+ try {
208
+ const dir = path.dirname(this.registryPath);
209
+ await fs.mkdir(dir, { recursive: true });
210
+ const data = {};
211
+ for (const [pid, entry] of this.entries) {
212
+ data[pid] = entry;
213
+ }
214
+ await fs.writeFile(this.registryPath, JSON.stringify(data, null, 2), 'utf-8');
215
+ }
216
+ catch (err) {
217
+ console.error('[ProcessRegistry] Failed to persist:', err);
218
+ }
219
+ }
220
+ async shutdown() {
221
+ this.stopHeartbeat();
222
+ if (this.cleanupTimer) {
223
+ clearInterval(this.cleanupTimer);
224
+ this.cleanupTimer = null;
225
+ }
226
+ await this.unregister();
227
+ }
228
+ }
229
+ export const processRegistry = ProcessRegistry.getInstance();
230
+ //# sourceMappingURL=index.js.map