@web-auto/camo 0.1.2 → 0.1.4

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 (51) hide show
  1. package/README.md +137 -0
  2. package/package.json +7 -3
  3. package/scripts/check-file-size.mjs +80 -0
  4. package/scripts/file-size-policy.json +8 -0
  5. package/src/autoscript/action-providers/index.mjs +9 -0
  6. package/src/autoscript/action-providers/xhs/comments.mjs +412 -0
  7. package/src/autoscript/action-providers/xhs/common.mjs +77 -0
  8. package/src/autoscript/action-providers/xhs/detail.mjs +181 -0
  9. package/src/autoscript/action-providers/xhs/interaction.mjs +466 -0
  10. package/src/autoscript/action-providers/xhs/like-rules.mjs +57 -0
  11. package/src/autoscript/action-providers/xhs/persistence.mjs +167 -0
  12. package/src/autoscript/action-providers/xhs/search.mjs +174 -0
  13. package/src/autoscript/action-providers/xhs.mjs +133 -0
  14. package/src/autoscript/impact-engine.mjs +78 -0
  15. package/src/autoscript/runtime.mjs +1015 -0
  16. package/src/autoscript/schema.mjs +370 -0
  17. package/src/autoscript/xhs-unified-template.mjs +931 -0
  18. package/src/cli.mjs +190 -78
  19. package/src/commands/autoscript.mjs +1100 -0
  20. package/src/commands/browser.mjs +20 -4
  21. package/src/commands/container.mjs +401 -0
  22. package/src/commands/events.mjs +152 -0
  23. package/src/commands/lifecycle.mjs +17 -3
  24. package/src/commands/window.mjs +32 -1
  25. package/src/container/change-notifier.mjs +311 -0
  26. package/src/container/element-filter.mjs +143 -0
  27. package/src/container/index.mjs +3 -0
  28. package/src/container/runtime-core/checkpoint.mjs +195 -0
  29. package/src/container/runtime-core/index.mjs +21 -0
  30. package/src/container/runtime-core/operations/index.mjs +351 -0
  31. package/src/container/runtime-core/operations/selector-scripts.mjs +68 -0
  32. package/src/container/runtime-core/operations/tab-pool.mjs +544 -0
  33. package/src/container/runtime-core/operations/viewport.mjs +143 -0
  34. package/src/container/runtime-core/subscription.mjs +87 -0
  35. package/src/container/runtime-core/utils.mjs +94 -0
  36. package/src/container/runtime-core/validation.mjs +127 -0
  37. package/src/container/runtime-core.mjs +1 -0
  38. package/src/container/subscription-registry.mjs +459 -0
  39. package/src/core/actions.mjs +573 -0
  40. package/src/core/browser.mjs +270 -0
  41. package/src/core/index.mjs +53 -0
  42. package/src/core/utils.mjs +87 -0
  43. package/src/events/daemon-entry.mjs +33 -0
  44. package/src/events/daemon.mjs +80 -0
  45. package/src/events/progress-log.mjs +109 -0
  46. package/src/events/ws-server.mjs +239 -0
  47. package/src/lib/client.mjs +200 -0
  48. package/src/lifecycle/session-registry.mjs +8 -4
  49. package/src/lifecycle/session-watchdog.mjs +220 -0
  50. package/src/utils/browser-service.mjs +232 -9
  51. package/src/utils/help.mjs +28 -0
package/src/cli.mjs CHANGED
@@ -11,6 +11,9 @@ import { handleCookiesCommand } from './commands/cookies.mjs';
11
11
  import { handleWindowCommand } from './commands/window.mjs';
12
12
  import { handleMouseCommand } from './commands/mouse.mjs';
13
13
  import { handleSystemCommand } from './commands/system.mjs';
