claw-browser-automation 0.2.0

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 (135) hide show
  1. package/README.md +288 -0
  2. package/dist/actions/action.d.ts +50 -0
  3. package/dist/actions/action.d.ts.map +1 -0
  4. package/dist/actions/action.js +189 -0
  5. package/dist/actions/action.js.map +1 -0
  6. package/dist/actions/assertions.d.ts +15 -0
  7. package/dist/actions/assertions.d.ts.map +1 -0
  8. package/dist/actions/assertions.js +75 -0
  9. package/dist/actions/assertions.js.map +1 -0
  10. package/dist/actions/extract-structured.d.ts +26 -0
  11. package/dist/actions/extract-structured.d.ts.map +1 -0
  12. package/dist/actions/extract-structured.js +112 -0
  13. package/dist/actions/extract-structured.js.map +1 -0
  14. package/dist/actions/extract.d.ts +13 -0
  15. package/dist/actions/extract.d.ts.map +1 -0
  16. package/dist/actions/extract.js +119 -0
  17. package/dist/actions/extract.js.map +1 -0
  18. package/dist/actions/interact.d.ts +32 -0
  19. package/dist/actions/interact.d.ts.map +1 -0
  20. package/dist/actions/interact.js +263 -0
  21. package/dist/actions/interact.js.map +1 -0
  22. package/dist/actions/navigate.d.ts +13 -0
  23. package/dist/actions/navigate.d.ts.map +1 -0
  24. package/dist/actions/navigate.js +91 -0
  25. package/dist/actions/navigate.js.map +1 -0
  26. package/dist/actions/page.d.ts +21 -0
  27. package/dist/actions/page.d.ts.map +1 -0
  28. package/dist/actions/page.js +63 -0
  29. package/dist/actions/page.js.map +1 -0
  30. package/dist/actions/resilience.d.ts +21 -0
  31. package/dist/actions/resilience.d.ts.map +1 -0
  32. package/dist/actions/resilience.js +112 -0
  33. package/dist/actions/resilience.js.map +1 -0
  34. package/dist/actions/semantic.d.ts +58 -0
  35. package/dist/actions/semantic.d.ts.map +1 -0
  36. package/dist/actions/semantic.js +181 -0
  37. package/dist/actions/semantic.js.map +1 -0
  38. package/dist/actions/wait.d.ts +10 -0
  39. package/dist/actions/wait.d.ts.map +1 -0
  40. package/dist/actions/wait.js +69 -0
  41. package/dist/actions/wait.js.map +1 -0
  42. package/dist/errors.d.ts +30 -0
  43. package/dist/errors.d.ts.map +1 -0
  44. package/dist/errors.js +54 -0
  45. package/dist/errors.js.map +1 -0
  46. package/dist/index.d.ts +34 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +88 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/observe/logger.d.ts +4 -0
  51. package/dist/observe/logger.d.ts.map +1 -0
  52. package/dist/observe/logger.js +52 -0
  53. package/dist/observe/logger.js.map +1 -0
  54. package/dist/observe/trace.d.ts +46 -0
  55. package/dist/observe/trace.d.ts.map +1 -0
  56. package/dist/observe/trace.js +102 -0
  57. package/dist/observe/trace.js.map +1 -0
  58. package/dist/plugin.d.ts +9 -0
  59. package/dist/plugin.d.ts.map +1 -0
  60. package/dist/plugin.js +58 -0
  61. package/dist/plugin.js.map +1 -0
  62. package/dist/pool/browser-pool.d.ts +48 -0
  63. package/dist/pool/browser-pool.d.ts.map +1 -0
  64. package/dist/pool/browser-pool.js +216 -0
  65. package/dist/pool/browser-pool.js.map +1 -0
  66. package/dist/pool/health.d.ts +28 -0
  67. package/dist/pool/health.d.ts.map +1 -0
  68. package/dist/pool/health.js +96 -0
  69. package/dist/pool/health.js.map +1 -0
  70. package/dist/selectors/strategy.d.ts +37 -0
  71. package/dist/selectors/strategy.d.ts.map +1 -0
  72. package/dist/selectors/strategy.js +111 -0
  73. package/dist/selectors/strategy.js.map +1 -0
  74. package/dist/session/handle-registry.d.ts +59 -0
  75. package/dist/session/handle-registry.d.ts.map +1 -0
  76. package/dist/session/handle-registry.js +92 -0
  77. package/dist/session/handle-registry.js.map +1 -0
  78. package/dist/session/profiles.d.ts +11 -0
  79. package/dist/session/profiles.d.ts.map +1 -0
  80. package/dist/session/profiles.js +76 -0
  81. package/dist/session/profiles.js.map +1 -0
  82. package/dist/session/session.d.ts +34 -0
  83. package/dist/session/session.d.ts.map +1 -0
  84. package/dist/session/session.js +155 -0
  85. package/dist/session/session.js.map +1 -0
  86. package/dist/session/snapshot.d.ts +18 -0
  87. package/dist/session/snapshot.d.ts.map +1 -0
  88. package/dist/session/snapshot.js +2 -0
  89. package/dist/session/snapshot.js.map +1 -0
  90. package/dist/store/action-log.d.ts +31 -0
  91. package/dist/store/action-log.d.ts.map +1 -0
  92. package/dist/store/action-log.js +52 -0
  93. package/dist/store/action-log.js.map +1 -0
  94. package/dist/store/artifacts.d.ts +22 -0
  95. package/dist/store/artifacts.d.ts.map +1 -0
  96. package/dist/store/artifacts.js +101 -0
  97. package/dist/store/artifacts.js.map +1 -0
  98. package/dist/store/db.d.ts +16 -0
  99. package/dist/store/db.d.ts.map +1 -0
  100. package/dist/store/db.js +91 -0
  101. package/dist/store/db.js.map +1 -0
  102. package/dist/store/sessions.d.ts +25 -0
  103. package/dist/store/sessions.d.ts.map +1 -0
  104. package/dist/store/sessions.js +63 -0
  105. package/dist/store/sessions.js.map +1 -0
  106. package/dist/tools/action-tools.d.ts +4 -0
  107. package/dist/tools/action-tools.d.ts.map +1 -0
  108. package/dist/tools/action-tools.js +356 -0
  109. package/dist/tools/action-tools.js.map +1 -0
  110. package/dist/tools/approval-tools.d.ts +4 -0
  111. package/dist/tools/approval-tools.d.ts.map +1 -0
  112. package/dist/tools/approval-tools.js +28 -0
  113. package/dist/tools/approval-tools.js.map +1 -0
  114. package/dist/tools/context.d.ts +31 -0
  115. package/dist/tools/context.d.ts.map +1 -0
  116. package/dist/tools/context.js +32 -0
  117. package/dist/tools/context.js.map +1 -0
  118. package/dist/tools/handle-tools.d.ts +4 -0
  119. package/dist/tools/handle-tools.d.ts.map +1 -0
  120. package/dist/tools/handle-tools.js +103 -0
  121. package/dist/tools/handle-tools.js.map +1 -0
  122. package/dist/tools/page-tools.d.ts +4 -0
  123. package/dist/tools/page-tools.d.ts.map +1 -0
  124. package/dist/tools/page-tools.js +109 -0
  125. package/dist/tools/page-tools.js.map +1 -0
  126. package/dist/tools/semantic-tools.d.ts +4 -0
  127. package/dist/tools/semantic-tools.d.ts.map +1 -0
  128. package/dist/tools/semantic-tools.js +173 -0
  129. package/dist/tools/semantic-tools.js.map +1 -0
  130. package/dist/tools/session-tools.d.ts +18 -0
  131. package/dist/tools/session-tools.d.ts.map +1 -0
  132. package/dist/tools/session-tools.js +118 -0
  133. package/dist/tools/session-tools.js.map +1 -0
  134. package/openclaw.plugin.json +15 -0
  135. package/package.json +68 -0
