@omnivoice/page-agent 0.4.0 → 0.5.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.
@@ -0,0 +1,1076 @@
1
+ import * as z from 'zod/v4';
2
+
3
+ declare interface ActionResult {
4
+ success: boolean;
5
+ message: string;
6
+ }
7
+
8
+ /**
9
+ * Agent activity - transient state for immediate UI feedback.
10
+ *
11
+ * Unlike historical events (which are persisted), activities are ephemeral
12
+ * and represent "what the agent is doing right now". UI components should
13
+ * listen to 'activity' events to show real-time feedback.
14
+ *
15
+ * Note: There is no 'idle' activity - absence of activity events means idle.
16
+ */
17
+ export declare type AgentActivity = {
18
+ type: 'thinking';
19
+ } | {
20
+ type: 'executing';
21
+ tool: string;
22
+ input: unknown;
23
+ } | {
24
+ type: 'executed';
25
+ tool: string;
26
+ input: unknown;
27
+ output: string;
28
+ duration: number;
29
+ } | {
30
+ type: 'retrying';
31
+ attempt: number;
32
+ maxAttempts: number;
33
+ } | {
34
+ type: 'error';
35
+ message: string;
36
+ };
37
+
38
+ export declare interface AgentConfig extends LLMConfig {
39
+ language?: SupportedLanguage;
40
+ /**
41
+ * Maximum number of steps the agent can take per task.
42
+ * @default 40
43
+ */
44
+ maxSteps?: number;
45
+ /**
46
+ * Custom tools to extend PageAgent capabilities
47
+ * @experimental
48
+ * @note You can also override or remove internal tools by using the same name.
49
+ * @see PageAgentTool
50
+ *
51
+ * @example
52
+ * // override internal tool
53
+ * import { z } from 'zod/v4'
54
+ * import { tool } from 'page-agent'
55
+ * const customTools = {
56
+ * ask_user: tool({
57
+ * description:
58
+ * 'Ask the user or parent model a question and wait for their answer. Use this if you need more information or clarification.',
59
+ * inputSchema: z.object({
60
+ * question: z.string(),
61
+ * }),
62
+ * execute: async function (this: PageAgent, input) {
63
+ * const answer = await do_some_thing(input.question)
64
+ * return "✅ Received user answer: " + answer
65
+ * },
66
+ * })
67
+ * }
68
+ *
69
+ * @example
70
+ * // remove internal tool
71
+ * const customTools = {
72
+ * ask_user: null // never ask user questions
73
+ * }
74
+ */
75
+ customTools?: Record<string, PageAgentTool | null>;
76
+ /**
77
+ * Instructions to guide the agent's behavior
78
+ */
79
+ instructions?: {
80
+ /**
81
+ * Global system-level instructions, applied to all tasks
82
+ */
83
+ system?: string;
84
+ /**
85
+ * Dynamic page-level instructions callback
86
+ * Called before each step to get instructions for the current page
87
+ * @param url - Current page URL (window.location.href)
88
+ * @returns Instructions string, or undefined/null to skip
89
+ */
90
+ getPageInstructions?: (url: string) => string | undefined | null;
91
+ };
92
+ /**
93
+ * Lifecycle hooks for task execution.
94
+ * @experimental API may change in future versions.
95
+ *
96
+ * All hooks receive the agent instance as first parameter.
97
+ */
98
+ /**
99
+ * Called before each step execution.
100
+ * @experimental
101
+ * @param agent - The PageAgentCore instance
102
+ * @param stepCount - Current step number (0-indexed)
103
+ */
104
+ onBeforeStep?: (agent: PageAgentCore, stepCount: number) => Promise<void> | void;
105
+ /**
106
+ * Called after each step execution.
107
+ * @experimental
108
+ * @param agent - The PageAgentCore instance
109
+ * @param history - Current history of events
110
+ */
111
+ onAfterStep?: (agent: PageAgentCore, history: HistoricalEvent[]) => Promise<void> | void;
112
+ /**
113
+ * Called before task execution starts.
114
+ * @experimental
115
+ * @param agent - The PageAgentCore instance
116
+ */
117
+ onBeforeTask?: (agent: PageAgentCore) => Promise<void> | void;
118
+ /**
119
+ * Called after task execution completes (success or failure).
120
+ * @experimental
121
+ * @param agent - The PageAgentCore instance
122
+ * @param result - The execution result
123
+ */
124
+ onAfterTask?: (agent: PageAgentCore, result: ExecutionResult) => Promise<void> | void;
125
+ /**
126
+ * Called when the agent is disposed.
127
+ * @experimental
128
+ * @note This hook can block the disposal process if it's async.
129
+ * @param agent - The PageAgentCore instance
130
+ * @param reason - Optional reason for disposal
131
+ */
132
+ onDispose?: (agent: PageAgentCore, reason?: string) => void;
133
+ /**
134
+ * @experimental
135
+ * Enable the experimental script execution tool that allows executing generated JavaScript code on the page.
136
+ * @note Can cause unpredictable side effects.
137
+ * @note May bypass some safe guards and data-masking mechanisms.
138
+ */
139
+ experimentalScriptExecutionTool?: boolean;
140
+ /**
141
+ * @experimental
142
+ * Fetch /llms.txt from current site origin and include as context.
143
+ * Only fetched once per origin per task.
144
+ * @default false
145
+ */
146
+ experimentalLlmsTxt?: boolean;
147
+ /**
148
+ * Transform page content before sending to LLM.
149
+ * Called after DOM extraction and simplification, before LLM invocation.
150
+ * Use cases: inspect extraction results, modify page info, mask sensitive data.
151
+ *
152
+ * @param content - Simplified page content that will be sent to LLM
153
+ * @returns Transformed content
154
+ *
155
+ * @example
156
+ * // Mask phone numbers
157
+ * transformPageContent: async (content) => {
158
+ * return content.replace(/1[3-9]\d{9}/g, '***********')
159
+ * }
160
+ */
161
+ transformPageContent?: (content: string) => Promise<string> | string;
162
+ /**
163
+ * Completely override the default system prompt.
164
+ * @experimental Use with caution - incorrect prompts may break agent behavior.
165
+ */
166
+ customSystemPrompt?: string;
167
+ /**
168
+ * Delay between steps in seconds.
169
+ * @default 0.4
170
+ */
171
+ stepDelay?: number;
172
+ }
173
+
174
+ /**
175
+ * Error event - fatal error from LLM or execution
176
+ */
177
+ export declare interface AgentErrorEvent {
178
+ type: 'error';
179
+ message: string;
180
+ rawResponse?: unknown;
181
+ }
182
+
183
+ /**
184
+ * Agent reflection state - the reflection-before-action model
185
+ *
186
+ * Every tool call must first reflect on:
187
+ * - evaluation_previous_goal: How well did the previous action achieve its goal?
188
+ * - memory: Key information to remember for future steps
189
+ * - next_goal: What should be accomplished in the next action?
190
+ */
191
+ export declare interface AgentReflection {
192
+ evaluation_previous_goal: string;
193
+ memory: string;
194
+ next_goal: string;
195
+ }
196
+
197
+ /**
198
+ * Agent lifecycle status.
199
+ */
200
+ export declare type AgentStatus = 'idle' | 'running' | 'completed' | 'error' | 'stopped';
201
+
202
+ /**
203
+ * A single agent step with reflection and action
204
+ */
205
+ export declare interface AgentStepEvent {
206
+ type: 'step';
207
+ stepIndex: number;
208
+ reflection: Partial<AgentReflection>;
209
+ action: {
210
+ name: string;
211
+ input: any;
212
+ output: string;
213
+ };
214
+ usage: {
215
+ promptTokens: number;
216
+ completionTokens: number;
217
+ totalTokens: number;
218
+ cachedTokens?: number;
219
+ reasoningTokens?: number;
220
+ };
221
+ /** Raw LLM response for debugging */
222
+ rawResponse?: unknown;
223
+ /** Raw LLM request for debugging */
224
+ rawRequest?: unknown;
225
+ }
226
+
227
+ /**
228
+ * Structured browser state for LLM consumption
229
+ */
230
+ declare interface BrowserState {
231
+ url: string;
232
+ title: string;
233
+ /** Page info + scroll position hint (e.g. "Page info: 1920x1080px...\n[Start of page]") */
234
+ header: string;
235
+ /** Simplified HTML of interactive elements */
236
+ content: string;
237
+ /** Page footer hint (e.g. "... 300 pixels below ..." or "[End of page]") */
238
+ footer: string;
239
+ }
240
+
241
+ declare function cleanUpHighlights(): void;
242
+
243
+ export declare function createVoice(options?: VoiceOptions): Voice;
244
+
245
+ declare namespace dom {
246
+ export {
247
+ resolveViewportExpansion,
248
+ getFlatTree,
249
+ flatTreeToString,
250
+ getSelectorMap,
251
+ getElementTextMap,
252
+ cleanUpHighlights,
253
+ DomConfig,
254
+ getAllTextTillNextClickableElement
255
+ }
256
+ }
257
+
258
+ declare interface DomConfig {
259
+ viewportExpansion?: number;
260
+ interactiveBlacklist?: (Element | (() => Element))[];
261
+ interactiveWhitelist?: (Element | (() => Element))[];
262
+ includeAttributes?: string[];
263
+ highlightOpacity?: number;
264
+ highlightLabelOpacity?: number;
265
+ /**
266
+ * Preserve semantic landmark tags in dehydrated output even if not interactive
267
+ * @note maybe confusing for LLM combining with page scrolling, use with caution
268
+ **/
269
+ keepSemanticTags?: boolean;
270
+ }
271
+
272
+ declare type DomNode = TextDomNode | ElementDomNode | InteractiveElementDomNode;
273
+
274
+ declare interface ElementDomNode {
275
+ tagName: string;
276
+ attributes?: Record<string, string>;
277
+ xpath?: string;
278
+ children?: string[];
279
+ isVisible?: boolean;
280
+ isTopElement?: boolean;
281
+ isInViewport?: boolean;
282
+ isNew?: boolean;
283
+ isInteractive?: false;
284
+ highlightIndex?: number;
285
+ extra?: Record<string, any>;
286
+ [key: string]: unknown;
287
+ }
288
+
289
+ export declare interface ExecutionResult {
290
+ success: boolean;
291
+ data: string;
292
+ history: HistoricalEvent[];
293
+ }
294
+
295
+ declare interface FlatDomTree {
296
+ rootId: string;
297
+ map: Record<string, DomNode>;
298
+ }
299
+
300
+ /**
301
+ * 对应 python 中的 views::clickable_elements_to_string,
302
+ * 将 dom 信息处理成适合 llm 阅读的文本格式
303
+ * @形如
304
+ * ``` text
305
+ * [0]<a aria-label=page-agent.js 首页 />
306
+ * [1]<div >P />
307
+ * [2]<div >page-agent.js
308
+ * UI Agent in your webpage />
309
+ * [3]<a >文档 />
310
+ * [4]<a aria-label=查看源码(在新窗口打开)>源码 />
311
+ * UI Agent in your webpage
312
+ * 用户输入需求,AI 理解页面并自动操作。
313
+ * [5]<a role=button>快速开始 />
314
+ * [6]<a role=button>查看文档 />
315
+ * 无需后端
316
+ * ```
317
+ * 其中可交互元素用序号标出,提示llm可以用序号操作。
318
+ * 缩进代表父子关系。
319
+ * 普通文本则直接列出来。
320
+ *
321
+ * @todo 数据脱敏过滤器
322
+ */
323
+ declare function flatTreeToString(flatTree: FlatDomTree, includeAttributes?: string[], keepSemanticTags?: boolean): string;
324
+
325
+ declare const getAllTextTillNextClickableElement: (node: TreeNode, maxDepth?: number) => string;
326
+
327
+ declare function getElementTextMap(simplifiedHTML: string): Map<number, string>;
328
+
329
+ declare function getFlatTree(config: DomConfig): FlatDomTree;
330
+
331
+ declare function getSelectorMap(flatTree: FlatDomTree): Map<number, InteractiveElementDomNode>;
332
+
333
+ /**
334
+ * Union type for all history events
335
+ */
336
+ export declare type HistoricalEvent = AgentStepEvent | ObservationEvent | UserTakeoverEvent | RetryEvent | AgentErrorEvent;
337
+
338
+ declare interface InteractiveElementDomNode {
339
+ tagName: string;
340
+ attributes?: Record<string, string>;
341
+ xpath?: string;
342
+ children?: string[];
343
+ isVisible?: boolean;
344
+ isTopElement?: boolean;
345
+ isInViewport?: boolean;
346
+ isInteractive: true;
347
+ highlightIndex: number;
348
+ /**
349
+ * 可交互元素的 dom 引用
350
+ */
351
+ ref: HTMLElement;
352
+ [key: string]: unknown;
353
+ }
354
+
355
+ /**
356
+ * LLM configuration
357
+ */
358
+ declare interface LLMConfig {
359
+ baseURL: string;
360
+ model: string;
361
+ apiKey?: string;
362
+ /**
363
+ * @deprecated No longer a standard parameter; many models reject it outright.
364
+ * Use `transformRequestBody` to set it only for models you've verified.
365
+ */
366
+ temperature?: number;
367
+ maxRetries?: number;
368
+ /**
369
+ * Transform the final request body before sending it to the provider.
370
+ * Use this to implement provider-specific request tweaks such as caching hints or custom flags.
371
+ *
372
+ * Return a new object, or mutate the input object and return undefined.
373
+ */
374
+ transformRequestBody?: (requestBody: Record<string, unknown>) => Record<string, unknown> | undefined;
375
+ /**
376
+ * remove the tool_choice field from the request.
377
+ * @note fix "Invalid tool_choice type: 'object'" for some LLMs.
378
+ */
379
+ disableNamedToolChoice?: boolean;
380
+ /**
381
+ * Custom fetch function for LLM API requests.
382
+ * Use this to customize headers, credentials, proxy, etc.
383
+ * The response should follow OpenAI API format.
384
+ */
385
+ customFetch?: typeof globalThis.fetch;
386
+ }
387
+
388
+ declare const locales: {
389
+ readonly 'en-US': {
390
+ readonly ui: {
391
+ readonly panel: {
392
+ readonly ready: "Ready";
393
+ readonly thinking: "Thinking...";
394
+ readonly taskInput: "Enter new task, describe steps in detail, press Enter to submit";
395
+ readonly userAnswerPrompt: "Please answer the question above, press Enter to submit";
396
+ readonly taskTerminated: "Task terminated";
397
+ readonly taskCompleted: "Task completed";
398
+ readonly userAnswer: "User answer: {{input}}";
399
+ readonly question: "Question: {{question}}";
400
+ readonly waitingPlaceholder: "Waiting for task to start...";
401
+ readonly stop: "Stop";
402
+ readonly close: "Close";
403
+ readonly expand: "Expand history";
404
+ readonly collapse: "Collapse history";
405
+ readonly step: "Step {{number}}";
406
+ readonly userTakeover: "User takeover";
407
+ readonly retrying: "Retrying";
408
+ readonly errorLabel: "Error";
409
+ readonly reflectionEvaluation: "Assessment";
410
+ readonly reflectionMemory: "Memory";
411
+ readonly reflectionNextGoal: "Next goal";
412
+ readonly authorPerson: "You";
413
+ readonly authorAgent: "Agent";
414
+ readonly authorReasoning: "Reasoning";
415
+ readonly authorAction: "Action";
416
+ readonly authorResult: "Result";
417
+ readonly authorPage: "Page";
418
+ readonly authorSystem: "System";
419
+ readonly historyLabel: "Agent activity history";
420
+ readonly panelLabel: "Agent panel";
421
+ };
422
+ readonly tools: {
423
+ readonly clicking: "Clicking element [{{index}}]...";
424
+ readonly inputting: "Inputting text to element [{{index}}]...";
425
+ readonly selecting: "Selecting option \"{{text}}\"...";
426
+ readonly scrolling: "Scrolling page...";
427
+ readonly waiting: "Waiting {{seconds}} seconds...";
428
+ readonly askingUser: "Asking user...";
429
+ readonly done: "Task done";
430
+ readonly clicked: "Clicked element [{{index}}]";
431
+ readonly inputted: "Inputted text \"{{text}}\"";
432
+ readonly selected: "Selected option \"{{text}}\"";
433
+ readonly scrolled: "Page scrolled";
434
+ readonly waited: "Wait completed";
435
+ readonly executing: "Executing {{toolName}}...";
436
+ readonly resultSuccess: "success";
437
+ readonly resultFailure: "failed";
438
+ readonly resultError: "error";
439
+ };
440
+ readonly errors: {
441
+ readonly elementNotFound: "No interactive element found at index {{index}}";
442
+ readonly taskRequired: "Task description is required";
443
+ readonly executionFailed: "Task execution failed";
444
+ readonly notInputElement: "Element is not an input or textarea";
445
+ readonly notSelectElement: "Element is not a select element";
446
+ readonly optionNotFound: "Option \"{{text}}\" not found";
447
+ };
448
+ };
449
+ };
450
+ readonly 'pt-BR': {
451
+ readonly ui: {
452
+ readonly panel: {
453
+ readonly ready: "Pronto";
454
+ readonly thinking: "Pensando...";
455
+ readonly taskInput: "Descreva a próxima tarefa com os passos em detalhe e tecle Enter";
456
+ readonly userAnswerPrompt: "Responda à pergunta acima e tecle Enter";
457
+ readonly taskTerminated: "Tarefa interrompida";
458
+ readonly taskCompleted: "Tarefa concluída";
459
+ readonly userAnswer: "Resposta: {{input}}";
460
+ readonly question: "Pergunta: {{question}}";
461
+ readonly waitingPlaceholder: "Aguardando o início da tarefa...";
462
+ readonly stop: "Parar";
463
+ readonly close: "Fechar";
464
+ readonly expand: "Abrir histórico";
465
+ readonly collapse: "Fechar histórico";
466
+ readonly step: "Passo {{number}}";
467
+ readonly userTakeover: "A pessoa assumiu o controle";
468
+ readonly retrying: "Tentando de novo";
469
+ readonly errorLabel: "Erro";
470
+ readonly reflectionEvaluation: "Avaliação";
471
+ readonly reflectionMemory: "Memória";
472
+ readonly reflectionNextGoal: "Próximo passo";
473
+ readonly authorPerson: "Você";
474
+ readonly authorAgent: "Agente";
475
+ readonly authorReasoning: "Raciocínio";
476
+ readonly authorAction: "Ação";
477
+ readonly authorResult: "Resultado";
478
+ readonly authorPage: "Página";
479
+ readonly authorSystem: "Sistema";
480
+ readonly historyLabel: "Histórico de atividade do agente";
481
+ readonly panelLabel: "Painel do agente";
482
+ };
483
+ readonly tools: {
484
+ readonly clicking: "Clicando no elemento [{{index}}]...";
485
+ readonly inputting: "Digitando no elemento [{{index}}]...";
486
+ readonly selecting: "Escolhendo a opção \"{{text}}\"...";
487
+ readonly scrolling: "Rolando a página...";
488
+ readonly waiting: "Aguardando {{seconds}} segundos...";
489
+ readonly askingUser: "Perguntando à pessoa...";
490
+ readonly done: "Tarefa encerrada";
491
+ readonly clicked: "Elemento [{{index}}] clicado";
492
+ readonly inputted: "Texto \"{{text}}\" digitado";
493
+ readonly selected: "Opção \"{{text}}\" escolhida";
494
+ readonly scrolled: "Página rolada";
495
+ readonly waited: "Espera concluída";
496
+ readonly executing: "Executando {{toolName}}...";
497
+ readonly resultSuccess: "sucesso";
498
+ readonly resultFailure: "falha";
499
+ readonly resultError: "erro";
500
+ };
501
+ readonly errors: {
502
+ readonly elementNotFound: "Nenhum elemento interativo no índice {{index}}";
503
+ readonly taskRequired: "A descrição da tarefa é obrigatória";
504
+ readonly executionFailed: "A execução da tarefa falhou";
505
+ readonly notInputElement: "O elemento não é um campo de texto";
506
+ readonly notSelectElement: "O elemento não é uma lista de seleção";
507
+ readonly optionNotFound: "Opção \"{{text}}\" não encontrada";
508
+ };
509
+ };
510
+ };
511
+ };
512
+
513
+ /**
514
+ * MacroTool input structure
515
+ *
516
+ * This is the core abstraction that enforces the "reflection-before-action" mental model.
517
+ * Before executing any action, the LLM must output its reasoning state.
518
+ */
519
+ export declare interface MacroToolInput extends Partial<AgentReflection> {
520
+ action: Record<string, any>;
521
+ }
522
+
523
+ /**
524
+ * MacroTool output structure
525
+ */
526
+ export declare interface MacroToolResult {
527
+ input: MacroToolInput;
528
+ output: string;
529
+ }
530
+
531
+ export declare function mountWidget(options?: WidgetOptions): Widget;
532
+
533
+ /**
534
+ * Persistent observation event (stays in memory)
535
+ */
536
+ export declare interface ObservationEvent {
537
+ type: 'observation';
538
+ content: string;
539
+ }
540
+
541
+ export declare class PageAgent extends PageAgentCore {
542
+ panel: Panel;
543
+ constructor(config: PageAgentConfig);
544
+ }
545
+
546
+ export declare type PageAgentConfig = AgentConfig & PageControllerConfig & Omit<PanelConfig, 'language'>;
547
+
548
+ /**
549
+ * AI agent for browser automation.
550
+ *
551
+ * @remarks
552
+ * ## Re-act Agent Loop
553
+ * - step
554
+ * - observe (gather information about current environment and context)
555
+ * - think (LLM calling)
556
+ * - reflection (evaluate history, generate memory, short-term planning)
557
+ * - action (give the action to approach the next goal)
558
+ * - act (execute the action)
559
+ * - loop
560
+ *
561
+ * ## Event System
562
+ * - `statuschange` - Agent status transitions (idle → running → completed/error/stopped)
563
+ * - `historychange` - History events updated (persistent, part of agent memory)
564
+ * - `activity` - Real-time activity feedback (transient, for UI only)
565
+ * - `dispose` - Agent cleanup triggered
566
+ *
567
+ * ## Information Streams
568
+ * 1. **History Events** (`history` array)
569
+ * - Persistent event stream that forms agent's memory
570
+ * - Included in LLM context across steps
571
+ * - Types: steps, observations, user takeovers, llm errors
572
+ *
573
+ * 2. **Activity Events** (via `activity` event)
574
+ * - Transient UI feedback during task execution
575
+ * - NOT included in LLM context
576
+ * - Types: thinking, executing, executed, retrying, error
577
+ */
578
+ export declare class PageAgentCore extends EventTarget {
579
+ #private;
580
+ readonly id: string;
581
+ readonly config: PageAgentCoreConfig & {
582
+ maxSteps: number;
583
+ };
584
+ readonly tools: typeof tools;
585
+ /** PageController for DOM operations */
586
+ readonly pageController: PageController;
587
+ task: string;
588
+ taskId: string;
589
+ /** History events */
590
+ history: HistoricalEvent[];
591
+ /** Whether this agent has been disposed */
592
+ disposed: boolean;
593
+ /**
594
+ * Called when the agent needs to ask the user questions.
595
+ * If unset, the `ask_user` tool will be disabled.
596
+ * Implementations should reject the promise when `signal` aborts.
597
+ * @example onAskUser: (q) => window.prompt(q) || ''
598
+ */
599
+ onAskUser?: (question: string, options?: {
600
+ signal: AbortSignal;
601
+ }) => Promise<string>;
602
+ constructor(config: PageAgentCoreConfig);
603
+ /** Get current agent status */
604
+ get status(): AgentStatus;
605
+ /** Result of the most recent run, or `null` before the first run completes. */
606
+ get lastResult(): ExecutionResult | null;
607
+ /* Excluded from this release type: pushObservation */
608
+ /**
609
+ * Stop the current task and wait until the run has fully settled (including lifecycle hooks).
610
+ * @note never await .stop() in a lifecycle hook.
611
+ */
612
+ stop(): Promise<void>;
613
+ /**
614
+ * external errors (pre-checks/config/hooks) will threw;
615
+ * agent errors will be caught and added to history, and return a failed result
616
+ */
617
+ execute(task: string): Promise<ExecutionResult>;
618
+ dispose(): void;
619
+ }
620
+
621
+ export declare type PageAgentCoreConfig = AgentConfig & {
622
+ pageController: PageController;
623
+ };
624
+
625
+ /** `window.PageAgent` na build IIFE (CDN): a classe com `mountWidget` e `createVoice` anexados. */
626
+ export declare type PageAgentGlobal = typeof PageAgent & {
627
+ mountWidget: typeof mountWidget;
628
+ createVoice: typeof createVoice;
629
+ };
630
+
631
+ /**
632
+ * Internal tool definition that has access to PageAgent `this` context
633
+ */
634
+ export declare interface PageAgentTool<TParams = any> {
635
+ description: string;
636
+ inputSchema: z.ZodType<TParams>;
637
+ execute: (this: PageAgentCore, args: TParams, ctx: ToolContext) => Promise<string>;
638
+ }
639
+
640
+ /**
641
+ * PageController manages DOM state and element interactions.
642
+ * It provides async methods for all DOM operations, keeping state isolated.
643
+ *
644
+ * @lifecycle
645
+ * - beforeUpdate: Emitted before the DOM tree is updated.
646
+ * - afterUpdate: Emitted after the DOM tree is updated.
647
+ */
648
+ declare class PageController extends EventTarget {
649
+ private config;
650
+ /** Corresponds to eval_page in browser-use */
651
+ private flatTree;
652
+ /**
653
+ * All highlighted index-mapped interactive elements
654
+ * Corresponds to DOMState.selector_map in browser-use
655
+ */
656
+ private selectorMap;
657
+ /** Index -> element text description mapping */
658
+ private elementTextMap;
659
+ /**
660
+ * Simplified HTML for LLM consumption.
661
+ * Corresponds to clickable_elements_to_string in browser-use
662
+ */
663
+ private simplifiedHTML;
664
+ /** last time the tree was updated */
665
+ private lastTimeUpdate;
666
+ /** Whether the tree has been indexed at least once */
667
+ private isIndexed;
668
+ /** Visual mask overlay for blocking user interaction during automation */
669
+ private mask;
670
+ private maskReady;
671
+ constructor(config?: PageControllerConfig);
672
+ /**
673
+ * FORK: expõe, somente leitura, a árvore achatada da última `updateTree()`.
674
+ * O perfilador da página precisa descrever os mesmos elementos que o agente vê, e `flatTree`
675
+ * é privado (o pacote nem exporta o namespace `dom`). O campo continua privado: quem lê
676
+ * não pode substituir a árvore do agente. Ver vendor/UPSTREAM.md.
677
+ */
678
+ readFlatTree(): FlatDomTree | null;
679
+ /**
680
+ * FORK: expõe, somente leitura, o mapa índice -> elemento interativo da última `updateTree()`.
681
+ * Mesmo motivo de `readFlatTree()`; o tipo `ReadonlyMap` impede `set`/`delete` por quem lê.
682
+ */
683
+ readSelectorMap(): ReadonlyMap<number, InteractiveElementDomNode>;
684
+ /**
685
+ * Initialize mask asynchronously (dynamic import to avoid CSS loading in Node)
686
+ */
687
+ initMask(): void;
688
+ /**
689
+ * Get current page URL
690
+ */
691
+ getCurrentUrl(): Promise<string>;
692
+ /**
693
+ * Get last tree update timestamp
694
+ */
695
+ getLastUpdateTime(): Promise<number>;
696
+ /**
697
+ * Get structured browser state for LLM consumption.
698
+ * Automatically calls updateTree() to refresh the DOM state.
699
+ */
700
+ getBrowserState(): Promise<BrowserState>;
701
+ /**
702
+ * Update DOM tree, returns simplified HTML for LLM.
703
+ * This is the main method to refresh the page state.
704
+ * Automatically bypasses mask during DOM extraction if enabled.
705
+ */
706
+ updateTree(): Promise<string>;
707
+ /**
708
+ * Clean up all element highlights
709
+ */
710
+ cleanUpHighlights(): Promise<void>;
711
+ /**
712
+ * Ensure the tree has been indexed before any index-based operation.
713
+ * Throws if updateTree() hasn't been called yet.
714
+ */
715
+ private assertIndexed;
716
+ /**
717
+ * Click element by index
718
+ */
719
+ clickElement(index: number): Promise<ActionResult>;
720
+ /**
721
+ * Input text into element by index
722
+ */
723
+ inputText(index: number, text: string): Promise<ActionResult>;
724
+ /**
725
+ * Select dropdown option by index and option text
726
+ */
727
+ selectOption(index: number, optionText: string): Promise<ActionResult>;
728
+ /**
729
+ * Scroll vertically
730
+ */
731
+ scroll(options: {
732
+ down: boolean;
733
+ numPages: number;
734
+ pixels?: number;
735
+ index?: number;
736
+ }): Promise<ActionResult>;
737
+ /**
738
+ * Scroll horizontally
739
+ */
740
+ scrollHorizontally(options: {
741
+ right: boolean;
742
+ pixels: number;
743
+ index?: number;
744
+ }): Promise<ActionResult>;
745
+ /**
746
+ * Execute arbitrary JavaScript on the page.
747
+ * The optional `signal` is exposed to the script scope so cooperative code
748
+ * can abort promptly when the task is stopped.
749
+ */
750
+ executeJavascript(script: string, signal?: AbortSignal): Promise<ActionResult>;
751
+ /**
752
+ * Show the visual mask overlay.
753
+ * Only works after mask is setup.
754
+ */
755
+ showMask(): Promise<void>;
756
+ /**
757
+ * Hide the visual mask overlay.
758
+ * Only works after mask is setup.
759
+ */
760
+ hideMask(): Promise<void>;
761
+ /**
762
+ * Dispose and clean up resources
763
+ */
764
+ dispose(): void;
765
+ }
766
+
767
+ /**
768
+ * Configuration for PageController
769
+ */
770
+ declare interface PageControllerConfig extends dom.DomConfig {
771
+ /** Enable visual mask overlay during operations (default: false) */
772
+ enableMask?: boolean;
773
+ }
774
+
775
+ /**
776
+ * Agent control panel
777
+ *
778
+ * Architecture:
779
+ * - History list: renders directly from agent.history (historical events)
780
+ * - Header bar: shows activity events (transient state) and agent status
781
+ *
782
+ * This separation ensures data consistency - history is the single source of truth
783
+ * for what has been done, while activity shows what is happening now.
784
+ */
785
+ declare class Panel {
786
+ #private;
787
+ get wrapper(): HTMLElement;
788
+ /**
789
+ * Create a Panel bound to an agent
790
+ * @param agent - Agent instance that implements PanelAgentAdapter
791
+ * @param config - Optional panel configuration
792
+ */
793
+ constructor(agent: PanelAgentAdapter, config?: PanelConfig);
794
+ show(): void;
795
+ hide(): void;
796
+ reset(): void;
797
+ expand(): void;
798
+ collapse(): void;
799
+ /**
800
+ * Dispose panel and clean up event listeners
801
+ */
802
+ dispose(): void;
803
+ }
804
+
805
+ /**
806
+ * Minimal interface that Panel expects from an agent.
807
+ * Panel does not depend on PageAgent directly - it only requires this interface.
808
+ * This enables decoupling and allows any agent implementation to work with Panel.
809
+ *
810
+ * Events:
811
+ * - 'statuschange': Agent status changed
812
+ * - 'historychange': Historical events updated (persisted)
813
+ * - 'activity': Transient activity for immediate UI feedback (thinking/executing/etc)
814
+ * - 'dispose': Agent is being disposed
815
+ */
816
+ declare interface PanelAgentAdapter extends EventTarget {
817
+ /** Current agent status */
818
+ readonly status: 'idle' | 'running' | 'completed' | 'error' | 'stopped';
819
+ /** Result of the most recent run, or `null` before the first run completes */
820
+ readonly lastResult: {
821
+ success: boolean;
822
+ } | null;
823
+ /** History of agent events */
824
+ readonly history: readonly {
825
+ type: 'step' | 'observation' | 'user_takeover' | 'retry' | 'error';
826
+ stepIndex?: number;
827
+ /** For 'step' type */
828
+ reflection?: {
829
+ evaluation_previous_goal?: string;
830
+ memory?: string;
831
+ next_goal?: string;
832
+ };
833
+ /** For 'step' type */
834
+ action?: {
835
+ name: string;
836
+ input: unknown;
837
+ output: string;
838
+ };
839
+ /** For 'observation' type */
840
+ content?: string;
841
+ /** For 'retry' type */
842
+ attempt?: number;
843
+ maxAttempts?: number;
844
+ /** For 'retry' and 'error' types */
845
+ message?: string;
846
+ }[];
847
+ /** Current task being executed */
848
+ readonly task: string;
849
+ /**
850
+ * Called when the agent needs to ask the user questions.
851
+ * If unset, the `ask_user` tool will be disabled.
852
+ * Panel will set this to handle user questions via its UI.
853
+ * The optional `signal` aborts when the task is stopped or disposed.
854
+ */
855
+ onAskUser?: (question: string, options?: {
856
+ signal: AbortSignal;
857
+ }) => Promise<string>;
858
+ /** Execute a task */
859
+ execute(task: string): Promise<unknown>;
860
+ /** Stop the current task (agent remains reusable) */
861
+ stop(): Promise<void>;
862
+ /** Dispose the agent (terminal, cannot be reused) */
863
+ dispose(): void;
864
+ }
865
+
866
+ /**
867
+ * Panel configuration
868
+ */
869
+ declare interface PanelConfig {
870
+ /**
871
+ * FORK: aceita qualquer língua do núcleo, inclusive uma que o painel não traduza. O I18n já
872
+ * cai em 'en-US' nesse caso, e recusar no tipo obrigaria o chamador a converter sem ganho.
873
+ */
874
+ language?: SupportedLanguage_2 | 'en-US' | 'zh-CN' | 'pt-BR';
875
+ /**
876
+ * Whether to prompt for next task after task completion
877
+ * @default true
878
+ */
879
+ promptForNextTask?: boolean;
880
+ }
881
+
882
+ declare function resolveViewportExpansion(viewportExpansion?: number): number;
883
+
884
+ /**
885
+ * Retry event - LLM call is being retried
886
+ */
887
+ export declare interface RetryEvent {
888
+ type: 'retry';
889
+ message: string;
890
+ attempt: number;
891
+ maxAttempts: number;
892
+ }
893
+
894
+ /** Supported UI languages */
895
+ export declare type SupportedLanguage = 'en-US' | 'zh-CN' | 'pt-BR';
896
+
897
+ declare type SupportedLanguage_2 = keyof typeof locales;
898
+
899
+ declare interface TextDomNode {
900
+ type: 'TEXT_NODE';
901
+ text: string;
902
+ isVisible: boolean;
903
+ [key: string]: unknown;
904
+ }
905
+
906
+ export declare function tool<TParams>(options: PageAgentTool<TParams>): PageAgentTool<TParams>;
907
+
908
+ /**
909
+ * Per-invocation context passed to every tool execution.
910
+ * Tools MUST honor `signal` to support cooperative cancellation.
911
+ */
912
+ export declare interface ToolContext {
913
+ signal: AbortSignal;
914
+ }
915
+
916
+ /**
917
+ * Internal tools for PageAgent.
918
+ * Note: Using any to allow different parameter types for each tool
919
+ */
920
+ declare const tools: Map<string, PageAgentTool<any>>;
921
+
922
+ /**
923
+ * elementsToString 内部使用的类型
924
+ */
925
+ declare interface TreeNode {
926
+ type: 'text' | 'element';
927
+ parent: TreeNode | null;
928
+ children: TreeNode[];
929
+ isVisible: boolean;
930
+ text?: string;
931
+ tagName?: string;
932
+ attributes?: Record<string, string>;
933
+ isInteractive?: boolean;
934
+ isTopElement?: boolean;
935
+ isNew?: boolean;
936
+ highlightIndex?: number;
937
+ extra?: Record<string, any>;
938
+ }
939
+
940
+ /**
941
+ * User takeover event
942
+ */
943
+ export declare interface UserTakeoverEvent {
944
+ type: 'user_takeover';
945
+ }
946
+
947
+ export declare interface Voice {
948
+ /** O que o navegador realmente oferece. A UI usa isto para mostrar/ocultar controles. */
949
+ readonly supported: {
950
+ input: boolean;
951
+ output: boolean;
952
+ };
953
+ /**
954
+ * Escuta uma vez e resolve com a transcrição final. Rejeita em erro real; resolve com ""
955
+ * quando o usuário não fala nada ('no-speech') — não é falha, é "nada foi dito".
956
+ */
957
+ listen(): Promise<string>;
958
+ /** Interrompe a escuta em andamento. */
959
+ stopListening(): void;
960
+ /** Fala um texto. `interrupt` corta o que estiver sendo dito antes de começar. */
961
+ speak(text: string, opts?: {
962
+ interrupt?: boolean;
963
+ }): void;
964
+ /** Para a síntese em andamento. */
965
+ stopSpeaking(): void;
966
+ /** Observa transições de estado (a UI mostra o indicador de "ouvindo/falando"). */
967
+ onStatus(cb: (status: VoiceStatus) => void): () => void;
968
+ }
969
+
970
+ export declare interface VoiceOptions {
971
+ /** Idioma BCP-47 do reconhecimento e da síntese. @default 'pt-BR' */
972
+ lang?: string;
973
+ /** Habilita o reconhecimento de fala (botão de microfone). @default true */
974
+ input?: boolean;
975
+ /** Habilita a síntese de fala (agente fala o resultado). @default false */
976
+ output?: boolean;
977
+ /** URI de uma voz específica do speechSynthesis (deixa o módulo escolher quando ausente). */
978
+ voiceURI?: string;
979
+ /** Velocidade da síntese (0.1–10). @default 1 */
980
+ rate?: number;
981
+ /** Tom da síntese (0–2). @default 1 */
982
+ pitch?: number;
983
+ /** Trava de segurança para `listen()`: ms até rejeitar se o reconhecimento não terminar. @default 30000 */
984
+ listenTimeoutMs?: number;
985
+ }
986
+
987
+ /**
988
+ * FORK: módulo de voz do widget. Zero dependências — usa apenas a Web Speech API nativa do
989
+ * navegador (reconhecimento + síntese), o que mantém o bundle leve e funciona offline/sem rede
990
+ * além das chamadas do próprio agente.
991
+ *
992
+ * Filosofia (regras do laboratório):
993
+ * - Degrada sem quebrar: se o navegador não tem mic nem síntese, `supported` informa e os
994
+ * métodos viram no-op silenciosos — a UI decide esconder os botões, o agente segue funcionando.
995
+ * - Espera por condição, nunca por relógio: `listen()` resolve quando chega o resultado final;
996
+ * o timeout é só uma trava de segurança contra um reconhecimento que "prende" a UI.
997
+ * - Nada de rede própria: o reconhecimento/síntese são do navegador (Chrome/Edge/Safari enviam
998
+ * apenas o áudio necessário para o serviço de voz do SO; em rede limitada isso é mínimo).
999
+ */
1000
+ declare type VoiceStatus = 'idle' | 'listening' | 'speaking';
1001
+
1002
+ export declare interface Widget {
1003
+ /** Agente centralizado (mesma instância que o painel controla). `null` até a primeira abertura. */
1004
+ readonly agent: PageAgent | null;
1005
+ /** Voz centralizada (reconhecimento + síntese). `null` até a primeira abertura. */
1006
+ readonly voice: Voice | null;
1007
+ /** Posição do botão-lançador. */
1008
+ readonly launcher: HTMLElement;
1009
+ /** Garante config (busca o `configUrl`) + voz + agente prontos. Idempotente; devolve o agente. */
1010
+ ready(): Promise<PageAgent>;
1011
+ /** Executa uma tarefa programaticamente. */
1012
+ run(task: string): Promise<ExecutionResult>;
1013
+ /** Para a tarefa em andamento (o agente segue reutilizável). */
1014
+ stop(): Promise<void>;
1015
+ /** Abre o painel (propaga erro de config). `hide()`/`toggle()` para fechar/alternar. */
1016
+ show(): Promise<void>;
1017
+ hide(): void;
1018
+ toggle(): void;
1019
+ /** Atualiza config em runtime (recria o agente quando muda algo de LLM/agente). */
1020
+ setConfig(patch: Partial<WidgetOptions>): void;
1021
+ /** Remove launcher, painel e voz da página. */
1022
+ unmount(): void;
1023
+ }
1024
+
1025
+ export declare interface WidgetOptions {
1026
+ /** Modelo. Ex.: "gpt-4o-mini". */
1027
+ model?: string;
1028
+ /** Endpoint OpenAI-compatible. */
1029
+ baseURL?: string;
1030
+ /**
1031
+ * Chave da API. Só para uso local/sem gateway (ex.: laboratório). Em produção, prefira
1032
+ * `configUrl` + gateway: a chave fica no servidor e não aparece no front-end.
1033
+ */
1034
+ apiKey?: string;
1035
+ /**
1036
+ * URL de uma config pública servida pelo gateway do projeto (ex.: "/api/agent/config").
1037
+ * O widget busca model/idioma/passos/voz DE LÁ — o front nunca precisa da chave. O gateway
1038
+ * é a autoridade: ele injeta a `apiKey` no servidor e força o modelo configurado.
1039
+ */
1040
+ configUrl?: string;
1041
+ /** Customiza o corpo da request (providers específicos). */
1042
+ transformRequestBody?: PageAgentConfig['transformRequestBody'];
1043
+ /** `fetch` custom (proxy, credentials, baixa latência). */
1044
+ customFetch?: PageAgentConfig['customFetch'];
1045
+ maxRetries?: number;
1046
+ /** Idioma da interface e do raciocínio. @default 'pt-BR' */
1047
+ language?: PageAgentConfig['language'];
1048
+ /** Máximo de passos por tarefa. @default 30 */
1049
+ maxSteps?: number;
1050
+ /** Instruções globais/por página. */
1051
+ instructions?: PageAgentConfig['instructions'];
1052
+ /** Ferramentas customizadas. */
1053
+ customTools?: PageAgentConfig['customTools'];
1054
+ /** Máscula sobre a página durante a execução. @default true */
1055
+ enableMask?: boolean;
1056
+ /** Expansão da viewport ao enumerar elementos. @default 0 (só o que está visível) */
1057
+ viewportExpansion?: number;
1058
+ /** Pergunta pela próxima tarefa ao concluir. @default true */
1059
+ promptForNextTask?: boolean;
1060
+ /** Posição do botão-lançador. @default 'bottom-right' */
1061
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
1062
+ /** Rótulo acessível do botão-lançador. @default 'Abrir assistente da página' */
1063
+ launcherLabel?: string;
1064
+ /** Começa com o painel aberto (em vez de só o botão). @default false */
1065
+ open?: boolean;
1066
+ voice?: WidgetVoiceOptions;
1067
+ }
1068
+
1069
+ export declare interface WidgetVoiceOptions extends VoiceOptions {
1070
+ /** Fala o resultado quando a tarefa termina (requer `output: true`). @default true */
1071
+ speakOnComplete?: boolean;
1072
+ /** Fala o próximo objetivo a cada passo (mais falante; útil para mãos-livres). @default false */
1073
+ speakSteps?: boolean;
1074
+ }
1075
+
1076
+ export { }