@web-auto/camo 0.2.0 → 0.2.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.
- package/LICENSE +21 -21
- package/README.md +586 -586
- package/bin/browser-service.mjs +11 -11
- package/bin/camo.mjs +22 -22
- package/package.json +48 -48
- package/scripts/build.mjs +19 -19
- package/scripts/bump-version.mjs +34 -34
- package/scripts/check-file-size.mjs +80 -80
- package/scripts/file-size-policy.json +12 -2
- package/scripts/install.mjs +76 -76
- package/scripts/release.sh +54 -54
- package/src/autoscript/action-providers/index.mjs +6 -6
- package/src/autoscript/impact-engine.mjs +78 -78
- package/src/autoscript/runtime.mjs +1017 -1017
- package/src/autoscript/schema.mjs +376 -376
- package/src/cli.mjs +405 -405
- package/src/commands/attach.mjs +141 -141
- package/src/commands/autoscript.mjs +1011 -1011
- package/src/commands/browser.mjs +1255 -1255
- package/src/commands/container.mjs +401 -401
- package/src/commands/cookies.mjs +69 -69
- package/src/commands/create.mjs +98 -98
- package/src/commands/devtools.mjs +349 -349
- package/src/commands/events.mjs +152 -152
- package/src/commands/highlight-mode.mjs +24 -24
- package/src/commands/init.mjs +68 -68
- package/src/commands/lifecycle.mjs +275 -275
- package/src/commands/mouse.mjs +45 -45
- package/src/commands/profile.mjs +46 -46
- package/src/commands/record.mjs +115 -115
- package/src/commands/system.mjs +14 -14
- package/src/commands/window.mjs +123 -123
- package/src/container/change-notifier.mjs +362 -362
- package/src/container/element-filter.mjs +143 -143
- package/src/container/index.mjs +3 -3
- package/src/container/runtime-core/checkpoint.mjs +209 -209
- package/src/container/runtime-core/index.mjs +21 -21
- package/src/container/runtime-core/operations/index.mjs +774 -774
- package/src/container/runtime-core/operations/selector-scripts.mjs +277 -277
- package/src/container/runtime-core/operations/tab-pool.mjs +746 -746
- package/src/container/runtime-core/operations/viewport.mjs +189 -189
- package/src/container/runtime-core/search.mjs +190 -190
- package/src/container/runtime-core/subscription.mjs +224 -224
- package/src/container/runtime-core/utils.mjs +94 -94
- package/src/container/runtime-core/validation.mjs +127 -127
- package/src/container/runtime-core.mjs +1 -1
- package/src/container/subscription-registry.mjs +459 -459
- package/src/core/actions.mjs +561 -561
- package/src/core/browser.mjs +266 -266
- package/src/core/index.mjs +52 -52
- package/src/core/utils.mjs +91 -91
- package/src/events/daemon-entry.mjs +33 -33
- package/src/events/daemon.mjs +80 -80
- package/src/events/progress-log.mjs +109 -109
- package/src/events/ws-server.mjs +239 -239
- package/src/lib/client.mjs +200 -200
- package/src/lifecycle/cleanup.mjs +83 -83
- package/src/lifecycle/lock.mjs +126 -126
- package/src/lifecycle/session-registry.mjs +279 -279
- package/src/lifecycle/session-view.mjs +76 -76
- package/src/lifecycle/session-watchdog.mjs +281 -281
- package/src/services/browser-service/index.js +671 -671
- package/src/services/browser-service/internal/BrowserSession.input.test.js +389 -389
- package/src/services/browser-service/internal/BrowserSession.js +325 -304
- package/src/services/browser-service/internal/ElementRegistry.js +60 -60
- package/src/services/browser-service/internal/ProfileLock.js +84 -84
- package/src/services/browser-service/internal/SessionManager.js +184 -184
- package/src/services/browser-service/internal/SessionManager.test.js +39 -39
- package/src/services/browser-service/internal/browser-session/cookies.js +144 -144
- package/src/services/browser-service/internal/browser-session/input-ops.js +222 -222
- package/src/services/browser-service/internal/browser-session/input-pipeline.js +144 -144
- package/src/services/browser-service/internal/browser-session/logging.js +46 -46
- package/src/services/browser-service/internal/browser-session/navigation.js +38 -38
- package/src/services/browser-service/internal/browser-session/page-hooks.js +442 -442
- package/src/services/browser-service/internal/browser-session/page-management.js +302 -302
- package/src/services/browser-service/internal/browser-session/page-management.test.js +148 -148
- package/src/services/browser-service/internal/browser-session/recording.js +198 -198
- package/src/services/browser-service/internal/browser-session/runtime-events.js +61 -61
- package/src/services/browser-service/internal/browser-session/session-core.js +84 -84
- package/src/services/browser-service/internal/browser-session/session-state.js +38 -38
- package/src/services/browser-service/internal/browser-session/types.js +14 -14
- package/src/services/browser-service/internal/browser-session/utils.js +95 -95
- package/src/services/browser-service/internal/browser-session/viewport-manager.js +46 -46
- package/src/services/browser-service/internal/browser-session/viewport.js +215 -215
- package/src/services/browser-service/internal/container-matcher.js +851 -851
- package/src/services/browser-service/internal/container-registry.js +182 -182
- package/src/services/browser-service/internal/engine-manager.js +259 -259
- package/src/services/browser-service/internal/fingerprint.js +203 -203
- package/src/services/browser-service/internal/heartbeat.js +137 -137
- package/src/services/browser-service/internal/logging.js +46 -46
- package/src/services/browser-service/internal/page-runtime/runtime.js +1317 -1317
- package/src/services/browser-service/internal/pageRuntime.js +28 -28
- package/src/services/browser-service/internal/runtimeInjector.js +31 -31
- package/src/services/browser-service/internal/service-process-logger.js +140 -140
- package/src/services/browser-service/internal/state-bus.js +45 -45
- package/src/services/browser-service/internal/storage-paths.js +42 -42
- package/src/services/browser-service/internal/ws-server.js +1194 -1194
- package/src/services/browser-service/internal/ws-server.test.js +58 -58
- package/src/services/browser-service/server.mjs +6 -6
- package/src/services/controller/cli-bridge.js +93 -93
- package/src/services/controller/container-index.js +50 -50
- package/src/services/controller/container-storage.js +36 -36
- package/src/services/controller/controller-actions.js +207 -207
- package/src/services/controller/controller.js +1138 -1138
- package/src/services/controller/selectors.js +54 -54
- package/src/services/controller/transport.js +125 -125
- package/src/utils/args.mjs +26 -26
- package/src/utils/browser-service.mjs +544 -544
- package/src/utils/command-log.mjs +64 -64
- package/src/utils/config.mjs +214 -214
- package/src/utils/fingerprint.mjs +181 -181
- package/src/utils/help.mjs +216 -216
- package/src/utils/js-policy.mjs +13 -13
- package/src/utils/ws-client.mjs +30 -30
package/src/lifecycle/lock.mjs
CHANGED
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Lock manager for browser session lifecycle
|
|
4
|
-
* Prevents multiple instances from conflicting
|
|
5
|
-
*/
|
|
6
|
-
import fs from 'node:fs';
|
|
7
|
-
import path from 'node:path';
|
|
8
|
-
import { CONFIG_DIR } from '../utils/config.mjs';
|
|
9
|
-
|
|
10
|
-
const LOCK_DIR = path.join(CONFIG_DIR, 'locks');
|
|
11
|
-
|
|
12
|
-
function ensureLockDir() {
|
|
13
|
-
if (!fs.existsSync(LOCK_DIR)) {
|
|
14
|
-
fs.mkdirSync(LOCK_DIR, { recursive: true });
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function getLockFile(profileId) {
|
|
19
|
-
return path.join(LOCK_DIR, `${profileId}.lock`);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function getLockInfo(profileId) {
|
|
23
|
-
const lockFile = getLockFile(profileId);
|
|
24
|
-
if (!fs.existsSync(lockFile)) return null;
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
const content = fs.readFileSync(lockFile, 'utf-8');
|
|
28
|
-
return JSON.parse(content);
|
|
29
|
-
} catch {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function acquireLock(profileId, sessionInfo = {}) {
|
|
35
|
-
ensureLockDir();
|
|
36
|
-
const lockFile = getLockFile(profileId);
|
|
37
|
-
|
|
38
|
-
const lockData = {
|
|
39
|
-
profileId,
|
|
40
|
-
pid: process.pid,
|
|
41
|
-
startTime: Date.now(),
|
|
42
|
-
...sessionInfo,
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
fs.writeFileSync(lockFile, JSON.stringify(lockData, null, 2));
|
|
46
|
-
return lockData;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function releaseLock(profileId) {
|
|
50
|
-
const lockFile = getLockFile(profileId);
|
|
51
|
-
try {
|
|
52
|
-
if (fs.existsSync(lockFile)) {
|
|
53
|
-
fs.unlinkSync(lockFile);
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
} catch {
|
|
57
|
-
// Ignore missing lock file or racing cleanup.
|
|
58
|
-
}
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function isLocked(profileId) {
|
|
63
|
-
const lockFile = getLockFile(profileId);
|
|
64
|
-
return fs.existsSync(lockFile);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function cleanupStaleLocks() {
|
|
68
|
-
ensureLockDir();
|
|
69
|
-
const files = fs.readdirSync(LOCK_DIR);
|
|
70
|
-
const now = Date.now();
|
|
71
|
-
const staleThreshold = 24 * 60 * 60 * 1000; // 24 hours
|
|
72
|
-
|
|
73
|
-
let cleaned = 0;
|
|
74
|
-
for (const file of files) {
|
|
75
|
-
if (!file.endsWith('.lock')) continue;
|
|
76
|
-
|
|
77
|
-
const lockFile = path.join(LOCK_DIR, file);
|
|
78
|
-
try {
|
|
79
|
-
const stats = fs.statSync(lockFile);
|
|
80
|
-
const age = now - stats.mtimeMs;
|
|
81
|
-
|
|
82
|
-
if (age > staleThreshold) {
|
|
83
|
-
fs.unlinkSync(lockFile);
|
|
84
|
-
cleaned++;
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const content = fs.readFileSync(lockFile, 'utf-8');
|
|
89
|
-
const lockData = JSON.parse(content);
|
|
90
|
-
|
|
91
|
-
// Check if process is still alive
|
|
92
|
-
if (lockData.pid) {
|
|
93
|
-
try {
|
|
94
|
-
process.kill(lockData.pid, 0); // Signal 0 checks existence
|
|
95
|
-
} catch {
|
|
96
|
-
// Process not running, lock is stale
|
|
97
|
-
fs.unlinkSync(lockFile);
|
|
98
|
-
cleaned++;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
} catch (err) {
|
|
102
|
-
// Corrupted lock file, remove it
|
|
103
|
-
try {
|
|
104
|
-
fs.unlinkSync(lockFile);
|
|
105
|
-
cleaned++;
|
|
106
|
-
} catch {}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return cleaned;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function listActiveLocks() {
|
|
114
|
-
ensureLockDir();
|
|
115
|
-
const files = fs.readdirSync(LOCK_DIR);
|
|
116
|
-
const locks = [];
|
|
117
|
-
|
|
118
|
-
for (const file of files) {
|
|
119
|
-
if (!file.endsWith('.lock')) continue;
|
|
120
|
-
const profileId = file.replace('.lock', '');
|
|
121
|
-
const info = getLockInfo(profileId);
|
|
122
|
-
if (info) locks.push({ profileId, ...info });
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return locks;
|
|
126
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Lock manager for browser session lifecycle
|
|
4
|
+
* Prevents multiple instances from conflicting
|
|
5
|
+
*/
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { CONFIG_DIR } from '../utils/config.mjs';
|
|
9
|
+
|
|
10
|
+
const LOCK_DIR = path.join(CONFIG_DIR, 'locks');
|
|
11
|
+
|
|
12
|
+
function ensureLockDir() {
|
|
13
|
+
if (!fs.existsSync(LOCK_DIR)) {
|
|
14
|
+
fs.mkdirSync(LOCK_DIR, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function getLockFile(profileId) {
|
|
19
|
+
return path.join(LOCK_DIR, `${profileId}.lock`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getLockInfo(profileId) {
|
|
23
|
+
const lockFile = getLockFile(profileId);
|
|
24
|
+
if (!fs.existsSync(lockFile)) return null;
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const content = fs.readFileSync(lockFile, 'utf-8');
|
|
28
|
+
return JSON.parse(content);
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function acquireLock(profileId, sessionInfo = {}) {
|
|
35
|
+
ensureLockDir();
|
|
36
|
+
const lockFile = getLockFile(profileId);
|
|
37
|
+
|
|
38
|
+
const lockData = {
|
|
39
|
+
profileId,
|
|
40
|
+
pid: process.pid,
|
|
41
|
+
startTime: Date.now(),
|
|
42
|
+
...sessionInfo,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
fs.writeFileSync(lockFile, JSON.stringify(lockData, null, 2));
|
|
46
|
+
return lockData;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function releaseLock(profileId) {
|
|
50
|
+
const lockFile = getLockFile(profileId);
|
|
51
|
+
try {
|
|
52
|
+
if (fs.existsSync(lockFile)) {
|
|
53
|
+
fs.unlinkSync(lockFile);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
} catch {
|
|
57
|
+
// Ignore missing lock file or racing cleanup.
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function isLocked(profileId) {
|
|
63
|
+
const lockFile = getLockFile(profileId);
|
|
64
|
+
return fs.existsSync(lockFile);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function cleanupStaleLocks() {
|
|
68
|
+
ensureLockDir();
|
|
69
|
+
const files = fs.readdirSync(LOCK_DIR);
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
const staleThreshold = 24 * 60 * 60 * 1000; // 24 hours
|
|
72
|
+
|
|
73
|
+
let cleaned = 0;
|
|
74
|
+
for (const file of files) {
|
|
75
|
+
if (!file.endsWith('.lock')) continue;
|
|
76
|
+
|
|
77
|
+
const lockFile = path.join(LOCK_DIR, file);
|
|
78
|
+
try {
|
|
79
|
+
const stats = fs.statSync(lockFile);
|
|
80
|
+
const age = now - stats.mtimeMs;
|
|
81
|
+
|
|
82
|
+
if (age > staleThreshold) {
|
|
83
|
+
fs.unlinkSync(lockFile);
|
|
84
|
+
cleaned++;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const content = fs.readFileSync(lockFile, 'utf-8');
|
|
89
|
+
const lockData = JSON.parse(content);
|
|
90
|
+
|
|
91
|
+
// Check if process is still alive
|
|
92
|
+
if (lockData.pid) {
|
|
93
|
+
try {
|
|
94
|
+
process.kill(lockData.pid, 0); // Signal 0 checks existence
|
|
95
|
+
} catch {
|
|
96
|
+
// Process not running, lock is stale
|
|
97
|
+
fs.unlinkSync(lockFile);
|
|
98
|
+
cleaned++;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
} catch (err) {
|
|
102
|
+
// Corrupted lock file, remove it
|
|
103
|
+
try {
|
|
104
|
+
fs.unlinkSync(lockFile);
|
|
105
|
+
cleaned++;
|
|
106
|
+
} catch {}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return cleaned;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function listActiveLocks() {
|
|
114
|
+
ensureLockDir();
|
|
115
|
+
const files = fs.readdirSync(LOCK_DIR);
|
|
116
|
+
const locks = [];
|
|
117
|
+
|
|
118
|
+
for (const file of files) {
|
|
119
|
+
if (!file.endsWith('.lock')) continue;
|
|
120
|
+
const profileId = file.replace('.lock', '');
|
|
121
|
+
const info = getLockInfo(profileId);
|
|
122
|
+
if (info) locks.push({ profileId, ...info });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return locks;
|
|
126
|
+
}
|