@@ -0,0 +1,48 @@
1
+ import type { LaunchOptions } from "playwright-core";
2
+ import type { Logger } from "../observe/logger.js";
3
+ import { BrowserSession } from "../session/session.js";
4
+ export interface PoolConfig {
5
+ maxContexts?: number;
6
+ launchOptions?: LaunchOptions;
7
+ healthCheckIntervalMs?: number;
8
+ logger?: Logger;
9
+ }
10
+ export interface PoolStatus {
11
+ running: boolean;
12
+ activeSessions: number;
13
+ maxContexts: number;
14
+ sessions: Array<{
15
+ id: string;
16
+ url: string;
17
+ healthy: boolean;
18
+ profile: string | undefined;
19
+ }>;
20
+ }
21
+ export interface AcquireOptions {
22
+ profile?: string;
23
+ url?: string;
24
+ }
25
+ export declare class BrowserPool {
26
+ private _browser;
27
+ private _sessions;
28
+ private _health;
29
+ private _maxContexts;
30
+ private _launchOptions;
31
+ private _log;
32
+ private _launching;
33
+ private _shuttingDown;
34
+ constructor(config?: PoolConfig);
35
+ acquire(opts?: AcquireOptions): Promise<BrowserSession>;
36
+ release(session: BrowserSession): Promise<void>;
37
+ destroy(sessionId: string): Promise<void>;
38
+ getSession(sessionId: string): BrowserSession | undefined;
39
+ listSessions(): BrowserSession[];
40
+ status(): PoolStatus;
41
+ shutdown(): Promise<void>;
42
+ private _ensureBrowser;
43
+ private _launchBrowser;
44
+ private _persistProfileSnapshot;
45
+ private _handleUnhealthy;
46
+ private _recoverUnhealthy;
47
+ }
48
+ //# sourceMappingURL=browser-pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-pool.d.ts","sourceRoot":"","sources":["../../src/pool/browser-pool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAKvD,MAAM,WAAW,UAAU;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;CAC5F;AAED,MAAM,WAAW,cAAc;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,WAAW;IACvB,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,SAAS,CAA0C;IAC3D,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,aAAa,CAAS;gBAElB,MAAM,GAAE,UAAe;IAc7B,OAAO,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,cAAc,CAAC;IAyC3D,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/C,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa/C,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIzD,YAAY,IAAI,cAAc,EAAE;IAIhC,MAAM,IAAI,UAAU;IAcd,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YA2BjB,cAAc;YAkBd,cAAc;YAuBd,uBAAuB;IAerC,OAAO,CAAC,gBAAgB;YAMV,iBAAiB;CAmD/B"}
@@ -0,0 +1,216 @@
1
+ import { chromium } from "playwright-core";
2
+ import { createLogger } from "../observe/logger.js";
3
+ import { ensureProfileDir, loadProfileSnapshot, saveProfileSnapshot } from "../session/profiles.js";
4
+ import { BrowserSession } from "../session/session.js";
5
+ import { HealthMonitor } from "./health.js";
6
+ export class BrowserPool {
7
+ _browser = null;
8
+ _sessions = new Map();
9
+ _health;
10
+ _maxContexts;
11
+ _launchOptions;
12
+ _log;
13
+ _launching = null;
14
+ _shuttingDown = false;
15
+ constructor(config = {}) {
16
+ this._maxContexts = config.maxContexts ?? 4;
17
+ this._launchOptions = config.launchOptions ?? {};
18
+ this._log = config.logger ?? createLogger("browser-pool");
19
+ const healthOpts = {
20
+ onUnhealthy: (session) => this._handleUnhealthy(session),
21
+ };
22
+ if (config.healthCheckIntervalMs !== undefined) {
23
+ healthOpts.intervalMs = config.healthCheckIntervalMs;
24
+ }
25
+ this._health = new HealthMonitor(this._log, healthOpts);
26
+ }
27
+ async acquire(opts = {}) {
28
+ if (this._sessions.size >= this._maxContexts) {
29
+ throw new Error(`pool limit reached: ${this._sessions.size}/${this._maxContexts} contexts in use`);
30
+ }
31
+ let profileSnapshot;
32
+ if (opts.profile) {
33
+ ensureProfileDir(opts.profile);
34
+ profileSnapshot = loadProfileSnapshot(opts.profile);
35
+ }
36
+ const browser = await this._ensureBrowser();
37
+ const context = await browser.newContext();
38
+ const page = await context.newPage();
39
+ const session = new BrowserSession({
40
+ context,
41
+ page,
42
+ profile: opts.profile,
43
+ logger: this._log,
44
+ });
45
+ if (profileSnapshot) {
46
+ await session.restore(profileSnapshot);
47
+ }
48
+ if (opts.url) {
49
+ await page.goto(opts.url, { waitUntil: "domcontentloaded" });
50
+ }
51
+ this._sessions.set(session.id, session);
52
+ this._health.track(session);
53
+ this._log.info({ sessionId: session.id, profile: opts.profile, url: opts.url }, "session acquired");
54
+ return session;
55
+ }
56
+ async release(session) {
57
+ await this._persistProfileSnapshot(session);
58
+ this._health.untrack(session.id);
59
+ this._sessions.delete(session.id);
60
+ await session.close();
61
+ this._log.info({ sessionId: session.id }, "session released");
62
+ }
63
+ async destroy(sessionId) {
64
+ const session = this._sessions.get(sessionId);
65
+ if (!session) {
66
+ this._log.warn({ sessionId }, "destroy called on unknown session");
67
+ return;
68
+ }
69
+ await this._persistProfileSnapshot(session);
70
+ this._health.untrack(sessionId);
71
+ this._sessions.delete(sessionId);
72
+ await session.close();
73
+ this._log.info({ sessionId }, "session destroyed");
74
+ }
75
+ getSession(sessionId) {
76
+ return this._sessions.get(sessionId);
77
+ }
78
+ listSessions() {
79
+ return [...this._sessions.values()];
80
+ }
81
+ status() {
82
+ return {
83
+ running: this._browser !== null,
84
+ activeSessions: this._sessions.size,
85
+ maxContexts: this._maxContexts,
86
+ sessions: [...this._sessions.values()].map((s) => ({
87
+ id: s.id,
88
+ url: s.currentUrl(),
89
+ healthy: s.isHealthy(),
90
+ profile: s.profile,
91
+ })),
92
+ };
93
+ }
94
+ async shutdown() {
95
+ this._shuttingDown = true;
96
+ this._log.info("shutting down browser pool");
97
+ this._health.stop();
98
+ const closeTasks = [...this._sessions.values()].map((session) => session.close().catch((err) => {
99
+ this._log.warn({ sessionId: session.id, err }, "error closing session during shutdown");
100
+ }));
101
+ await Promise.allSettled(closeTasks);
102
+ this._sessions.clear();
103
+ if (this._browser) {
104
+ try {
105
+ await this._browser.close();
106
+ }
107
+ catch (err) {
108
+ this._log.warn({ err }, "error closing browser during shutdown");
109
+ }
110
+ this._browser = null;
111
+ }
112
+ this._launching = null;
113
+ this._shuttingDown = false;
114
+ this._log.info("browser pool shut down");
115
+ }
116
+ async _ensureBrowser() {
117
+ if (this._browser?.isConnected()) {
118
+ return this._browser;
119
+ }
120
+ if (this._launching) {
121
+ return this._launching;
122
+ }
123
+ this._launching = this._launchBrowser();
124
+ try {
125
+ const browser = await this._launching;
126
+ return browser;
127
+ }
128
+ finally {
129
+ this._launching = null;
130
+ }
131
+ }
132
+ async _launchBrowser() {
133
+ this._log.info("launching browser");
134
+ const browser = await chromium.launch({
135
+ ...this._launchOptions,
136
+ handleSIGINT: false,
137
+ handleSIGTERM: false,
138
+ handleSIGHUP: false,
139
+ });
140
+ browser.on("disconnected", () => {
141
+ this._log.warn("browser disconnected");
142
+ this._browser = null;
143
+ for (const session of this._sessions.values()) {
144
+ session.markUnhealthy();
145
+ this._handleUnhealthy(session);
146
+ }
147
+ });
148
+ this._browser = browser;
149
+ this._log.info("browser launched");
150
+ return browser;
151
+ }
152
+ async _persistProfileSnapshot(session) {
153
+ if (!session.profile) {
154
+ return;
155
+ }
156
+ try {
157
+ const snapshot = await session.snapshot();
158
+ saveProfileSnapshot(session.profile, snapshot);
159
+ }
160
+ catch (err) {
161
+ this._log.warn({ sessionId: session.id, profile: session.profile, err }, "failed to persist profile snapshot");
162
+ }
163
+ }
164
+ _handleUnhealthy(session) {
165
+ this._recoverUnhealthy(session).catch((err) => {
166
+ this._log.error({ sessionId: session.id, err }, "unhealthy session recovery failed");
167
+ });
168
+ }
169
+ async _recoverUnhealthy(session) {
170
+ if (this._shuttingDown) {
171
+ return;
172
+ }
173
+ if (!this._sessions.has(session.id)) {
174
+ return;
175
+ }
176
+ this._log.error({ sessionId: session.id }, "session unhealthy — recreating context");
177
+ let snapshot;
178
+ try {
179
+ snapshot = await session.snapshot();
180
+ }
181
+ catch {
182
+ if (session.profile) {
183
+ snapshot = loadProfileSnapshot(session.profile);
184
+ }
185
+ }
186
+ this._health.untrack(session.id);
187
+ this._sessions.delete(session.id);
188
+ try {
189
+ await session.close();
190
+ }
191
+ catch (err) {
192
+ this._log.warn({ sessionId: session.id, err }, "error closing unhealthy session");
193
+ }
194
+ try {
195
+ const browser = await this._ensureBrowser();
196
+ const context = await browser.newContext();
197
+ const page = await context.newPage();
198
+ const replacement = new BrowserSession({
199
+ context,
200
+ page,
201
+ profile: session.profile,
202
+ logger: this._log,
203
+ });
204
+ if (snapshot) {
205
+ await replacement.restore(snapshot);
206
+ }
207
+ this._sessions.set(replacement.id, replacement);
208
+ this._health.track(replacement);
209
+ this._log.info({ oldSessionId: session.id, sessionId: replacement.id }, "unhealthy session recovered");
210
+ }
211
+ catch (err) {
212
+ this._log.error({ sessionId: session.id, err }, "failed to recover unhealthy session");
213
+ }
214
+ }
215
+ }
216
+ //# sourceMappingURL=browser-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-pool.js","sourceRoot":"","sources":["../../src/pool/browser-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { Logger } from "../observe/logger.js";
2
+ import type { BrowserSession } from "../session/session.js";
3
+ export interface HealthProbeOptions {
4
+ intervalMs?: number;
5
+ timeoutMs?: number;
6
+ maxFailures?: number;
7
+ onUnhealthy: (session: BrowserSession) => void;
8
+ }
9
+ export declare class HealthMonitor {
10
+ private _tracked;
11
+ private _timer;
12
+ private _intervalMs;
13
+ private _timeoutMs;
14
+ private _maxFailures;
15
+ private _onUnhealthy;
16
+ private _log;
17
+ constructor(logger: Logger, opts: HealthProbeOptions);
18
+ track(session: BrowserSession): void;
19
+ untrack(sessionId: string): void;
20
+ checkOne(sessionId: string): Promise<boolean>;
21
+ stop(): void;
22
+ private _ensureRunning;
23
+ private _stop;
24
+ private _checkAll;
25
+ private _probe;
26
+ private _recordFailure;
27
+ }
28
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/pool/health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAM5D,MAAM,WAAW,kBAAkB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;CAC/C;AAOD,qBAAa,aAAa;IACzB,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,MAAM,CAA+C;IAC7D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,IAAI,CAAS;gBAET,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB;IAQpD,KAAK,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAKpC,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAO1B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQnD,IAAI,IAAI,IAAI;IAKZ,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,KAAK;YAOC,SAAS;YAKT,MAAM;IAyBpB,OAAO,CAAC,cAAc;CAsBtB"}
@@ -0,0 +1,96 @@
1
+ const HEALTH_CHECK_INTERVAL_MS = 30_000;
2
+ const HEALTH_CHECK_TIMEOUT_MS = 5_000;
3
+ const MAX_CONSECUTIVE_FAILURES = 3;
4
+ export class HealthMonitor {
5
+ _tracked = new Map();
6
+ _timer = null;
7
+ _intervalMs;
8
+ _timeoutMs;
9
+ _maxFailures;
10
+ _onUnhealthy;
11
+ _log;
12
+ constructor(logger, opts) {
13
+ this._intervalMs = opts.intervalMs ?? HEALTH_CHECK_INTERVAL_MS;
14
+ this._timeoutMs = opts.timeoutMs ?? HEALTH_CHECK_TIMEOUT_MS;
15
+ this._maxFailures = opts.maxFailures ?? MAX_CONSECUTIVE_FAILURES;
16
+ this._onUnhealthy = opts.onUnhealthy;
17
+ this._log = logger.child({ component: "health" });
18
+ }
19
+ track(session) {
20
+ this._tracked.set(session.id, { session, consecutiveFailures: 0 });
21
+ this._ensureRunning();
22
+ }
23
+ untrack(sessionId) {
24
+ this._tracked.delete(sessionId);
25
+ if (this._tracked.size === 0) {
26
+ this._stop();
27
+ }
28
+ }
29
+ async checkOne(sessionId) {
30
+ const tracked = this._tracked.get(sessionId);
31
+ if (!tracked) {
32
+ return false;
33
+ }
34
+ return this._probe(tracked);
35
+ }
36
+ stop() {
37
+ this._stop();
38
+ this._tracked.clear();
39
+ }
40
+ _ensureRunning() {
41
+ if (this._timer !== null) {
42
+ return;
43
+ }
44
+ this._timer = setInterval(() => {
45
+ this._checkAll().catch((err) => {
46
+ this._log.error({ err }, "health check cycle failed");
47
+ });
48
+ }, this._intervalMs);
49
+ }
50
+ _stop() {
51
+ if (this._timer !== null) {
52
+ clearInterval(this._timer);
53
+ this._timer = null;
54
+ }
55
+ }
56
+ async _checkAll() {
57
+ const checks = [...this._tracked.values()].map((tracked) => this._probe(tracked));
58
+ await Promise.allSettled(checks);
59
+ }
60
+ async _probe(tracked) {
61
+ const { session } = tracked;
62
+ if (!session.isHealthy()) {
63
+ return false;
64
+ }
65
+ try {
66
+ const result = await Promise.race([
67
+ session.page.evaluate(() => document.readyState),
68
+ new Promise((_, reject) => setTimeout(() => reject(new Error("health check timeout")), this._timeoutMs)),
69
+ ]);
70
+ if (result === "complete" || result === "interactive" || result === "loading") {
71
+ tracked.consecutiveFailures = 0;
72
+ return true;
73
+ }
74
+ return this._recordFailure(tracked, "unexpected readyState");
75
+ }
76
+ catch (err) {
77
+ const message = err instanceof Error ? err.message : "unknown error";
78
+ return this._recordFailure(tracked, message);
79
+ }
80
+ }
81
+ _recordFailure(tracked, reason) {
82
+ tracked.consecutiveFailures++;
83
+ this._log.warn({
84
+ sessionId: tracked.session.id,
85
+ failures: tracked.consecutiveFailures,
86
+ reason,
87
+ }, "health check failed");
88
+ if (tracked.consecutiveFailures >= this._maxFailures) {
89
+ this._log.error({ sessionId: tracked.session.id }, `${this._maxFailures} consecutive failures — marking unhealthy`);
90
+ tracked.session.markUnhealthy();
91
+ this._onUnhealthy(tracked.session);
92
+ }
93
+ return false;
94
+ }
95
+ }
96
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/pool/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { Locator, Page } from "playwright-core";
2
+ export interface SelectorResolution {
3
+ locator: Locator;
4
+ strategy: SelectorStrategy;
5
+ strategyIndex: number;
6
+ resolutionMs: number;
7
+ chainLength: number;
8
+ }
9
+ export type SelectorStrategy = {
10
+ type: "aria";
11
+ role: string;
12
+ name: string;
13
+ } | {
14
+ type: "text";
15
+ text: string;
16
+ exact?: boolean;
17
+ } | {
18
+ type: "label";
19
+ text: string;
20
+ } | {
21
+ type: "testid";
22
+ id: string;
23
+ } | {
24
+ type: "css";
25
+ selector: string;
26
+ } | {
27
+ type: "xpath";
28
+ expression: string;
29
+ };
30
+ export type Selector = string | SelectorStrategy | SelectorStrategy[];
31
+ export type SelectorWaitState = "visible" | "hidden" | "attached" | "detached";
32
+ export declare function resolveSelector(page: Page, selector: Selector): Locator;
33
+ export declare function resolveFirstVisible(page: Page, selector: Selector, timeoutMs: number): Promise<Locator>;
34
+ export declare function resolveWithConfidence(page: Page, selector: Selector, state: SelectorWaitState, timeoutMs: number): Promise<SelectorResolution>;
35
+ /** @deprecated Use resolveWithConfidence — this wrapper extracts .locator for backward compat */
36
+ export declare function resolveBestSelector(page: Page, selector: Selector, state: SelectorWaitState, timeoutMs: number): Promise<Locator>;
37
+ //# sourceMappingURL=strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../../src/selectors/strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAGrD,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,gBAAgB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;AACtE,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC;AAE/E,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAcvE;AAED,wBAAsB,mBAAmB,CACxC,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED,wBAAsB,qBAAqB,CAC1C,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,iBAAiB,EACxB,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CA0E7B;AAED,iGAAiG;AACjG,wBAAsB,mBAAmB,CACxC,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,iBAAiB,EACxB,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAGlB"}
@@ -0,0 +1,111 @@
1
+ import { TargetNotFoundError } from "../errors.js";
2
+ export function resolveSelector(page, selector) {
3
+ if (typeof selector === "string") {
4
+ return page.locator(selector);
5
+ }
6
+ if (Array.isArray(selector)) {
7
+ const first = selector[0];
8
+ if (!first) {
9
+ throw new TargetNotFoundError("empty selector strategy array");
10
+ }
11
+ return resolveOne(page, first);
12
+ }
13
+ return resolveOne(page, selector);
14
+ }
15
+ export async function resolveFirstVisible(page, selector, timeoutMs) {
16
+ const resolution = await resolveWithConfidence(page, selector, "visible", timeoutMs);
17
+ return resolution.locator.first();
18
+ }
19
+ export async function resolveWithConfidence(page, selector, state, timeoutMs) {
20
+ const start = performance.now();
21
+ if (typeof selector === "string") {
22
+ const locator = page.locator(selector);
23
+ const strategy = { type: "css", selector };
24
+ return {
25
+ locator,
26
+ strategy,
27
+ strategyIndex: 0,
28
+ resolutionMs: Math.round(performance.now() - start),
29
+ chainLength: 1,
30
+ };
31
+ }
32
+ if (!Array.isArray(selector)) {
33
+ const locator = resolveOne(page, selector);
34
+ return {
35
+ locator,
36
+ strategy: selector,
37
+ strategyIndex: 0,
38
+ resolutionMs: Math.round(performance.now() - start),
39
+ chainLength: 1,
40
+ };
41
+ }
42
+ if (selector.length === 0) {
43
+ throw new TargetNotFoundError("empty selector strategy array");
44
+ }
45
+ // Hidden/detached semantics can pass on missing elements, so fallback probing is not meaningful.
46
+ if (state === "hidden" || state === "detached") {
47
+ const first = selector[0];
48
+ if (!first) {
49
+ throw new TargetNotFoundError("empty selector strategy array");
50
+ }
51
+ return {
52
+ locator: resolveOne(page, first),
53
+ strategy: first,
54
+ strategyIndex: 0,
55
+ resolutionMs: Math.round(performance.now() - start),
56
+ chainLength: selector.length,
57
+ };
58
+ }
59
+ const deadline = Date.now() + timeoutMs;
60
+ for (let i = 0; i < selector.length; i++) {
61
+ const strategy = selector[i];
62
+ if (!strategy) {
63
+ continue;
64
+ }
65
+ const remaining = deadline - Date.now();
66
+ if (remaining <= 0) {
67
+ break;
68
+ }
69
+ try {
70
+ const locator = resolveOne(page, strategy);
71
+ await locator.first().waitFor({ state, timeout: Math.min(remaining, 2000) });
72
+ return {
73
+ locator,
74
+ strategy,
75
+ strategyIndex: i,
76
+ resolutionMs: Math.round(performance.now() - start),
77
+ chainLength: selector.length,
78
+ };
79
+ }
80
+ catch {
81
+ // Strategy didn't match — try next one
82
+ }
83
+ }
84
+ throw new TargetNotFoundError(`no selector strategy matched within ${timeoutMs}ms for state ${state}`, "Try a different selector strategy or increase the timeout.");
85
+ }
86
+ /** @deprecated Use resolveWithConfidence — this wrapper extracts .locator for backward compat */
87
+ export async function resolveBestSelector(page, selector, state, timeoutMs) {
88
+ const resolution = await resolveWithConfidence(page, selector, state, timeoutMs);
89
+ return resolution.locator;
90
+ }
91
+ function resolveOne(page, strategy) {
92
+ switch (strategy.type) {
93
+ case "aria":
94
+ return page.getByRole(strategy.role, {
95
+ name: strategy.name,
96
+ });
97
+ case "text":
98
+ return strategy.exact !== undefined
99
+ ? page.getByText(strategy.text, { exact: strategy.exact })
100
+ : page.getByText(strategy.text);
101
+ case "label":
102
+ return page.getByLabel(strategy.text);
103
+ case "testid":
104
+ return page.getByTestId(strategy.id);
105
+ case "css":
106
+ return page.locator(strategy.selector);
107
+ case "xpath":
108
+ return page.locator(`xpath=${strategy.expression}`);
109
+ }
110
+ }
111
+ //# sourceMappingURL=strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.js","sourceRoot":"","sources":["../../src/selectors/strategy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Stable element handle registry.
3
+ *
4
+ * Maps agent-friendly handle IDs to selector strategies so elements
5
+ * can be referenced across multiple action steps without re-specifying
6
+ * the selector. Re-resolution happens lazily on each `resolve()` call,
7
+ * tracking remaps when the winning strategy changes.
8
+ */
9
+ import type { Locator, Page } from "playwright-core";
10
+ import type { SelectorResolution, SelectorStrategy } from "../selectors/strategy.js";
11
+ export interface ElementHandle {
12
+ handleId: string;
13
+ selector: SelectorStrategy | SelectorStrategy[];
14
+ /** The strategy that last successfully resolved. */
15
+ lastStrategy: SelectorStrategy;
16
+ /** How many times the winning strategy changed since registration. */
17
+ remapCount: number;
18
+ }
19
+ export interface HandleResolution {
20
+ locator: Locator;
21
+ handle: ElementHandle;
22
+ resolution: SelectorResolution;
23
+ remapped: boolean;
24
+ }
25
+ export declare class HandleRegistry {
26
+ private _handles;
27
+ get size(): number;
28
+ /**
29
+ * Register an element by resolving its selector and assigning a stable ID.
30
+ */
31
+ register(page: Page, selector: SelectorStrategy | SelectorStrategy[], timeoutMs?: number): Promise<ElementHandle>;
32
+ /**
33
+ * Resolve a handle to a live locator. Re-resolves via the original selector
34
+ * strategy, trying the last successful strategy first for speed.
35
+ */
36
+ resolve(page: Page, handleId: string, timeoutMs?: number): Promise<HandleResolution>;
37
+ /**
38
+ * Release a single handle.
39
+ */
40
+ release(handleId: string): boolean;
41
+ /**
42
+ * Release all handles.
43
+ */
44
+ clear(): void;
45
+ /**
46
+ * Get a handle by ID without resolving it.
47
+ */
48
+ get(handleId: string): ElementHandle | undefined;
49
+ /**
50
+ * List all registered handles.
51
+ */
52
+ list(): ElementHandle[];
53
+ /**
54
+ * Build a strategy array with the last successful strategy first,
55
+ * followed by the remaining strategies in original order.
56
+ */
57
+ private _buildPrioritizedStrategies;
58
+ }
59
+ //# sourceMappingURL=handle-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle-registry.d.ts","sourceRoot":"","sources":["../../src/session/handle-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGrF,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;IAChD,oDAAoD;IACpD,YAAY,EAAE,gBAAgB,CAAC;IAC/B,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAoC;IAEpD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACG,QAAQ,CACb,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,EAC/C,SAAS,SAAO,GACd,OAAO,CAAC,aAAa,CAAC;IAczB;;;OAGG;IACG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAyBxF;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIlC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIhD;;OAEG;IACH,IAAI,IAAI,aAAa,EAAE;IAIvB;;;OAGG;IACH,OAAO,CAAC,2BAA2B;CAQnC"}