@diegosouzacdv/jev-browser-mcp 0.3.1 → 0.4.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 +52 -32
- package/config/ui-testing.json +15 -3
- package/docs/jev-browser-mcp.md +52 -32
- package/mcp_servers/jev-browser-npm/bin/jev-browser-mcp.cjs +1 -1
- package/mcp_servers/jev-browser-npm/src/config.mjs +49 -8
- package/mcp_servers/jev-browser-npm/src/flow.mjs +548 -228
- package/mcp_servers/jev-browser-npm/src/server.mjs +8 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,10 +17,10 @@ versão em produção, use o número explícito no argumento do pacote:
|
|
|
17
17
|
"mcpServers": {
|
|
18
18
|
"jev-browser": {
|
|
19
19
|
"command": "npx",
|
|
20
|
-
"args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.
|
|
20
|
+
"args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.4.0"],
|
|
21
21
|
"env": {
|
|
22
22
|
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
|
|
23
|
-
"JEV_BROWSER_MODE": "
|
|
23
|
+
"JEV_BROWSER_MODE": "computer"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -31,15 +31,18 @@ O formato de interpolação de variáveis varia por harness. Injete a chave por
|
|
|
31
31
|
um secret manager ou pelo ambiente do processo; não grave a chave no arquivo
|
|
32
32
|
de configuração. Para instalar no projeto Node do próprio harness:
|
|
33
33
|
|
|
34
|
-
```sh
|
|
35
|
-
npm install @diegosouzacdv/jev-browser-mcp
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
```sh
|
|
35
|
+
npm install @diegosouzacdv/jev-browser-mcp
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
O padrão `computer` exige Chrome ou Edge instalado. Se optar por `harness`,
|
|
39
|
+
configure `JEV_BROWSER_MODE=harness` antes de instalar o navegador gerenciado
|
|
40
|
+
pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp --install-browser`.
|
|
41
|
+
|
|
42
|
+
O padrão é `computer`: o pacote abre o Chrome/Edge instalado e usa um perfil
|
|
43
|
+
persistente exclusivo em `browser.computer_user_data_dir`. No modo `harness`, a
|
|
44
|
+
instalação baixa uma vez o Chrome/Edge que o Playwright controlará. Personalize
|
|
45
|
+
as escolhas com `JEV_BROWSER_MODE`, `JEV_BROWSER_CHANNEL` e
|
|
43
46
|
`JEV_BROWSER_PROFILE`. O browser permanece aquecido enquanto o processo MCP
|
|
44
47
|
estiver ativo e fecha quando o harness encerra o processo. `JEV_PROVIDER_URL`
|
|
45
48
|
e `JEV_MODEL` podem substituir os valores centrais; a credencial continua no
|
|
@@ -86,12 +89,17 @@ resultado esperado na tela.
|
|
|
86
89
|
|
|
87
90
|
Cada plano pode usar:
|
|
88
91
|
|
|
89
|
-
- `click`, `type`, `hover` e `select_option` com papel/nome acessível exatos;
|
|
90
|
-
- `
|
|
91
|
-
|
|
92
|
+
- `click`, `type`, `hover` e `select_option` com papel/nome acessível exatos;
|
|
93
|
+
- `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
|
|
94
|
+
- `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
|
|
95
|
+
`blur: true` para desfocar o campo e `sensitive: false` para permitir que o
|
|
96
|
+
valor apareça nas evidências;
|
|
97
|
+
- `wait_for_text` e `wait_for_condition` (`network_idle`, `hidden` ou
|
|
98
|
+
`text_hidden`);
|
|
92
99
|
- `press_key` com `PageDown`, `PageUp`, `Home`, `End`, `ArrowDown`, `ArrowUp`,
|
|
93
100
|
`Enter`, `Escape` ou `Tab`;
|
|
94
|
-
- `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`;
|
|
101
|
+
- `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`; `assert_text`
|
|
102
|
+
pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
|
|
95
103
|
- `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
|
|
96
104
|
dropzone;
|
|
97
105
|
- `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
|
|
@@ -239,9 +247,9 @@ do pacote Node ficam no bloco opcional `jev_browser_mcp`, que não altera o
|
|
|
239
247
|
contrato lido pelo servidor Python. Preserve a estrutura completa exigida pelos
|
|
240
248
|
validadores.
|
|
241
249
|
|
|
242
|
-
`browser.mode` aceita `harness` ou `computer`:
|
|
250
|
+
`browser.mode` aceita `harness` ou `computer`; o padrão é `computer`:
|
|
243
251
|
|
|
244
|
-
- `harness` usa Chrome headless e
|
|
252
|
+
- `harness` usa Chrome headless e contexto isolado, adequado a execuções do
|
|
245
253
|
harness e CI; o estado de autenticação é descartado ao final da chamada.
|
|
246
254
|
- `computer` abre o Chrome ou Edge instalado em modo visível e usa o diretório
|
|
247
255
|
persistente `browser.computer_user_data_dir`, separado por navegador. Não
|
|
@@ -250,12 +258,15 @@ validadores.
|
|
|
250
258
|
|
|
251
259
|
`browser.max_flow_steps` limita a soma de passos declarados entre os planos e
|
|
252
260
|
`browser.max_text_entry_chars` limita cada valor digitado. O resultado contém
|
|
253
|
-
`status`, o plano escolhido, as ações executadas, a última captura acessível e
|
|
254
|
-
se o critério esperado apareceu. Quando existem asserções explícitas, `status`
|
|
255
|
-
também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
|
|
256
|
-
esse resultado e `expected_outcome_visible` continua descrevendo somente o
|
|
257
|
-
texto global. `incomplete` significa que nenhum critério foi comprovado;
|
|
258
|
-
confiança do Jev não substitui essa verificação.
|
|
261
|
+
`status`, o plano escolhido, as ações executadas, a última captura acessível e
|
|
262
|
+
se o critério esperado apareceu. Quando existem asserções explícitas, `status`
|
|
263
|
+
também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
|
|
264
|
+
esse resultado e `expected_outcome_visible` continua descrevendo somente o
|
|
265
|
+
texto global. `incomplete` significa que nenhum critério foi comprovado;
|
|
266
|
+
confiança do Jev não substitui essa verificação. `timings_ms.ready_ms` mede a
|
|
267
|
+
espera da SPA; `warnings` registra capturas vazias durante transições; e
|
|
268
|
+
`failed_step` identifica índice, ação, alvo, timeout e erro resumido quando uma
|
|
269
|
+
etapa falha.
|
|
259
270
|
|
|
260
271
|
`jev_browser_mcp.browser.max_action_timeout_seconds` limita esperas por ações,
|
|
261
272
|
seletores e condições. `JEV_BROWSER_UPLOAD_ROOT` libera uploads somente dentro
|
|
@@ -271,12 +282,18 @@ Os limites de download ficam no mesmo bloco: `max_download_files`,
|
|
|
271
282
|
limita quantas descrições de violações axe entram no resultado; a contagem total
|
|
272
283
|
continua informada mesmo quando a lista é truncada.
|
|
273
284
|
|
|
274
|
-
O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
|
|
275
|
-
`block_trackers`, `capture_console_errors`, `capture_network_errors`,
|
|
276
|
-
`
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
285
|
+
O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
|
|
286
|
+
`block_trackers`, `capture_console_errors`, `capture_network_errors`,
|
|
287
|
+
`capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
|
|
288
|
+
`ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure` e
|
|
289
|
+
`trace_on_failure`. Sem override, os padrões são lidos de `jev_browser_mcp` em
|
|
290
|
+
`config/ui-testing.json`: um plano candidato pula a chamada Decisions;
|
|
291
|
+
captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
|
|
292
|
+
de recursos ficam desligados. O browser espera a SPA renderizar uma captura
|
|
293
|
+
acessível estável. `ready_text` pode identificar o conteúdo que marca a
|
|
294
|
+
prontidão. `reuse_page: true` pula a navegação somente quando a página e
|
|
295
|
+
`initial_url` têm a mesma origem. `snapshot_scope` aceita `body`, `main` ou
|
|
296
|
+
`dialog`.
|
|
280
297
|
|
|
281
298
|
`block_trackers: true` bloqueia os domínios e tipos de recurso listados na
|
|
282
299
|
configuração (analytics, Hotjar, fontes externas e mídia). Isso pode alterar o
|
|
@@ -284,9 +301,12 @@ layout ou o comportamento do site, então a opção é desligada por padrão.
|
|
|
284
301
|
|
|
285
302
|
Com `capture_console_errors` e `capture_network_errors`, o retorno traz
|
|
286
303
|
`console_errors` e `network_failures`, limitados em quantidade e tamanho.
|
|
287
|
-
Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
|
|
288
|
-
fragmentos, valores de formulário e nomes de arquivo são removidos ou
|
|
289
|
-
sanitizados.
|
|
304
|
+
Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
|
|
305
|
+
fragmentos, valores de formulário e nomes de arquivo são removidos ou
|
|
306
|
+
sanitizados. `capture_network_error_bodies: true` lê somente respostas JSON
|
|
307
|
+
4xx/5xx da mesma origem, limita o corpo e inclui apenas o campo textual
|
|
308
|
+
`message`, também sanitizado. Em falhas, `screenshot_on_failure` salva
|
|
309
|
+
screenshot local e retorna
|
|
290
310
|
`screenshot_path`. `trace_on_failure: true` também grava um `.zip` compatível
|
|
291
311
|
com o Trace Viewer do Playwright e retorna `trace_path`. O diretório padrão é
|
|
292
312
|
`~/.cache/orquestrador/jev-browser-artifacts`; `JEV_BROWSER_ARTIFACT_DIR` pode
|
package/config/ui-testing.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
3
|
"browser": {
|
|
4
|
-
"mode": "
|
|
4
|
+
"mode": "computer",
|
|
5
5
|
"harness_browser": "chrome",
|
|
6
6
|
"playwright_mcp_package": "@playwright/mcp@0.0.79",
|
|
7
7
|
"computer_browser": "chrome",
|
|
@@ -22,8 +22,20 @@
|
|
|
22
22
|
},
|
|
23
23
|
"jev_browser_mcp": {
|
|
24
24
|
"browser": {
|
|
25
|
-
"max_action_timeout_seconds": 8,
|
|
26
|
-
"
|
|
25
|
+
"max_action_timeout_seconds": 8,
|
|
26
|
+
"ready_timeout_seconds_default": 15,
|
|
27
|
+
"max_ready_timeout_seconds": 60,
|
|
28
|
+
"ready_network_idle_default": true,
|
|
29
|
+
"ready_stable_ms_default": 400,
|
|
30
|
+
"max_ready_stable_ms": 2000,
|
|
31
|
+
"post_step_ready_timeout_seconds_default": 5,
|
|
32
|
+
"max_step_timeout_seconds": 60,
|
|
33
|
+
"key_delay_ms_default": 30,
|
|
34
|
+
"reuse_page_default": false,
|
|
35
|
+
"capture_network_error_bodies_default": false,
|
|
36
|
+
"max_network_error_body_bytes": 65536,
|
|
37
|
+
"max_network_error_message_chars": 300,
|
|
38
|
+
"max_upload_files": 5,
|
|
27
39
|
"max_upload_path_chars": 4096,
|
|
28
40
|
"max_upload_file_bytes": 10485760,
|
|
29
41
|
"max_upload_total_bytes": 26214400,
|
package/docs/jev-browser-mcp.md
CHANGED
|
@@ -17,10 +17,10 @@ versão em produção, use o número explícito no argumento do pacote:
|
|
|
17
17
|
"mcpServers": {
|
|
18
18
|
"jev-browser": {
|
|
19
19
|
"command": "npx",
|
|
20
|
-
"args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.
|
|
20
|
+
"args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.4.0"],
|
|
21
21
|
"env": {
|
|
22
22
|
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
|
|
23
|
-
"JEV_BROWSER_MODE": "
|
|
23
|
+
"JEV_BROWSER_MODE": "computer"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -31,15 +31,18 @@ O formato de interpolação de variáveis varia por harness. Injete a chave por
|
|
|
31
31
|
um secret manager ou pelo ambiente do processo; não grave a chave no arquivo
|
|
32
32
|
de configuração. Para instalar no projeto Node do próprio harness:
|
|
33
33
|
|
|
34
|
-
```sh
|
|
35
|
-
npm install @diegosouzacdv/jev-browser-mcp
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
```sh
|
|
35
|
+
npm install @diegosouzacdv/jev-browser-mcp
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
O padrão `computer` exige Chrome ou Edge instalado. Se optar por `harness`,
|
|
39
|
+
configure `JEV_BROWSER_MODE=harness` antes de instalar o navegador gerenciado
|
|
40
|
+
pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp --install-browser`.
|
|
41
|
+
|
|
42
|
+
O padrão é `computer`: o pacote abre o Chrome/Edge instalado e usa um perfil
|
|
43
|
+
persistente exclusivo em `browser.computer_user_data_dir`. No modo `harness`, a
|
|
44
|
+
instalação baixa uma vez o Chrome/Edge que o Playwright controlará. Personalize
|
|
45
|
+
as escolhas com `JEV_BROWSER_MODE`, `JEV_BROWSER_CHANNEL` e
|
|
43
46
|
`JEV_BROWSER_PROFILE`. O browser permanece aquecido enquanto o processo MCP
|
|
44
47
|
estiver ativo e fecha quando o harness encerra o processo. `JEV_PROVIDER_URL`
|
|
45
48
|
e `JEV_MODEL` podem substituir os valores centrais; a credencial continua no
|
|
@@ -86,12 +89,17 @@ resultado esperado na tela.
|
|
|
86
89
|
|
|
87
90
|
Cada plano pode usar:
|
|
88
91
|
|
|
89
|
-
- `click`, `type`, `hover` e `select_option` com papel/nome acessível exatos;
|
|
90
|
-
- `
|
|
91
|
-
|
|
92
|
+
- `click`, `type`, `hover` e `select_option` com papel/nome acessível exatos;
|
|
93
|
+
- `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
|
|
94
|
+
- `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
|
|
95
|
+
`blur: true` para desfocar o campo e `sensitive: false` para permitir que o
|
|
96
|
+
valor apareça nas evidências;
|
|
97
|
+
- `wait_for_text` e `wait_for_condition` (`network_idle`, `hidden` ou
|
|
98
|
+
`text_hidden`);
|
|
92
99
|
- `press_key` com `PageDown`, `PageUp`, `Home`, `End`, `ArrowDown`, `ArrowUp`,
|
|
93
100
|
`Enter`, `Escape` ou `Tab`;
|
|
94
|
-
- `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`;
|
|
101
|
+
- `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`; `assert_text`
|
|
102
|
+
pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
|
|
95
103
|
- `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
|
|
96
104
|
dropzone;
|
|
97
105
|
- `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
|
|
@@ -239,9 +247,9 @@ do pacote Node ficam no bloco opcional `jev_browser_mcp`, que não altera o
|
|
|
239
247
|
contrato lido pelo servidor Python. Preserve a estrutura completa exigida pelos
|
|
240
248
|
validadores.
|
|
241
249
|
|
|
242
|
-
`browser.mode` aceita `harness` ou `computer`:
|
|
250
|
+
`browser.mode` aceita `harness` ou `computer`; o padrão é `computer`:
|
|
243
251
|
|
|
244
|
-
- `harness` usa Chrome headless e
|
|
252
|
+
- `harness` usa Chrome headless e contexto isolado, adequado a execuções do
|
|
245
253
|
harness e CI; o estado de autenticação é descartado ao final da chamada.
|
|
246
254
|
- `computer` abre o Chrome ou Edge instalado em modo visível e usa o diretório
|
|
247
255
|
persistente `browser.computer_user_data_dir`, separado por navegador. Não
|
|
@@ -250,12 +258,15 @@ validadores.
|
|
|
250
258
|
|
|
251
259
|
`browser.max_flow_steps` limita a soma de passos declarados entre os planos e
|
|
252
260
|
`browser.max_text_entry_chars` limita cada valor digitado. O resultado contém
|
|
253
|
-
`status`, o plano escolhido, as ações executadas, a última captura acessível e
|
|
254
|
-
se o critério esperado apareceu. Quando existem asserções explícitas, `status`
|
|
255
|
-
também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
|
|
256
|
-
esse resultado e `expected_outcome_visible` continua descrevendo somente o
|
|
257
|
-
texto global. `incomplete` significa que nenhum critério foi comprovado;
|
|
258
|
-
confiança do Jev não substitui essa verificação.
|
|
261
|
+
`status`, o plano escolhido, as ações executadas, a última captura acessível e
|
|
262
|
+
se o critério esperado apareceu. Quando existem asserções explícitas, `status`
|
|
263
|
+
também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
|
|
264
|
+
esse resultado e `expected_outcome_visible` continua descrevendo somente o
|
|
265
|
+
texto global. `incomplete` significa que nenhum critério foi comprovado;
|
|
266
|
+
confiança do Jev não substitui essa verificação. `timings_ms.ready_ms` mede a
|
|
267
|
+
espera da SPA; `warnings` registra capturas vazias durante transições; e
|
|
268
|
+
`failed_step` identifica índice, ação, alvo, timeout e erro resumido quando uma
|
|
269
|
+
etapa falha.
|
|
259
270
|
|
|
260
271
|
`jev_browser_mcp.browser.max_action_timeout_seconds` limita esperas por ações,
|
|
261
272
|
seletores e condições. `JEV_BROWSER_UPLOAD_ROOT` libera uploads somente dentro
|
|
@@ -271,12 +282,18 @@ Os limites de download ficam no mesmo bloco: `max_download_files`,
|
|
|
271
282
|
limita quantas descrições de violações axe entram no resultado; a contagem total
|
|
272
283
|
continua informada mesmo quando a lista é truncada.
|
|
273
284
|
|
|
274
|
-
O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
|
|
275
|
-
`block_trackers`, `capture_console_errors`, `capture_network_errors`,
|
|
276
|
-
`
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
285
|
+
O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
|
|
286
|
+
`block_trackers`, `capture_console_errors`, `capture_network_errors`,
|
|
287
|
+
`capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
|
|
288
|
+
`ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure` e
|
|
289
|
+
`trace_on_failure`. Sem override, os padrões são lidos de `jev_browser_mcp` em
|
|
290
|
+
`config/ui-testing.json`: um plano candidato pula a chamada Decisions;
|
|
291
|
+
captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
|
|
292
|
+
de recursos ficam desligados. O browser espera a SPA renderizar uma captura
|
|
293
|
+
acessível estável. `ready_text` pode identificar o conteúdo que marca a
|
|
294
|
+
prontidão. `reuse_page: true` pula a navegação somente quando a página e
|
|
295
|
+
`initial_url` têm a mesma origem. `snapshot_scope` aceita `body`, `main` ou
|
|
296
|
+
`dialog`.
|
|
280
297
|
|
|
281
298
|
`block_trackers: true` bloqueia os domínios e tipos de recurso listados na
|
|
282
299
|
configuração (analytics, Hotjar, fontes externas e mídia). Isso pode alterar o
|
|
@@ -284,9 +301,12 @@ layout ou o comportamento do site, então a opção é desligada por padrão.
|
|
|
284
301
|
|
|
285
302
|
Com `capture_console_errors` e `capture_network_errors`, o retorno traz
|
|
286
303
|
`console_errors` e `network_failures`, limitados em quantidade e tamanho.
|
|
287
|
-
Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
|
|
288
|
-
fragmentos, valores de formulário e nomes de arquivo são removidos ou
|
|
289
|
-
sanitizados.
|
|
304
|
+
Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
|
|
305
|
+
fragmentos, valores de formulário e nomes de arquivo são removidos ou
|
|
306
|
+
sanitizados. `capture_network_error_bodies: true` lê somente respostas JSON
|
|
307
|
+
4xx/5xx da mesma origem, limita o corpo e inclui apenas o campo textual
|
|
308
|
+
`message`, também sanitizado. Em falhas, `screenshot_on_failure` salva
|
|
309
|
+
screenshot local e retorna
|
|
290
310
|
`screenshot_path`. `trace_on_failure: true` também grava um `.zip` compatível
|
|
291
311
|
com o Trace Viewer do Playwright e retorna `trace_path`. O diretório padrão é
|
|
292
312
|
`~/.cache/orquestrador/jev-browser-artifacts`; `JEV_BROWSER_ARTIFACT_DIR` pode
|
|
@@ -10,7 +10,7 @@ Usage:
|
|
|
10
10
|
jev-browser-mcp --help Show this help
|
|
11
11
|
|
|
12
12
|
Configuration is read from config/ui-testing.json. Set OPENROUTER_API_KEY in
|
|
13
|
-
the environment
|
|
13
|
+
the environment. The default mode is computer; use JEV_BROWSER_MODE=harness to select isolated headless mode.
|
|
14
14
|
For upload_file, set JEV_BROWSER_UPLOAD_ROOT to a dedicated fixture directory.
|
|
15
15
|
`;
|
|
16
16
|
|
|
@@ -16,8 +16,20 @@ const CONFIG_KEYS = {
|
|
|
16
16
|
"max_flow_steps",
|
|
17
17
|
"max_text_entry_chars",
|
|
18
18
|
],
|
|
19
|
-
nodeBrowser: [
|
|
20
|
-
"max_action_timeout_seconds",
|
|
19
|
+
nodeBrowser: [
|
|
20
|
+
"max_action_timeout_seconds",
|
|
21
|
+
"ready_timeout_seconds_default",
|
|
22
|
+
"max_ready_timeout_seconds",
|
|
23
|
+
"ready_network_idle_default",
|
|
24
|
+
"ready_stable_ms_default",
|
|
25
|
+
"max_ready_stable_ms",
|
|
26
|
+
"post_step_ready_timeout_seconds_default",
|
|
27
|
+
"max_step_timeout_seconds",
|
|
28
|
+
"key_delay_ms_default",
|
|
29
|
+
"reuse_page_default",
|
|
30
|
+
"capture_network_error_bodies_default",
|
|
31
|
+
"max_network_error_body_bytes",
|
|
32
|
+
"max_network_error_message_chars",
|
|
21
33
|
"max_upload_files",
|
|
22
34
|
"max_upload_path_chars",
|
|
23
35
|
"max_upload_file_bytes",
|
|
@@ -206,7 +218,7 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
|
|
|
206
218
|
const uploadRoot = configuredUploadRoot
|
|
207
219
|
? configuredDirectory(configuredUploadRoot, `environment ${uploadRootEnv}`)
|
|
208
220
|
: null;
|
|
209
|
-
const snapshotScope = browserOptions.snapshot_scope_default;
|
|
221
|
+
const snapshotScope = browserOptions.snapshot_scope_default;
|
|
210
222
|
if (!new Set(["body", "main", "dialog"]).has(snapshotScope)) {
|
|
211
223
|
throw new JevBrowserError("config/ui-testing.json jev_browser_mcp.browser.snapshot_scope_default must be body, main, or dialog");
|
|
212
224
|
}
|
|
@@ -215,11 +227,28 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
|
|
|
215
227
|
"jev_browser_mcp.browser.tracker_host_suffixes",
|
|
216
228
|
(host) => /^[a-z0-9.-]+$/i.test(host) && !host.startsWith(".") && !host.endsWith("."),
|
|
217
229
|
);
|
|
218
|
-
const blockedResourceTypes = stringList(
|
|
230
|
+
const blockedResourceTypes = stringList(
|
|
219
231
|
browserOptions.blocked_resource_types,
|
|
220
232
|
"jev_browser_mcp.browser.blocked_resource_types",
|
|
221
233
|
(type) => new Set(["font", "media", "image"]).has(type),
|
|
222
|
-
);
|
|
234
|
+
);
|
|
235
|
+
const maxReadyTimeoutSeconds = positiveNumber(browserOptions.max_ready_timeout_seconds, "jev_browser_mcp.browser.max_ready_timeout_seconds");
|
|
236
|
+
const readyTimeoutSecondsDefault = positiveNumber(browserOptions.ready_timeout_seconds_default, "jev_browser_mcp.browser.ready_timeout_seconds_default");
|
|
237
|
+
const maxReadyStableMs = positiveNumber(browserOptions.max_ready_stable_ms, "jev_browser_mcp.browser.max_ready_stable_ms", true);
|
|
238
|
+
const readyStableMsDefault = positiveNumber(browserOptions.ready_stable_ms_default, "jev_browser_mcp.browser.ready_stable_ms_default", true);
|
|
239
|
+
if (readyTimeoutSecondsDefault > maxReadyTimeoutSeconds) {
|
|
240
|
+
throw new JevBrowserError("config/ui-testing.json ready timeout default exceeds its configured maximum");
|
|
241
|
+
}
|
|
242
|
+
if (readyStableMsDefault > maxReadyStableMs) {
|
|
243
|
+
throw new JevBrowserError("config/ui-testing.json stable snapshot default exceeds its configured maximum");
|
|
244
|
+
}
|
|
245
|
+
const postStepReadyTimeoutSeconds = positiveNumber(
|
|
246
|
+
browserOptions.post_step_ready_timeout_seconds_default,
|
|
247
|
+
"jev_browser_mcp.browser.post_step_ready_timeout_seconds_default",
|
|
248
|
+
);
|
|
249
|
+
if (postStepReadyTimeoutSeconds > maxReadyTimeoutSeconds) {
|
|
250
|
+
throw new JevBrowserError("config/ui-testing.json post-step readiness timeout exceeds its configured maximum");
|
|
251
|
+
}
|
|
223
252
|
|
|
224
253
|
return Object.freeze({
|
|
225
254
|
env,
|
|
@@ -229,7 +258,14 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
|
|
|
229
258
|
profileDir: profileDirectory(profileTemplate, channel, env.JEV_BROWSER_PROFILE),
|
|
230
259
|
maxFlowSteps: positiveNumber(document.browser.max_flow_steps, "browser.max_flow_steps", true),
|
|
231
260
|
maxTextEntryChars: positiveNumber(document.browser.max_text_entry_chars, "browser.max_text_entry_chars", true),
|
|
232
|
-
actionTimeoutMs: positiveNumber(browserOptions.max_action_timeout_seconds, "jev_browser_mcp.browser.max_action_timeout_seconds") * 1000,
|
|
261
|
+
actionTimeoutMs: positiveNumber(browserOptions.max_action_timeout_seconds, "jev_browser_mcp.browser.max_action_timeout_seconds") * 1000,
|
|
262
|
+
maxReadyTimeoutSeconds,
|
|
263
|
+
maxReadyStableMs,
|
|
264
|
+
postStepReadyTimeoutMs: postStepReadyTimeoutSeconds * 1000,
|
|
265
|
+
maxStepTimeoutSeconds: positiveNumber(browserOptions.max_step_timeout_seconds, "jev_browser_mcp.browser.max_step_timeout_seconds"),
|
|
266
|
+
keyDelayMs: positiveNumber(browserOptions.key_delay_ms_default, "jev_browser_mcp.browser.key_delay_ms_default", true),
|
|
267
|
+
maxNetworkErrorBodyBytes: positiveNumber(browserOptions.max_network_error_body_bytes, "jev_browser_mcp.browser.max_network_error_body_bytes", true),
|
|
268
|
+
maxNetworkErrorMessageChars: positiveNumber(browserOptions.max_network_error_message_chars, "jev_browser_mcp.browser.max_network_error_message_chars", true),
|
|
233
269
|
maxUploadFiles: positiveNumber(browserOptions.max_upload_files, "jev_browser_mcp.browser.max_upload_files", true),
|
|
234
270
|
maxUploadPathChars: positiveNumber(browserOptions.max_upload_path_chars, "jev_browser_mcp.browser.max_upload_path_chars", true),
|
|
235
271
|
maxUploadFileBytes: positiveNumber(browserOptions.max_upload_file_bytes, "jev_browser_mcp.browser.max_upload_file_bytes", true),
|
|
@@ -246,8 +282,13 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
|
|
|
246
282
|
screenshotOnFailure: booleanValue(browserOptions.screenshot_on_failure_default, "jev_browser_mcp.browser.screenshot_on_failure_default"),
|
|
247
283
|
traceOnFailure: booleanValue(browserOptions.trace_on_failure_default, "jev_browser_mcp.browser.trace_on_failure_default"),
|
|
248
284
|
captureConsoleErrors: booleanValue(browserOptions.capture_console_errors_default, "jev_browser_mcp.browser.capture_console_errors_default"),
|
|
249
|
-
captureNetworkErrors: booleanValue(browserOptions.capture_network_errors_default, "jev_browser_mcp.browser.capture_network_errors_default"),
|
|
250
|
-
|
|
285
|
+
captureNetworkErrors: booleanValue(browserOptions.capture_network_errors_default, "jev_browser_mcp.browser.capture_network_errors_default"),
|
|
286
|
+
captureNetworkErrorBodies: booleanValue(browserOptions.capture_network_error_bodies_default, "jev_browser_mcp.browser.capture_network_error_bodies_default"),
|
|
287
|
+
blockTrackers: booleanValue(browserOptions.block_trackers_default, "jev_browser_mcp.browser.block_trackers_default"),
|
|
288
|
+
readyNetworkIdle: booleanValue(browserOptions.ready_network_idle_default, "jev_browser_mcp.browser.ready_network_idle_default"),
|
|
289
|
+
reusePage: booleanValue(browserOptions.reuse_page_default, "jev_browser_mcp.browser.reuse_page_default"),
|
|
290
|
+
readyTimeoutSeconds: readyTimeoutSecondsDefault,
|
|
291
|
+
readyStableMs: readyStableMsDefault,
|
|
251
292
|
snapshotScope,
|
|
252
293
|
}),
|
|
253
294
|
trackerHostSuffixes: Object.freeze(trackerHostSuffixes),
|