@framers/agentos-ext-browser-automation 0.1.0 → 0.2.1
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/README.md +80 -0
- package/dist/BrowserService.js +9 -45
- package/dist/BrowserService.js.map +1 -1
- package/dist/attach/AttachController.d.ts +183 -0
- package/dist/attach/AttachController.d.ts.map +1 -0
- package/dist/attach/AttachController.js +286 -0
- package/dist/attach/AttachController.js.map +1 -0
- package/dist/attach/backends/jxa.d.ts +39 -0
- package/dist/attach/backends/jxa.d.ts.map +1 -0
- package/dist/attach/backends/jxa.js +155 -0
- package/dist/attach/backends/jxa.js.map +1 -0
- package/dist/attach/backends/raw-cdp.d.ts +53 -0
- package/dist/attach/backends/raw-cdp.d.ts.map +1 -0
- package/dist/attach/backends/raw-cdp.js +213 -0
- package/dist/attach/backends/raw-cdp.js.map +1 -0
- package/dist/attach/daemon/client.d.ts +64 -0
- package/dist/attach/daemon/client.d.ts.map +1 -0
- package/dist/attach/daemon/client.js +120 -0
- package/dist/attach/daemon/client.js.map +1 -0
- package/dist/attach/daemon/daemon-lock.d.ts +19 -0
- package/dist/attach/daemon/daemon-lock.d.ts.map +1 -0
- package/dist/attach/daemon/daemon-lock.js +84 -0
- package/dist/attach/daemon/daemon-lock.js.map +1 -0
- package/dist/attach/daemon/daemon-main.d.ts +17 -0
- package/dist/attach/daemon/daemon-main.d.ts.map +1 -0
- package/dist/attach/daemon/daemon-main.js +99 -0
- package/dist/attach/daemon/daemon-main.js.map +1 -0
- package/dist/attach/daemon/daemon.d.ts +52 -0
- package/dist/attach/daemon/daemon.d.ts.map +1 -0
- package/dist/attach/daemon/daemon.js +273 -0
- package/dist/attach/daemon/daemon.js.map +1 -0
- package/dist/attach/daemon/index.d.ts +12 -0
- package/dist/attach/daemon/index.d.ts.map +1 -0
- package/dist/attach/daemon/index.js +12 -0
- package/dist/attach/daemon/index.js.map +1 -0
- package/dist/attach/daemon/protocol.d.ts +69 -0
- package/dist/attach/daemon/protocol.d.ts.map +1 -0
- package/dist/attach/daemon/protocol.js +96 -0
- package/dist/attach/daemon/protocol.js.map +1 -0
- package/dist/attach/daemon/runner.d.ts +64 -0
- package/dist/attach/daemon/runner.d.ts.map +1 -0
- package/dist/attach/daemon/runner.js +57 -0
- package/dist/attach/daemon/runner.js.map +1 -0
- package/dist/attach/daemon/surface.d.ts +31 -0
- package/dist/attach/daemon/surface.d.ts.map +1 -0
- package/dist/attach/daemon/surface.js +87 -0
- package/dist/attach/daemon/surface.js.map +1 -0
- package/dist/attach/devtools-port.d.ts +37 -0
- package/dist/attach/devtools-port.d.ts.map +1 -0
- package/dist/attach/devtools-port.js +47 -0
- package/dist/attach/devtools-port.js.map +1 -0
- package/dist/attach/errors.d.ts +38 -0
- package/dist/attach/errors.d.ts.map +1 -0
- package/dist/attach/errors.js +67 -0
- package/dist/attach/errors.js.map +1 -0
- package/dist/attach/lease.d.ts +43 -0
- package/dist/attach/lease.d.ts.map +1 -0
- package/dist/attach/lease.js +87 -0
- package/dist/attach/lease.js.map +1 -0
- package/dist/attach/singleton-lock.d.ts +21 -0
- package/dist/attach/singleton-lock.d.ts.map +1 -0
- package/dist/attach/singleton-lock.js +27 -0
- package/dist/attach/singleton-lock.js.map +1 -0
- package/dist/attach/state.d.ts +31 -0
- package/dist/attach/state.d.ts.map +1 -0
- package/dist/attach/state.js +71 -0
- package/dist/attach/state.js.map +1 -0
- package/dist/attach/tools.d.ts +208 -0
- package/dist/attach/tools.d.ts.map +1 -0
- package/dist/attach/tools.js +191 -0
- package/dist/attach/tools.js.map +1 -0
- package/dist/attach/url-policy.d.ts +41 -0
- package/dist/attach/url-policy.d.ts.map +1 -0
- package/dist/attach/url-policy.js +55 -0
- package/dist/attach/url-policy.js.map +1 -0
- package/dist/attach.d.ts +18 -0
- package/dist/attach.d.ts.map +1 -0
- package/dist/attach.js +18 -0
- package/dist/attach.js.map +1 -0
- package/dist/captcha/CaptchaSolver.js +4 -7
- package/dist/captcha/CaptchaSolver.js.map +1 -1
- package/dist/captcha/ICaptchaProvider.js +1 -2
- package/dist/captcha/ICaptchaProvider.js.map +1 -1
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -65
- package/dist/index.js.map +1 -1
- package/dist/proxy/IProxyProvider.js +1 -2
- package/dist/proxy/IProxyProvider.js.map +1 -1
- package/dist/proxy/ProxyManager.js +7 -10
- package/dist/proxy/ProxyManager.js.map +1 -1
- package/dist/tools/ClickTool.js +17 -20
- package/dist/tools/ClickTool.js.map +1 -1
- package/dist/tools/EvaluateTool.js +16 -19
- package/dist/tools/EvaluateTool.js.map +1 -1
- package/dist/tools/ExtractTool.js +23 -26
- package/dist/tools/ExtractTool.js.map +1 -1
- package/dist/tools/FillTool.js +17 -20
- package/dist/tools/FillTool.js.map +1 -1
- package/dist/tools/NavigateTool.js +31 -34
- package/dist/tools/NavigateTool.js.map +1 -1
- package/dist/tools/PageSnapshotTool.js +13 -16
- package/dist/tools/PageSnapshotTool.js.map +1 -1
- package/dist/tools/ScreenshotTool.js +16 -19
- package/dist/tools/ScreenshotTool.js.map +1 -1
- package/dist/tools/ScrollTool.js +17 -20
- package/dist/tools/ScrollTool.js.map +1 -1
- package/dist/tools/SessionTool.js +24 -27
- package/dist/tools/SessionTool.js.map +1 -1
- package/dist/tools/WaitTool.js +22 -25
- package/dist/tools/WaitTool.js.map +1 -1
- package/manifest.json +1 -1
- package/package.json +23 -7
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Runnable attach-daemon entry: `node .../daemon-main.js`.
|
|
3
|
+
*
|
|
4
|
+
* Spawned by `wunderland attach start` (and by autostart, exactly once).
|
|
5
|
+
* Reads WUNDERLAND_ATTACH_* env, builds RawCdpBackend + AttachController +
|
|
6
|
+
* AttachDaemon, runs until quit/SIGTERM. This process is the ONLY one that
|
|
7
|
+
* touches the network; every caller talks to it through files.
|
|
8
|
+
*
|
|
9
|
+
* @module browser-automation/attach/daemon/daemon-main
|
|
10
|
+
*/
|
|
11
|
+
import { realpathSync } from 'node:fs';
|
|
12
|
+
import { homedir } from 'node:os';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
import { AttachController } from '../AttachController.js';
|
|
16
|
+
import { RawCdpBackend } from '../backends/raw-cdp.js';
|
|
17
|
+
import { AttachDaemon } from './daemon.js';
|
|
18
|
+
import { resolveIpcDir, statusPath, writeAtomicJson, DEFAULT_PID_FILE } from './protocol.js';
|
|
19
|
+
/**
|
|
20
|
+
* Build and run the daemon from an environment map. Returns the process exit
|
|
21
|
+
* code (0 clean stop, 2 failure). Exported for tests and for the CLI.
|
|
22
|
+
*/
|
|
23
|
+
export async function main(env = process.env) {
|
|
24
|
+
const ipcDir = resolveIpcDir(undefined, env);
|
|
25
|
+
const fail = (msg) => {
|
|
26
|
+
writeAtomicJson(statusPath(ipcDir), { t: Date.now(), pid: process.pid, state: 'failed', lastError: msg });
|
|
27
|
+
console.error(`attach daemon: ${msg}`);
|
|
28
|
+
return 2;
|
|
29
|
+
};
|
|
30
|
+
// Node 22 floor: the raw-CDP transport is the built-in WebSocket. Guarded so
|
|
31
|
+
// an older runtime gets an actionable message, never a bare ReferenceError.
|
|
32
|
+
if (typeof WebSocket === 'undefined') {
|
|
33
|
+
return fail('this runtime has no built-in WebSocket; the attach daemon requires Node 22 or newer');
|
|
34
|
+
}
|
|
35
|
+
const expectedIdentity = env.WUNDERLAND_ATTACH_IDENTITY?.trim();
|
|
36
|
+
if (!expectedIdentity) {
|
|
37
|
+
return fail('WUNDERLAND_ATTACH_IDENTITY is required (the profile identity the daemon must verify)');
|
|
38
|
+
}
|
|
39
|
+
const backend = new RawCdpBackend({
|
|
40
|
+
profileRoot: env.WUNDERLAND_ATTACH_PROFILE_ROOT?.trim() || undefined,
|
|
41
|
+
identityProbeUrl: env.WUNDERLAND_ATTACH_PROBE_URL?.trim() || undefined,
|
|
42
|
+
settleMs: 0, // settle is applied daemon-side per goto op (default 1800ms)
|
|
43
|
+
});
|
|
44
|
+
const allowHosts = env.WUNDERLAND_ATTACH_HOSTS?.split(',')
|
|
45
|
+
.map((s) => s.trim())
|
|
46
|
+
.filter(Boolean);
|
|
47
|
+
const deadlineMs = Number(env.WUNDERLAND_ATTACH_DEADLINE_MS);
|
|
48
|
+
const controller = new AttachController({
|
|
49
|
+
backend,
|
|
50
|
+
// Mirrors the pack default in src/index.ts so CLI-started and pack-embedded
|
|
51
|
+
// sessions contend on the SAME lease file.
|
|
52
|
+
leaseFile: env.WUNDERLAND_ATTACH_LEASE?.trim() || join(homedir(), '.wunderland', 'attach.lease'),
|
|
53
|
+
expectedIdentity,
|
|
54
|
+
urlPolicy: allowHosts?.length ? { allowHosts } : undefined,
|
|
55
|
+
dryRun: env.WUNDERLAND_ATTACH_DRYRUN === '1' || env.WUNDERLAND_ATTACH_DRYRUN === 'true',
|
|
56
|
+
deadlineMs: Number.isFinite(deadlineMs) && deadlineMs > 0 ? deadlineMs : undefined,
|
|
57
|
+
});
|
|
58
|
+
const daemon = new AttachDaemon({
|
|
59
|
+
controller,
|
|
60
|
+
backend,
|
|
61
|
+
ipcDir,
|
|
62
|
+
pidFile: env.WUNDERLAND_ATTACH_PID_FILE?.trim() || DEFAULT_PID_FILE,
|
|
63
|
+
log: (line) => console.error(`[attach-daemon] ${line}`),
|
|
64
|
+
});
|
|
65
|
+
process.on('SIGTERM', () => daemon.requestStop('SIGTERM'));
|
|
66
|
+
process.on('SIGINT', () => daemon.requestStop('SIGINT'));
|
|
67
|
+
try {
|
|
68
|
+
await daemon.run();
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
return fail(err.message);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* True when `moduleUrl` is the script Node was started with (`node <entryPath>`).
|
|
77
|
+
*
|
|
78
|
+
* Both sides resolve to a real path before the comparison: a file URL
|
|
79
|
+
* percent-encodes characters such as spaces, Node follows symlinks when it
|
|
80
|
+
* builds `import.meta.url` for the entry script but keeps them under
|
|
81
|
+
* `--preserve-symlinks-main`, and the entry path may be relative. A missing
|
|
82
|
+
* or unreadable entry path, or a module URL that is not a file, is not this
|
|
83
|
+
* module. Exported for tests.
|
|
84
|
+
*/
|
|
85
|
+
export function isEntryPoint(moduleUrl, entryPath) {
|
|
86
|
+
if (!entryPath)
|
|
87
|
+
return false;
|
|
88
|
+
try {
|
|
89
|
+
return realpathSync(fileURLToPath(moduleUrl)) === realpathSync(entryPath);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Invoked directly (not imported): run and exit with the returned code.
|
|
96
|
+
if (isEntryPoint(import.meta.url, process.argv[1])) {
|
|
97
|
+
void main().then((code) => process.exit(code));
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=daemon-main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-main.js","sourceRoot":"","sources":["../../../src/attach/daemon/daemon-main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { AttachBackend, AttachController } from '../AttachController.js';
|
|
2
|
+
/** Constructor options. */
|
|
3
|
+
export interface AttachDaemonOptions {
|
|
4
|
+
controller: AttachController;
|
|
5
|
+
/** Same backend instance the controller wraps (boot connect + drop hook + identity cache). */
|
|
6
|
+
backend: AttachBackend & {
|
|
7
|
+
onUnexpectedClose?: ((err: Error) => void) | null;
|
|
8
|
+
};
|
|
9
|
+
ipcDir: string;
|
|
10
|
+
pidFile: string;
|
|
11
|
+
/** Loop tick ms (default 350). */
|
|
12
|
+
pollMs?: number;
|
|
13
|
+
/** Default claimant ttl ms (default 600000). */
|
|
14
|
+
claimTtlMs?: number;
|
|
15
|
+
log?: (line: string) => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* See fileoverview. `run()` resolves after a `quit` op or {@link requestStop}.
|
|
19
|
+
* Never launches, quits, or signals Chrome under any failure.
|
|
20
|
+
*/
|
|
21
|
+
export declare class AttachDaemon {
|
|
22
|
+
private readonly controller;
|
|
23
|
+
private readonly backend;
|
|
24
|
+
private readonly ipcDir;
|
|
25
|
+
private readonly pidFile;
|
|
26
|
+
private readonly pollMs;
|
|
27
|
+
private readonly claimTtlMs;
|
|
28
|
+
private readonly log;
|
|
29
|
+
private lock;
|
|
30
|
+
private state;
|
|
31
|
+
private lastError?;
|
|
32
|
+
private identity?;
|
|
33
|
+
private claimant;
|
|
34
|
+
private controllerClaimed;
|
|
35
|
+
private stopRequested;
|
|
36
|
+
private reconnectAt;
|
|
37
|
+
private backoffMs;
|
|
38
|
+
private gcCountdown;
|
|
39
|
+
constructor(opts: AttachDaemonOptions);
|
|
40
|
+
/** External stop (signal handlers route here). */
|
|
41
|
+
requestStop(reason: string): void;
|
|
42
|
+
/** Acquire the singleton, open the transport, serve the queue until quit. */
|
|
43
|
+
run(): Promise<void>;
|
|
44
|
+
private setState;
|
|
45
|
+
private heartbeat;
|
|
46
|
+
private expireClaimant;
|
|
47
|
+
private maybeReconnect;
|
|
48
|
+
private requireClaimant;
|
|
49
|
+
private execute;
|
|
50
|
+
private shutdown;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../../src/attach/daemon/daemon.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAgB9E,2BAA2B;AAC3B,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,8FAA8F;IAC9F,OAAO,EAAE,aAAa,GAAG;QAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAA;KAAE,CAAC;IAC/E,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAQD;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAyB;IAE7C,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAqE;IACrF,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,WAAW,CAAkB;gBAEzB,IAAI,EAAE,mBAAmB;IAUrC,kDAAkD;IAClD,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKjC,6EAA6E;IACvE,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAoD1B,OAAO,CAAC,QAAQ;IAMhB,OAAO,CAAC,SAAS;IAejB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,eAAe;YAOT,OAAO;YAuFP,QAAQ;CAgBvB"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The attach daemon: one process, one controller, one held session.
|
|
3
|
+
*
|
|
4
|
+
* Owns the file-queue loop. Consumes `cmd-*.json` oldest-first, executes ops
|
|
5
|
+
* SERIALLY against the hosted {@link AttachController} (the single policy
|
|
6
|
+
* enforcement point), writes `resp-<id>.json`, and heartbeats `status.json`
|
|
7
|
+
* every tick. Command files are deleted BEFORE execution (at-most-once: a
|
|
8
|
+
* crash mid-op must never replay a navigation on restart). Responses are
|
|
9
|
+
* deleted by their reader; strays age out via the periodic GC — shutdown does
|
|
10
|
+
* not bulk-sweep, because that would race a client still polling for the quit
|
|
11
|
+
* response.
|
|
12
|
+
*
|
|
13
|
+
* Two-layer claim model: the controller's lease belongs to this process for
|
|
14
|
+
* the daemon's lifetime; per-caller driving rights are daemon-level
|
|
15
|
+
* bookkeeping (`claimant`). `release` parks the tab and clears the claimant;
|
|
16
|
+
* only `quit` detaches the controller.
|
|
17
|
+
*
|
|
18
|
+
* @module browser-automation/attach/daemon/daemon
|
|
19
|
+
*/
|
|
20
|
+
import { unlinkSync } from 'node:fs';
|
|
21
|
+
import { AttachError, redactDiagnostic, toStructuredError } from '../errors.js';
|
|
22
|
+
import { acquireDaemonLock } from './daemon-lock.js';
|
|
23
|
+
import { resolveIpcDir, writeAtomicJson, readJson, listPendingCmds, gcStale, respPath, statusPath, } from './protocol.js';
|
|
24
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
25
|
+
const BACKOFF_START_MS = 5_000;
|
|
26
|
+
const BACKOFF_CAP_MS = 60_000;
|
|
27
|
+
/** Loop ticks between periodic GC passes (~35s at the default tick). */
|
|
28
|
+
const GC_EVERY_TICKS = 100;
|
|
29
|
+
/**
|
|
30
|
+
* See fileoverview. `run()` resolves after a `quit` op or {@link requestStop}.
|
|
31
|
+
* Never launches, quits, or signals Chrome under any failure.
|
|
32
|
+
*/
|
|
33
|
+
export class AttachDaemon {
|
|
34
|
+
controller;
|
|
35
|
+
backend;
|
|
36
|
+
ipcDir;
|
|
37
|
+
pidFile;
|
|
38
|
+
pollMs;
|
|
39
|
+
claimTtlMs;
|
|
40
|
+
log;
|
|
41
|
+
lock = null;
|
|
42
|
+
state = 'starting';
|
|
43
|
+
lastError;
|
|
44
|
+
identity;
|
|
45
|
+
claimant = null;
|
|
46
|
+
controllerClaimed = false;
|
|
47
|
+
stopRequested = false;
|
|
48
|
+
reconnectAt = 0;
|
|
49
|
+
backoffMs = BACKOFF_START_MS;
|
|
50
|
+
gcCountdown = GC_EVERY_TICKS;
|
|
51
|
+
constructor(opts) {
|
|
52
|
+
this.controller = opts.controller;
|
|
53
|
+
this.backend = opts.backend;
|
|
54
|
+
this.ipcDir = opts.ipcDir;
|
|
55
|
+
this.pidFile = opts.pidFile;
|
|
56
|
+
this.pollMs = opts.pollMs ?? 350;
|
|
57
|
+
this.claimTtlMs = opts.claimTtlMs ?? 600_000;
|
|
58
|
+
this.log = opts.log ?? (() => { });
|
|
59
|
+
}
|
|
60
|
+
/** External stop (signal handlers route here). */
|
|
61
|
+
requestStop(reason) {
|
|
62
|
+
this.log(`stop requested: ${reason}`);
|
|
63
|
+
this.stopRequested = true;
|
|
64
|
+
}
|
|
65
|
+
/** Acquire the singleton, open the transport, serve the queue until quit. */
|
|
66
|
+
async run() {
|
|
67
|
+
// Own the IPC dir: created here (0700) so embedders passing a raw path get
|
|
68
|
+
// a working daemon, and so the dir + a 'connecting' status.json both exist
|
|
69
|
+
// before run()'s first await returns control to the caller.
|
|
70
|
+
resolveIpcDir(this.ipcDir);
|
|
71
|
+
this.lock = acquireDaemonLock(this.pidFile);
|
|
72
|
+
try {
|
|
73
|
+
this.setState('connecting');
|
|
74
|
+
this.backend.onUnexpectedClose = (err) => {
|
|
75
|
+
this.setState('degraded', redactDiagnostic(err.message));
|
|
76
|
+
this.controllerClaimed = false;
|
|
77
|
+
this.claimant = null;
|
|
78
|
+
this.reconnectAt = Date.now() + this.backoffMs;
|
|
79
|
+
};
|
|
80
|
+
await this.backend.connect();
|
|
81
|
+
this.setState('connected');
|
|
82
|
+
while (!this.stopRequested) {
|
|
83
|
+
await sleep(this.pollMs);
|
|
84
|
+
this.heartbeat();
|
|
85
|
+
this.expireClaimant();
|
|
86
|
+
this.maybeReconnect();
|
|
87
|
+
if (--this.gcCountdown <= 0) {
|
|
88
|
+
gcStale(this.ipcDir);
|
|
89
|
+
this.gcCountdown = GC_EVERY_TICKS;
|
|
90
|
+
}
|
|
91
|
+
for (const pending of listPendingCmds(this.ipcDir)) {
|
|
92
|
+
const cmd = readJson(pending.path);
|
|
93
|
+
try {
|
|
94
|
+
unlinkSync(pending.path);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
/* consumed by a GC race */
|
|
98
|
+
}
|
|
99
|
+
if (!cmd || typeof cmd.id !== 'string' || typeof cmd.op !== 'string' || typeof cmd.client !== 'string') {
|
|
100
|
+
this.log(`malformed cmd file dropped: ${pending.path}`);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const resp = await this.execute(cmd);
|
|
104
|
+
writeAtomicJson(respPath(this.ipcDir, cmd.id), resp);
|
|
105
|
+
if (cmd.op === 'quit' && resp.ok) {
|
|
106
|
+
this.stopRequested = true;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
await this.shutdown();
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
this.lock?.release();
|
|
115
|
+
this.lock = null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
setState(state, lastError) {
|
|
119
|
+
this.state = state;
|
|
120
|
+
this.lastError = lastError;
|
|
121
|
+
this.heartbeat();
|
|
122
|
+
}
|
|
123
|
+
heartbeat() {
|
|
124
|
+
const cs = this.controller.status();
|
|
125
|
+
writeAtomicJson(statusPath(this.ipcDir), {
|
|
126
|
+
t: Date.now(),
|
|
127
|
+
pid: process.pid,
|
|
128
|
+
state: this.state,
|
|
129
|
+
targetId: cs.agentTab,
|
|
130
|
+
identity: this.identity,
|
|
131
|
+
claimant: this.claimant?.client,
|
|
132
|
+
paused: cs.paused,
|
|
133
|
+
dryRun: cs.dryRun,
|
|
134
|
+
lastError: this.lastError,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
expireClaimant() {
|
|
138
|
+
if (this.claimant && Date.now() > this.claimant.expiresAt) {
|
|
139
|
+
this.log(`claim ttl expired for ${this.claimant.client}; parking`);
|
|
140
|
+
this.claimant = null;
|
|
141
|
+
if (this.controllerClaimed) {
|
|
142
|
+
void this.controller.goto('about:blank').catch(() => {
|
|
143
|
+
/* park is best-effort */
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
maybeReconnect() {
|
|
149
|
+
if (this.state !== 'degraded' || Date.now() < this.reconnectAt)
|
|
150
|
+
return;
|
|
151
|
+
this.reconnectAt = Number.MAX_SAFE_INTEGER; // one attempt in flight
|
|
152
|
+
void this.backend
|
|
153
|
+
.connect()
|
|
154
|
+
.then(() => {
|
|
155
|
+
this.backoffMs = BACKOFF_START_MS;
|
|
156
|
+
this.setState('connected');
|
|
157
|
+
})
|
|
158
|
+
.catch(() => {
|
|
159
|
+
this.backoffMs = Math.min(this.backoffMs * 2, BACKOFF_CAP_MS);
|
|
160
|
+
this.reconnectAt = Date.now() + this.backoffMs;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
requireClaimant(cmd) {
|
|
164
|
+
if (!this.claimant || this.claimant.client !== cmd.client) {
|
|
165
|
+
throw new AttachError('NOT_CLAIMANT', 'no active claim for this client; send claim first');
|
|
166
|
+
}
|
|
167
|
+
this.claimant.expiresAt = Date.now() + this.claimant.ttlMs; // activity extends the ttl
|
|
168
|
+
}
|
|
169
|
+
async execute(cmd) {
|
|
170
|
+
const base = { id: cmd.id, op: cmd.op };
|
|
171
|
+
try {
|
|
172
|
+
const a = cmd.args ?? {};
|
|
173
|
+
switch (cmd.op) {
|
|
174
|
+
case 'ping':
|
|
175
|
+
return { ...base, ok: true, data: { pong: true, pid: process.pid } };
|
|
176
|
+
case 'status':
|
|
177
|
+
return {
|
|
178
|
+
...base,
|
|
179
|
+
ok: true,
|
|
180
|
+
data: {
|
|
181
|
+
...this.controller.status(),
|
|
182
|
+
daemonState: this.state,
|
|
183
|
+
identity: this.identity,
|
|
184
|
+
claimant: this.claimant?.client ?? null,
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
case 'claim': {
|
|
188
|
+
if (this.claimant && this.claimant.client !== cmd.client) {
|
|
189
|
+
throw new AttachError('LEASE_DENIED', `claimed by ${this.claimant.client}`);
|
|
190
|
+
}
|
|
191
|
+
if (!this.controllerClaimed) {
|
|
192
|
+
await this.controller.claim();
|
|
193
|
+
this.controllerClaimed = true;
|
|
194
|
+
this.identity = await this.backend.probeIdentity().catch(() => undefined);
|
|
195
|
+
}
|
|
196
|
+
const ttlMs = typeof a.ttlMs === 'number' && a.ttlMs > 0 ? a.ttlMs : this.claimTtlMs;
|
|
197
|
+
this.claimant = { client: cmd.client, ttlMs, expiresAt: Date.now() + ttlMs };
|
|
198
|
+
return { ...base, ok: true, data: { ...this.controller.status(), identity: this.identity } };
|
|
199
|
+
}
|
|
200
|
+
case 'goto': {
|
|
201
|
+
this.requireClaimant(cmd);
|
|
202
|
+
const landed = await this.controller.goto(String(a.url ?? ''));
|
|
203
|
+
const settle = typeof a.settle === 'number' && a.settle >= 0 ? a.settle : 1800;
|
|
204
|
+
if (settle > 0)
|
|
205
|
+
await sleep(settle);
|
|
206
|
+
return { ...base, ok: true, data: { url: landed } };
|
|
207
|
+
}
|
|
208
|
+
case 'read': {
|
|
209
|
+
this.requireClaimant(cmd);
|
|
210
|
+
const text = await this.controller.read(typeof a.selector === 'string' ? a.selector : undefined, typeof a.maxChars === 'number' ? a.maxChars : undefined);
|
|
211
|
+
return { ...base, ok: true, data: { untrusted: true, text } };
|
|
212
|
+
}
|
|
213
|
+
case 'extract': {
|
|
214
|
+
this.requireClaimant(cmd);
|
|
215
|
+
const data = await this.controller.extract(a.fields);
|
|
216
|
+
return { ...base, ok: true, data: { untrusted: true, data } };
|
|
217
|
+
}
|
|
218
|
+
case 'eval': {
|
|
219
|
+
this.requireClaimant(cmd);
|
|
220
|
+
const value = await this.controller.evaluate(String(a.expression ?? ''), typeof a.timeoutMs === 'number' ? a.timeoutMs : undefined);
|
|
221
|
+
return { ...base, ok: true, data: { untrusted: true, value } };
|
|
222
|
+
}
|
|
223
|
+
case 'release': {
|
|
224
|
+
this.requireClaimant(cmd);
|
|
225
|
+
this.claimant = null;
|
|
226
|
+
await this.controller.goto('about:blank').catch(() => {
|
|
227
|
+
/* park is best-effort */
|
|
228
|
+
});
|
|
229
|
+
return { ...base, ok: true, data: { released: true } };
|
|
230
|
+
}
|
|
231
|
+
case 'control': {
|
|
232
|
+
this.requireClaimant(cmd);
|
|
233
|
+
const action = String(a.action ?? 'status');
|
|
234
|
+
if (action === 'pause')
|
|
235
|
+
this.controller.pause();
|
|
236
|
+
else if (action === 'resume')
|
|
237
|
+
this.controller.resume();
|
|
238
|
+
else if (action === 'dry_run_on')
|
|
239
|
+
this.controller.setDryRun(true);
|
|
240
|
+
else if (action === 'dry_run_off')
|
|
241
|
+
this.controller.setDryRun(false);
|
|
242
|
+
return { ...base, ok: true, data: this.controller.status() };
|
|
243
|
+
}
|
|
244
|
+
case 'quit':
|
|
245
|
+
return { ...base, ok: true, data: { stopping: true } };
|
|
246
|
+
default:
|
|
247
|
+
throw new AttachError('UNSUPPORTED_OP', `unknown op ${String(cmd.op)}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
const s = toStructuredError(err);
|
|
252
|
+
return { ...base, ok: false, error: { code: s.code, message: s.message } };
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
async shutdown() {
|
|
256
|
+
if (this.controllerClaimed) {
|
|
257
|
+
await this.controller.goto('about:blank').catch(() => {
|
|
258
|
+
/* park best-effort */
|
|
259
|
+
});
|
|
260
|
+
await this.controller.detach().catch(() => {
|
|
261
|
+
/* transport may be gone */
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
await this.backend.disconnectTransport().catch(() => {
|
|
266
|
+
/* never held a tab */
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
this.claimant = null;
|
|
270
|
+
this.setState('stopped');
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../../src/attach/daemon/daemon.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Barrel for the attach daemon lane (`./attach/daemon` subpath).
|
|
3
|
+
* @module browser-automation/attach/daemon
|
|
4
|
+
*/
|
|
5
|
+
export * from './protocol.js';
|
|
6
|
+
export * from './daemon-lock.js';
|
|
7
|
+
export * from './daemon.js';
|
|
8
|
+
export * from './client.js';
|
|
9
|
+
export * from './surface.js';
|
|
10
|
+
export * from './runner.js';
|
|
11
|
+
export { main as daemonMain } from './daemon-main.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/attach/daemon/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Barrel for the attach daemon lane (`./attach/daemon` subpath).
|
|
3
|
+
* @module browser-automation/attach/daemon
|
|
4
|
+
*/
|
|
5
|
+
export * from './protocol.js';
|
|
6
|
+
export * from './daemon-lock.js';
|
|
7
|
+
export * from './daemon.js';
|
|
8
|
+
export * from './client.js';
|
|
9
|
+
export * from './surface.js';
|
|
10
|
+
export * from './runner.js';
|
|
11
|
+
export { main as daemonMain } from './daemon-main.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/attach/daemon/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** Daemon-routable operations. */
|
|
2
|
+
export type AttachOp = 'ping' | 'status' | 'claim' | 'goto' | 'read' | 'extract' | 'eval' | 'release' | 'control' | 'quit';
|
|
3
|
+
/** A command file body. */
|
|
4
|
+
export interface AttachCmd {
|
|
5
|
+
id: string;
|
|
6
|
+
client: string;
|
|
7
|
+
op: AttachOp;
|
|
8
|
+
args?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
/** Response bodies (structured error codes ride `error.code`). */
|
|
11
|
+
export type AttachResp = {
|
|
12
|
+
id: string;
|
|
13
|
+
op: AttachOp;
|
|
14
|
+
ok: true;
|
|
15
|
+
data: unknown;
|
|
16
|
+
} | {
|
|
17
|
+
id: string;
|
|
18
|
+
op: AttachOp;
|
|
19
|
+
ok: false;
|
|
20
|
+
error: {
|
|
21
|
+
code: string;
|
|
22
|
+
message: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
/** Daemon lifecycle states mirrored in status.json. */
|
|
26
|
+
export type DaemonState = 'starting' | 'connecting' | 'connected' | 'degraded' | 'stopped' | 'failed';
|
|
27
|
+
/** status.json shape (heartbeat `t` refreshes every daemon loop tick). */
|
|
28
|
+
export interface DaemonStatusFile {
|
|
29
|
+
t: number;
|
|
30
|
+
pid: number;
|
|
31
|
+
state: DaemonState;
|
|
32
|
+
targetId?: string;
|
|
33
|
+
identity?: string;
|
|
34
|
+
claimant?: string;
|
|
35
|
+
paused?: boolean;
|
|
36
|
+
dryRun?: boolean;
|
|
37
|
+
lastError?: string;
|
|
38
|
+
}
|
|
39
|
+
/** Default IPC directory (created 0700). */
|
|
40
|
+
export declare const DEFAULT_IPC_DIR: string;
|
|
41
|
+
/** Default daemon pidfile. */
|
|
42
|
+
export declare const DEFAULT_PID_FILE: string;
|
|
43
|
+
/** cmd/resp files older than this are garbage-collected. */
|
|
44
|
+
export declare const STALE_FILE_MS: number;
|
|
45
|
+
/** status.json heartbeats older than this mark the daemon stale. */
|
|
46
|
+
export declare const HEARTBEAT_STALE_MS = 30000;
|
|
47
|
+
/** Resolve the IPC dir from an explicit override or env, ensuring it exists 0700. */
|
|
48
|
+
export declare function resolveIpcDir(override?: string, env?: Record<string, string | undefined>): string;
|
|
49
|
+
/** New string command id: `<client>-<epochMs>-<random8>`. */
|
|
50
|
+
export declare function newCmdId(client: string): string;
|
|
51
|
+
/** Path of a command file. */
|
|
52
|
+
export declare function cmdPath(dir: string, id: string): string;
|
|
53
|
+
/** Path of a response file. */
|
|
54
|
+
export declare function respPath(dir: string, id: string): string;
|
|
55
|
+
/** Path of the daemon heartbeat file. */
|
|
56
|
+
export declare function statusPath(dir: string): string;
|
|
57
|
+
/** Write JSON via tmp-then-rename so readers never see a torn body. */
|
|
58
|
+
export declare function writeAtomicJson(file: string, value: unknown): void;
|
|
59
|
+
/** Read+parse JSON; undefined when missing or torn. */
|
|
60
|
+
export declare function readJson<T>(file: string): T | undefined;
|
|
61
|
+
/** Pending command files, oldest first (mtime, then name for determinism). */
|
|
62
|
+
export declare function listPendingCmds(dir: string): Array<{
|
|
63
|
+
id: string;
|
|
64
|
+
path: string;
|
|
65
|
+
mtimeMs: number;
|
|
66
|
+
}>;
|
|
67
|
+
/** Delete cmd/resp files older than {@link STALE_FILE_MS} (pass `now` = Infinity to sweep all). */
|
|
68
|
+
export declare function gcStale(dir: string, now?: number): void;
|
|
69
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/attach/daemon/protocol.ts"],"names":[],"mappings":"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"}
|