aiden-runtime 4.1.5 → 4.6.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/README.md +265 -847
- package/dist/api/server.js +32 -5
- package/dist/cli/v4/aidenCLI.js +536 -152
- package/dist/cli/v4/callbacks.js +170 -0
- package/dist/cli/v4/chatSession.js +245 -3
- package/dist/cli/v4/commands/_runtimeToggleHelpers.js +94 -0
- package/dist/cli/v4/commands/browserDepth.js +45 -0
- package/dist/cli/v4/commands/cron.js +264 -0
- package/dist/cli/v4/commands/daemon.js +541 -0
- package/dist/cli/v4/commands/daemonStatus.js +253 -0
- package/dist/cli/v4/commands/fanout.js +42 -59
- package/dist/cli/v4/commands/help.js +13 -0
- package/dist/cli/v4/commands/index.js +35 -1
- package/dist/cli/v4/commands/mcp.js +80 -54
- package/dist/cli/v4/commands/plannerGuard.js +53 -0
- package/dist/cli/v4/commands/recovery.js +122 -0
- package/dist/cli/v4/commands/runs.js +223 -0
- package/dist/cli/v4/commands/sandbox.js +48 -0
- package/dist/cli/v4/commands/spawnPause.js +93 -0
- package/dist/cli/v4/commands/suggestions.js +68 -0
- package/dist/cli/v4/commands/tce.js +41 -0
- package/dist/cli/v4/commands/trigger.js +378 -0
- package/dist/cli/v4/commands/update.js +95 -3
- package/dist/cli/v4/daemonAgentBuilder.js +145 -0
- package/dist/cli/v4/defaultSoul.js +1 -1
- package/dist/cli/v4/display/capabilityCard.js +26 -0
- package/dist/cli/v4/display.js +18 -8
- package/dist/cli/v4/replyRenderer.js +31 -23
- package/dist/cli/v4/updateBootPrompt.js +170 -0
- package/dist/core/playwrightBridge.js +129 -0
- package/dist/core/v4/aidenAgent.js +527 -5
- package/dist/core/v4/browserState.js +436 -0
- package/dist/core/v4/checkpoint.js +79 -0
- package/dist/core/v4/daemon/bootstrap.js +651 -0
- package/dist/core/v4/daemon/cleanShutdown.js +154 -0
- package/dist/core/v4/daemon/cron/cronBridge.js +126 -0
- package/dist/core/v4/daemon/cron/cronEmitter.js +173 -0
- package/dist/core/v4/daemon/cron/migration.js +199 -0
- package/dist/core/v4/daemon/cron/misfirePolicy.js +115 -0
- package/dist/core/v4/daemon/daemonConfig.js +90 -0
- package/dist/core/v4/daemon/db/connection.js +106 -0
- package/dist/core/v4/daemon/db/migrations.js +362 -0
- package/dist/core/v4/daemon/db/schema/v1.spec.js +18 -0
- package/dist/core/v4/daemon/dispatcher/agentRunner.js +98 -0
- package/dist/core/v4/daemon/dispatcher/budgetGate.js +127 -0
- package/dist/core/v4/daemon/dispatcher/daemonApproval.js +113 -0
- package/dist/core/v4/daemon/dispatcher/dailyBudgetTracker.js +120 -0
- package/dist/core/v4/daemon/dispatcher/dispatcher.js +389 -0
- package/dist/core/v4/daemon/dispatcher/fireRateLimiter.js +113 -0
- package/dist/core/v4/daemon/dispatcher/index.js +53 -0
- package/dist/core/v4/daemon/dispatcher/promptTemplate.js +95 -0
- package/dist/core/v4/daemon/dispatcher/realAgentRunner.js +356 -0
- package/dist/core/v4/daemon/dispatcher/resolveModel.js +93 -0
- package/dist/core/v4/daemon/dispatcher/sessionId.js +93 -0
- package/dist/core/v4/daemon/drain.js +156 -0
- package/dist/core/v4/daemon/eventLoopLag.js +73 -0
- package/dist/core/v4/daemon/health.js +159 -0
- package/dist/core/v4/daemon/idempotencyStore.js +204 -0
- package/dist/core/v4/daemon/index.js +179 -0
- package/dist/core/v4/daemon/instanceTracker.js +99 -0
- package/dist/core/v4/daemon/resourceRegistry.js +150 -0
- package/dist/core/v4/daemon/restartCode.js +32 -0
- package/dist/core/v4/daemon/restartFailureCounter.js +77 -0
- package/dist/core/v4/daemon/runStore.js +144 -0
- package/dist/core/v4/daemon/runtimeLock.js +167 -0
- package/dist/core/v4/daemon/signals.js +50 -0
- package/dist/core/v4/daemon/supervisor.js +272 -0
- package/dist/core/v4/daemon/triggerBus.js +279 -0
- package/dist/core/v4/daemon/triggers/email/allowlist.js +70 -0
- package/dist/core/v4/daemon/triggers/email/automatedSender.js +78 -0
- package/dist/core/v4/daemon/triggers/email/bodyExtractor.js +0 -0
- package/dist/core/v4/daemon/triggers/email/emailSeenStore.js +99 -0
- package/dist/core/v4/daemon/triggers/email/emailSpec.js +107 -0
- package/dist/core/v4/daemon/triggers/email/imapConnection.js +211 -0
- package/dist/core/v4/daemon/triggers/email/index.js +332 -0
- package/dist/core/v4/daemon/triggers/email/seenUids.js +60 -0
- package/dist/core/v4/daemon/triggers/fileObservationsStore.js +93 -0
- package/dist/core/v4/daemon/triggers/fileWatcher.js +253 -0
- package/dist/core/v4/daemon/triggers/fileWatcherSpec.js +88 -0
- package/dist/core/v4/daemon/triggers/fsIdentity.js +42 -0
- package/dist/core/v4/daemon/triggers/globMatcher.js +100 -0
- package/dist/core/v4/daemon/triggers/reconcile.js +206 -0
- package/dist/core/v4/daemon/triggers/settleStat.js +81 -0
- package/dist/core/v4/daemon/triggers/webhook.js +376 -0
- package/dist/core/v4/daemon/triggers/webhookDeliveriesStore.js +109 -0
- package/dist/core/v4/daemon/triggers/webhookIdempotency.js +72 -0
- package/dist/core/v4/daemon/triggers/webhookRateLimit.js +56 -0
- package/dist/core/v4/daemon/triggers/webhookSpec.js +76 -0
- package/dist/core/v4/daemon/triggers/webhookVerifier.js +128 -0
- package/dist/core/v4/daemon/types.js +15 -0
- package/dist/core/v4/dockerSession.js +461 -0
- package/dist/core/v4/dryRun.js +117 -0
- package/dist/core/v4/failureClassifier.js +779 -0
- package/dist/core/v4/providerFallback.js +35 -2
- package/dist/core/v4/recoveryReport.js +449 -0
- package/dist/core/v4/runtimeToggles.js +214 -0
- package/dist/core/v4/sandboxConfig.js +285 -0
- package/dist/core/v4/sandboxFs.js +316 -0
- package/dist/core/v4/selfimprovement/recoveryStore.js +307 -0
- package/dist/core/v4/selfimprovement/signatureBuilder.js +158 -0
- package/dist/core/v4/subagent/childBuilder.js +391 -0
- package/dist/core/v4/subagent/fanout.js +75 -51
- package/dist/core/v4/subagent/spawnPause.js +191 -0
- package/dist/core/v4/subagent/spawnSubAgent.js +310 -0
- package/dist/core/v4/suggestionCatalog.js +41 -0
- package/dist/core/v4/suggestionEngine.js +210 -0
- package/dist/core/v4/toolRegistry.js +37 -3
- package/dist/core/v4/turnState.js +587 -0
- package/dist/core/v4/update/checkUpdate.js +63 -3
- package/dist/core/v4/update/installMethodDetect.js +115 -0
- package/dist/core/v4/update/registryClient.js +121 -0
- package/dist/core/v4/update/skipState.js +75 -0
- package/dist/core/v4/verifier.js +448 -0
- package/dist/core/version.js +1 -1
- package/dist/moat/plannerGuard.js +29 -0
- package/dist/providers/v4/anthropicAdapter.js +31 -3
- package/dist/providers/v4/chatCompletionsAdapter.js +26 -3
- package/dist/providers/v4/codexResponsesAdapter.js +25 -2
- package/dist/providers/v4/ollamaPromptToolsAdapter.js +57 -2
- package/dist/tools/v4/browser/_observer.js +224 -0
- package/dist/tools/v4/browser/browserBlocker.js +396 -0
- package/dist/tools/v4/browser/browserClick.js +18 -1
- package/dist/tools/v4/browser/browserClose.js +18 -1
- package/dist/tools/v4/browser/browserExtract.js +5 -1
- package/dist/tools/v4/browser/browserFill.js +17 -1
- package/dist/tools/v4/browser/browserGetUrl.js +5 -1
- package/dist/tools/v4/browser/browserNavigate.js +16 -1
- package/dist/tools/v4/browser/browserScreenshot.js +5 -1
- package/dist/tools/v4/browser/browserScroll.js +18 -1
- package/dist/tools/v4/browser/browserType.js +17 -1
- package/dist/tools/v4/browser/captchaCheck.js +5 -1
- package/dist/tools/v4/executeCode.js +1 -0
- package/dist/tools/v4/files/fileCopy.js +56 -2
- package/dist/tools/v4/files/fileDelete.js +38 -1
- package/dist/tools/v4/files/fileList.js +12 -1
- package/dist/tools/v4/files/fileMove.js +59 -2
- package/dist/tools/v4/files/filePatch.js +43 -1
- package/dist/tools/v4/files/fileRead.js +12 -1
- package/dist/tools/v4/files/fileWrite.js +41 -1
- package/dist/tools/v4/index.js +88 -61
- package/dist/tools/v4/memory/memoryAdd.js +14 -0
- package/dist/tools/v4/memory/memoryRemove.js +14 -0
- package/dist/tools/v4/memory/memoryReplace.js +15 -0
- package/dist/tools/v4/memory/sessionSummary.js +12 -0
- package/dist/tools/v4/process/processKill.js +19 -0
- package/dist/tools/v4/process/processList.js +1 -0
- package/dist/tools/v4/process/processLogRead.js +1 -0
- package/dist/tools/v4/process/processSpawn.js +13 -0
- package/dist/tools/v4/process/processWait.js +1 -0
- package/dist/tools/v4/sessions/recallSession.js +1 -0
- package/dist/tools/v4/sessions/sessionList.js +1 -0
- package/dist/tools/v4/sessions/sessionSearch.js +1 -0
- package/dist/tools/v4/skills/lookupToolSchema.js +7 -0
- package/dist/tools/v4/skills/skillManage.js +13 -0
- package/dist/tools/v4/skills/skillView.js +1 -0
- package/dist/tools/v4/skills/skillsList.js +1 -0
- package/dist/tools/v4/subagent/spawnSubAgentTool.js +334 -0
- package/dist/tools/v4/subagent/subagentFanout.js +54 -1
- package/dist/tools/v4/system/aidenSelfUpdate.js +16 -0
- package/dist/tools/v4/system/appClose.js +13 -0
- package/dist/tools/v4/system/appInput.js +13 -0
- package/dist/tools/v4/system/appLaunch.js +13 -0
- package/dist/tools/v4/system/clipboardRead.js +1 -0
- package/dist/tools/v4/system/clipboardWrite.js +14 -0
- package/dist/tools/v4/system/mediaKey.js +12 -0
- package/dist/tools/v4/system/mediaSessions.js +1 -0
- package/dist/tools/v4/system/mediaTransport.js +13 -0
- package/dist/tools/v4/system/naturalEvents.js +1 -0
- package/dist/tools/v4/system/nowPlaying.js +1 -0
- package/dist/tools/v4/system/osProcessList.js +1 -0
- package/dist/tools/v4/system/screenshot.js +1 -0
- package/dist/tools/v4/system/systemInfo.js +1 -0
- package/dist/tools/v4/system/volumeSet.js +17 -0
- package/dist/tools/v4/terminal/shellExec.js +81 -9
- package/dist/tools/v4/web/deepResearch.js +1 -0
- package/dist/tools/v4/web/openUrl.js +1 -0
- package/dist/tools/v4/web/webFetch.js +1 -0
- package/dist/tools/v4/web/webPage.js +1 -0
- package/dist/tools/v4/web/webSearch.js +1 -0
- package/dist/tools/v4/web/youtubeSearch.js +1 -0
- package/package.json +13 -3
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Shiva Deore (Taracod).
|
|
4
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
5
|
+
*
|
|
6
|
+
* Aiden — local-first agent.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* tools/v4/browser/browserBlocker.ts — v4.3 Phase 3: Manual-blocker
|
|
10
|
+
* detection.
|
|
11
|
+
*
|
|
12
|
+
* Five-tier substring + URL pattern pipeline that surfaces "the
|
|
13
|
+
* agent needs your help" situations: CAPTCHA challenges, sign-in
|
|
14
|
+
* walls, 2FA prompts, identity verification, cookie/GDPR consent.
|
|
15
|
+
*
|
|
16
|
+
* Distinct from Phase 1's BrowserState observer (which records
|
|
17
|
+
* state-delta evidence) and Phase 2's stale-ref retry (which auto-
|
|
18
|
+
* corrects transient races). Phase 3 detects situations that
|
|
19
|
+
* **cannot be solved by retry** — the page is asking for a human
|
|
20
|
+
* action — and surfaces them as structured cards so the model
|
|
21
|
+
* doesn't grind through retry attempts.
|
|
22
|
+
*
|
|
23
|
+
* Non-negotiable: NEVER auto-solve a CAPTCHA. The pause-and-surface
|
|
24
|
+
* contract from Q-CDP5(c) is enforced structurally — this module
|
|
25
|
+
* only detects + surfaces. No vision-attempt fallback, no clicking
|
|
26
|
+
* "I'm not a robot" tickboxes, no submitting forms blindly. The
|
|
27
|
+
* model reads `result.browserState.blocker` in its tool message and
|
|
28
|
+
* tells the user.
|
|
29
|
+
*
|
|
30
|
+
* The CAPTCHA tier reuses Aiden's existing `captchaCheck.ts` 24-
|
|
31
|
+
* marker scan — Phase 3 doesn't refactor it, only wraps it as one
|
|
32
|
+
* of five detectors. The other four tiers (2FA, login, verification,
|
|
33
|
+
* consent) are new in Phase 3.
|
|
34
|
+
*
|
|
35
|
+
* Priority order: captcha > 2fa > login > verification > consent.
|
|
36
|
+
* Only ONE blocker reported per detection (highest priority wins).
|
|
37
|
+
* Pages that match multiple tiers (a 2FA challenge inside an
|
|
38
|
+
* obscured cookie banner) report the most-blocking kind — the
|
|
39
|
+
* lower-priority match can wait until the higher-priority is
|
|
40
|
+
* cleared.
|
|
41
|
+
*
|
|
42
|
+
* Pure module — types + 5 detectors + 1 orchestrator. No I/O, no
|
|
43
|
+
* async, no Playwright dependency. Easy to unit-test against
|
|
44
|
+
* canonical page-text fixtures. The observer HOC consumes the
|
|
45
|
+
* `pwSnapshot()` text via the existing playwrightBridge helper.
|
|
46
|
+
*/
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.detectBlocker = detectBlocker;
|
|
49
|
+
const captchaCheck_1 = require("./captchaCheck");
|
|
50
|
+
// ── Pattern tables ──────────────────────────────────────────────────────────
|
|
51
|
+
// CAPTCHA tier reuses captchaCheck.ts markers + adds subtype detection.
|
|
52
|
+
const CAPTCHA_SUBTYPE_MARKERS = [
|
|
53
|
+
['recaptcha', 'recaptcha'],
|
|
54
|
+
['g-recaptcha', 'recaptcha'],
|
|
55
|
+
['hcaptcha.com', 'hcaptcha'],
|
|
56
|
+
['cf-turnstile', 'turnstile'],
|
|
57
|
+
['cloudflare', 'cloudflare'],
|
|
58
|
+
['just a moment', 'cloudflare'],
|
|
59
|
+
['checking your browser', 'cloudflare'],
|
|
60
|
+
];
|
|
61
|
+
// 2FA / MFA tier — input attributes, text, and URL.
|
|
62
|
+
const TWOFA_TEXT_PATTERNS = [
|
|
63
|
+
'enter the code',
|
|
64
|
+
'enter your code',
|
|
65
|
+
'verification code',
|
|
66
|
+
'authentication code',
|
|
67
|
+
'6-digit code',
|
|
68
|
+
'two-factor',
|
|
69
|
+
'two factor',
|
|
70
|
+
'2-step verification',
|
|
71
|
+
'two-step verification',
|
|
72
|
+
'authenticator app',
|
|
73
|
+
'sms code',
|
|
74
|
+
'sent a code',
|
|
75
|
+
'we sent you a code',
|
|
76
|
+
'text message',
|
|
77
|
+
'security code',
|
|
78
|
+
'one-time code',
|
|
79
|
+
'one-time password',
|
|
80
|
+
];
|
|
81
|
+
const TWOFA_URL_PATTERNS = [
|
|
82
|
+
'/2fa',
|
|
83
|
+
'/mfa',
|
|
84
|
+
'/verify-code',
|
|
85
|
+
'/verify_code',
|
|
86
|
+
'/auth/challenge',
|
|
87
|
+
'/two-factor',
|
|
88
|
+
'/two_factor',
|
|
89
|
+
];
|
|
90
|
+
const TWOFA_DOM_HINTS = [
|
|
91
|
+
'autocomplete="one-time-code"',
|
|
92
|
+
"autocomplete='one-time-code'",
|
|
93
|
+
'inputmode="numeric"',
|
|
94
|
+
];
|
|
95
|
+
const TWOFA_SUBTYPE_HINTS = [
|
|
96
|
+
['authenticator app', 'totp'],
|
|
97
|
+
['totp', 'totp'],
|
|
98
|
+
['sms', 'sms'],
|
|
99
|
+
['text message', 'sms'],
|
|
100
|
+
['phone', 'sms'],
|
|
101
|
+
];
|
|
102
|
+
// Login tier — sign-in forms, OAuth, SSO.
|
|
103
|
+
const LOGIN_TEXT_PATTERNS = [
|
|
104
|
+
'sign in',
|
|
105
|
+
'sign-in',
|
|
106
|
+
'log in',
|
|
107
|
+
'log-in',
|
|
108
|
+
'login',
|
|
109
|
+
'enter your password',
|
|
110
|
+
'enter password',
|
|
111
|
+
'continue with google',
|
|
112
|
+
'continue with apple',
|
|
113
|
+
'continue with github',
|
|
114
|
+
'continue with microsoft',
|
|
115
|
+
'sign in with',
|
|
116
|
+
'single sign-on',
|
|
117
|
+
'single sign on',
|
|
118
|
+
];
|
|
119
|
+
const LOGIN_URL_PATTERNS = [
|
|
120
|
+
'/login',
|
|
121
|
+
'/signin',
|
|
122
|
+
'/sign-in',
|
|
123
|
+
'/auth',
|
|
124
|
+
'/oauth',
|
|
125
|
+
'/sso',
|
|
126
|
+
'/account/login',
|
|
127
|
+
];
|
|
128
|
+
const LOGIN_DOM_HINTS = [
|
|
129
|
+
'type="password"',
|
|
130
|
+
"type='password'",
|
|
131
|
+
'input password', // generic fallback
|
|
132
|
+
];
|
|
133
|
+
const LOGIN_SUBTYPE_HINTS = [
|
|
134
|
+
['oauth', 'oauth'],
|
|
135
|
+
['sso', 'oauth'],
|
|
136
|
+
['continue with google', 'oauth'],
|
|
137
|
+
['continue with apple', 'oauth'],
|
|
138
|
+
['continue with github', 'oauth'],
|
|
139
|
+
];
|
|
140
|
+
// Verification tier — identity / phone / email confirmation.
|
|
141
|
+
const VERIFY_TEXT_PATTERNS = [
|
|
142
|
+
'verify your phone',
|
|
143
|
+
'phone verification',
|
|
144
|
+
'verify your email',
|
|
145
|
+
'email verification',
|
|
146
|
+
'confirm your email',
|
|
147
|
+
'verify your identity',
|
|
148
|
+
'identity verification',
|
|
149
|
+
'identity check',
|
|
150
|
+
'prove your identity',
|
|
151
|
+
];
|
|
152
|
+
const VERIFY_URL_PATTERNS = [
|
|
153
|
+
'/verify',
|
|
154
|
+
'/verification',
|
|
155
|
+
'/confirm',
|
|
156
|
+
'/confirm-email',
|
|
157
|
+
'/confirm_email',
|
|
158
|
+
];
|
|
159
|
+
const VERIFY_SUBTYPE_HINTS = [
|
|
160
|
+
['phone', 'phone'],
|
|
161
|
+
['email', 'email'],
|
|
162
|
+
['identity', 'identity'],
|
|
163
|
+
];
|
|
164
|
+
// Consent tier — cookie banners, GDPR.
|
|
165
|
+
const CONSENT_TEXT_PATTERNS = [
|
|
166
|
+
'accept all cookies',
|
|
167
|
+
'reject all cookies',
|
|
168
|
+
'manage cookies',
|
|
169
|
+
'manage your preferences',
|
|
170
|
+
'we use cookies',
|
|
171
|
+
'this site uses cookies',
|
|
172
|
+
'gdpr',
|
|
173
|
+
'cookie preferences',
|
|
174
|
+
'cookie consent',
|
|
175
|
+
'privacy preferences',
|
|
176
|
+
];
|
|
177
|
+
const CONSENT_URL_PATTERNS = [
|
|
178
|
+
'/cookie',
|
|
179
|
+
'/consent',
|
|
180
|
+
];
|
|
181
|
+
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
182
|
+
function lowercase(s) {
|
|
183
|
+
return (s ?? '').toLowerCase();
|
|
184
|
+
}
|
|
185
|
+
function matchesAny(haystack, patterns) {
|
|
186
|
+
for (const p of patterns) {
|
|
187
|
+
if (haystack.includes(p))
|
|
188
|
+
return p;
|
|
189
|
+
}
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
function pickSubtype(haystack, hints, fallback) {
|
|
193
|
+
for (const [marker, subtype] of hints) {
|
|
194
|
+
if (haystack.includes(marker))
|
|
195
|
+
return subtype;
|
|
196
|
+
}
|
|
197
|
+
return fallback;
|
|
198
|
+
}
|
|
199
|
+
function hostnameOf(url) {
|
|
200
|
+
try {
|
|
201
|
+
return new URL(url).hostname || url;
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return url;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// ── Per-tier detectors ─────────────────────────────────────────────────────
|
|
208
|
+
/**
|
|
209
|
+
* Markers from captchaCheck.ts that aren't CAPTCHA-specific —
|
|
210
|
+
* they overlap semantically with the Verification tier (phone /
|
|
211
|
+
* email / identity confirmation). When captchaCheck's only hit
|
|
212
|
+
* is one of these, defer to the Verification tier; CAPTCHA needs
|
|
213
|
+
* a more specific signal.
|
|
214
|
+
*/
|
|
215
|
+
const AMBIGUOUS_CAPTCHA_MARKERS = new Set([
|
|
216
|
+
'verify your identity',
|
|
217
|
+
]);
|
|
218
|
+
function detectCaptcha(text, url) {
|
|
219
|
+
const result = (0, captchaCheck_1.detectCaptchaMarkers)(text);
|
|
220
|
+
if (!result.detected)
|
|
221
|
+
return null;
|
|
222
|
+
// Demote: when the only matched marker is an ambiguous one (e.g.
|
|
223
|
+
// "verify your identity" — used by both CAPTCHAs and identity-
|
|
224
|
+
// verification flows), let the Verification tier handle it.
|
|
225
|
+
// CAPTCHA needs at least one specific signal.
|
|
226
|
+
if (result.markers.length === 1 &&
|
|
227
|
+
AMBIGUOUS_CAPTCHA_MARKERS.has(result.markers[0])) {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
const lowerText = lowercase(text);
|
|
231
|
+
const subtype = pickSubtype(lowerText, CAPTCHA_SUBTYPE_MARKERS, 'unknown');
|
|
232
|
+
const evidence = result.markers.map((m) => `captcha-marker:${m}`);
|
|
233
|
+
// Multi-marker boosts confidence.
|
|
234
|
+
const confidence = result.markers.length >= 3 ? 0.95 :
|
|
235
|
+
result.markers.length === 2 ? 0.85 : 0.7;
|
|
236
|
+
return {
|
|
237
|
+
kind: 'captcha',
|
|
238
|
+
subtype,
|
|
239
|
+
url,
|
|
240
|
+
confidence,
|
|
241
|
+
evidence,
|
|
242
|
+
message: `${subtype === 'unknown' ? 'CAPTCHA' : subtype} challenge at ${hostnameOf(url)}. Solve it in the browser tab, then tell me when ready.`,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function detect2FA(text, url) {
|
|
246
|
+
const lowerText = lowercase(text);
|
|
247
|
+
const lowerUrl = lowercase(url);
|
|
248
|
+
const textHit = matchesAny(lowerText, TWOFA_TEXT_PATTERNS);
|
|
249
|
+
const urlHit = matchesAny(lowerUrl, TWOFA_URL_PATTERNS);
|
|
250
|
+
const domHit = matchesAny(lowerText, TWOFA_DOM_HINTS);
|
|
251
|
+
// Need at least ONE strong signal — text or URL match. DOM hint
|
|
252
|
+
// alone isn't enough (the text may be misleading on a docs page).
|
|
253
|
+
if (!textHit && !urlHit)
|
|
254
|
+
return null;
|
|
255
|
+
const evidence = [];
|
|
256
|
+
if (textHit)
|
|
257
|
+
evidence.push(`text:${textHit}`);
|
|
258
|
+
if (urlHit)
|
|
259
|
+
evidence.push(`url:${urlHit}`);
|
|
260
|
+
if (domHit)
|
|
261
|
+
evidence.push(`dom:${domHit}`);
|
|
262
|
+
const subtype = pickSubtype(lowerText, TWOFA_SUBTYPE_HINTS, 'unknown');
|
|
263
|
+
// Confidence: text+url+dom = 0.9, text+url = 0.8, text+dom = 0.75,
|
|
264
|
+
// text-only or url-only = 0.6.
|
|
265
|
+
let confidence = 0.6;
|
|
266
|
+
const signals = (textHit ? 1 : 0) + (urlHit ? 1 : 0) + (domHit ? 1 : 0);
|
|
267
|
+
if (signals === 2)
|
|
268
|
+
confidence = textHit && urlHit ? 0.8 : 0.75;
|
|
269
|
+
if (signals === 3)
|
|
270
|
+
confidence = 0.9;
|
|
271
|
+
return {
|
|
272
|
+
kind: '2fa',
|
|
273
|
+
subtype,
|
|
274
|
+
url,
|
|
275
|
+
confidence,
|
|
276
|
+
evidence,
|
|
277
|
+
message: `Two-factor code required at ${hostnameOf(url)}. Enter your ${subtype === 'totp' ? 'authenticator app code' : subtype === 'sms' ? 'SMS code' : 'verification code'} in the browser tab and tell me when complete.`,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function detectLogin(text, url) {
|
|
281
|
+
const lowerText = lowercase(text);
|
|
282
|
+
const lowerUrl = lowercase(url);
|
|
283
|
+
const textHit = matchesAny(lowerText, LOGIN_TEXT_PATTERNS);
|
|
284
|
+
const urlHit = matchesAny(lowerUrl, LOGIN_URL_PATTERNS);
|
|
285
|
+
const domHit = matchesAny(lowerText, LOGIN_DOM_HINTS);
|
|
286
|
+
if (!textHit && !urlHit)
|
|
287
|
+
return null;
|
|
288
|
+
const evidence = [];
|
|
289
|
+
if (textHit)
|
|
290
|
+
evidence.push(`text:${textHit}`);
|
|
291
|
+
if (urlHit)
|
|
292
|
+
evidence.push(`url:${urlHit}`);
|
|
293
|
+
if (domHit)
|
|
294
|
+
evidence.push(`dom:${domHit}`);
|
|
295
|
+
// Subtype: prefer text-marker match, then check URL for oauth/sso
|
|
296
|
+
// indicators (a `/oauth` or `/sso` URL is a strong OAuth signal
|
|
297
|
+
// even when the visible text is generic like "Authorize access").
|
|
298
|
+
let subtype = pickSubtype(lowerText, LOGIN_SUBTYPE_HINTS, '');
|
|
299
|
+
if (!subtype) {
|
|
300
|
+
if (lowerUrl.includes('oauth') || lowerUrl.includes('sso')) {
|
|
301
|
+
subtype = 'oauth';
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
subtype = 'password';
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
let confidence = 0.6;
|
|
308
|
+
const signals = (textHit ? 1 : 0) + (urlHit ? 1 : 0) + (domHit ? 1 : 0);
|
|
309
|
+
if (signals === 2)
|
|
310
|
+
confidence = 0.8;
|
|
311
|
+
if (signals === 3)
|
|
312
|
+
confidence = 0.9;
|
|
313
|
+
return {
|
|
314
|
+
kind: 'login',
|
|
315
|
+
subtype,
|
|
316
|
+
url,
|
|
317
|
+
confidence,
|
|
318
|
+
evidence,
|
|
319
|
+
message: `Sign-in required at ${hostnameOf(url)}. Authenticate in the browser tab and let me know when done.`,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function detectVerify(text, url) {
|
|
323
|
+
const lowerText = lowercase(text);
|
|
324
|
+
const lowerUrl = lowercase(url);
|
|
325
|
+
const textHit = matchesAny(lowerText, VERIFY_TEXT_PATTERNS);
|
|
326
|
+
const urlHit = matchesAny(lowerUrl, VERIFY_URL_PATTERNS);
|
|
327
|
+
if (!textHit && !urlHit)
|
|
328
|
+
return null;
|
|
329
|
+
const evidence = [];
|
|
330
|
+
if (textHit)
|
|
331
|
+
evidence.push(`text:${textHit}`);
|
|
332
|
+
if (urlHit)
|
|
333
|
+
evidence.push(`url:${urlHit}`);
|
|
334
|
+
const subtype = pickSubtype(lowerText, VERIFY_SUBTYPE_HINTS, 'unknown');
|
|
335
|
+
// Url-only is the weaker case here (lots of /verify URLs do other
|
|
336
|
+
// things), so URL-only matches need text-marker reinforcement to
|
|
337
|
+
// reach 0.6+ confidence.
|
|
338
|
+
let confidence = 0.5;
|
|
339
|
+
if (textHit && urlHit)
|
|
340
|
+
confidence = 0.85;
|
|
341
|
+
else if (textHit)
|
|
342
|
+
confidence = 0.7;
|
|
343
|
+
return {
|
|
344
|
+
kind: 'verification',
|
|
345
|
+
subtype,
|
|
346
|
+
url,
|
|
347
|
+
confidence,
|
|
348
|
+
evidence,
|
|
349
|
+
message: `Identity verification required at ${hostnameOf(url)}. Complete the verification in the browser tab and tell me when done.`,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function detectConsent(text, url) {
|
|
353
|
+
const lowerText = lowercase(text);
|
|
354
|
+
const lowerUrl = lowercase(url);
|
|
355
|
+
const textHit = matchesAny(lowerText, CONSENT_TEXT_PATTERNS);
|
|
356
|
+
const urlHit = matchesAny(lowerUrl, CONSENT_URL_PATTERNS);
|
|
357
|
+
if (!textHit && !urlHit)
|
|
358
|
+
return null;
|
|
359
|
+
const evidence = [];
|
|
360
|
+
if (textHit)
|
|
361
|
+
evidence.push(`text:${textHit}`);
|
|
362
|
+
if (urlHit)
|
|
363
|
+
evidence.push(`url:${urlHit}`);
|
|
364
|
+
let confidence = 0.5;
|
|
365
|
+
if (textHit && urlHit)
|
|
366
|
+
confidence = 0.8;
|
|
367
|
+
else if (textHit)
|
|
368
|
+
confidence = 0.65;
|
|
369
|
+
return {
|
|
370
|
+
kind: 'consent',
|
|
371
|
+
subtype: 'cookies',
|
|
372
|
+
url,
|
|
373
|
+
confidence,
|
|
374
|
+
evidence,
|
|
375
|
+
message: `Consent banner at ${hostnameOf(url)}. Dismiss the cookie/privacy banner in the browser tab — I can retry afterward.`,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
// ── Orchestrator ───────────────────────────────────────────────────────────
|
|
379
|
+
/**
|
|
380
|
+
* Detect the highest-priority manual blocker on a page. Priority
|
|
381
|
+
* order: captcha > 2fa > login > verification > consent. Returns
|
|
382
|
+
* null when no tier matches.
|
|
383
|
+
*
|
|
384
|
+
* Pure function — same inputs always produce the same output.
|
|
385
|
+
* Public for unit tests + the HOC's per-action detection call.
|
|
386
|
+
*/
|
|
387
|
+
function detectBlocker(input) {
|
|
388
|
+
const text = input.text ?? '';
|
|
389
|
+
const url = input.url ?? '';
|
|
390
|
+
// Priority pipeline — first non-null wins.
|
|
391
|
+
return (detectCaptcha(text, url) ??
|
|
392
|
+
detect2FA(text, url) ??
|
|
393
|
+
detectLogin(text, url) ??
|
|
394
|
+
detectVerify(text, url) ??
|
|
395
|
+
detectConsent(text, url));
|
|
396
|
+
}
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.browserClickTool = void 0;
|
|
19
19
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
20
|
-
|
|
20
|
+
const _observer_1 = require("./_observer");
|
|
21
|
+
const _browserClickTool = {
|
|
21
22
|
schema: {
|
|
22
23
|
name: 'browser_click',
|
|
23
24
|
description: 'Click an element by CSS selector or visible text. Use target="first_result" to click the first organic search result on supported engines.',
|
|
@@ -35,6 +36,18 @@ exports.browserClickTool = {
|
|
|
35
36
|
category: 'browser',
|
|
36
37
|
mutates: true,
|
|
37
38
|
toolset: 'browser',
|
|
39
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
40
|
+
buildPreview(args) {
|
|
41
|
+
const target = String(args.target ?? args.selector ?? '');
|
|
42
|
+
return {
|
|
43
|
+
tool: 'browser_click',
|
|
44
|
+
args,
|
|
45
|
+
riskTier: 'caution',
|
|
46
|
+
sideEffects: [{ type: 'browser_action', action: 'click', target }],
|
|
47
|
+
detectedRisks: [],
|
|
48
|
+
summary: `Would click browser element: ${target}`,
|
|
49
|
+
};
|
|
50
|
+
},
|
|
38
51
|
async execute(args) {
|
|
39
52
|
const target = String(args.target ?? args.selector ?? '').trim();
|
|
40
53
|
if (!target)
|
|
@@ -51,3 +64,7 @@ exports.browserClickTool = {
|
|
|
51
64
|
return { success: false, error: r.error, target };
|
|
52
65
|
},
|
|
53
66
|
};
|
|
67
|
+
// v4.3 Phase 1 — observer HOC captures pre/post page state when
|
|
68
|
+
// browser depth is enabled (default ON; opt-out via
|
|
69
|
+
// AIDEN_BROWSER_DEPTH=0) and embeds it as a `browserState` sidecar.
|
|
70
|
+
exports.browserClickTool = (0, _observer_1.withBrowserState)(_browserClickTool);
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.browserCloseTool = void 0;
|
|
18
18
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
19
|
-
|
|
19
|
+
const _observer_1 = require("./_observer");
|
|
20
|
+
const _browserCloseTool = {
|
|
20
21
|
schema: {
|
|
21
22
|
name: 'browser_close',
|
|
22
23
|
description: 'Close the persistent browser session. The next browser tool will start a new one.',
|
|
@@ -25,6 +26,17 @@ exports.browserCloseTool = {
|
|
|
25
26
|
category: 'browser',
|
|
26
27
|
mutates: true,
|
|
27
28
|
toolset: 'browser',
|
|
29
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
30
|
+
buildPreview(args) {
|
|
31
|
+
return {
|
|
32
|
+
tool: 'browser_close',
|
|
33
|
+
args,
|
|
34
|
+
riskTier: 'caution',
|
|
35
|
+
sideEffects: [{ type: 'browser_action', action: 'close' }],
|
|
36
|
+
detectedRisks: [],
|
|
37
|
+
summary: 'Would close the browser session',
|
|
38
|
+
};
|
|
39
|
+
},
|
|
28
40
|
async execute() {
|
|
29
41
|
try {
|
|
30
42
|
await (0, playwrightBridge_1.pwClose)();
|
|
@@ -36,3 +48,8 @@ exports.browserCloseTool = {
|
|
|
36
48
|
}
|
|
37
49
|
},
|
|
38
50
|
};
|
|
51
|
+
// v4.3 Phase 1 — observer HOC. After close the post-snapshot will
|
|
52
|
+
// either spin up a fresh context (and return null on the first call
|
|
53
|
+
// since the page is blank) or fail cleanly — either way the sidecar
|
|
54
|
+
// just doesn't embed. Tiny overhead, uniform pattern.
|
|
55
|
+
exports.browserCloseTool = (0, _observer_1.withBrowserState)(_browserCloseTool);
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.browserExtractTool = void 0;
|
|
20
20
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
21
|
-
|
|
21
|
+
const _observer_1 = require("./_observer");
|
|
22
|
+
const _browserExtractTool = {
|
|
22
23
|
schema: {
|
|
23
24
|
name: 'browser_extract',
|
|
24
25
|
description: 'Extract the visible text content of the current browser page. Requires the browser to be on a page (navigate first using a Phase-8 navigation tool, or via the search-then-click flow).',
|
|
@@ -30,6 +31,7 @@ exports.browserExtractTool = {
|
|
|
30
31
|
category: 'browser',
|
|
31
32
|
mutates: false,
|
|
32
33
|
toolset: 'browser',
|
|
34
|
+
riskTier: 'safe', // v4.4 Phase 1
|
|
33
35
|
async execute() {
|
|
34
36
|
const r = await (0, playwrightBridge_1.pwSnapshot)();
|
|
35
37
|
if (r.ok)
|
|
@@ -37,3 +39,5 @@ exports.browserExtractTool = {
|
|
|
37
39
|
return { success: false, error: r.error };
|
|
38
40
|
},
|
|
39
41
|
};
|
|
42
|
+
// v4.3 Phase 1 — observer HOC.
|
|
43
|
+
exports.browserExtractTool = (0, _observer_1.withBrowserState)(_browserExtractTool);
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.browserFillTool = void 0;
|
|
19
19
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
20
|
-
|
|
20
|
+
const _observer_1 = require("./_observer");
|
|
21
|
+
const _browserFillTool = {
|
|
21
22
|
schema: {
|
|
22
23
|
name: 'browser_fill',
|
|
23
24
|
description: 'Fill multiple form fields. Pass `fields` as an object mapping CSS selectors to text values.',
|
|
@@ -35,6 +36,19 @@ exports.browserFillTool = {
|
|
|
35
36
|
category: 'browser',
|
|
36
37
|
mutates: true,
|
|
37
38
|
toolset: 'browser',
|
|
39
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
40
|
+
buildPreview(args) {
|
|
41
|
+
const fields = (args.fields ?? {});
|
|
42
|
+
const keys = fields && typeof fields === 'object' ? Object.keys(fields) : [];
|
|
43
|
+
return {
|
|
44
|
+
tool: 'browser_fill',
|
|
45
|
+
args,
|
|
46
|
+
riskTier: 'caution',
|
|
47
|
+
sideEffects: [{ type: 'browser_action', action: 'fill', target: keys.join(', ') }],
|
|
48
|
+
detectedRisks: [],
|
|
49
|
+
summary: `Would fill ${keys.length} form field${keys.length === 1 ? '' : 's'}: ${keys.join(', ')}`,
|
|
50
|
+
};
|
|
51
|
+
},
|
|
38
52
|
async execute(args) {
|
|
39
53
|
const fields = (args.fields ?? {});
|
|
40
54
|
if (!fields || typeof fields !== 'object' || Array.isArray(fields)) {
|
|
@@ -57,3 +71,5 @@ exports.browserFillTool = {
|
|
|
57
71
|
return { success: true, filled, count: filled.length };
|
|
58
72
|
},
|
|
59
73
|
};
|
|
74
|
+
// v4.3 Phase 1 — observer HOC.
|
|
75
|
+
exports.browserFillTool = (0, _observer_1.withBrowserState)(_browserFillTool);
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.browserGetUrlTool = void 0;
|
|
18
18
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
19
|
-
|
|
19
|
+
const _observer_1 = require("./_observer");
|
|
20
|
+
const _browserGetUrlTool = {
|
|
20
21
|
schema: {
|
|
21
22
|
name: 'browser_get_url',
|
|
22
23
|
description: 'Return the URL of the page currently loaded in the browser. Useful for verifying navigation succeeded after a click.',
|
|
@@ -28,6 +29,7 @@ exports.browserGetUrlTool = {
|
|
|
28
29
|
category: 'browser',
|
|
29
30
|
mutates: false,
|
|
30
31
|
toolset: 'browser',
|
|
32
|
+
riskTier: 'safe', // v4.4 Phase 1
|
|
31
33
|
async execute() {
|
|
32
34
|
const r = await (0, playwrightBridge_1.pwGetUrl)();
|
|
33
35
|
if (r.ok)
|
|
@@ -35,3 +37,5 @@ exports.browserGetUrlTool = {
|
|
|
35
37
|
return { success: false, error: r.error };
|
|
36
38
|
},
|
|
37
39
|
};
|
|
40
|
+
// v4.3 Phase 1 — observer HOC.
|
|
41
|
+
exports.browserGetUrlTool = (0, _observer_1.withBrowserState)(_browserGetUrlTool);
|
|
@@ -18,7 +18,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
18
18
|
exports.browserNavigateTool = void 0;
|
|
19
19
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
20
20
|
const captchaCheck_1 = require("./captchaCheck");
|
|
21
|
-
|
|
21
|
+
const _observer_1 = require("./_observer");
|
|
22
|
+
const _browserNavigateTool = {
|
|
22
23
|
schema: {
|
|
23
24
|
name: 'browser_navigate',
|
|
24
25
|
description: 'Navigate the browser to a URL. Reuses the active tab; opens one if none exists. ' +
|
|
@@ -35,6 +36,18 @@ exports.browserNavigateTool = {
|
|
|
35
36
|
category: 'browser',
|
|
36
37
|
mutates: true,
|
|
37
38
|
toolset: 'browser',
|
|
39
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
40
|
+
buildPreview(args) {
|
|
41
|
+
const url = String(args.url ?? '');
|
|
42
|
+
return {
|
|
43
|
+
tool: 'browser_navigate',
|
|
44
|
+
args,
|
|
45
|
+
riskTier: 'caution',
|
|
46
|
+
sideEffects: [{ type: 'browser_action', action: 'navigate', url }],
|
|
47
|
+
detectedRisks: [],
|
|
48
|
+
summary: `Would navigate browser to: ${url}`,
|
|
49
|
+
};
|
|
50
|
+
},
|
|
38
51
|
async execute(args) {
|
|
39
52
|
const url = String(args.url ?? '').trim();
|
|
40
53
|
if (!url)
|
|
@@ -73,3 +86,5 @@ exports.browserNavigateTool = {
|
|
|
73
86
|
return { success: true, url: r.url };
|
|
74
87
|
},
|
|
75
88
|
};
|
|
89
|
+
// v4.3 Phase 1 — observer HOC.
|
|
90
|
+
exports.browserNavigateTool = (0, _observer_1.withBrowserState)(_browserNavigateTool);
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
exports.browserScreenshotTool = void 0;
|
|
24
24
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
25
|
-
|
|
25
|
+
const _observer_1 = require("./_observer");
|
|
26
|
+
const _browserScreenshotTool = {
|
|
26
27
|
schema: {
|
|
27
28
|
name: 'browser_screenshot',
|
|
28
29
|
description: 'Take a screenshot of the current browser page (the page you previously navigated to). Saves to disk and returns the file path. Requires that the browser was opened earlier in this session.',
|
|
@@ -34,6 +35,7 @@ exports.browserScreenshotTool = {
|
|
|
34
35
|
category: 'browser',
|
|
35
36
|
mutates: false,
|
|
36
37
|
toolset: 'browser',
|
|
38
|
+
riskTier: 'safe', // v4.4 Phase 1
|
|
37
39
|
async execute() {
|
|
38
40
|
const r = await (0, playwrightBridge_1.pwScreenshot)();
|
|
39
41
|
if (r.ok)
|
|
@@ -41,3 +43,5 @@ exports.browserScreenshotTool = {
|
|
|
41
43
|
return { success: false, error: r.error };
|
|
42
44
|
},
|
|
43
45
|
};
|
|
46
|
+
// v4.3 Phase 1 — observer HOC.
|
|
47
|
+
exports.browserScreenshotTool = (0, _observer_1.withBrowserState)(_browserScreenshotTool);
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.browserScrollTool = void 0;
|
|
19
19
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
20
|
-
|
|
20
|
+
const _observer_1 = require("./_observer");
|
|
21
|
+
const _browserScrollTool = {
|
|
21
22
|
schema: {
|
|
22
23
|
name: 'browser_scroll',
|
|
23
24
|
description: 'Scroll the browser page (or a specific element via `selector`). `direction` ∈ up|down|top|bottom; `amount` is pixels for up/down (default 500).',
|
|
@@ -43,6 +44,20 @@ exports.browserScrollTool = {
|
|
|
43
44
|
category: 'browser',
|
|
44
45
|
mutates: true,
|
|
45
46
|
toolset: 'browser',
|
|
47
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
48
|
+
buildPreview(args) {
|
|
49
|
+
const direction = String(args.direction ?? 'down');
|
|
50
|
+
const amount = typeof args.amount === 'number' ? args.amount : 500;
|
|
51
|
+
const selector = typeof args.selector === 'string' ? args.selector : '';
|
|
52
|
+
return {
|
|
53
|
+
tool: 'browser_scroll',
|
|
54
|
+
args,
|
|
55
|
+
riskTier: 'caution',
|
|
56
|
+
sideEffects: [{ type: 'browser_action', action: `scroll:${direction}`, target: selector || 'window' }],
|
|
57
|
+
detectedRisks: [],
|
|
58
|
+
summary: `Would scroll browser ${direction}${direction === 'up' || direction === 'down' ? ` ${amount}px` : ''}${selector ? ` (${selector})` : ''}`,
|
|
59
|
+
};
|
|
60
|
+
},
|
|
46
61
|
async execute(args) {
|
|
47
62
|
const directionRaw = String(args.direction ?? 'down').toLowerCase();
|
|
48
63
|
const direction = ['up', 'down', 'top', 'bottom'].includes(directionRaw)
|
|
@@ -56,3 +71,5 @@ exports.browserScrollTool = {
|
|
|
56
71
|
return { success: false, error: r.error };
|
|
57
72
|
},
|
|
58
73
|
};
|
|
74
|
+
// v4.3 Phase 1 — observer HOC.
|
|
75
|
+
exports.browserScrollTool = (0, _observer_1.withBrowserState)(_browserScrollTool);
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.browserTypeTool = void 0;
|
|
17
17
|
const playwrightBridge_1 = require("../../../core/playwrightBridge");
|
|
18
|
-
|
|
18
|
+
const _observer_1 = require("./_observer");
|
|
19
|
+
const _browserTypeTool = {
|
|
19
20
|
schema: {
|
|
20
21
|
name: 'browser_type',
|
|
21
22
|
description: 'Type text into a browser input identified by CSS selector. Replaces existing value.',
|
|
@@ -34,6 +35,19 @@ exports.browserTypeTool = {
|
|
|
34
35
|
category: 'browser',
|
|
35
36
|
mutates: true,
|
|
36
37
|
toolset: 'browser',
|
|
38
|
+
riskTier: 'caution', // v4.4 Phase 1
|
|
39
|
+
buildPreview(args) {
|
|
40
|
+
const selector = String(args.selector ?? 'input');
|
|
41
|
+
const text = String(args.text ?? '');
|
|
42
|
+
return {
|
|
43
|
+
tool: 'browser_type',
|
|
44
|
+
args,
|
|
45
|
+
riskTier: 'caution',
|
|
46
|
+
sideEffects: [{ type: 'browser_action', action: 'type', target: selector }],
|
|
47
|
+
detectedRisks: [],
|
|
48
|
+
summary: `Would type ${text.length} chars into ${selector}`,
|
|
49
|
+
};
|
|
50
|
+
},
|
|
37
51
|
async execute(args) {
|
|
38
52
|
const selector = String(args.selector ?? 'input').trim();
|
|
39
53
|
const text = String(args.text ?? '');
|
|
@@ -43,3 +57,5 @@ exports.browserTypeTool = {
|
|
|
43
57
|
return { success: false, error: r.error, selector };
|
|
44
58
|
},
|
|
45
59
|
};
|
|
60
|
+
// v4.3 Phase 1 — observer HOC captures pre/post page state.
|
|
61
|
+
exports.browserTypeTool = (0, _observer_1.withBrowserState)(_browserTypeTool);
|