@web-auto/camo 0.1.3 → 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 (50) hide show
  1. package/README.md +137 -0
  2. package/package.json +2 -1
  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 +185 -79
  19. package/src/commands/autoscript.mjs +1100 -0
  20. package/src/commands/browser.mjs +20 -4
  21. package/src/commands/container.mjs +298 -75
  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 +165 -24
  26. package/src/container/element-filter.mjs +51 -5
  27. package/src/container/runtime-core/checkpoint.mjs +195 -0
  28. package/src/container/runtime-core/index.mjs +21 -0
  29. package/src/container/runtime-core/operations/index.mjs +351 -0
  30. package/src/container/runtime-core/operations/selector-scripts.mjs +68 -0
  31. package/src/container/runtime-core/operations/tab-pool.mjs +544 -0
  32. package/src/container/runtime-core/operations/viewport.mjs +143 -0
  33. package/src/container/runtime-core/subscription.mjs +87 -0
  34. package/src/container/runtime-core/utils.mjs +94 -0
  35. package/src/container/runtime-core/validation.mjs +127 -0
  36. package/src/container/runtime-core.mjs +1 -0
  37. package/src/container/subscription-registry.mjs +459 -0
  38. package/src/core/actions.mjs +573 -0
  39. package/src/core/browser.mjs +270 -0
  40. package/src/core/index.mjs +53 -0
  41. package/src/core/utils.mjs +87 -0
  42. package/src/events/daemon-entry.mjs +33 -0
  43. package/src/events/daemon.mjs +80 -0
  44. package/src/events/progress-log.mjs +109 -0
  45. package/src/events/ws-server.mjs +239 -0
  46. package/src/lib/client.mjs +8 -5
  47. package/src/lifecycle/session-registry.mjs +8 -4
  48. package/src/lifecycle/session-watchdog.mjs +220 -0
  49. package/src/utils/browser-service.mjs +232 -9
  50. package/src/utils/help.mjs +26 -3
package/src/cli.mjs CHANGED
@@ -12,6 +12,8 @@ import { handleWindowCommand } from './commands/window.mjs';
12
12
  import { handleMouseCommand } from './commands/mouse.mjs';
13
13
  import { handleSystemCommand } from './commands/system.mjs';
14
14
  import { handleContainerCommand } from './commands/container.mjs';
