@anweat/dsh-browser 0.1.15 → 0.2.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +272 -75
- package/assets/skills/dsh-browser/SKILL.md +120 -0
- package/assets/skills/dsh-browser/references/develop.md +48 -0
- package/assets/skills/dsh-browser/references/observe.md +91 -0
- package/assets/skills/dsh-browser/references/opencli.md +25 -0
- package/assets/skills/dsh-browser/references/recipes.md +149 -0
- package/assets/skills/dsh-browser/references/userscripts.md +44 -0
- package/cordis.patch.yml +4 -0
- package/lib/actions/act.d.ts +3 -0
- package/lib/actions/act.js +147 -0
- package/lib/actions/act.js.map +1 -0
- package/lib/actions/automation.d.ts +3 -0
- package/lib/actions/automation.js +356 -0
- package/lib/actions/automation.js.map +1 -0
- package/lib/actions/crawl.d.ts +3 -0
- package/lib/actions/crawl.js +28 -0
- package/lib/actions/crawl.js.map +1 -0
- package/lib/actions/errors.d.ts +53 -0
- package/lib/actions/errors.js +178 -0
- package/lib/actions/errors.js.map +1 -0
- package/lib/actions/index-view.d.ts +42 -0
- package/lib/actions/index-view.js +268 -0
- package/lib/actions/index-view.js.map +1 -0
- package/lib/actions/inspect.d.ts +3 -0
- package/lib/actions/inspect.js +35 -0
- package/lib/actions/inspect.js.map +1 -0
- package/lib/actions/observe.d.ts +3 -0
- package/lib/actions/observe.js +121 -0
- package/lib/actions/observe.js.map +1 -0
- package/lib/actions/opencli.d.ts +3 -0
- package/lib/actions/opencli.js +51 -0
- package/lib/actions/opencli.js.map +1 -0
- package/lib/actions/registry.d.ts +35 -0
- package/lib/actions/registry.js +89 -0
- package/lib/actions/registry.js.map +1 -0
- package/lib/actions/run.d.ts +34 -0
- package/lib/actions/run.js +226 -0
- package/lib/actions/run.js.map +1 -0
- package/lib/actions/runtime.d.ts +3 -0
- package/lib/actions/runtime.js +33 -0
- package/lib/actions/runtime.js.map +1 -0
- package/lib/actions/schema.d.ts +31 -0
- package/lib/actions/schema.js +309 -0
- package/lib/actions/schema.js.map +1 -0
- package/lib/actions/script.d.ts +3 -0
- package/lib/actions/script.js +97 -0
- package/lib/actions/script.js.map +1 -0
- package/lib/actions/shared.d.ts +31 -0
- package/lib/actions/shared.js +45 -0
- package/lib/actions/shared.js.map +1 -0
- package/lib/actions/surface.d.ts +22 -0
- package/lib/actions/surface.js +18 -0
- package/lib/actions/surface.js.map +1 -0
- package/lib/actions/target.d.ts +3 -0
- package/lib/actions/target.js +66 -0
- package/lib/actions/target.js.map +1 -0
- package/lib/actions/types.d.ts +181 -0
- package/lib/actions/types.js +48 -0
- package/lib/actions/types.js.map +1 -0
- package/lib/activation-rules.d.ts +29 -0
- package/lib/activation-rules.js +33 -0
- package/lib/activation-rules.js.map +1 -0
- package/lib/approval-policy.d.ts +40 -2
- package/lib/approval-policy.js +184 -97
- package/lib/approval-policy.js.map +1 -1
- package/lib/automation-assets-rpc.d.ts +8 -2
- package/lib/automation-assets-rpc.js +67 -6
- package/lib/automation-assets-rpc.js.map +1 -1
- package/lib/automation-assets.d.ts +152 -4
- package/lib/automation-assets.js +255 -15
- package/lib/automation-assets.js.map +1 -1
- package/lib/automation-convert.d.ts +23 -0
- package/lib/automation-convert.js +110 -0
- package/lib/automation-convert.js.map +1 -0
- package/lib/automation-development.d.ts +26 -0
- package/lib/automation-development.js +47 -0
- package/lib/automation-development.js.map +1 -1
- package/lib/automation-execution.d.ts +57 -1
- package/lib/automation-execution.js +167 -11
- package/lib/automation-execution.js.map +1 -1
- package/lib/automation-journal.d.ts +92 -0
- package/lib/automation-journal.js +449 -0
- package/lib/automation-journal.js.map +1 -0
- package/lib/automation-v2.d.ts +138 -0
- package/lib/automation-v2.js +631 -0
- package/lib/automation-v2.js.map +1 -0
- package/lib/automation.d.ts +82 -5
- package/lib/automation.js +239 -82
- package/lib/automation.js.map +1 -1
- package/lib/browser-service.d.ts +304 -32
- package/lib/browser-service.js +631 -182
- package/lib/browser-service.js.map +1 -1
- package/lib/client/SettingsCard.js +95 -57
- package/lib/client/SettingsCard.js.map +1 -1
- package/lib/client/asset-editor.d.ts +55 -0
- package/lib/client/asset-editor.js +101 -0
- package/lib/client/asset-editor.js.map +1 -0
- package/lib/client/automation-assets-client.d.ts +99 -2
- package/lib/client/automation-assets-client.js +243 -10
- package/lib/client/automation-assets-client.js.map +1 -1
- package/lib/client/form.d.ts +48 -4
- package/lib/client/form.js +142 -29
- package/lib/client/form.js.map +1 -1
- package/lib/client/index.d.ts +25 -2
- package/lib/client/index.js +5 -1
- package/lib/client/index.js.map +1 -1
- package/lib/client/locales.d.ts +85 -6
- package/lib/client/locales.js +64 -12
- package/lib/client/locales.js.map +1 -1
- package/lib/client/prompts-form.d.ts +67 -0
- package/lib/client/prompts-form.js +140 -0
- package/lib/client/prompts-form.js.map +1 -0
- package/lib/client/prompts-status-client.d.ts +34 -0
- package/lib/client/prompts-status-client.js +53 -0
- package/lib/client/prompts-status-client.js.map +1 -0
- package/lib/client.js +1914 -329
- package/lib/client.js.map +1 -1
- package/lib/config.d.ts +50 -1
- package/lib/config.js +31 -1
- package/lib/config.js.map +1 -1
- package/lib/dialogs.d.ts +37 -0
- package/lib/dialogs.js +73 -0
- package/lib/dialogs.js.map +1 -0
- package/lib/freedom.d.ts +23 -7
- package/lib/freedom.js +48 -59
- package/lib/freedom.js.map +1 -1
- package/lib/index.d.ts +4 -4
- package/lib/index.js +36 -10
- package/lib/index.js.map +1 -1
- package/lib/journal.d.ts +109 -0
- package/lib/journal.js +238 -0
- package/lib/journal.js.map +1 -0
- package/lib/locator.d.ts +82 -0
- package/lib/locator.js +190 -0
- package/lib/locator.js.map +1 -0
- package/lib/observe-script.d.ts +27 -0
- package/lib/observe-script.js +565 -0
- package/lib/observe-script.js.map +1 -0
- package/lib/observe.d.ts +179 -0
- package/lib/observe.js +368 -0
- package/lib/observe.js.map +1 -0
- package/lib/policy-keys.d.ts +30 -0
- package/lib/policy-keys.js +34 -0
- package/lib/policy-keys.js.map +1 -0
- package/lib/prompt-limits.d.ts +30 -0
- package/lib/prompt-limits.js +31 -0
- package/lib/prompt-limits.js.map +1 -0
- package/lib/prompts.d.ts +131 -0
- package/lib/prompts.js +295 -0
- package/lib/prompts.js.map +1 -0
- package/lib/skill.d.ts +100 -0
- package/lib/skill.js +181 -0
- package/lib/skill.js.map +1 -0
- package/lib/tool-defs.d.ts +72 -0
- package/lib/tool-defs.js +67 -0
- package/lib/tool-defs.js.map +1 -0
- package/lib/tools.d.ts +19 -4
- package/lib/tools.js +124 -922
- package/lib/tools.js.map +1 -1
- package/package.json +35 -30
- package/scripts/dump-prompts.mjs +29 -0
- package/scripts/measure-tool-surface.mjs +190 -0
package/lib/browser-service.d.ts
CHANGED
|
@@ -20,11 +20,17 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { type CliResult } from './deps.ts';
|
|
22
22
|
import type { ResolvedConfig } from './config.ts';
|
|
23
|
-
import { type
|
|
23
|
+
import { type ResolvedAuthProfile } from './auth-profiles.ts';
|
|
24
|
+
import { type ResolvedRulePack } from './rule-packs.ts';
|
|
25
|
+
import { type AnyRecipeStep, type RecipeRunResult, type RecipeStepResult } from './automation.ts';
|
|
26
|
+
import type { OutputSpec, Postcondition } from './automation-v2.ts';
|
|
24
27
|
import { type UserscriptValidation } from './scripts.ts';
|
|
25
28
|
import { type AutomationMode } from './freedom.ts';
|
|
26
29
|
import { type OpencliCatalogFilter, type OpencliCatalogItem } from './opencli-catalog.ts';
|
|
27
30
|
import { UsageGovernor } from './usage-policy.ts';
|
|
31
|
+
import { type BrowserTarget } from './locator.ts';
|
|
32
|
+
import { SessionJournal } from './journal.ts';
|
|
33
|
+
import { type ObserveRegion, type ObserveSection } from './observe.ts';
|
|
28
34
|
export interface RenderRule {
|
|
29
35
|
hostname: string;
|
|
30
36
|
contentSelectors: string[];
|
|
@@ -59,9 +65,21 @@ export interface InteractiveState {
|
|
|
59
65
|
url: string;
|
|
60
66
|
title: string;
|
|
61
67
|
text: string;
|
|
68
|
+
/** The session page this state describes (`t1`, `t2`, ...). Absent only when the page is already gone. */
|
|
69
|
+
targetId?: string;
|
|
70
|
+
/**
|
|
71
|
+
* The page's generation when this state was read. It changes whenever the page's main frame navigates
|
|
72
|
+
* (see {@link SessionState.generationClock}); pass it back as `expectGeneration` to refuse acting on a page
|
|
73
|
+
* that moved on since it was observed.
|
|
74
|
+
*/
|
|
75
|
+
generation?: number;
|
|
62
76
|
screenshotPath?: string;
|
|
77
|
+
/** The page the action ran on closed itself (a popup's own close button): url/title/text describe the page the session fell back to, or are empty. */
|
|
78
|
+
closedPage?: true;
|
|
63
79
|
}
|
|
64
|
-
|
|
80
|
+
/** The page state after a recipe, plus what the run did ({@link RecipeRunResult}). */
|
|
81
|
+
export interface RecipeServiceResult extends InteractiveState, RecipeRunResult {
|
|
82
|
+
/** Same array as `completedSteps`; kept for service consumers written before B2. */
|
|
65
83
|
steps: RecipeStepResult[];
|
|
66
84
|
}
|
|
67
85
|
export interface ScriptRunResult {
|
|
@@ -82,21 +100,7 @@ export interface EvaluateResult {
|
|
|
82
100
|
export interface FileUploadResult extends InteractiveState {
|
|
83
101
|
files: string[];
|
|
84
102
|
}
|
|
85
|
-
export
|
|
86
|
-
selector?: string;
|
|
87
|
-
name?: string;
|
|
88
|
-
url?: string;
|
|
89
|
-
}
|
|
90
|
-
export interface BrowserLocatorSpec {
|
|
91
|
-
selector?: string;
|
|
92
|
-
role?: string;
|
|
93
|
-
name?: string;
|
|
94
|
-
text?: string;
|
|
95
|
-
label?: string;
|
|
96
|
-
exact?: boolean;
|
|
97
|
-
frame?: BrowserFrameSpec;
|
|
98
|
-
}
|
|
99
|
-
export type BrowserTarget = string | BrowserLocatorSpec;
|
|
103
|
+
export type { BrowserFrameSpec, BrowserLocatorSpec, BrowserTarget } from './locator.ts';
|
|
100
104
|
export interface BrowserConsoleRecord {
|
|
101
105
|
type: string;
|
|
102
106
|
text: string;
|
|
@@ -157,7 +161,10 @@ export interface BrowserStatus {
|
|
|
157
161
|
opencliInstalled: boolean;
|
|
158
162
|
opencliEntryPath?: string;
|
|
159
163
|
automationMode: AutomationMode;
|
|
164
|
+
/** Tool names registered for the model under the configured toolSurface. */
|
|
160
165
|
exposedTools: string[];
|
|
166
|
+
/** Browser actions (`group.action`) the model can run. */
|
|
167
|
+
exposedActions: string[];
|
|
161
168
|
directInteractionPolicy: 'deny' | 'ask' | 'allow';
|
|
162
169
|
mutatingRecipePolicy: 'deny' | 'ask' | 'allow';
|
|
163
170
|
externalUserscriptPolicy: 'deny' | 'ask' | 'allow';
|
|
@@ -180,25 +187,149 @@ export interface BrowserStatus {
|
|
|
180
187
|
activeUrl?: string;
|
|
181
188
|
activeAuthProfile?: string;
|
|
182
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* The interactive page state owned by ONE session.
|
|
192
|
+
*
|
|
193
|
+
* A single `BrowserService` instance is provided to every consumer, so before
|
|
194
|
+
* this existed two concurrent sessions shared one `activePage`: whichever
|
|
195
|
+
* session called `target.open` last owned the page, and the other session's
|
|
196
|
+
* `observe.read` / `script.evaluate` / `inspect.console` then operated on a
|
|
197
|
+
* page it never opened — including the other session's cookies and DOM.
|
|
198
|
+
*
|
|
199
|
+
* State is therefore keyed by session. The browser PROCESS stays shared on
|
|
200
|
+
* purpose: launching N Chromium processes costs hundreds of MB each, while one
|
|
201
|
+
* process with N `BrowserContext`s is what Chromium itself does for N profiles
|
|
202
|
+
* and is properly isolated (separate cookies, storage, cache, permissions).
|
|
203
|
+
* "Different tabs" would not be enough — pages in the SAME context share
|
|
204
|
+
* cookies and storage, so each session gets its own context, not just its own
|
|
205
|
+
* page.
|
|
206
|
+
*/
|
|
207
|
+
interface SessionState {
|
|
208
|
+
context?: any;
|
|
209
|
+
/** The ACTIVE page: the one every action targets. Always one of `pages` while set. */
|
|
210
|
+
page?: any;
|
|
211
|
+
/** Every open page of this session's context (the page it opened plus popups), in the order they appeared. */
|
|
212
|
+
pages: SessionPage[];
|
|
213
|
+
/** Counter behind the `t1`, `t2`, ... target ids of this session. */
|
|
214
|
+
nextTarget: number;
|
|
215
|
+
/**
|
|
216
|
+
* Source of page generations. A page takes the next value when it is tracked and again on every main-frame
|
|
217
|
+
* navigation (cross-document, reload, history back/forward, `location` assignment, `pushState`/`replaceState`,
|
|
218
|
+
* hash changes), so values only grow and never repeat inside a session, not even across pages: an
|
|
219
|
+
* `expectGeneration` from one page can never match another page by coincidence. Subframe navigation and
|
|
220
|
+
* DOM re-rendering do not change it.
|
|
221
|
+
*/
|
|
222
|
+
generationClock: number;
|
|
223
|
+
profile?: ResolvedAuthProfile;
|
|
224
|
+
rulePack?: ResolvedRulePack;
|
|
225
|
+
captureConsole: boolean;
|
|
226
|
+
captureNetwork: boolean;
|
|
227
|
+
capturedConsole: BrowserConsoleRecord[];
|
|
228
|
+
capturedRequests: BrowserRequestRecord[];
|
|
229
|
+
/** Monotonic tick of last use, for least-recently-used eviction. */
|
|
230
|
+
lastUsed: number;
|
|
231
|
+
}
|
|
232
|
+
/** One tracked page of a session. */
|
|
233
|
+
interface SessionPage {
|
|
234
|
+
id: string;
|
|
235
|
+
page: any;
|
|
236
|
+
generation: number;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Session key for a tool execution.
|
|
240
|
+
*
|
|
241
|
+
* `ToolExecution.agent` is documented as "the agent on whose behalf the call
|
|
242
|
+
* runs (set by the agent loop)". Two session identities hang off it and BOTH are
|
|
243
|
+
* the session, not the turn:
|
|
244
|
+
*
|
|
245
|
+
* - `agent.session.id` — the live `Agent` face exposes `readonly session:
|
|
246
|
+
* Session`, and `Session.id` is a `SessionId`. This is the path the
|
|
247
|
+
* automation-asset recorder already uses in production, so it is tried first.
|
|
248
|
+
* - `agent.id` — the base `Agent` contract documents `readonly id: SessionId`
|
|
249
|
+
* as "Session-backed Agent identity". Used as a fallback.
|
|
250
|
+
*
|
|
251
|
+
* A session therefore keeps ONE page across all of its turns, and two
|
|
252
|
+
* concurrent sessions never share one. Calls carrying no agent at all
|
|
253
|
+
* (automation-asset replays, non-agent dispatchers) land in one shared bucket,
|
|
254
|
+
* which is the pre-existing single-session behaviour rather than a new hazard.
|
|
255
|
+
*/
|
|
256
|
+
export declare function sessionKeyFor(agent: SessionIdentity | undefined): string;
|
|
257
|
+
/** The two shapes a live Agent presents for session identity. */
|
|
258
|
+
export interface SessionIdentity {
|
|
259
|
+
readonly id?: unknown;
|
|
260
|
+
readonly session?: {
|
|
261
|
+
readonly id?: unknown;
|
|
262
|
+
};
|
|
263
|
+
}
|
|
183
264
|
export declare class BrowserService {
|
|
184
265
|
private readonly config;
|
|
185
266
|
private browser;
|
|
186
267
|
private launching?;
|
|
187
|
-
|
|
188
|
-
private
|
|
189
|
-
|
|
190
|
-
private
|
|
268
|
+
/** Per-session interactive state. Replaces the former global activePage. */
|
|
269
|
+
private readonly sessions;
|
|
270
|
+
/** The tracked entry (target id, generation) of every page the service created. */
|
|
271
|
+
private readonly pageEntries;
|
|
272
|
+
private clock;
|
|
191
273
|
private readonly authProfiles;
|
|
192
274
|
private readonly usageGovernor;
|
|
193
275
|
private opencliCatalogCache?;
|
|
194
|
-
|
|
195
|
-
private
|
|
196
|
-
|
|
197
|
-
private
|
|
276
|
+
/** Per-session exploration journals (see src/journal.ts). Released with the session, never written to disk. */
|
|
277
|
+
private readonly journals;
|
|
278
|
+
/** How many sessions may hold a context+page at once before LRU eviction. */
|
|
279
|
+
private readonly sessionLimit;
|
|
198
280
|
constructor(config: ResolvedConfig);
|
|
199
281
|
available(): boolean;
|
|
282
|
+
/**
|
|
283
|
+
* This session's exploration journal, created on first use. It outlives `target.close` (the session is
|
|
284
|
+
* still the same) and is released when the session is evicted or the service closes. A session that never
|
|
285
|
+
* records anything costs nothing: journals are only created by the action dispatcher.
|
|
286
|
+
*/
|
|
287
|
+
journalFor(session: string): SessionJournal;
|
|
288
|
+
/** The active page of a session as `{targetId, generation, url}`, without opening or creating anything. */
|
|
289
|
+
pageStamp(session: string): {
|
|
290
|
+
targetId?: string;
|
|
291
|
+
generation?: number;
|
|
292
|
+
url?: string;
|
|
293
|
+
} | undefined;
|
|
294
|
+
/**
|
|
295
|
+
* Whether the control a fill/type would hit is a secret field (password, one-time code, name that says so).
|
|
296
|
+
* Best effort and quick: any trouble (no page, several matches, a slow page) answers false, and the journal
|
|
297
|
+
* still treats secret-looking values and secret-looking locators as sensitive.
|
|
298
|
+
*/
|
|
299
|
+
inputSensitivity(target: BrowserTarget, opts?: {
|
|
300
|
+
session?: string;
|
|
301
|
+
}): Promise<boolean>;
|
|
302
|
+
/**
|
|
303
|
+
* The state bucket belonging to a tool execution's session.
|
|
304
|
+
*
|
|
305
|
+
* Tools use this for the few operations that act on the bucket itself
|
|
306
|
+
* (`target.close`) rather than passing a key into a method.
|
|
307
|
+
*/
|
|
308
|
+
sessionState(agent: SessionIdentity | undefined): SessionState | undefined;
|
|
200
309
|
private assertEnabled;
|
|
201
310
|
private browserConnected;
|
|
311
|
+
/**
|
|
312
|
+
* The state bucket for one session, created on demand.
|
|
313
|
+
*
|
|
314
|
+
* Eviction is least-recently-used and never touches the caller's own bucket,
|
|
315
|
+
* so a session cannot have its page closed out from under it by a burst of
|
|
316
|
+
* other sessions.
|
|
317
|
+
*/
|
|
318
|
+
private state;
|
|
319
|
+
/**
|
|
320
|
+
* Look up an existing bucket WITHOUT creating one and WITHOUT evicting.
|
|
321
|
+
*
|
|
322
|
+
* Queries (`runtime.status`, `inspect.console`, `inspect.requests`) must go
|
|
323
|
+
* through this, not {@link state}. Creating a bucket for a session that only
|
|
324
|
+
* *asks* a question would both leak a slot and push a live session past the
|
|
325
|
+
* limit, so a read could evict the very page it was trying to describe.
|
|
326
|
+
*/
|
|
327
|
+
private peek;
|
|
328
|
+
/** Close the least-recently-used sessions that exceed the limit. */
|
|
329
|
+
private evictSessions;
|
|
330
|
+
/** Close one session's page+context without persisting its auth state. */
|
|
331
|
+
private disposeState;
|
|
332
|
+
/** Drop all per-session state after a browser-level failure. */
|
|
202
333
|
private clearActiveState;
|
|
203
334
|
private handleBrowserDisconnected;
|
|
204
335
|
private trackBrowser;
|
|
@@ -271,25 +402,65 @@ export declare class BrowserService {
|
|
|
271
402
|
rulePack?: string;
|
|
272
403
|
inputs?: Record<string, string>;
|
|
273
404
|
}): Promise<ScriptRunResult>;
|
|
405
|
+
/**
|
|
406
|
+
* Return the calling session's live page, creating one when needed.
|
|
407
|
+
*
|
|
408
|
+
* `session` is the key from {@link sessionKeyFor}. Every read and write below
|
|
409
|
+
* is confined to that bucket, which is what stops one session from observing
|
|
410
|
+
* or mutating another's page, cookies, console or network log.
|
|
411
|
+
*/
|
|
274
412
|
private ensureActivePage;
|
|
275
|
-
|
|
413
|
+
/**
|
|
414
|
+
* Add a page to the session's list and wire its capture and close handling.
|
|
415
|
+
* Idempotent: the context 'page' event and the explicit call both land here.
|
|
416
|
+
*/
|
|
417
|
+
private trackPage;
|
|
276
418
|
private resetCapture;
|
|
277
419
|
private resolveTarget;
|
|
420
|
+
/**
|
|
421
|
+
* Run an action on a strict locator. More than one match performs nothing and
|
|
422
|
+
* fails with LOCATOR_AMBIGUOUS plus a summary of the first candidates.
|
|
423
|
+
*/
|
|
424
|
+
private onTarget;
|
|
278
425
|
private screenshotFile;
|
|
279
426
|
private captureScreenshot;
|
|
427
|
+
/** `{targetId, generation}` of a tracked page (empty for a page the service does not track). */
|
|
428
|
+
private stamp;
|
|
429
|
+
/**
|
|
430
|
+
* Refuse to act when the page's generation is not the one the caller observed. Nothing has been done yet
|
|
431
|
+
* at this point, so the caller only needs to observe again.
|
|
432
|
+
*/
|
|
433
|
+
private assertGeneration;
|
|
280
434
|
private readState;
|
|
281
435
|
open(url: string, opts?: {
|
|
282
436
|
waitMs?: number;
|
|
283
437
|
authProfile?: string;
|
|
284
438
|
rulePack?: string;
|
|
285
439
|
capture?: readonly ('console' | 'network')[];
|
|
440
|
+
session?: string;
|
|
286
441
|
}): Promise<InteractiveState>;
|
|
287
442
|
click(target: BrowserTarget, opts?: {
|
|
443
|
+
expectGeneration?: number;
|
|
288
444
|
timeoutMs?: number;
|
|
289
445
|
waitMs?: number;
|
|
446
|
+
session?: string;
|
|
290
447
|
}): Promise<InteractiveState>;
|
|
291
448
|
type(target: BrowserTarget, text: string, opts?: {
|
|
449
|
+
expectGeneration?: number;
|
|
450
|
+
timeoutMs?: number;
|
|
451
|
+
session?: string;
|
|
452
|
+
}): Promise<InteractiveState>;
|
|
453
|
+
/** Type key by key (pressSequentially), so per-key handlers fire; unlike `type`, which replaces the whole value. */
|
|
454
|
+
typeKeys(target: BrowserTarget, text: string, opts?: {
|
|
455
|
+
expectGeneration?: number;
|
|
456
|
+
delayMs?: number;
|
|
457
|
+
timeoutMs?: number;
|
|
458
|
+
session?: string;
|
|
459
|
+
}): Promise<InteractiveState>;
|
|
460
|
+
clear(target: BrowserTarget, opts?: {
|
|
461
|
+
expectGeneration?: number;
|
|
292
462
|
timeoutMs?: number;
|
|
463
|
+
session?: string;
|
|
293
464
|
}): Promise<InteractiveState>;
|
|
294
465
|
wait(target: BrowserTarget | undefined, opts?: {
|
|
295
466
|
urlPattern?: string;
|
|
@@ -297,34 +468,95 @@ export declare class BrowserService {
|
|
|
297
468
|
timeMs?: number;
|
|
298
469
|
state?: 'visible' | 'hidden' | 'attached' | 'detached';
|
|
299
470
|
timeoutMs?: number;
|
|
471
|
+
session?: string;
|
|
300
472
|
}): Promise<InteractiveState>;
|
|
301
473
|
press(target: BrowserTarget | undefined, key: string, opts?: {
|
|
474
|
+
expectGeneration?: number;
|
|
302
475
|
timeoutMs?: number;
|
|
476
|
+
session?: string;
|
|
303
477
|
}): Promise<InteractiveState>;
|
|
304
478
|
select(target: BrowserTarget, values: readonly string[], opts?: {
|
|
479
|
+
expectGeneration?: number;
|
|
305
480
|
timeoutMs?: number;
|
|
481
|
+
session?: string;
|
|
306
482
|
}): Promise<InteractiveState>;
|
|
307
483
|
check(target: BrowserTarget, checked?: boolean, opts?: {
|
|
484
|
+
expectGeneration?: number;
|
|
308
485
|
timeoutMs?: number;
|
|
486
|
+
session?: string;
|
|
309
487
|
}): Promise<InteractiveState>;
|
|
310
488
|
hover(target: BrowserTarget, opts?: {
|
|
489
|
+
expectGeneration?: number;
|
|
311
490
|
timeoutMs?: number;
|
|
312
491
|
waitMs?: number;
|
|
492
|
+
session?: string;
|
|
313
493
|
}): Promise<InteractiveState>;
|
|
314
494
|
setFiles(target: BrowserTarget, files: readonly string[], opts?: {
|
|
495
|
+
expectGeneration?: number;
|
|
315
496
|
timeoutMs?: number;
|
|
497
|
+
session?: string;
|
|
316
498
|
}): Promise<FileUploadResult>;
|
|
317
499
|
evaluate(expression: string, opts?: {
|
|
318
500
|
timeoutMs?: number;
|
|
501
|
+
session?: string;
|
|
319
502
|
}): Promise<EvaluateResult>;
|
|
503
|
+
/**
|
|
504
|
+
* The pages this session holds: the one it opened plus any popup that page
|
|
505
|
+
* (or a later one) opened in the same context. Pure query: it never creates
|
|
506
|
+
* a bucket and never changes the active page.
|
|
507
|
+
*/
|
|
508
|
+
listTargets(opts?: {
|
|
509
|
+
session?: string;
|
|
510
|
+
}): Promise<{
|
|
511
|
+
targets: {
|
|
512
|
+
id: string;
|
|
513
|
+
url: string;
|
|
514
|
+
title: string;
|
|
515
|
+
active: boolean;
|
|
516
|
+
generation: number;
|
|
517
|
+
}[];
|
|
518
|
+
}>;
|
|
519
|
+
/** Make one of this session's pages the active page: every later action, read, and screenshot targets it. */
|
|
520
|
+
selectTarget(id: string, opts?: {
|
|
521
|
+
session?: string;
|
|
522
|
+
}): Promise<InteractiveState & {
|
|
523
|
+
id: string;
|
|
524
|
+
}>;
|
|
320
525
|
scroll(deltaY: number, opts?: {
|
|
526
|
+
expectGeneration?: number;
|
|
321
527
|
waitMs?: number;
|
|
528
|
+
session?: string;
|
|
529
|
+
}): Promise<InteractiveState>;
|
|
530
|
+
read(opts?: {
|
|
531
|
+
session?: string;
|
|
322
532
|
}): Promise<InteractiveState>;
|
|
323
|
-
|
|
533
|
+
/**
|
|
534
|
+
* Run a read of the page. If the page navigates under it ("Execution context was destroyed"), the read is
|
|
535
|
+
* tried once more on the new document; if that fails the same way the page is still moving, which is a
|
|
536
|
+
* stale observation (TARGET_STALE), not a failed action. Nothing a read does changes the page.
|
|
537
|
+
*/
|
|
538
|
+
private readingNavigation;
|
|
539
|
+
/**
|
|
540
|
+
* Structured observation of the active page (or of one element's subtree): readable text, controls, links,
|
|
541
|
+
* and tables, each section bounded by `maxItems` and the whole record by `maxBytes` (see src/observe.ts).
|
|
542
|
+
* With only the default `content` section, no scope and no limits it is exactly {@link read}.
|
|
543
|
+
*/
|
|
544
|
+
observe(opts?: {
|
|
545
|
+
sections?: readonly ObserveSection[];
|
|
546
|
+
target?: BrowserTarget;
|
|
547
|
+
region?: ObserveRegion;
|
|
548
|
+
maxItems?: number;
|
|
549
|
+
maxBytes?: number;
|
|
550
|
+
includeValues?: boolean;
|
|
551
|
+
timeoutMs?: number;
|
|
552
|
+
session?: string;
|
|
553
|
+
}): Promise<Record<string, unknown>>;
|
|
554
|
+
private observeOnce;
|
|
324
555
|
consoleMessages(opts?: {
|
|
325
556
|
level?: string;
|
|
326
557
|
limit?: number;
|
|
327
558
|
clear?: boolean;
|
|
559
|
+
session?: string;
|
|
328
560
|
}): {
|
|
329
561
|
enabled: boolean;
|
|
330
562
|
records: BrowserConsoleRecord[];
|
|
@@ -332,21 +564,61 @@ export declare class BrowserService {
|
|
|
332
564
|
networkRequests(opts?: {
|
|
333
565
|
limit?: number;
|
|
334
566
|
clear?: boolean;
|
|
567
|
+
session?: string;
|
|
335
568
|
}): {
|
|
336
569
|
enabled: boolean;
|
|
337
570
|
records: BrowserRequestRecord[];
|
|
338
571
|
};
|
|
339
|
-
screenshot(options?: BrowserScreenshotOptions
|
|
572
|
+
screenshot(options?: BrowserScreenshotOptions & {
|
|
573
|
+
session?: string;
|
|
574
|
+
}): Promise<{
|
|
340
575
|
path: string;
|
|
341
576
|
}>;
|
|
342
|
-
|
|
577
|
+
/**
|
|
578
|
+
* Run a recipe on the session's page.
|
|
579
|
+
*
|
|
580
|
+
* A business failure comes back as a value (`executionStatus`, `failedStep`,
|
|
581
|
+
* `completedSteps`, `effects`), never as an exception; only problems before
|
|
582
|
+
* any step ran (no page, navigation failure, a malformed recipe) throw.
|
|
583
|
+
*
|
|
584
|
+
* Cancelling stops this recipe only: the session page stays open and usable.
|
|
585
|
+
* A step that is already running cannot be interrupted, so the call returns
|
|
586
|
+
* once that step has returned. The caller therefore still holds the session
|
|
587
|
+
* (browser_call is serialized per agent) until the page is quiet again.
|
|
588
|
+
*/
|
|
589
|
+
recipe(steps: readonly AnyRecipeStep[], opts?: {
|
|
343
590
|
url?: string;
|
|
344
591
|
waitMs?: number;
|
|
345
592
|
authProfile?: string;
|
|
346
593
|
rulePack?: string;
|
|
347
594
|
signal?: AbortSignal;
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
595
|
+
session?: string;
|
|
596
|
+
legacyRecipe?: boolean;
|
|
597
|
+
/** 2: strict LocatorSpec steps, goto/clear, postconditions (see src/automation-v2.ts). Default 1. */
|
|
598
|
+
schemaVersion?: 1 | 2;
|
|
599
|
+
postconditions?: readonly Postcondition[];
|
|
600
|
+
outputSchema?: readonly OutputSpec[];
|
|
601
|
+
/** v2 goto may land on these domains. */
|
|
602
|
+
allowedDomains?: readonly string[];
|
|
603
|
+
/** v2 goto may also stay on the origin the recipe started on (inline recipes; stored assets are limited to their domains). */
|
|
604
|
+
gotoSameOrigin?: boolean;
|
|
605
|
+
/** Run in a brand-new BrowserContext (its own cookies and storage) that is closed afterwards; the session's page is not touched. Needs `url`. */
|
|
606
|
+
isolated?: boolean;
|
|
607
|
+
}): Promise<RecipeServiceResult>;
|
|
608
|
+
/** A recipe in its own context: nothing of the caller's session (page, cookies, storage, journal) is shared or changed. */
|
|
609
|
+
private isolatedRecipe;
|
|
610
|
+
private runRecipeOn;
|
|
611
|
+
/**
|
|
612
|
+
* Close one session's page.
|
|
613
|
+
*
|
|
614
|
+
* `session` is the caller's bucket: a tool call closes only the page that
|
|
615
|
+
* session opened. Only a caller with no session (a service consumer outside
|
|
616
|
+
* the agent loop) reaches the shared bucket, which preserves the historical
|
|
617
|
+
* behaviour for those consumers.
|
|
618
|
+
*/
|
|
619
|
+
closePage(session?: SessionState): Promise<void>;
|
|
620
|
+
status(opts?: {
|
|
621
|
+
session?: string;
|
|
622
|
+
}): Promise<BrowserStatus>;
|
|
351
623
|
close(): Promise<void>;
|
|
352
624
|
}
|