@omnivoice/page-agent 0.2.0 → 0.3.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 +117 -201
- package/package.json +74 -62
- package/src/voice/README.md +48 -0
- package/src/voice/bridge.ts +230 -0
- package/src/voice/config.ts +200 -0
- package/src/voice/engines.ts +161 -0
- package/src/voice/index.ts +17 -0
- package/src/voice/session.ts +309 -0
- package/src/voice/types.ts +98 -0
- package/LICENSE +0 -22
- package/dist/esm/PageAgent.d.ts +0 -160
- package/dist/esm/page-agent.js +0 -426
- package/dist/esm/page-agent.js.map +0 -1
- package/dist/iife/page-agent.demo.js +0 -402
- package/server/agent-gateway.mjs +0 -215
package/README.md
CHANGED
|
@@ -1,250 +1,166 @@
|
|
|
1
|
-
#
|
|
1
|
+
# PageAgent Lab — Fork with Voice Integration
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
> [page-agent](https://github.com/alibaba/page-agent) upstream `v1.12.4` (commit `9eb6b66`), MIT.**
|
|
3
|
+
Laboratório local para observar o `page-agent` controlando uma página real, com formulário, animações, cursor visual, console de debug e proxy seguro para OpenAI.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
**Recursos desta fork:**
|
|
6
|
+
- OpenAI Realtime full-duplex voice integration
|
|
7
|
+
- Suporte a motores local (on-device) e realtime (cloud)
|
|
8
|
+
- Documentação em `src/voice/README.md`
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
lista o conjunto completo). As principais:
|
|
10
|
+
## Rodar
|
|
10
11
|
|
|
11
|
-
|
|
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/*`.
|
|
12
|
+
Requisitos: Node `^22.22.1 || >=24` e npm `^11.6.3`, mais uma conexão para instalar os pacotes.
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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.
|
|
14
|
+
O piso de versão vem de `vendor/page-agent`, não do laboratório: o monorepo do fork declara esses
|
|
15
|
+
`engines` e falha de formas que não nomeiam a causa em versões mais antigas. `npm run test:vendor`
|
|
16
|
+
verifica essa precondição antes de comparar os artefatos.
|
|
73
17
|
|
|
74
18
|
```bash
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
19
|
+
cd /home/bugson/PycharmProjects/test-pageagent
|
|
20
|
+
cp .env.example .env
|
|
21
|
+
# edite .env e coloque OPENAI_API_KEY=...
|
|
22
|
+
npm install
|
|
23
|
+
npm run vendor:install # dependências do fork vendorizado
|
|
24
|
+
npm run vendor:build # constrói as libs do fork
|
|
25
|
+
npm run dev
|
|
82
26
|
```
|
|
83
27
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
PageAgent.mountWidget({
|
|
87
|
-
baseURL: "http://127.0.0.1:8790/v1",
|
|
88
|
-
configUrl: "http://127.0.0.1:8790/config",
|
|
89
|
-
});
|
|
90
|
-
```
|
|
28
|
+
O `dist` do fork fica fora do git, então um clone novo precisa dos dois passos `vendor:*` antes de
|
|
29
|
+
subir o laboratório. O `make build` falha com esse comando na mensagem se o `dist` não existir.
|
|
91
30
|
|
|
92
|
-
|
|
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+).
|
|
31
|
+
Abra <http://127.0.0.1:8797>.
|
|
95
32
|
|
|
96
|
-
|
|
33
|
+
O mesmo processo serve o frontend e o proxy da API. O endpoint `http://127.0.0.1:8797/api/health` mostra se a chave foi carregada. A porta `8787` pertence a outro serviço (`agent-relay`) e não é usada pelo laboratório.
|
|
97
34
|
|
|
98
|
-
|
|
99
|
-
npm install @omnivoice/page-agent
|
|
100
|
-
```
|
|
35
|
+
## Suíte de desafios
|
|
101
36
|
|
|
102
|
-
|
|
103
|
-
import { PageAgent } from "@omnivoice/page-agent";
|
|
104
|
-
```
|
|
37
|
+
O laboratório agora contém mais de 100 desafios locais em 10 categorias: formulários, navegação, loading, recuperação, DOM profundo, dados, permissões, interação visual, adversarial e limites. O seletor mostra no máximo 12 cards por vez para não poluir o DOM que o PageAgent precisa observar; todos continuam disponíveis por busca e filtro.
|
|
105
38
|
|
|
106
|
-
|
|
39
|
+
Cada desafio tem uma tarefa, uma dificuldade, um alvo renderizado, reset determinístico e evidência esperada. Os casos de cross-origin, gesto real e canvas são representados como limites explícitos da superfície local, não como falsos sucessos.
|
|
107
40
|
|
|
108
|
-
|
|
109
|
-
<script src="https://unpkg.com/@omnivoice/page-agent@0.2.0/dist/iife/page-agent.demo.js"></script>
|
|
110
|
-
```
|
|
41
|
+
## Comandos do laboratório
|
|
111
42
|
|
|
112
|
-
|
|
43
|
+
Para não precisar controlar processos manualmente:
|
|
113
44
|
|
|
114
45
|
```bash
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
46
|
+
make up # inicia e espera a API ficar saudável
|
|
47
|
+
make status # mostra UP/DOWN e a configuração do modelo
|
|
48
|
+
make verify # verifica frontend, API e chave OpenAI
|
|
49
|
+
make logs # acompanha os logs
|
|
50
|
+
make restart # reinicia
|
|
51
|
+
make down # encerra somente a instância iniciada pelo Makefile
|
|
52
|
+
make test # executa os testes Playwright
|
|
119
53
|
```
|
|
120
54
|
|
|
121
|
-
|
|
122
|
-
(`--access public`). O repo de origem pode continuar privado — o npm recebe só os artefatos
|
|
123
|
-
buildados.
|
|
55
|
+
O navegador recebe apenas `local-browser-session`. A chave real fica no `.env` e é usada pelo `server.mjs`, que encaminha chamadas para `https://api.openai.com/v1/chat/completions`.
|
|
124
56
|
|
|
125
|
-
|
|
57
|
+
## Como testar
|
|
126
58
|
|
|
127
|
-
|
|
59
|
+
1. Clique em `Preencher nome`, `Escolher especialidade` ou `Clicar em agendar` para preparar uma tarefa.
|
|
60
|
+
2. Clique em `Executar com PageAgent`.
|
|
61
|
+
3. Observe o painel visual do PageAgent, o cursor de clique, o formulário e o `DEBUG STREAM`.
|
|
62
|
+
4. Para confirmar o efeito, use uma instrução como:
|
|
128
63
|
|
|
129
|
-
|
|
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>
|
|
64
|
+
`Preencha o nome com Maria Oliveira, escolha Clínica geral e escreva "Primeira consulta" na observação.`
|
|
133
65
|
|
|
134
|
-
|
|
135
|
-
[](https://www.npmjs.com/package/page-agent)
|
|
136
|
-
[](https://www.npmjs.com/package/page-agent)
|
|
137
|
-
[](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
|
-
[](https://opensource.org/licenses/MIT)
|
|
139
|
-
[](http://www.typescriptlang.org/)
|
|
140
|
-
[](https://chromewebstore.google.com/detail/page-agent-ext/akldabonmimlicnjlflnapfeklbfemhj)
|
|
141
|
-
[](https://github.com/alibaba/page-agent)
|
|
66
|
+
Sem uma chave configurada, a interface e o modo manual funcionam, mas a execução do LLM retorna o erro de configuração do proxy.
|
|
142
67
|
|
|
143
|
-
|
|
68
|
+
Se aparecer `EADDRINUSE` na porta `8797`, não troque a porta: verifique qual processo está ocupando a porta e encerre somente se ele for uma instância antiga deste laboratório.
|
|
144
69
|
|
|
145
|
-
|
|
70
|
+
O `make down` encerra somente a sessão registrada em `.pageagent.pid`; ele não encerra serviços externos.
|
|
146
71
|
|
|
147
|
-
|
|
72
|
+
## Testes automatizados
|
|
148
73
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
[](https://github.com/user-attachments/assets/a1f2eae2-13fb-4aae-98cf-a3fc1620a6c2)
|
|
154
|
-
|
|
155
|
-
---
|
|
74
|
+
```bash
|
|
75
|
+
npx playwright install chromium
|
|
76
|
+
npm test
|
|
77
|
+
```
|
|
156
78
|
|
|
157
|
-
|
|
79
|
+
Os testes cobrem o carregamento da página, acessibilidade básica, envio do formulário, animação do cursor e botões de comando rápido. A execução do LLM não é incluída no teste automatizado para não consumir créditos.
|
|
158
80
|
|
|
159
|
-
|
|
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
|
|
81
|
+
## Arquivos principais
|
|
168
82
|
|
|
169
|
-
|
|
83
|
+
- `src/main.ts`: instancia o `PageAgent` real e monta o laboratório.
|
|
84
|
+
- `src/durable-runtime.ts`: checkpoint IndexedDB, lease por aba, recuperação após `pagehide` e proteção contra replay cego.
|
|
85
|
+
- `src/browser-capabilities.ts`: contrato opcional para upload, download e nova aba na mesma origem.
|
|
86
|
+
- `src/action-journal.ts`: captura eventos, mutações DOM, loading, notificações, navegação e requests sanitizados em paralelo, correlacionados por ação, sem substituir as ferramentas do PageAgent.
|
|
87
|
+
- `src/styles.css`: layout, estados de foco, cursor/mouse visual e animações.
|
|
88
|
+
- `server.mjs`: proxy local da OpenAI e endpoint `/api/health`.
|
|
89
|
+
- `runtime-coordinator.mjs`: contrato local de runs, eventos idempotentes e lease remoto; grava o estado de desenvolvimento em `.pageagent-runtime.json`.
|
|
90
|
+
- `tests/lab.spec.ts`: testes Playwright.
|
|
91
|
+
- `vite.config.ts`: encaminha `/api` para o proxy local.
|
|
170
92
|
|
|
171
|
-
|
|
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.
|
|
93
|
+
## Evidência em tempo real
|
|
176
94
|
|
|
177
|
-
|
|
95
|
+
Durante cada execução, o laboratório inicia um `ActionJournal` antes do agente. Ele captura `input`, `change`, `click`, `submit` e mutações relevantes do DOM enquanto a ferramenta está executando. A evidência é coalescida por `actionId` e adicionada ao histórico do próximo passo; ela indica que houve alteração, mas o sucesso final continua dependendo do verificador do desafio.
|
|
178
96
|
|
|
179
|
-
|
|
97
|
+
## Retomada e recursos do navegador
|
|
180
98
|
|
|
181
|
-
|
|
99
|
+
O widget agora cria um `runId` e salva checkpoints locais em IndexedDB. Em refresh ou navegação completa, a última ação fica como `unknown`; o agente não a repete automaticamente sem reconciliação. O lease em `localStorage` evita duas abas executarem o mesmo run, e `pagehide`/`pageshow` fazem a transição do documento.
|
|
182
100
|
|
|
183
|
-
|
|
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>
|
|
101
|
+
Para integrar recursos que uma página comum não consegue controlar sozinha, o host pode instalar um Browser Provider antes de carregar o widget:
|
|
188
102
|
|
|
189
|
-
|
|
190
|
-
|
|
103
|
+
```js
|
|
104
|
+
window.pageAgentBrowserProvider = {
|
|
105
|
+
async uploadFile({ selector, fileName }) {
|
|
106
|
+
// A extensão/CDP escolhe o arquivo no contexto autorizado.
|
|
107
|
+
return `upload confirmado: ${selector} <- ${fileName}`;
|
|
108
|
+
},
|
|
109
|
+
async waitForDownload({ selector, url }) {
|
|
110
|
+
// A extensão/CDP aguarda o download real e devolve o resultado.
|
|
111
|
+
return `download confirmado: ${selector || url}`;
|
|
112
|
+
},
|
|
113
|
+
async openTab({ url }) {
|
|
114
|
+
// O host pode criar/controlar a nova aba no mesmo site.
|
|
115
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
116
|
+
return `aba aberta: ${url}`;
|
|
117
|
+
},
|
|
118
|
+
};
|
|
191
119
|
```
|
|
192
120
|
|
|
193
|
-
|
|
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.
|
|
121
|
+
Sem esse provider, o widget ainda pode disparar links de download e abrir uma aba da mesma origem, mas reporta upload como `UNSUPPORTED` em vez de fingir que escolheu um arquivo local. URLs de outra origem são rejeitadas.
|
|
196
122
|
|
|
197
|
-
|
|
123
|
+
O Provider de laboratório só é ativado em `localhost`/`127.0.0.1`. Para validar o bundle compilado localmente, use `http://127.0.0.1:8000/?labProvider=1`; esse flag não habilita o Provider fora de localhost.
|
|
198
124
|
|
|
199
|
-
|
|
200
|
-
npm install page-agent
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
```javascript
|
|
204
|
-
import { PageAgent } from 'page-agent'
|
|
125
|
+
Também existe uma ponte para extensão/relay via `postMessage`, sem acesso a outra origem:
|
|
205
126
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
await
|
|
127
|
+
```js
|
|
128
|
+
window.addEventListener("message", async (event) => {
|
|
129
|
+
if (event.source !== window || event.origin !== location.origin) return;
|
|
130
|
+
const request = event.data;
|
|
131
|
+
if (request?.type !== "page-agent:provider:request") return;
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const result = await provider[request.capability](request.payload);
|
|
135
|
+
window.postMessage({
|
|
136
|
+
type: "page-agent:provider:response",
|
|
137
|
+
requestId: request.requestId,
|
|
138
|
+
ok: true,
|
|
139
|
+
result,
|
|
140
|
+
}, location.origin);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
window.postMessage({
|
|
143
|
+
type: "page-agent:provider:response",
|
|
144
|
+
requestId: request.requestId,
|
|
145
|
+
ok: false,
|
|
146
|
+
error: String(error),
|
|
147
|
+
}, location.origin);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
214
150
|
```
|
|
215
151
|
|
|
216
|
-
|
|
152
|
+
O `requestId`, a origem e o timeout impedem que uma resposta atrasada seja associada a outra ação.
|
|
217
153
|
|
|
218
|
-
|
|
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.
|
|
154
|
+
O laboratório também expõe o coordenador same-origin:
|
|
237
155
|
|
|
156
|
+
```text
|
|
157
|
+
POST /api/runtime/runs
|
|
158
|
+
GET /api/runtime/runs/:runId
|
|
159
|
+
POST /api/runtime/runs/:runId/events
|
|
160
|
+
POST /api/runtime/runs/:runId/lease
|
|
161
|
+
DELETE /api/runtime/runs/:runId/lease
|
|
238
162
|
```
|
|
239
|
-
DOM processing components and prompt are derived from browser-use:
|
|
240
163
|
|
|
241
|
-
|
|
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
|
-
```
|
|
164
|
+
No desenvolvimento, ele persiste em `.pageagent-runtime.json`. Em produção, essa implementação deve ser substituída por Durable Object, Redis ou banco compartilhado, mantendo o mesmo contrato do widget.
|
|
249
165
|
|
|
250
|
-
|
|
166
|
+
O `agent-relay` local existente não foi usado como Provider: o protocolo dele entrega tarefas de chat para um worker de terminal e não possui operações de navegador como `uploadFile`, `waitForDownload` ou `openTab`. O adaptador `postMessage` evita acoplar o widget a esse protocolo incorreto; uma extensão/CDP pode implementar o Provider sem expor o token do relay à página.
|
package/package.json
CHANGED
|
@@ -1,64 +1,76 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
2
|
+
"name": "@omnivoice/page-agent",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "PageAgent with OpenAI Realtime full-duplex voice integration",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/SorPuti/page-agent-fork.git"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/SorPuti/page-agent-fork",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/SorPuti/page-agent-fork/issues"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"pageagent",
|
|
15
|
+
"voice",
|
|
16
|
+
"openai",
|
|
17
|
+
"realtime",
|
|
18
|
+
"duplex",
|
|
19
|
+
"speech",
|
|
20
|
+
"browser-automation"
|
|
21
|
+
],
|
|
22
|
+
"author": "Lucas",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "./src/voice/index.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": "./src/voice/index.ts",
|
|
28
|
+
"./voice": "./src/voice/index.ts",
|
|
29
|
+
"./voice/session": "./src/voice/session.ts",
|
|
30
|
+
"./voice/engines": "./src/voice/engines.ts",
|
|
31
|
+
"./voice/config": "./src/voice/config.ts",
|
|
32
|
+
"./voice/types": "./src/voice/types.ts"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"src/voice",
|
|
36
|
+
"dist"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"dev": "vite --host 127.0.0.1",
|
|
40
|
+
"dev:api": "node server.mjs",
|
|
41
|
+
"dev:web": "vite",
|
|
42
|
+
"build": "vite build",
|
|
43
|
+
"preview": "vite preview",
|
|
44
|
+
"vendor:install": "npm --prefix vendor/page-agent install --no-audit --no-fund",
|
|
45
|
+
"vendor:build": "npm --prefix vendor/page-agent run build:libs",
|
|
46
|
+
"test": "playwright test",
|
|
47
|
+
"test:routine": "node --experimental-strip-types scripts/verify-routine.mjs",
|
|
48
|
+
"test:runner": "node --experimental-strip-types scripts/verify-routine-runner.mjs",
|
|
49
|
+
"test:compactor": "node --experimental-strip-types scripts/verify-history-compactor.mjs",
|
|
50
|
+
"test:condition": "node --experimental-strip-types scripts/verify-condition.mjs",
|
|
51
|
+
"test:record": "node --experimental-strip-types scripts/verify-run-record.mjs",
|
|
52
|
+
"test:espera": "node --experimental-strip-types scripts/verify-espera-externa.mjs",
|
|
53
|
+
"test:chess": "node --experimental-strip-types scripts/verify-chess.mjs",
|
|
54
|
+
"test:schemas": "node --experimental-strip-types scripts/verify-tool-schemas.mjs",
|
|
55
|
+
"test:guard": "node --experimental-strip-types scripts/verify-action-guard.mjs",
|
|
56
|
+
"test:contract": "node --experimental-strip-types scripts/verify-task-contract.mjs",
|
|
57
|
+
"test:session": "node --experimental-strip-types scripts/verify-session-catalog.mjs",
|
|
58
|
+
"test:surface": "node --experimental-strip-types scripts/verify-surface-signature.mjs",
|
|
59
|
+
"test:vendor-provenance": "node scripts/verify-vendor-provenance.mjs",
|
|
60
|
+
"test:vendor": "node scripts/verify-vendor-parity.mjs",
|
|
61
|
+
"test:vendor-wiring": "node scripts/verify-vendor-wiring.mjs",
|
|
62
|
+
"test:fork": "node scripts/verify-fork-customizations.mjs",
|
|
63
|
+
"test:vendor-bundle": "node scripts/verify-vendor-bundle.mjs",
|
|
64
|
+
"test:all": "npm run test:vendor-provenance && npm run test:vendor && npm run test:vendor-wiring && npm run test:vendor-bundle && npm run test:fork && npm run test:contract && npm run test:session && npm run test:surface && npm run test:guard && npm run test:routine && npm run test:runner && npm run test:compactor && npm run test:condition && npm run test:record && npm run test:espera && npm run test:chess && npm run test:schemas && npm run test:gateway",
|
|
65
|
+
"test:gateway": "node scripts/verify-agent-gateway.mjs"
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"chalk": "^6.0.0",
|
|
69
|
+
"zod": "^4.6.7"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@playwright/test": "^1.55.0",
|
|
73
|
+
"concurrently": "^9.1.2",
|
|
74
|
+
"vite": "^7.1.7"
|
|
75
|
+
}
|
|
64
76
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# PageAgent Voice Module
|
|
2
|
+
|
|
3
|
+
Full-duplex voice conversation integration for PageAgent with OpenAI Realtime API support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Realtime Engine**: OpenAI Realtime API full-duplex mode (gpt-4o-realtime-preview)
|
|
8
|
+
- **Local Engine**: On-device speech models (Nemotron ASR + Supertonic TTS) — stub
|
|
9
|
+
- **Barge-in Support**: Interrupt agent responses while speaking
|
|
10
|
+
- **Session Management**: Voice context, conversation history, turn management
|
|
11
|
+
- **Multi-backend**: Flexible configuration for different deployment scenarios
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### 1. Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @pageagent/fork
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 2. Configure
|
|
22
|
+
|
|
23
|
+
Create `.env`:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
SPEECH_MODE=realtime
|
|
27
|
+
OPENAI_API_KEY=sk-...
|
|
28
|
+
REALTIME_VOICE=marin
|
|
29
|
+
NOSTOP_SERVER_URL=http://localhost:8000
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 3. Usage
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { createVoiceSession, readVoiceSettings } from "@pageagent/fork/voice";
|
|
36
|
+
|
|
37
|
+
const settings = readVoiceSettings(process.env);
|
|
38
|
+
const session = await createVoiceSession(settings);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Engines
|
|
42
|
+
|
|
43
|
+
| Mode | Input | Output | Latency | Cost |
|
|
44
|
+
|------|-------|--------|---------|------|
|
|
45
|
+
| realtime | OpenAI Realtime | OpenAI Realtime | 1.3 s p50 | 💰 |
|
|
46
|
+
| local | Nemotron ASR | Supertonic TTS | 0.4 s p50 | ✅ |
|
|
47
|
+
|
|
48
|
+
See full documentation in [VOICE_ARCHITECTURE.md](../../docs/VOICE_ARCHITECTURE.md)
|