14
+ import { handleContainerCommand } from './commands/container.mjs';
15
+ import { handleAutoscriptCommand } from './commands/autoscript.mjs';
16
+ import { handleEventsCommand } from './commands/events.mjs';
14
17
  import {
15
18
  handleStartCommand, handleStopCommand, handleStatusCommand,
16
19
  handleGotoCommand, handleBackCommand, handleScreenshotCommand,
@@ -23,10 +26,88 @@ import {
23
26
  handleCleanupCommand, handleForceStopCommand, handleLockCommand,
24
27
  handleUnlockCommand, handleSessionsCommand
25
28
  } from './commands/lifecycle.mjs';
29
+ import { handleSessionWatchdogCommand } from './lifecycle/session-watchdog.mjs';
30
+ import { safeAppendProgressEvent } from './events/progress-log.mjs';
31
+ import { ensureProgressEventDaemon } from './events/daemon.mjs';
26
32
 
27
33
  const CURRENT_DIR = path.dirname(fileURLToPath(import.meta.url));
28
34
  const START_SCRIPT_REL = path.join('runtime', 'infra', 'utils', 'scripts', 'service', 'start-browser-service.mjs');
29
35
 
36
+ function readFlagValue(args, names) {
37
+ for (let i = 0; i < args.length; i += 1) {
38
+ if (!names.includes(args[i])) continue;
39
+ const value = args[i + 1];
40
+ if (!value || String(value).startsWith('-')) return null;
41
+ return value;
42
+ }
43
+ return null;
44
+ }
45
+
46
+ function inferProfileId(cmd, args) {
47
+ const explicitProfile = readFlagValue(args, ['--profile', '-p']);
48
+ if (explicitProfile) return explicitProfile;
49
+ const positionals = args.slice(1).filter((item) => item && !String(item).startsWith('-'));
50
+ if (positionals.length === 0) return null;
51
+
52
+ if ([
53
+ 'start', 'stop', 'status', 'list', 'goto', 'navigate', 'back', 'screenshot',
54
+ 'scroll', 'click', 'type', 'highlight', 'clear-highlight', 'viewport',
55
+ 'new-page', 'close-page', 'switch-page', 'list-pages',
56
+ 'cleanup', 'force-stop', 'lock', 'unlock', 'sessions',
57
+ ].includes(cmd)) {
58
+ return positionals[0] || null;
59
+ }
60
+
61
+ if (cmd === 'autoscript' && positionals[0] === 'run') {
62
+ return explicitProfile || null;
63
+ }
64
+
65
+ if (cmd === 'container' && ['watch', 'filter', 'list', 'targets', 'register'].includes(positionals[0])) {
66
+ return positionals[1] || null;
67
+ }
68
+
69
+ return null;
70
+ }
71
+
72
+ async function runTrackedCommand(cmd, args, fn) {
73
+ const startedAt = Date.now();
74
+ const profileId = inferProfileId(cmd, args);
75
+ safeAppendProgressEvent({
76
+ source: 'cli.command',
77
+ mode: cmd === 'autoscript' ? 'autoscript' : 'normal',
78
+ profileId,
79
+ event: 'cli.command_start',
80
+ payload: { cmd, args: args.slice(1), startedAt },
81
+ });
82
+ try {
83
+ const result = await fn();
84
+ safeAppendProgressEvent({
85
+ source: 'cli.command',
86
+ mode: cmd === 'autoscript' ? 'autoscript' : 'normal',
87
+ profileId,
88
+ event: 'cli.command_done',
89
+ payload: { cmd, args: args.slice(1), startedAt, endedAt: Date.now(), durationMs: Date.now() - startedAt },
90
+ });
91
+ return result;
92
+ } catch (err) {
93
+ safeAppendProgressEvent({
94
+ source: 'cli.command',
95
+ mode: cmd === 'autoscript' ? 'autoscript' : 'normal',
96
+ profileId,
97
+ event: 'cli.command_error',
98
+ payload: {
99
+ cmd,
100
+ args: args.slice(1),
101
+ startedAt,
102
+ endedAt: Date.now(),
103
+ durationMs: Date.now() - startedAt,
104
+ error: err?.message || String(err),
105
+ },
106
+ });
107
+ throw err;
108
+ }
109
+ }
110
+
30
111
  async function handleConfigCommand(args) {
31
112
  const sub = args[1];
32
113
  if (sub !== 'repo-root') {
@@ -59,6 +140,20 @@ async function main() {
59
140
  return;
60
141
  }
61
142
 
143
+ if (cmd === '__session-watchdog') {
144
+ await handleSessionWatchdogCommand(args);
145
+ return;
146
+ }
147
+
148
+ const skipProgressAutoStart = new Set(['help', '--help', '-h', 'profiles', 'events', '__session-watchdog']);
149
+ if (!skipProgressAutoStart.has(cmd)) {
150
+ try {
151
+ await ensureProgressEventDaemon();
152
+ } catch {
153
+ // Progress daemon auto-start is best-effort and must not block command execution.
154
+ }
155
+ }
156
+
62
157
  if (cmd === 'profiles') {
63
158
  const profiles = listProfiles();
64
159
  const defaultProfile = getDefaultProfile();
@@ -67,48 +162,63 @@ async function main() {
67
162
  }
68
163
 
69
164
  if (cmd === 'profile') {
70
- await handleProfileCommand(args);
165
+ await runTrackedCommand(cmd, args, () => handleProfileCommand(args));
71
166
  return;
72
167
  }
73
168
 
74
169
  if (cmd === 'config') {
75
- await handleConfigCommand(args);
170
+ await runTrackedCommand(cmd, args, () => handleConfigCommand(args));
76
171
  return;
77
172
  }
78
173
 
79
174
  if (cmd === 'init') {
80
- await handleInitCommand(args);
175
+ await runTrackedCommand(cmd, args, () => handleInitCommand(args));
81
176
  return;
82
177
  }
83
178
 
84
179
  if (cmd === 'create') {
85
- await handleCreateCommand(args);
180
+ await runTrackedCommand(cmd, args, () => handleCreateCommand(args));
181
+ return;
182
+ }
183
+
184
+ if (cmd === 'events') {
185
+ await runTrackedCommand(cmd, args, () => handleEventsCommand(args));
86
186
  return;
87
187
  }
88
188
 
89
189
  // Lifecycle commands
90
190
  if (cmd === 'cleanup') {
91
- await handleCleanupCommand(args);
191
+ await runTrackedCommand(cmd, args, () => handleCleanupCommand(args));
92
192
  return;
93
193
  }
94
194
 
95
195
  if (cmd === 'force-stop') {
96
- await handleForceStopCommand(args);
196
+ await runTrackedCommand(cmd, args, () => handleForceStopCommand(args));
97
197
  return;
98
198
  }
99
199
 
100
200
  if (cmd === 'lock') {
101
- await handleLockCommand(args);
201
+ await runTrackedCommand(cmd, args, () => handleLockCommand(args));
102
202
  return;
103
203
  }
104
204
 
105
205
  if (cmd === 'unlock') {
106
- await handleUnlockCommand(args);
206
+ await runTrackedCommand(cmd, args, () => handleUnlockCommand(args));
107
207
  return;
108
208
  }
109
209
 
110
210
  if (cmd === 'sessions') {
111
- await handleSessionsCommand(args);
211
+ await runTrackedCommand(cmd, args, () => handleSessionsCommand(args));
212
+ return;
213
+ }
214
+
215
+ if (cmd === 'container') {
216
+ await runTrackedCommand(cmd, args, () => handleContainerCommand(args));
217
+ return;
218
+ }
219
+
220
+ if (cmd === 'autoscript') {
221
+ await runTrackedCommand(cmd, args, () => handleAutoscriptCommand(args));
112
222
  return;
113
223
  }
114
224
 
@@ -116,81 +226,83 @@ async function main() {
116
226
  'start', 'stop', 'close', 'status', 'list', 'goto', 'navigate', 'back', 'screenshot',
117
227
  'new-page', 'close-page', 'switch-page', 'list-pages', 'shutdown',
118
228
  'scroll', 'click', 'type', 'highlight', 'clear-highlight', 'viewport',
119
- 'cookies', 'window', 'mouse', 'system',
229
+ 'cookies', 'window', 'mouse', 'system', 'container', 'autoscript', 'events',
120
230
  ]);
121
231
 
122
232
  if (!serviceCommands.has(cmd)) {
123
233
  throw new Error(`Unknown command: ${cmd}`);
124
234
  }
125
235
 
126
- switch (cmd) {
127
- case 'start':
128
- await handleStartCommand(args);
129
- break;
130
- case 'stop':
131
- case 'close':
132
- await handleStopCommand(args);
133
- break;
134
- case 'status':
135
- case 'list':
136
- await handleStatusCommand(args);
137
- break;
138
- case 'goto':
139
- case 'navigate':
140
- await handleGotoCommand(args);
141
- break;
142
- case 'back':
143
- await handleBackCommand(args);
144
- break;
145
- case 'screenshot':
146
- await handleScreenshotCommand(args);
147
- break;
148
- case 'scroll':
149
- await handleScrollCommand(args);
150
- break;
151
- case 'click':
152
- await handleClickCommand(args);
153
- break;
154
- case 'type':
155
- await handleTypeCommand(args);
156
- break;
157
- case 'highlight':
158
- await handleHighlightCommand(args);
159
- break;
160
- case 'clear-highlight':
161
- await handleClearHighlightCommand(args);
162
- break;
163
- case 'viewport':
164
- await handleViewportCommand(args);
165
- break;
166
- case 'new-page':
167
- await handleNewPageCommand(args);
168
- break;
169
- case 'close-page':
170
- await handleClosePageCommand(args);
171
- break;
172
- case 'switch-page':
173
- await handleSwitchPageCommand(args);
174
- break;
175
- case 'list-pages':
176
- await handleListPagesCommand(args);
177
- break;
178
- case 'shutdown':
179
- await handleShutdownCommand();
180
- break;
181
- case 'cookies':
182
- await handleCookiesCommand(args);
183
- break;
184
- case 'window':
185
- await handleWindowCommand(args);
186
- break;
187
- case 'mouse':
188
- await handleMouseCommand(args);
189
- break;
190
- case 'system':
191
- await handleSystemCommand(args);
192
- break;
193
- }
236
+ await runTrackedCommand(cmd, args, async () => {
237
+ switch (cmd) {
238
+ case 'start':
239
+ await handleStartCommand(args);
240
+ break;
241
+ case 'stop':
242
+ case 'close':
243
+ await handleStopCommand(args);
244
+ break;
245
+ case 'status':
246
+ case 'list':
247
+ await handleStatusCommand(args);
248
+ break;
249
+ case 'goto':
250
+ case 'navigate':
251
+ await handleGotoCommand(args);
252
+ break;
253
+ case 'back':
254
+ await handleBackCommand(args);
255
+ break;
256
+ case 'screenshot':
257
+ await handleScreenshotCommand(args);
258
+ break;
259
+ case 'scroll':
260
+ await handleScrollCommand(args);
261
+ break;
262
+ case 'click':
263
+ await handleClickCommand(args);
264
+ break;
265
+ case 'type':
266
+ await handleTypeCommand(args);
267
+ break;
268
+ case 'highlight':
269
+ await handleHighlightCommand(args);
270
+ break;
271
+ case 'clear-highlight':
272
+ await handleClearHighlightCommand(args);
273
+ break;
274
+ case 'viewport':
275
+ await handleViewportCommand(args);
276
+ break;
277
+ case 'new-page':
278
+ await handleNewPageCommand(args);
279
+ break;
280
+ case 'close-page':
281
+ await handleClosePageCommand(args);
282
+ break;
283
+ case 'switch-page':
284
+ await handleSwitchPageCommand(args);
285
+ break;
286
+ case 'list-pages':
287
+ await handleListPagesCommand(args);
288
+ break;
289
+ case 'shutdown':
290
+ await handleShutdownCommand();
291
+ break;
292
+ case 'cookies':
293
+ await handleCookiesCommand(args);
294
+ break;
295
+ case 'window':
296
+ await handleWindowCommand(args);
297
+ break;
298
+ case 'mouse':
299
+ await handleMouseCommand(args);
300
+ break;
301
+ case 'system':
302
+ await handleSystemCommand(args);
303
+ break;
304
+ }
305
+ });
194
306
  }
195
307
 
196
308
  main().catch((err) => {