15
+ import { handleAutoscriptCommand } from './commands/autoscript.mjs';
16
+ import { handleEventsCommand } from './commands/events.mjs';
15
17
  import {
16
18
  handleStartCommand, handleStopCommand, handleStatusCommand,
17
19
  handleGotoCommand, handleBackCommand, handleScreenshotCommand,
@@ -24,10 +26,88 @@ import {
24
26
  handleCleanupCommand, handleForceStopCommand, handleLockCommand,
25
27
  handleUnlockCommand, handleSessionsCommand
26
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';
27
32
 
28
33
  const CURRENT_DIR = path.dirname(fileURLToPath(import.meta.url));
29
34
  const START_SCRIPT_REL = path.join('runtime', 'infra', 'utils', 'scripts', 'service', 'start-browser-service.mjs');
30
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
+
31
111
  async function handleConfigCommand(args) {
32
112
  const sub = args[1];
33
113
  if (sub !== 'repo-root') {
@@ -60,6 +140,20 @@ async function main() {
60
140
  return;
61
141
  }
62
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
+
63
157
  if (cmd === 'profiles') {
64
158
  const profiles = listProfiles();
65
159
  const defaultProfile = getDefaultProfile();
@@ -68,53 +162,63 @@ async function main() {
68
162
  }
69
163
 
70
164
  if (cmd === 'profile') {
71
- await handleProfileCommand(args);
165
+ await runTrackedCommand(cmd, args, () => handleProfileCommand(args));
72
166
  return;
73
167
  }
74
168
 
75
169
  if (cmd === 'config') {
76
- await handleConfigCommand(args);
170
+ await runTrackedCommand(cmd, args, () => handleConfigCommand(args));
77
171
  return;
78
172
  }
79
173
 
80
174
  if (cmd === 'init') {
81
- await handleInitCommand(args);
175
+ await runTrackedCommand(cmd, args, () => handleInitCommand(args));
82
176
  return;
83
177
  }
84
178
 
85
179
  if (cmd === 'create') {
86
- 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));
87
186
  return;
88
187
  }
89
188
 
90
189
  // Lifecycle commands
91
190
  if (cmd === 'cleanup') {
92
- await handleCleanupCommand(args);
191
+ await runTrackedCommand(cmd, args, () => handleCleanupCommand(args));
93
192
  return;
94
193
  }
95
194
 
96
195
  if (cmd === 'force-stop') {
97
- await handleForceStopCommand(args);
196
+ await runTrackedCommand(cmd, args, () => handleForceStopCommand(args));
98
197
  return;
99
198
  }
100
199
 
101
200
  if (cmd === 'lock') {
102
- await handleLockCommand(args);
201
+ await runTrackedCommand(cmd, args, () => handleLockCommand(args));
103
202
  return;
104
203
  }
105
204
 
106
205
  if (cmd === 'unlock') {
107
- await handleUnlockCommand(args);
206
+ await runTrackedCommand(cmd, args, () => handleUnlockCommand(args));
108
207
  return;
109
208
  }
110
209
 
111
210
  if (cmd === 'sessions') {
112
- await handleSessionsCommand(args);
211
+ await runTrackedCommand(cmd, args, () => handleSessionsCommand(args));
113
212
  return;
114
213
  }
115
214
 
116
215
  if (cmd === 'container') {
117
- await handleContainerCommand(args);
216
+ await runTrackedCommand(cmd, args, () => handleContainerCommand(args));
217
+ return;
218
+ }
219
+
220
+ if (cmd === 'autoscript') {
221
+ await runTrackedCommand(cmd, args, () => handleAutoscriptCommand(args));
118
222
  return;
119
223
  }
120
224
 
@@ -122,81 +226,83 @@ async function main() {
122
226
  'start', 'stop', 'close', 'status', 'list', 'goto', 'navigate', 'back', 'screenshot',
123
227
  'new-page', 'close-page', 'switch-page', 'list-pages', 'shutdown',
124
228
  'scroll', 'click', 'type', 'highlight', 'clear-highlight', 'viewport',
125
- 'cookies', 'window', 'mouse', 'system', 'container',
229
+ 'cookies', 'window', 'mouse', 'system', 'container', 'autoscript', 'events',
126
230
  ]);
127
231
 
128
232
  if (!serviceCommands.has(cmd)) {
129
233
  throw new Error(`Unknown command: ${cmd}`);
130
234
  }
131
235
 
132
- switch (cmd) {
133
- case 'start':
134
- await handleStartCommand(args);
135
- break;
136
- case 'stop':
137
- case 'close':
138
- await handleStopCommand(args);
139
- break;
140
- case 'status':
141
- case 'list':
142
- await handleStatusCommand(args);
143
- break;
144
- case 'goto':
145
- case 'navigate':
146
- await handleGotoCommand(args);
147
- break;
148
- case 'back':
149
- await handleBackCommand(args);
150
- break;
151
- case 'screenshot':
152
- await handleScreenshotCommand(args);
153
- break;
154
- case 'scroll':
155
- await handleScrollCommand(args);
156
- break;
157
- case 'click':
158
- await handleClickCommand(args);
159
- break;
160
- case 'type':
161
- await handleTypeCommand(args);
162
- break;
163
- case 'highlight':
164
- await handleHighlightCommand(args);
165
- break;
166
- case 'clear-highlight':
167
- await handleClearHighlightCommand(args);
168
- break;
169
- case 'viewport':
170
- await handleViewportCommand(args);
171
- break;
172
- case 'new-page':
173
- await handleNewPageCommand(args);
174
- break;
175
- case 'close-page':
176
- await handleClosePageCommand(args);
177
- break;
178
- case 'switch-page':
179
- await handleSwitchPageCommand(args);
180
- break;
181
- case 'list-pages':
182
- await handleListPagesCommand(args);
183
- break;
184
- case 'shutdown':
185
- await handleShutdownCommand();
186
- break;
187
- case 'cookies':
188
- await handleCookiesCommand(args);
189
- break;
190
- case 'window':
191
- await handleWindowCommand(args);
192
- break;
193
- case 'mouse':
194
- await handleMouseCommand(args);
195
- break;
196
- case 'system':
197
- await handleSystemCommand(args);
198
- break;
199
- }
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
+ });
200
306
  }
201
307
 
202
308
  main().catch((err) => {