@omnivoice/page-agent 0.1.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 +119 -137
- package/package.json +74 -58
- 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 -26
- package/dist/esm/page-agent.js +0 -30
- package/dist/esm/page-agent.js.map +0 -1
- package/dist/iife/page-agent.demo.js +0 -402
package/README.md
CHANGED
|
@@ -1,184 +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
|
-
## Uso
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
npm install @omnivoice/page-agent
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
```js
|
|
37
|
-
import { PageAgent } from "@omnivoice/page-agent";
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Ou single-file via CDN (exposto como `window.PageAgent`):
|
|
41
|
-
|
|
42
|
-
```html
|
|
43
|
-
<script src="https://unpkg.com/@omnivoice/page-agent@0.1.0/dist/iife/page-agent.demo.js"></script>
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Como publicar
|
|
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.
|
|
47
17
|
|
|
48
18
|
```bash
|
|
19
|
+
cd /home/bugson/PycharmProjects/test-pageagent
|
|
20
|
+
cp .env.example .env
|
|
21
|
+
# edite .env e coloque OPENAI_API_KEY=...
|
|
49
22
|
npm install
|
|
50
|
-
npm run
|
|
51
|
-
npm run
|
|
52
|
-
npm run
|
|
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
|
|
53
26
|
```
|
|
54
27
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
buildados.
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
# Page Agent (upstream)
|
|
62
|
-
|
|
63
|
-
<picture>
|
|
64
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://page-agent.github.io/assets/readme/banner-dark.png">
|
|
65
|
-
<img alt="Page Agent Banner" src="https://page-agent.github.io/assets/readme/banner-light.png">
|
|
66
|
-
</picture>
|
|
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.
|
|
67
30
|
|
|
68
|
-
|
|
69
|
-
[](https://www.npmjs.com/package/page-agent)
|
|
70
|
-
[](https://www.npmjs.com/package/page-agent)
|
|
71
|
-
[](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')
|
|
72
|
-
[](https://opensource.org/licenses/MIT)
|
|
73
|
-
[](http://www.typescriptlang.org/)
|
|
74
|
-
[](https://chromewebstore.google.com/detail/page-agent-ext/akldabonmimlicnjlflnapfeklbfemhj)
|
|
75
|
-
[](https://github.com/alibaba/page-agent)
|
|
31
|
+
Abra <http://127.0.0.1:8797>.
|
|
76
32
|
|
|
77
|
-
|
|
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.
|
|
78
34
|
|
|
79
|
-
|
|
35
|
+
## Suíte de desafios
|
|
80
36
|
|
|
81
|
-
|
|
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.
|
|
82
38
|
|
|
83
|
-
|
|
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.
|
|
84
40
|
|
|
85
|
-
|
|
41
|
+
## Comandos do laboratório
|
|
86
42
|
|
|
87
|
-
|
|
43
|
+
Para não precisar controlar processos manualmente:
|
|
88
44
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- **🧠 Bring your own LLMs**
|
|
99
|
-
- Works with most mainstream models, including locally deployed ones. See [supported models](https://alibaba.github.io/page-agent/docs/features/models).
|
|
100
|
-
- **🐙 Optional [chrome extension](https://alibaba.github.io/page-agent/docs/features/chrome-extension) for multi-page tasks.**
|
|
101
|
-
- And an [MCP Server (Beta)](https://alibaba.github.io/page-agent/docs/features/mcp-server) to control it from outside
|
|
102
|
-
|
|
103
|
-
## 💡 Use Cases
|
|
45
|
+
```bash
|
|
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
|
|
53
|
+
```
|
|
104
54
|
|
|
105
|
-
|
|
106
|
-
- **Smart Form Filling** — Turn 20-click workflows into one sentence. Perfect for ERP, CRM, and admin systems.
|
|
107
|
-
- **Accessibility** — Make any web app accessible through natural language. Voice commands, screen readers, zero barrier.
|
|
108
|
-
- **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).
|
|
109
|
-
- **MCP** - Allow your agent clients to control your browser.
|
|
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`.
|
|
110
56
|
|
|
111
|
-
##
|
|
57
|
+
## Como testar
|
|
112
58
|
|
|
113
|
-
|
|
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:
|
|
114
63
|
|
|
115
|
-
|
|
64
|
+
`Preencha o nome com Maria Oliveira, escolha Clínica geral e escreva "Primeira consulta" na observação.`
|
|
116
65
|
|
|
117
|
-
|
|
118
|
-
<script
|
|
119
|
-
src="https://cdn.jsdelivr.net/npm/page-agent@1.12.4/dist/iife/page-agent.demo.js"
|
|
120
|
-
crossorigin="anonymous"
|
|
121
|
-
></script>
|
|
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.
|
|
122
67
|
|
|
123
|
-
|
|
124
|
-
<!-- https://registry.npmmirror.com/page-agent/1.12.4/files/dist/iife/page-agent.demo.js -->
|
|
125
|
-
```
|
|
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.
|
|
126
69
|
|
|
127
|
-
|
|
128
|
-
>
|
|
129
|
-
> 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.
|
|
70
|
+
O `make down` encerra somente a sessão registrada em `.pageagent.pid`; ele não encerra serviços externos.
|
|
130
71
|
|
|
131
|
-
|
|
72
|
+
## Testes automatizados
|
|
132
73
|
|
|
133
74
|
```bash
|
|
134
|
-
|
|
75
|
+
npx playwright install chromium
|
|
76
|
+
npm test
|
|
135
77
|
```
|
|
136
78
|
|
|
137
|
-
|
|
138
|
-
import { PageAgent } from 'page-agent'
|
|
139
|
-
|
|
140
|
-
const agent = new PageAgent({
|
|
141
|
-
model: 'qwen3.5-plus',
|
|
142
|
-
baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
|
|
143
|
-
apiKey: 'YOUR_API_KEY',
|
|
144
|
-
language: 'en-US',
|
|
145
|
-
})
|
|
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.
|
|
146
80
|
|
|
147
|
-
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
For more programmatic usage, see [📖 Documentations](https://alibaba.github.io/page-agent/docs/introduction/overview).
|
|
81
|
+
## Arquivos principais
|
|
151
82
|
|
|
152
|
-
|
|
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.
|
|
153
92
|
|
|
154
|
-
|
|
93
|
+
## Evidência em tempo real
|
|
155
94
|
|
|
156
|
-
|
|
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.
|
|
157
96
|
|
|
158
|
-
|
|
97
|
+
## Retomada e recursos do navegador
|
|
159
98
|
|
|
160
|
-
|
|
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.
|
|
161
100
|
|
|
162
|
-
|
|
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:
|
|
163
102
|
|
|
164
|
-
|
|
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
|
+
};
|
|
119
|
+
```
|
|
165
120
|
|
|
166
|
-
|
|
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.
|
|
167
122
|
|
|
168
|
-
|
|
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.
|
|
169
124
|
|
|
170
|
-
|
|
125
|
+
Também existe uma ponte para extensão/relay via `postMessage`, sem acesso a outra origem:
|
|
171
126
|
|
|
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
|
+
});
|
|
172
150
|
```
|
|
173
|
-
DOM processing components and prompt are derived from browser-use:
|
|
174
151
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
152
|
+
O `requestId`, a origem e o timeout impedem que uma resposta atrasada seja associada a outra ação.
|
|
153
|
+
|
|
154
|
+
O laboratório também expõe o coordenador same-origin:
|
|
178
155
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
|
182
162
|
```
|
|
183
163
|
|
|
184
|
-
|
|
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.
|
|
165
|
+
|
|
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,60 +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
|
-
"
|
|
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
|
+
}
|
|
60
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)
|