@omnivoice/page-agent 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SimonLuvRamen
4
+ Copyright (c) 2026 Alibaba Group Holding Limited
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,250 @@
1
- # Temporary Holding Version
1
+ # Page Agent — fork `@omnivoice`
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > **Fork publicado como [`@omnivoice/*`](https://www.npmjs.com/org/omnivoice) (v0.2.0), a partir do
4
+ > [page-agent](https://github.com/alibaba/page-agent) upstream `v1.12.4` (commit `9eb6b66`), MIT.**
5
+
6
+ ## O que este fork muda
7
+
8
+ Toda divergência do upstream leva um comentário `FORK:` no código (`grep -rn "FORK:" packages/*/src`
9
+ lista o conjunto completo). As principais:
10
+
11
+ 1. **`PageController.readFlatTree()` / `readSelectorMap()`** — acessores somente leitura da
12
+ árvore e do mapa de elementos da última `updateTree()`, para que um perfilador de página
13
+ descreva os mesmos elementos que o agente vê.
14
+ 2. **Painel em pt-BR** — a UI do agente é traduzida; a língua de trabalho do modelo acompanha a
15
+ da interface.
16
+ 3. **Ícones SVG no lugar de emoji** no painel, e layout responsivo para telas pequenas.
17
+ 4. **Renomeado para o namespace publicável `@omnivoice/*`**, versionado de forma independente
18
+ (`0.1.0`) — o upstream mantém os nomes `page-agent`/`@page-agent/*`.
19
+
20
+ ## Pacotes publicados
21
+
22
+ | Pacote npm | Conteúdo |
23
+ |---|---|
24
+ | `@omnivoice/page-agent` | O agente completo (single-script; inclui o bundle IIFE `dist/iife/page-agent.demo.js`) |
25
+ | `@omnivoice/core` | Núcleo do laço de raciocínio/ação |
26
+ | `@omnivoice/llms` | Cliente de LLM com o mental model reflection-before-action |
27
+ | `@omnivoice/page-controller` | Operações de DOM e interação com elementos |
28
+ | `@omnivoice/ui` | Componentes de UI (painel e i18n) |
29
+
30
+ ## Widget central + voz (v0.2.0)
31
+
32
+ **Um único ponto de integração** para qualquer projeto: `mountWidget(config)` centraliza
33
+ agente + painel + voz + configuração num objeto só. O agente é criado **lazy** (a página não
34
+ paga startup até o widget abrir), e a voz (reconhecimento + síntese, pt-BR) usa a Web Speech API
35
+ nativa — degrada graciosamente se o navegador não tiver mic/voz.
36
+
37
+ ```js
38
+ import { mountWidget } from "@omnivoice/page-agent";
39
+
40
+ const w = mountWidget({
41
+ // config central do LLM (um lugar só)
42
+ model: "gpt-4o-mini",
43
+ baseURL: "https://api.exemplo.com/v1",
44
+ apiKey: "sk-...",
45
+ language: "pt-BR",
46
+ voice: { input: true, output: true, speakOnComplete: true }, // fala o resultado
47
+ });
48
+
49
+ // handle: w.run(task) · w.stop() · w.show()/hide()/toggle() · w.setConfig(patch) · w.unmount()
50
+ ```
51
+
52
+ Ou via CDN (IIFE) — desligue o auto-init do demo com `data-auto-init="false"`:
53
+
54
+ ```html
55
+ <script src="https://unpkg.com/@omnivoice/page-agent@0.2.0/dist/iife/page-agent.demo.js"
56
+ data-auto-init="false"></script>
57
+ <script>
58
+ const w = PageAgent.mountWidget({ model: "...", baseURL: "...", apiKey: "...",
59
+ voice: { input: true, output: true } });
60
+ </script>
61
+ ```
62
+
63
+ O widget injeta um **launcher** (botão flutuante, mobile-friendly, com safe-area) e um
64
+ **botão de microfone** ao lado do campo de tarefa. Sem assets externos, arquivo único e
65
+ cacheável via CDN versionada — pensado para mobile/desktop e rede limitada.
66
+
67
+ ### Gateway — a chave fica no servidor, não no front
68
+
69
+ Colocar `apiKey` no HTML/JS expõe a chave a qualquer um que abrir o devtools. O padrão: o front
70
+ fala com um **gateway do projeto** (mesma origem do site), que injeta a chave ao chamar o modelo
71
+ e **controla a config** (modelo, URL do provedor, voz) por servidor. Cada projeto roda o seu
72
+ gateway com a sua config.
73
+
74
+ ```bash
75
+ # No projeto (ex.: NoStopPageTest). A chave vive SÓ no ambiente do servidor.
76
+ AGENT_BASE_URL=https://api.openai.com/v1 \
77
+ AGENT_API_KEY=sk-… \
78
+ AGENT_MODEL=gpt-4o-mini \
79
+ AGENT_VOICE_OUTPUT=true \
80
+ npx omnivoice-agent-gateway # bin do pacote @omnivoice/page-agent
81
+ # → GET /config (config pública, SEM chave) · POST /v1/chat/completions (proxy p/ o provedor)
82
+ ```
83
+
84
+ ```js
85
+ // No front: só aponta pro gateway. Sem chave, sem modelo — o servidor decide.
86
+ PageAgent.mountWidget({
87
+ baseURL: "http://127.0.0.1:8790/v1",
88
+ configUrl: "http://127.0.0.1:8790/config",
89
+ });
90
+ ```
91
+
92
+ O gateway **força o modelo** configurado (o front não escolhe) e **descarta qualquer
93
+ `Authorization` vinda do client** — uma página comprometida não usa outra chave/conta.
94
+ Config por env **ou** `AGENT_CONFIG=agent.config.json`. Zero dependências (Node 18+).
95
+
96
+ ## Uso (classe)
97
+
98
+ ```bash
99
+ npm install @omnivoice/page-agent
100
+ ```
101
+
102
+ ```js
103
+ import { PageAgent } from "@omnivoice/page-agent";
104
+ ```
105
+
106
+ Ou single-file via CDN (exposto como `window.PageAgent`):
107
+
108
+ ```html
109
+ <script src="https://unpkg.com/@omnivoice/page-agent@0.2.0/dist/iife/page-agent.demo.js"></script>
110
+ ```
111
+
112
+ ## Como publicar
113
+
114
+ ```bash
115
+ npm install
116
+ npm run build:libs # builda os 5 pacotes
117
+ npm run publish:fork # publica em ordem de dependência (llms, ui, page-controller, core, page-agent)
118
+ npm run publish:fork -- --dry-run # simula sem publicar
119
+ ```
120
+
121
+ A publicação usa o token da conta corrente (`npm login`); os pacotes sobem como **public**
122
+ (`--access public`). O repo de origem pode continuar privado — o npm recebe só os artefatos
123
+ buildados.
124
+
125
+ ---
126
+
127
+ # Page Agent (upstream)
128
+
129
+ <picture>
130
+ <source media="(prefers-color-scheme: dark)" srcset="https://page-agent.github.io/assets/readme/banner-dark.png">
131
+ <img alt="Page Agent Banner" src="https://page-agent.github.io/assets/readme/banner-light.png">
132
+ </picture>
133
+
134
+ [![CI](https://img.shields.io/github/actions/workflow/status/alibaba/page-agent/main-ci.yml?branch=main&style=flat-square&label=ci)](https://github.com/alibaba/page-agent/actions/workflows/main-ci.yml)
135
+ [![npm](https://img.shields.io/npm/v/page-agent?style=flat-square&label=npm)](https://www.npmjs.com/package/page-agent)
136
+ [![downloads](https://img.shields.io/npm/dt/page-agent?style=flat-square)](https://www.npmjs.com/package/page-agent)
137
+ [![Minzipped bundle size (excluding Zod)](https://deno.bundlejs.com/?q=page-agent&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22zod%22%5D%7D%7D&badge&badge-style=flat-square)](https://bundlejs.com/?q=page-agent&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22zod%22%5D%7D%7D 'Minified + gzip size, excluding the Zod peer dependency')
138
+ [![license](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://opensource.org/licenses/MIT)
139
+ [![typescript](https://img.shields.io/badge/%3C%2F%3E-typescript-blue?style=flat-square)](http://www.typescriptlang.org/)
140
+ [![Chrome Web Store Rating](https://img.shields.io/chrome-web-store/rating/akldabonmimlicnjlflnapfeklbfemhj?style=flat-square&label=chrome%20rating)](https://chromewebstore.google.com/detail/page-agent-ext/akldabonmimlicnjlflnapfeklbfemhj)
141
+ [![GitHub stars](https://img.shields.io/github/stars/alibaba/page-agent.svg)](https://github.com/alibaba/page-agent)
142
+
143
+ The GUI Agent Living in Your Webpage. One script gives any web page its own AI agent.
144
+
145
+ <a href="https://trendshift.io/repositories/22551?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-22551" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/22551" alt="alibaba%2Fpage-agent | Trendshift" width="180"/></a>
146
+
147
+ 🌐 **English** | [中文](./docs/README-zh.md)
148
+
149
+ <a href="https://alibaba.github.io/page-agent/" target="_blank"><b>🚀 Demo</b></a> | <a href="https://alibaba.github.io/page-agent/docs/introduction/overview" target="_blank"><b>📖 Docs</b></a> | <a href="https://news.ycombinator.com/item?id=47264138" target="_blank"><b>📢 HN Discussion</b></a> | <a href="https://x.com/simonluvramen" target="_blank"><b>𝕏 Follow on X</b></a>
150
+
151
+ <!-- demo video -->
152
+
153
+ [![Watch the demo](https://page-agent.github.io/assets/readme/poster.jpg)](https://github.com/user-attachments/assets/a1f2eae2-13fb-4aae-98cf-a3fc1620a6c2)
154
+
155
+ ---
156
+
157
+ ## ✨ Features
158
+
159
+ - **🎯 Easy integration**
160
+ - No need for `browser extension` / `python` / `headless browser`.
161
+ - Just in-page javascript. Everything happens in your web page.
162
+ - **📖 Text-based DOM manipulation**
163
+ - No screenshots. No multi-modal LLMs or special permissions needed.
164
+ - **🧠 Bring your own LLMs**
165
+ - Works with most mainstream models, including locally deployed ones. See [supported models](https://alibaba.github.io/page-agent/docs/features/models).
166
+ - **🐙 Optional [chrome extension](https://alibaba.github.io/page-agent/docs/features/chrome-extension) for multi-page tasks.**
167
+ - And an [MCP Server (Beta)](https://alibaba.github.io/page-agent/docs/features/mcp-server) to control it from outside
168
+
169
+ ## 💡 Use Cases
170
+
171
+ - **SaaS AI Copilot** — Ship an AI copilot in your product in lines of code. No backend rewrite.
172
+ - **Smart Form Filling** — Turn 20-click workflows into one sentence. Perfect for ERP, CRM, and admin systems.
173
+ - **Accessibility** — Make any web app accessible through natural language. Voice commands, screen readers, zero barrier.
174
+ - **Multi-page Agent** — Extend your own web agent's reach across browser tabs via the [Chrome extension](https://alibaba.github.io/page-agent/docs/features/chrome-extension).
175
+ - **MCP** - Allow your agent clients to control your browser.
176
+
177
+ ## 🚀 Quick Start
178
+
179
+ ### One-line integration
180
+
181
+ Fastest way to try PageAgent with our free Demo LLM:
182
+
183
+ ```html
184
+ <script
185
+ src="https://cdn.jsdelivr.net/npm/page-agent@1.12.4/dist/iife/page-agent.demo.js"
186
+ crossorigin="anonymous"
187
+ ></script>
188
+
189
+ <!-- China CDN mirror if you can't access jsDelivr -->
190
+ <!-- https://registry.npmmirror.com/page-agent/1.12.4/files/dist/iife/page-agent.demo.js -->
191
+ ```
192
+
193
+ > **⚠️ For technical evaluation only.** This demo CDN uses our free [testing LLM API](https://alibaba.github.io/page-agent/docs/features/models#free-testing-api). By using it, you agree to its [terms](https://github.com/alibaba/page-agent/blob/main/docs/terms-and-privacy.md).
194
+ >
195
+ > Add `?autoInit=false` to load the script without creating the demo agent automatically. You can then instantiate it with `new window.PageAgent(...)` and your own LLMs.
196
+
197
+ ### NPM Installation
198
+
199
+ ```bash
200
+ npm install page-agent
201
+ ```
202
+
203
+ ```javascript
204
+ import { PageAgent } from 'page-agent'
205
+
206
+ const agent = new PageAgent({
207
+ model: 'qwen3.5-plus',
208
+ baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
209
+ apiKey: 'YOUR_API_KEY',
210
+ language: 'en-US',
211
+ })
212
+
213
+ await agent.execute('Click the login button')
214
+ ```
215
+
216
+ For more programmatic usage, see [📖 Documentations](https://alibaba.github.io/page-agent/docs/introduction/overview).
217
+
218
+ ## 🤝 Contributing
219
+
220
+ We welcome contributions from the community! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines and [docs/developer-guide.md](docs/developer-guide.md) for local development workflows.
221
+
222
+ Built something cool with PageAgent? Share it in [Show and Tell](https://github.com/alibaba/page-agent/discussions/categories/show-and-tell). 🙌
223
+
224
+ Please read the [maintainer's note](https://github.com/alibaba/page-agent/issues/349) on principles and current state.
225
+
226
+ Contributions generated entirely by **bots or AI** without substantial human involvement will **not be accepted**.
227
+
228
+ ## ⚖️ License
229
+
230
+ [MIT License](LICENSE)
231
+
232
+ ## 👏 Acknowledgments
233
+
234
+ This project builds upon the excellent work of **[`browser-use`](https://github.com/browser-use/browser-use)**.
235
+
236
+ `PageAgent` is designed for **client-side web enhancement**, not server-side automation.
237
+
238
+ ```
239
+ DOM processing components and prompt are derived from browser-use:
240
+
241
+ Browser Use <https://github.com/browser-use/browser-use>
242
+ Copyright (c) 2024 Gregor Zunic
243
+ Licensed under the MIT License
244
+
245
+ We gratefully acknowledge the browser-use project and its contributors for their
246
+ excellent work on web automation and DOM interaction patterns that helped make
247
+ this project possible.
248
+ ```
249
+
250
+ **⭐ Star this repo if you find PageAgent helpful!**
@@ -0,0 +1,160 @@
1
+ import { AgentConfig } from '@omnivoice/core';
2
+ import { ExecutionResult } from '@omnivoice/core';
3
+ import { PageAgentCore } from '@omnivoice/core';
4
+ import { PageControllerConfig } from '@omnivoice/page-controller';
5
+ import { Panel } from '@omnivoice/ui';
6
+ import { PanelConfig } from '@omnivoice/ui';
7
+
8
+ export declare function createVoice(options?: VoiceOptions): Voice;
9
+
10
+ export declare function mountWidget(options?: WidgetOptions): Widget;
11
+
12
+ export declare class PageAgent extends PageAgentCore {
13
+ panel: Panel;
14
+ constructor(config: PageAgentConfig);
15
+ }
16
+
17
+ export declare type PageAgentConfig = AgentConfig & PageControllerConfig & Omit<PanelConfig, 'language'>;
18
+
19
+ export declare interface Voice {
20
+ /** O que o navegador realmente oferece. A UI usa isto para mostrar/ocultar controles. */
21
+ readonly supported: {
22
+ input: boolean;
23
+ output: boolean;
24
+ };
25
+ /**
26
+ * Escuta uma vez e resolve com a transcrição final. Rejeita em erro real; resolve com ""
27
+ * quando o usuário não fala nada ('no-speech') — não é falha, é "nada foi dito".
28
+ */
29
+ listen(): Promise<string>;
30
+ /** Interrompe a escuta em andamento. */
31
+ stopListening(): void;
32
+ /** Fala um texto. `interrupt` corta o que estiver sendo dito antes de começar. */
33
+ speak(text: string, opts?: {
34
+ interrupt?: boolean;
35
+ }): void;
36
+ /** Para a síntese em andamento. */
37
+ stopSpeaking(): void;
38
+ /** Observa transições de estado (a UI mostra o indicador de "ouvindo/falando"). */
39
+ onStatus(cb: (status: VoiceStatus) => void): () => void;
40
+ }
41
+
42
+ export declare interface VoiceOptions {
43
+ /** Idioma BCP-47 do reconhecimento e da síntese. @default 'pt-BR' */
44
+ lang?: string;
45
+ /** Habilita o reconhecimento de fala (botão de microfone). @default true */
46
+ input?: boolean;
47
+ /** Habilita a síntese de fala (agente fala o resultado). @default false */
48
+ output?: boolean;
49
+ /** URI de uma voz específica do speechSynthesis (deixa o módulo escolher quando ausente). */
50
+ voiceURI?: string;
51
+ /** Velocidade da síntese (0.1–10). @default 1 */
52
+ rate?: number;
53
+ /** Tom da síntese (0–2). @default 1 */
54
+ pitch?: number;
55
+ /** Trava de segurança para `listen()`: ms até rejeitar se o reconhecimento não terminar. @default 30000 */
56
+ listenTimeoutMs?: number;
57
+ }
58
+
59
+ /**
60
+ * FORK: módulo de voz do widget. Zero dependências — usa apenas a Web Speech API nativa do
61
+ * navegador (reconhecimento + síntese), o que mantém o bundle leve e funciona offline/sem rede
62
+ * além das chamadas do próprio agente.
63
+ *
64
+ * Filosofia (regras do laboratório):
65
+ * - Degrada sem quebrar: se o navegador não tem mic nem síntese, `supported` informa e os
66
+ * métodos viram no-op silenciosos — a UI decide esconder os botões, o agente segue funcionando.
67
+ * - Espera por condição, nunca por relógio: `listen()` resolve quando chega o resultado final;
68
+ * o timeout é só uma trava de segurança contra um reconhecimento que "prende" a UI.
69
+ * - Nada de rede própria: o reconhecimento/síntese são do navegador (Chrome/Edge/Safari enviam
70
+ * apenas o áudio necessário para o serviço de voz do SO; em rede limitada isso é mínimo).
71
+ */
72
+ declare type VoiceStatus = 'idle' | 'listening' | 'speaking';
73
+
74
+ export declare interface Widget {
75
+ /** Agente centralizado (mesma instância que o painel controla). `null` até a primeira abertura. */
76
+ readonly agent: PageAgent | null;
77
+ /** Voz centralizada (reconhecimento + síntese). `null` até a primeira abertura. */
78
+ readonly voice: Voice | null;
79
+ /** Posição do botão-lançador. */
80
+ readonly launcher: HTMLElement;
81
+ /** Garante config (busca o `configUrl`) + voz + agente prontos. Idempotente; devolve o agente. */
82
+ ready(): Promise<PageAgent>;
83
+ /** Executa uma tarefa programaticamente. */
84
+ run(task: string): Promise<ExecutionResult>;
85
+ /** Para a tarefa em andamento (o agente segue reutilizável). */
86
+ stop(): Promise<void>;
87
+ /** Abre o painel (propaga erro de config). `hide()`/`toggle()` para fechar/alternar. */
88
+ show(): Promise<void>;
89
+ hide(): void;
90
+ toggle(): void;
91
+ /** Atualiza config em runtime (recria o agente quando muda algo de LLM/agente). */
92
+ setConfig(patch: Partial<WidgetOptions>): void;
93
+ /** Remove launcher, painel e voz da página. */
94
+ unmount(): void;
95
+ }
96
+
97
+ export declare interface WidgetOptions {
98
+ /** Modelo. Ex.: "gpt-4o-mini". */
99
+ model?: string;
100
+ /** Endpoint OpenAI-compatible. */
101
+ baseURL?: string;
102
+ /**
103
+ * Chave da API. Só para uso local/sem gateway (ex.: laboratório). Em produção, prefira
104
+ * `configUrl` + gateway: a chave fica no servidor e não aparece no front-end.
105
+ */
106
+ apiKey?: string;
107
+ /**
108
+ * URL de uma config pública servida pelo gateway do projeto (ex.: "/api/agent/config").
109
+ * O widget busca model/idioma/passos/voz DE LÁ — o front nunca precisa da chave. O gateway
110
+ * é a autoridade: ele injeta a `apiKey` no servidor e força o modelo configurado.
111
+ */
112
+ configUrl?: string;
113
+ /** Customiza o corpo da request (providers específicos). */
114
+ transformRequestBody?: PageAgentConfig['transformRequestBody'];
115
+ /** `fetch` custom (proxy, credentials, baixa latência). */
116
+ customFetch?: PageAgentConfig['customFetch'];
117
+ maxRetries?: number;
118
+ /** Idioma da interface e do raciocínio. @default 'pt-BR' */
119
+ language?: PageAgentConfig['language'];
120
+ /** Máximo de passos por tarefa. @default 30 */
121
+ maxSteps?: number;
122
+ /** Instruções globais/por página. */
123
+ instructions?: PageAgentConfig['instructions'];
124
+ /** Ferramentas customizadas. */
125
+ customTools?: PageAgentConfig['customTools'];
126
+ /** Máscula sobre a página durante a execução. @default true */
127
+ enableMask?: boolean;
128
+ /** Expansão da viewport ao enumerar elementos. @default 0 (só o que está visível) */
129
+ viewportExpansion?: number;
130
+ /** Pergunta pela próxima tarefa ao concluir. @default true */
131
+ promptForNextTask?: boolean;
132
+ /** Posição do botão-lançador. @default 'bottom-right' */
133
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
134
+ /** Rótulo acessível do botão-lançador. @default 'Abrir assistente da página' */
135
+ launcherLabel?: string;
136
+ /** Começa com o painel aberto (em vez de só o botão). @default false */
137
+ open?: boolean;
138
+ voice?: WidgetVoiceOptions;
139
+ }
140
+
141
+ export declare interface WidgetVoiceOptions extends VoiceOptions {
142
+ /** Fala o resultado quando a tarefa termina (requer `output: true`). @default true */
143
+ speakOnComplete?: boolean;
144
+ /** Fala o próximo objetivo a cada passo (mais falante; útil para mãos-livres). @default false */
145
+ speakSteps?: boolean;
146
+ }
147
+
148
+
149
+ export * from "@omnivoice/core";
150
+
151
+ export { }
152
+
153
+
154
+
155
+ declare global {
156
+ interface Window {
157
+ pageAgent?: PageAgent
158
+ PageAgent: typeof PageAgent
159
+ }
160
+ }