@steel-experiments/pi-steel 0.1.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.
- package/LICENSE +21 -0
- package/README.md +129 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/session-mode.d.ts +2 -0
- package/dist/session-mode.js +12 -0
- package/dist/session-mode.js.map +1 -0
- package/dist/steel-client.d.ts +79 -0
- package/dist/steel-client.js +463 -0
- package/dist/steel-client.js.map +1 -0
- package/dist/tools/captcha-guard.d.ts +25 -0
- package/dist/tools/captcha-guard.js +191 -0
- package/dist/tools/captcha-guard.js.map +1 -0
- package/dist/tools/click.d.ts +3 -0
- package/dist/tools/click.js +205 -0
- package/dist/tools/click.js.map +1 -0
- package/dist/tools/computer.d.ts +3 -0
- package/dist/tools/computer.js +328 -0
- package/dist/tools/computer.js.map +1 -0
- package/dist/tools/extract.d.ts +3 -0
- package/dist/tools/extract.js +437 -0
- package/dist/tools/extract.js.map +1 -0
- package/dist/tools/fill-form.d.ts +3 -0
- package/dist/tools/fill-form.js +193 -0
- package/dist/tools/fill-form.js.map +1 -0
- package/dist/tools/find-elements.d.ts +3 -0
- package/dist/tools/find-elements.js +205 -0
- package/dist/tools/find-elements.js.map +1 -0
- package/dist/tools/navigate.d.ts +3 -0
- package/dist/tools/navigate.js +228 -0
- package/dist/tools/navigate.js.map +1 -0
- package/dist/tools/navigation.d.ts +5 -0
- package/dist/tools/navigation.js +119 -0
- package/dist/tools/navigation.js.map +1 -0
- package/dist/tools/pdf.d.ts +3 -0
- package/dist/tools/pdf.js +166 -0
- package/dist/tools/pdf.js.map +1 -0
- package/dist/tools/scrape.d.ts +3 -0
- package/dist/tools/scrape.js +298 -0
- package/dist/tools/scrape.js.map +1 -0
- package/dist/tools/screenshot.d.ts +3 -0
- package/dist/tools/screenshot.js +250 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/scroll.d.ts +3 -0
- package/dist/tools/scroll.js +224 -0
- package/dist/tools/scroll.js.map +1 -0
- package/dist/tools/session-control.d.ts +11 -0
- package/dist/tools/session-control.js +67 -0
- package/dist/tools/session-control.js.map +1 -0
- package/dist/tools/session-state.d.ts +13 -0
- package/dist/tools/session-state.js +46 -0
- package/dist/tools/session-state.js.map +1 -0
- package/dist/tools/tool-runtime.d.ts +15 -0
- package/dist/tools/tool-runtime.js +187 -0
- package/dist/tools/tool-runtime.js.map +1 -0
- package/dist/tools/tool-settings.d.ts +4 -0
- package/dist/tools/tool-settings.js +43 -0
- package/dist/tools/tool-settings.js.map +1 -0
- package/dist/tools/type.d.ts +3 -0
- package/dist/tools/type.js +172 -0
- package/dist/tools/type.js.map +1 -0
- package/dist/tools/wait.d.ts +3 -0
- package/dist/tools/wait.js +157 -0
- package/dist/tools/wait.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { emitProgress, isAbortError, sleepWithSignal, throwIfAborted, } from "./tool-runtime.js";
|
|
2
|
+
const CAPTCHA_WAIT_MS_ENV = "STEEL_CAPTCHA_WAIT_MS";
|
|
3
|
+
const CAPTCHA_MAX_RETRIES_ENV = "STEEL_CAPTCHA_MAX_RETRIES";
|
|
4
|
+
const CAPTCHA_POLL_INTERVAL_MS_ENV = "STEEL_CAPTCHA_POLL_INTERVAL_MS";
|
|
5
|
+
const DEFAULT_CAPTCHA_WAIT_MS = 45_000;
|
|
6
|
+
const DEFAULT_CAPTCHA_MAX_RETRIES = 1;
|
|
7
|
+
const DEFAULT_CAPTCHA_POLL_INTERVAL_MS = 1_500;
|
|
8
|
+
const MIN_CAPTCHA_WAIT_MS = 1_000;
|
|
9
|
+
const MAX_CAPTCHA_WAIT_MS = 180_000;
|
|
10
|
+
const MIN_CAPTCHA_POLL_INTERVAL_MS = 250;
|
|
11
|
+
const MAX_CAPTCHA_POLL_INTERVAL_MS = 10_000;
|
|
12
|
+
const MAX_CAPTCHA_RETRIES = 3;
|
|
13
|
+
function parsePositiveInt(raw) {
|
|
14
|
+
if (raw === undefined) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const value = raw.trim();
|
|
18
|
+
if (!value) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const parsed = Number.parseInt(value, 10);
|
|
22
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return parsed;
|
|
26
|
+
}
|
|
27
|
+
function resolveCaptchaWaitMs() {
|
|
28
|
+
const parsed = parsePositiveInt(process.env[CAPTCHA_WAIT_MS_ENV]);
|
|
29
|
+
if (parsed === null) {
|
|
30
|
+
return DEFAULT_CAPTCHA_WAIT_MS;
|
|
31
|
+
}
|
|
32
|
+
return Math.max(MIN_CAPTCHA_WAIT_MS, Math.min(parsed, MAX_CAPTCHA_WAIT_MS));
|
|
33
|
+
}
|
|
34
|
+
function resolveCaptchaMaxRetries() {
|
|
35
|
+
const parsed = parsePositiveInt(process.env[CAPTCHA_MAX_RETRIES_ENV]);
|
|
36
|
+
if (parsed === null) {
|
|
37
|
+
return DEFAULT_CAPTCHA_MAX_RETRIES;
|
|
38
|
+
}
|
|
39
|
+
return Math.max(0, Math.min(parsed, MAX_CAPTCHA_RETRIES));
|
|
40
|
+
}
|
|
41
|
+
function resolveCaptchaPollIntervalMs() {
|
|
42
|
+
const parsed = parsePositiveInt(process.env[CAPTCHA_POLL_INTERVAL_MS_ENV]);
|
|
43
|
+
if (parsed === null) {
|
|
44
|
+
return DEFAULT_CAPTCHA_POLL_INTERVAL_MS;
|
|
45
|
+
}
|
|
46
|
+
return Math.max(MIN_CAPTCHA_POLL_INTERVAL_MS, Math.min(parsed, MAX_CAPTCHA_POLL_INTERVAL_MS));
|
|
47
|
+
}
|
|
48
|
+
function normalizeErrorText(error) {
|
|
49
|
+
if (error instanceof Error) {
|
|
50
|
+
return error.message.toLowerCase();
|
|
51
|
+
}
|
|
52
|
+
if (typeof error === "string") {
|
|
53
|
+
return error.toLowerCase();
|
|
54
|
+
}
|
|
55
|
+
return String(error ?? "").toLowerCase();
|
|
56
|
+
}
|
|
57
|
+
export function isCaptchaInterferenceError(error) {
|
|
58
|
+
const message = normalizeErrorText(error);
|
|
59
|
+
return (message.includes("captcha") ||
|
|
60
|
+
message.includes("hcaptcha") ||
|
|
61
|
+
message.includes("recaptcha") ||
|
|
62
|
+
message.includes("intercepts pointer events"));
|
|
63
|
+
}
|
|
64
|
+
function normalizeCaptchaStatusEntries(value) {
|
|
65
|
+
if (!Array.isArray(value)) {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
return value.filter((entry) => typeof entry === "object" && entry !== null);
|
|
69
|
+
}
|
|
70
|
+
function hasActiveCaptcha(entries) {
|
|
71
|
+
for (const entry of entries) {
|
|
72
|
+
if (entry.isSolvingCaptcha) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
if (Array.isArray(entry.tasks) && entry.tasks.length > 0) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
async function tryReadCaptchaStatus(session, summary, signal) {
|
|
82
|
+
throwIfAborted(signal);
|
|
83
|
+
if (typeof session.captchasStatus !== "function") {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
const status = await session.captchasStatus();
|
|
87
|
+
summary.statusChecks += 1;
|
|
88
|
+
return normalizeCaptchaStatusEntries(status);
|
|
89
|
+
}
|
|
90
|
+
async function runCaptchaRecoveryStep(session, context, actionLabel, onUpdate, summary, signal) {
|
|
91
|
+
throwIfAborted(signal);
|
|
92
|
+
const waitMs = resolveCaptchaWaitMs();
|
|
93
|
+
const pollIntervalMs = resolveCaptchaPollIntervalMs();
|
|
94
|
+
const deadline = Date.now() + waitMs;
|
|
95
|
+
let statusEntries = [];
|
|
96
|
+
try {
|
|
97
|
+
statusEntries = await tryReadCaptchaStatus(session, summary, signal);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
if (isAbortError(error)) {
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
await emitProgress(onUpdate, context, `Captcha status check failed: ${error instanceof Error ? error.message : "unknown error"}`);
|
|
104
|
+
}
|
|
105
|
+
if (statusEntries.length > 0) {
|
|
106
|
+
await emitProgress(onUpdate, context, `Captcha status detected for ${statusEntries.length} page(s)`);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
await emitProgress(onUpdate, context, "No explicit captcha status returned; attempting solve anyway");
|
|
110
|
+
}
|
|
111
|
+
if (typeof session.captchasSolve === "function") {
|
|
112
|
+
throwIfAborted(signal);
|
|
113
|
+
summary.solveAttempts += 1;
|
|
114
|
+
try {
|
|
115
|
+
const solveResult = await session.captchasSolve();
|
|
116
|
+
const message = typeof solveResult === "object" &&
|
|
117
|
+
solveResult !== null &&
|
|
118
|
+
"message" in solveResult &&
|
|
119
|
+
typeof solveResult.message === "string"
|
|
120
|
+
? solveResult.message
|
|
121
|
+
: "captcha solve requested";
|
|
122
|
+
await emitProgress(onUpdate, context, `Captcha solve call: ${message}`);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
if (isAbortError(error)) {
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
await emitProgress(onUpdate, context, `Captcha solve call failed: ${error instanceof Error ? error.message : "unknown error"}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
await emitProgress(onUpdate, context, "Session does not expose captchas.solve; proceeding with retry");
|
|
133
|
+
}
|
|
134
|
+
while (Date.now() < deadline && typeof session.captchasStatus === "function") {
|
|
135
|
+
throwIfAborted(signal);
|
|
136
|
+
await sleepWithSignal(pollIntervalMs, signal);
|
|
137
|
+
try {
|
|
138
|
+
statusEntries = await tryReadCaptchaStatus(session, summary, signal);
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
if (isAbortError(error)) {
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
await emitProgress(onUpdate, context, `Captcha status polling failed: ${error instanceof Error ? error.message : "unknown error"}`);
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
if (!hasActiveCaptcha(statusEntries)) {
|
|
148
|
+
await emitProgress(onUpdate, context, "Captcha state cleared; retrying action");
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (typeof session.captchasStatus === "function") {
|
|
153
|
+
summary.waitTimedOut = true;
|
|
154
|
+
await emitProgress(onUpdate, context, `Captcha wait reached ${waitMs}ms; retrying ${actionLabel}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
export async function runWithCaptchaRecovery(options) {
|
|
158
|
+
const { session, context, actionLabel, onUpdate, operation, signal, shouldRetry = isCaptchaInterferenceError, } = options;
|
|
159
|
+
const maxRetries = resolveCaptchaMaxRetries();
|
|
160
|
+
const summary = {
|
|
161
|
+
triggered: false,
|
|
162
|
+
retries: 0,
|
|
163
|
+
solveAttempts: 0,
|
|
164
|
+
statusChecks: 0,
|
|
165
|
+
waitTimedOut: false,
|
|
166
|
+
};
|
|
167
|
+
let attempt = 0;
|
|
168
|
+
while (true) {
|
|
169
|
+
throwIfAborted(signal);
|
|
170
|
+
try {
|
|
171
|
+
await operation();
|
|
172
|
+
return summary;
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if (isAbortError(error)) {
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
throwIfAborted(signal);
|
|
179
|
+
const retriable = shouldRetry(error);
|
|
180
|
+
if (!retriable || attempt >= maxRetries) {
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
summary.triggered = true;
|
|
184
|
+
summary.retries += 1;
|
|
185
|
+
await emitProgress(onUpdate, context, `Captcha-related blocker detected while trying to ${actionLabel}`);
|
|
186
|
+
await runCaptchaRecoveryStep(session, context, actionLabel, onUpdate, summary, signal);
|
|
187
|
+
attempt += 1;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=captcha-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captcha-guard.js","sourceRoot":"","sources":["../../src/tools/captcha-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { sessionDetails } from "../steel-client.js";
|
|
3
|
+
import { runWithCaptchaRecovery } from "./captcha-guard.js";
|
|
4
|
+
import { emitProgress, throwIfAborted, withAbortSignal, withToolError, } from "./tool-runtime.js";
|
|
5
|
+
import { MAX_TOOL_TIMEOUT_MS, resolveToolTimeoutMs, } from "./tool-settings.js";
|
|
6
|
+
function compactCaptchaRecovery(summary) {
|
|
7
|
+
return {
|
|
8
|
+
triggered: summary.triggered,
|
|
9
|
+
retries: summary.retries,
|
|
10
|
+
solveAttempts: summary.solveAttempts,
|
|
11
|
+
statusChecks: summary.statusChecks,
|
|
12
|
+
waitTimedOut: summary.waitTimedOut,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function normalizeSelector(selector) {
|
|
16
|
+
const trimmed = selector.trim();
|
|
17
|
+
if (!trimmed) {
|
|
18
|
+
throw new Error("Selector cannot be empty.");
|
|
19
|
+
}
|
|
20
|
+
return trimmed;
|
|
21
|
+
}
|
|
22
|
+
function normalizeTimeout(timeoutMs) {
|
|
23
|
+
return resolveToolTimeoutMs(timeoutMs);
|
|
24
|
+
}
|
|
25
|
+
function getLocator(session, selector) {
|
|
26
|
+
if (typeof session.locator === "function") {
|
|
27
|
+
return session.locator(selector);
|
|
28
|
+
}
|
|
29
|
+
if (typeof session.page?.locator === "function") {
|
|
30
|
+
return session.page.locator(selector);
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
function supportsCssSelectorFallback(selector) {
|
|
35
|
+
const normalized = selector.trim();
|
|
36
|
+
if (!normalized) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (normalized.includes(">>") ||
|
|
40
|
+
normalized.includes("text=") ||
|
|
41
|
+
normalized.includes("xpath=") ||
|
|
42
|
+
normalized.includes("nth=") ||
|
|
43
|
+
normalized.includes(":has-text(") ||
|
|
44
|
+
normalized.includes(":text(") ||
|
|
45
|
+
normalized.includes(":contains(")) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
async function waitForTarget(session, selector, timeoutMs, signal) {
|
|
51
|
+
throwIfAborted(signal);
|
|
52
|
+
const locator = getLocator(session, selector);
|
|
53
|
+
if (locator?.waitFor) {
|
|
54
|
+
await withAbortSignal(locator.waitFor({ state: "visible", timeout: timeoutMs }), signal);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (typeof session.waitForSelector === "function") {
|
|
58
|
+
await withAbortSignal(session.waitForSelector(selector, { state: "visible", timeout: timeoutMs }), signal);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (typeof session.page?.waitForSelector === "function") {
|
|
62
|
+
await withAbortSignal(session.page.waitForSelector(selector, { state: "visible", timeout: timeoutMs }), signal);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function ensureClickable(session, selector, signal) {
|
|
66
|
+
throwIfAborted(signal);
|
|
67
|
+
const locator = getLocator(session, selector);
|
|
68
|
+
if (locator) {
|
|
69
|
+
if (typeof locator.isVisible === "function") {
|
|
70
|
+
const visible = await withAbortSignal(locator.isVisible(), signal);
|
|
71
|
+
if (!visible) {
|
|
72
|
+
throw new Error(`Element is not visible: ${selector}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (typeof locator.isEnabled === "function") {
|
|
76
|
+
const enabled = await withAbortSignal(locator.isEnabled(), signal);
|
|
77
|
+
if (!enabled) {
|
|
78
|
+
throw new Error(`Element is disabled and cannot be clicked: ${selector}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (!supportsCssSelectorFallback(selector)) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const evaluate = session.evaluate ?? session.page?.evaluate;
|
|
87
|
+
if (typeof evaluate !== "function") {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const result = await withAbortSignal(evaluate((input) => {
|
|
91
|
+
const element = document.querySelector(input.selector);
|
|
92
|
+
if (!element) {
|
|
93
|
+
return { found: false, clickable: false, disabled: false };
|
|
94
|
+
}
|
|
95
|
+
const style = getComputedStyle(element);
|
|
96
|
+
const rect = element.getBoundingClientRect();
|
|
97
|
+
const visible = rect.width > 0 &&
|
|
98
|
+
rect.height > 0 &&
|
|
99
|
+
style.display !== "none" &&
|
|
100
|
+
style.visibility !== "hidden" &&
|
|
101
|
+
Number.parseFloat(style.opacity) > 0;
|
|
102
|
+
const disabled = element.disabled === true ||
|
|
103
|
+
element.getAttribute("aria-disabled") === "true";
|
|
104
|
+
const clickable = visible && !disabled && style.pointerEvents !== "none";
|
|
105
|
+
return { found: true, clickable, disabled };
|
|
106
|
+
}, { selector }), signal);
|
|
107
|
+
if (!result || typeof result !== "object") {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const found = Boolean(result.found);
|
|
111
|
+
const clickable = Boolean(result.clickable);
|
|
112
|
+
const disabled = Boolean(result.disabled);
|
|
113
|
+
if (!found) {
|
|
114
|
+
throw new Error(`No element matched selector: ${selector}`);
|
|
115
|
+
}
|
|
116
|
+
if (disabled) {
|
|
117
|
+
throw new Error(`Element is disabled and cannot be clicked: ${selector}`);
|
|
118
|
+
}
|
|
119
|
+
if (!clickable) {
|
|
120
|
+
throw new Error(`Element is not clickable: ${selector}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function invokeClick(session, selector, timeoutMs, signal) {
|
|
124
|
+
throwIfAborted(signal);
|
|
125
|
+
const locator = getLocator(session, selector);
|
|
126
|
+
if (locator?.click) {
|
|
127
|
+
await withAbortSignal(locator.click({ timeout: timeoutMs }), signal);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (typeof session.click === "function") {
|
|
131
|
+
await withAbortSignal(session.click(selector, { timeout: timeoutMs }), signal);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (typeof session.page?.click === "function") {
|
|
135
|
+
await withAbortSignal(session.page.click(selector, { timeout: timeoutMs }), signal);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const pageEvaluate = session.evaluate ?? session.page?.evaluate;
|
|
139
|
+
if (typeof pageEvaluate === "function" && supportsCssSelectorFallback(selector)) {
|
|
140
|
+
const clicked = await withAbortSignal(pageEvaluate((input) => {
|
|
141
|
+
const element = document.querySelector(input.selector);
|
|
142
|
+
if (!element) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
element.click();
|
|
146
|
+
return true;
|
|
147
|
+
}, { selector }), signal);
|
|
148
|
+
if (clicked) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
throw new Error("Session does not support click operations.");
|
|
153
|
+
}
|
|
154
|
+
export function clickTool(client) {
|
|
155
|
+
return {
|
|
156
|
+
name: "steel_click",
|
|
157
|
+
label: "Click",
|
|
158
|
+
description: "Click an element in the page",
|
|
159
|
+
parameters: Type.Object({
|
|
160
|
+
selector: Type.String({ description: "CSS selector of the element to click" }),
|
|
161
|
+
timeout: Type.Optional(Type.Integer({
|
|
162
|
+
minimum: 100,
|
|
163
|
+
maximum: MAX_TOOL_TIMEOUT_MS,
|
|
164
|
+
description: "Maximum milliseconds to wait for the element",
|
|
165
|
+
})),
|
|
166
|
+
}),
|
|
167
|
+
async execute(_toolCallId, params, signal, onUpdate, _ctx) {
|
|
168
|
+
return withToolError("steel_click", async () => {
|
|
169
|
+
throwIfAborted(signal);
|
|
170
|
+
const selector = normalizeSelector(params.selector);
|
|
171
|
+
const timeoutMs = normalizeTimeout(params.timeout);
|
|
172
|
+
await emitProgress(onUpdate, "steel_click", `Preparing click for ${selector}`);
|
|
173
|
+
const session = (await withAbortSignal(client.getOrCreateSession(), signal));
|
|
174
|
+
await emitProgress(onUpdate, "steel_click", "Running click sequence");
|
|
175
|
+
const captchaRecovery = await runWithCaptchaRecovery({
|
|
176
|
+
session,
|
|
177
|
+
context: "steel_click",
|
|
178
|
+
actionLabel: `click ${selector}`,
|
|
179
|
+
onUpdate,
|
|
180
|
+
signal,
|
|
181
|
+
operation: async () => {
|
|
182
|
+
throwIfAborted(signal);
|
|
183
|
+
await waitForTarget(session, selector, timeoutMs, signal);
|
|
184
|
+
throwIfAborted(signal);
|
|
185
|
+
await ensureClickable(session, selector, signal);
|
|
186
|
+
throwIfAborted(signal);
|
|
187
|
+
await invokeClick(session, selector, timeoutMs, signal);
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
await emitProgress(onUpdate, "steel_click", "Click succeeded");
|
|
191
|
+
return {
|
|
192
|
+
content: [{ type: "text", text: `Clicked element ${selector}` }],
|
|
193
|
+
details: {
|
|
194
|
+
...sessionDetails(session),
|
|
195
|
+
selector,
|
|
196
|
+
timeoutMs,
|
|
197
|
+
clicked: true,
|
|
198
|
+
captchaRecovery: compactCaptchaRecovery(captchaRecovery),
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
}, signal);
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=click.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"click.js","sourceRoot":"","sources":["../../src/tools/click.ts"],"names":[],"mappings":"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"}
|