Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@
PORT=3000

# Chave de API para proteger endpoints (opcional)
API_KEY=sua-chave-secreta-aqui
# API_KEY=sua-chave-secreta-aqui

# Configurações Playwright
PLAYWRIGHT_HEADLESS=true
PLAYWRIGHT_TIMEOUT=30000
PLAYWRIGHT_HEADLESS=false
PLAYWRIGHT_TIMEOUT=120000
# Playwright service port (for remote API, default 3001)
PLAYWRIGHT_SERVICE_PORT=3001

# Playwright / debug
DEBUG=pw:api


# Logging
LOG_LEVEL=info
LOG_LEVEL=debug
91 changes: 91 additions & 0 deletions DEV.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Desenvolvimento — deepsproxy

Este documento descreve como subir o ambiente de desenvolvimento, rodar testes que reaproveitam a sessão do navegador, inspecionar logs e exemplos de requisições.

1) Subir o ambiente de desenvolvimento

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Resolve markdownlint ordered-list warnings (MD029).

These ordered list items should follow the configured style (1. for each item) to avoid lint noise/failures.

Also applies to: 23-23, 37-37, 51-51, 68-68

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DEV.md` at line 5, The ordered lists in DEV.md use sequential numbering
instead of the required repeated "1." style (MD029); update each ordered list
item such as "Subir o ambiente de desenvolvimento" and the other occurrences to
use "1." for every entry (e.g., replace "1)", "2.", "3." etc. with "1.") so all
ordered list entries follow the configured markdownlint rule and remove the
MD029 warnings.


- Usando o helper `dev.sh` (recomendado):

```bash
./dev.sh up
```

Para trazer os containers e seguir logs do Playwright:

```bash
./dev.sh logs
```

Observações:
- `dev.sh` usa `docker-compose.yml` e `docker-compose.dev.yml` como override.
- O ambiente dev pode usar `network_mode: host` (visibilidade do X11) — se estiver ativo, os mapeamentos de porta não aparecem no `docker ps`, mas a API está acessível em `http://localhost:$PORT` (veja `.env`).

2) Rodar testes de desenvolvimento aproveitando a sessão existente

- O teste que reaproveita a sessão atual foi criado em `src/current_session.test.ts`.
- Para executá-lo dentro do container que tem a sessão do Playwright montada (não inicie um novo navegador):

```bash
docker exec -i deepsproxy sh -c 'cd /app && timeout 20s env RUN_REAL_BROWSER_TESTS=1 PLAYWRIGHT_HEADLESS=false npx tsx --test src/current_session.test.ts'
```

- Explicação:
- `RUN_REAL_BROWSER_TESTS=1` habilita o teste que exige uma sessão real.
- `PLAYWRIGHT_HEADLESS=false` garante que o navegador rode em modo headed se necessário.
- O comando assume que `deepsproxy-playwright` já está em execução e que `./deepseek_profile` está montado no container (para reaproveitar login).

3) Verificar logs de ambos os containers

- Logs do serviço Playwright (útil para ver inicialização do navegador e erros de Playwright):

```bash
docker logs -f deepsproxy-playwright
```

- Logs da API (deepsproxy):

```bash
docker logs -f deepsproxy
```

4) Diagrama de comunicação (Mermaid)

```mermaid
sequenceDiagram
participant Client as Cliente (curl / browser)
participant API as deepsproxy (API)
participant PW as Playwright Service
participant DS as deepseek.com

Client->>API: POST /v1/chat/completions (JSON)
API->>PW: requisita headers/session (PLAYWRIGHT_REMOTE_URL)
PW->>DS: faz requisições web automatizadas usando perfil (deepseek_profile)
DS-->>PW: resposta (cookies, tokens, SSE)
PW-->>API: headers e/ou stream
API-->>Client: resposta agregada (SSE ou JSON)
```

5) Exemplo de `curl` pedindo os presidentes do Brasil (2000–2025) em JSON curto

Observação: o `PORT` padrão do projeto é definido no arquivo `.env` (ex.: `PORT=9300`). Substitua se necessário.

```bash
curl -s -X POST http://localhost:9300/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model":"deepseek-thinking",
"messages":[{"role":"user","content":"Retorne SOMENTE em JSON compacto a lista dos presidentes do Brasil entre 2000 e 2025, no formato [{\"inicio_mandato\":2000,\"nome\":\"Nome\"}, ...] — inclua só ano e nome, respostas curtas."}],
"stream":false
}'

# Exemplo de saída esperada (apenas referência):
#{"presidentes":[{"ano":2003,"nome":"Luiz Inácio Lula da Silva"},{"ano":2011,"nome":"Dilma Rousseff"},{"ano":2016,"nome":"Michel Temer"}]}
```
Comment on lines +68 to +83

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix sample output to match the prompt contract and timeframe.

The prompt asks for presidents from 2000 to 2025 with inicio_mandato, but the sample output uses ano and omits entries for that interval. This can mislead anyone validating behavior from this doc.

Suggested doc fix
-# Exemplo de saída esperada (apenas referência):
-#{"presidentes":[{"ano":2003,"nome":"Luiz Inácio Lula da Silva"},{"ano":2011,"nome":"Dilma Rousseff"},{"ano":2016,"nome":"Michel Temer"}]}
+# Exemplo de saída esperada (apenas referência):
+#{"presidentes":[
+#  {"inicio_mandato":2000,"nome":"Fernando Henrique Cardoso"},
+#  {"inicio_mandato":2003,"nome":"Luiz Inácio Lula da Silva"},
+#  {"inicio_mandato":2011,"nome":"Dilma Rousseff"},
+#  {"inicio_mandato":2016,"nome":"Michel Temer"},
+#  {"inicio_mandato":2019,"nome":"Jair Bolsonaro"},
+#  {"inicio_mandato":2023,"nome":"Luiz Inácio Lula da Silva"}
+#]}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
5) Exemplo de `curl` pedindo os presidentes do Brasil (2000–2025) em JSON curto
Observação: o `PORT` padrão do projeto é definido no arquivo `.env` (ex.: `PORT=9300`). Substitua se necessário.
```bash
curl -s -X POST http://localhost:9300/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model":"deepseek-thinking",
"messages":[{"role":"user","content":"Retorne SOMENTE em JSON compacto a lista dos presidentes do Brasil entre 2000 e 2025, no formato [{\"inicio_mandato\":2000,\"nome\":\"Nome\"}, ...] — inclua só ano e nome, respostas curtas."}],
"stream":false
}'
# Exemplo de saída esperada (apenas referência):
#{"presidentes":[{"ano":2003,"nome":"Luiz Inácio Lula da Silva"},{"ano":2011,"nome":"Dilma Rousseff"},{"ano":2016,"nome":"Michel Temer"}]}
```
5) Exemplo de `curl` pedindo os presidentes do Brasil (2000–2025) em JSON curto
Observação: o `PORT` padrão do projeto é definido no arquivo `.env` (ex.: `PORT=9300`). Substitua se necessário.
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 68-68: Ordered list item prefix
Expected: 1; Actual: 5; Style: 1/1/1

(MD029, ol-prefix)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DEV.md` around lines 68 - 83, Update the example output in DEV.md so it
matches the prompt contract: replace the "ano" field with "inicio_mandato" and
include all presidents covering the 2000–2025 interval in compact JSON (e.g.,
[{"inicio_mandato":2000,"nome":"..."},...]) so the sample aligns with the
request in the curl example and uses the exact JSON structure required by the
"messages" prompt.


Dicas rápidas
- Se o `curl` apontando para `localhost:$PORT` falhar, verifique:
- Se os containers estão up: `docker ps`.
- Se o compose dev usa `network_mode: host`: nesse caso a porta é do host (acessível em `localhost`).
- Logs: `docker logs deepsproxy` e `docker logs deepsproxy-playwright`.

Se quiser, posso adicionar checks automáticos ao `dev.sh` (ex.: aguardar healthcheck do Playwright, rodar `curl /health` da API) — quer que eu adicione isso?
15 changes: 15 additions & 0 deletions Dockerfile.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM node:20-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production=false
COPY . .
RUN npm run build

FROM node:20-slim
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/src ./src
Comment on lines +4 to +13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Prune dev dependencies from API runtime image.

Current runtime copies builder node_modules with dev deps, so API image stays heavier than necessary and expands attack surface.

Suggested fix
 FROM node:20-slim AS builder
@@
 RUN npm ci --production=false
@@
 FROM node:20-slim
 WORKDIR /app
-COPY --from=builder /app/node_modules ./node_modules
 COPY --from=builder /app/package*.json ./
+RUN npm ci --omit=dev
 COPY --from=builder /app/dist ./dist
 COPY --from=builder /app/src ./src
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
RUN npm ci --production=false
COPY . .
RUN npm run build
FROM node:20-slim
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/src ./src
RUN npm ci --production=false
COPY . .
RUN npm run build
FROM node:20-slim
WORKDIR /app
COPY --from=builder /app/package*.json ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/src ./src
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dockerfile.api` around lines 4 - 13, The runtime image is copying the builder
node_modules (which were installed with RUN npm ci --production=false), so dev
dependencies are included; update the Dockerfile to avoid copying dev deps by
either installing production deps in the final stage or pruning dev deps: remove
COPY --from=builder /app/node_modules ./node_modules and instead COPY
--from=builder /app/package*.json ./ and run npm ci --production (or run npm
prune --production) in the final stage so only production dependencies are
present; refer to the existing RUN npm ci --production=false, COPY
--from=builder /app/node_modules, and COPY --from=builder /app/package*.json to
locate where to change.

EXPOSE 3000
CMD ["node", "dist/index.js"]
Comment on lines +8 to +15

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Run API container as non-root.

The final API image runs as root; switch to an unprivileged user for baseline hardening.

Suggested fix
 FROM node:20-slim
 WORKDIR /app
@@
 COPY --from=builder /app/src ./src
+RUN chown -R node:node /app
+USER node
 EXPOSE 3000
 CMD ["node", "dist/index.js"]
🧰 Tools
🪛 Checkov (3.2.529)

[low] 1-15: Ensure that HEALTHCHECK instructions have been added to container images

(CKV_DOCKER_2)


[low] 1-15: Ensure that a user for the container has been created

(CKV_DOCKER_3)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dockerfile.api` around lines 8 - 15, The final image runs as root—create and
switch to an unprivileged user in the Dockerfile: add a non-root user (or use
the existing node user) after the base image is set, ensure /app ownership is
transferred (chown) so the new user can access WORKDIR and copied files, then
add a USER directive before EXPOSE/CMD so the container runs as that
unprivileged user; reference the Dockerfile symbols FROM node:20-slim, WORKDIR
/app, COPY ..., and CMD ["node","dist/index.js"] to locate where to add the user
creation, chown, and USER lines.

17 changes: 13 additions & 4 deletions Dockerfile → Dockerfile.playwright
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
FROM node:20-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
RUN npm ci --production=false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Runtime image is likely shipping devDependencies.

npm ci --production=false in builder plus copying node_modules into runtime usually carries dev-only packages into production, increasing image size and attack surface. Keep full deps for build, but prune/omit dev deps before final runtime.

Suggested fix
 FROM node:20-slim AS builder
 WORKDIR /app
 COPY package*.json ./
 RUN npm ci --production=false
 COPY . .
 RUN npm run build

 FROM node:20-slim
@@
 WORKDIR /app
 COPY --from=builder /app/node_modules ./node_modules
 COPY --from=builder /app/package*.json ./
+RUN npm prune --omit=dev

Also applies to: 20-21

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dockerfile.playwright` at line 4, The Dockerfile currently runs "RUN npm ci
--production=false" which installs devDependencies into the build and then
copies node_modules into the runtime image; change the flow so devDependencies
are available during build but not in the final runtime: keep the existing "RUN
npm ci --production=false" in the builder stage (or install dev deps there), but
before creating the runtime image either run "npm ci --production=true" (or "npm
prune --production") in the final stage or rebuild/install only production deps
in the runtime stage so the final image does not include devDependencies; update
the Dockerfile lines referencing RUN npm ci --production=false and the
subsequent copy of node_modules accordingly.

COPY . .
RUN npm run build

FROM node:20-slim
RUN apt-get update && apt-get install -y \
wget \
gnupg \
ca-certificates \
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list \
&& apt-get update && apt-get install -y google-chrome-stable \
Expand All @@ -17,8 +18,16 @@ ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./

# Install Playwright browsers before copying application artifacts that
# change frequently. This keeps the browser download layer cached across
# rebuilds when only source files change.
RUN npx playwright install chromium
EXPOSE 3000
CMD ["node", "dist/index.js"]

# Now copy application artifacts (dist/src) last so code changes won't
# force re-downloading the browser.
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/src ./src
EXPOSE 9301
CMD ["node", "dist/playwright-service.js"]
104 changes: 104 additions & 0 deletions LAST_STATUS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# LAST STATUS

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix markdown heading/code-fence spacing to satisfy MD022/MD031.

Several headings and one fenced block are missing required blank lines before/after; this should be normalized to keep markdownlint clean.

Also applies to: 6-6, 13-13, 18-18, 25-25, 31-31, 39-39, 58-58, 62-62, 65-66, 94-94, 99-99

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 1-1: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@LAST_STATUS.md` at line 1, Adjust the markdown to satisfy MD022/MD031 by
ensuring there is a blank line before and after each top-level heading and
before/after any fenced code block; specifically update the "# LAST STATUS"
heading and the other headings referenced (lines noted in the review) to have a
blank line above and below, and ensure the fenced block(s) have a blank line
before the opening ``` and after the closing ```, so headings and fences follow
the required spacing rules.

Date: 2026-05-15 (atualizado após validação end-to-end com Nanobrowser)

## Problemas identificados nos logs (15/05/2026)

### Problema 1 — CRÍTICO (RESOLVIDO): Profile Singleton Lock
- **Erro:** `process_singleton_posix.cc:363 — profile in use by another computer (3d53ce7583a9), exitCode=21`
- **Causa:** Ao reiniciar o container, o Docker atribui um novo hostname. O arquivo `Singleton` do Chrome ficava para trás com PID + hostname do container anterior. O novo Chromium lia o lock de uma "máquina diferente" e recusava iniciar.
- **Fix aplicado em `src/services/playwright.ts`:**
- Função `clearProfileLocks()` que remove arquivos `Singleton*` antes de cada `launchPersistentContext`.
- Try/catch no launch: se falhar com erro de "profile" ou "Singleton", limpa e faz um retry automático.

### Problema 2 — CRÍTICO (RESOLVIDO): Cascata de retries sem cleanup
- **Erro:** 3 chamadas seguidas a `launchPersistentContext` no playwright-service, todas falhando com o mesmo lock.
- **Causa:** O `chat.ts` fazia retry no `createDeepSeekStream`, que chamava `/headers` no playwright-service, que tentava `launchPersistentContext` sem limpar locks entre tentativas.
- **Fix:** O `clearProfileLocks` antes de cada launch garante que mesmo os retries externos agora funcionam.

### Problema 3 — MÉDIO (RESOLVIDO): Browser não inicializado na subida
- **Causa:** O `playwright-service.ts` só inicializava o browser sob demanda (na primeira chamada `/headers`). Qualquer requisição chegando antes disso falhava.
- **Fix aplicado em `src/playwright-service.ts`:**
- `initPlaywright()` é chamado na inicialização do serviço (eager init).
- `/health` retorna HTTP 503 enquanto o browser não estiver pronto (`browserReady = false`).
- Tratamento de SIGTERM adicionado ao playwright-service.

### Problema 4 — MÉDIO (RESOLVIDO): Sem ordering entre containers
- **Causa:** `deepsproxy` subia junto com `deepsproxy-playwright` sem esperar o browser estar pronto.
- **Fix aplicado em `docker-compose.yml`:**
- `healthcheck` no container `playwright`: `curl -sf http://localhost:9301/health` a cada 5s, até 10 tentativas, com `start_period: 30s`.
- `depends_on` no container `deepsproxy` com `condition: service_healthy`.

## Estado atual após fixes
- Containers sobem em ordem: `playwright` → (healthy) → `deepsproxy`.
- Locks do profile são limpos automaticamente no startup do `playwright-service`.
- Recovery automático em caso de lock residual (retry após limpeza).
- `/health` do playwright-service reflete o estado real do browser.

## Checklist

### ✅ Feito
- [x] Singleton lock cleanup automático no startup do playwright-service
- [x] Retry automático após falha de lock (clearProfileLocks + try/catch)
- [x] Eager init do browser no playwright-service (não espera primeira requisição)
- [x] `/health` do playwright-service reflete estado real do browser (`browserReady`)
- [x] `docker-compose.dev.yml` com `network_mode: host` para acesso ao X11 do host
- [x] `dev.sh` para subir em modo headed (browser visível na tela)
- [x] Browser abrindo visível na tela do host com `./dev.sh` ✅ (confirmado 15/05)
- [x] Sessão DeepSeek válida e carregada no browser ✅
- [x] API respondendo: `GET /health` → `{"status":"ok"}` em :9300 e :9301 ✅
- [x] `/chat/completions` e `/v1/chat/completions` ambos roteados ao handler ✅
- [x] `stream: false` retorna `application/json` correto (não SSE) ✅
- [x] `response_format: json_schema` / `json_object` → injeta instrução JSON no systemPrompt + schema ✅
- [x] Strip de tags `<think>...</think>` na resposta non-streaming ✅
- [x] Extração do bloco `{...}` do conteúdo quando `needsJson=true` ✅
- [x] Smart windowing: KEEP_HEAD=3 + KEEP_TAIL=4, MAX_PROMPT_CHARS=14000 ✅
- [x] `console.log` de debug: `[chat] model=... stream=... msgs=... promptLen=... needsJson=...` ✅
- [x] Fluxo end-to-end com Nanobrowser validado ✅

### ❌ Pendente / com problema
- [ ] **Login automático** ainda não funciona (captcha na primeira sessão) — requer intervenção manual no browser headed.
- [ ] Erro `Cannot convert undefined or null to object` no Navigator do Nanobrowser — pode ocorrer se o JSON retornado não for válido. Monitorar.

## Próximo passo imediato
Testar o fluxo completo do Nanobrowser com tarefas reais (navegar, analisar página, executar ações).

## Comandos úteis
```bash
# Subir em modo headed (browser visível)
./dev.sh logs

Comment on lines +67 to +69

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the correct command for startup in headed mode.

Line 68 currently tails logs instead of starting the environment. Under this heading, it should be ./dev.sh up.

Suggested doc fix
 # Subir em modo headed (browser visível)
-./dev.sh logs
+./dev.sh up
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Subir em modo headed (browser visível)
./dev.sh logs
# Subir em modo headed (browser visível)
./dev.sh up
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@LAST_STATUS.md` around lines 67 - 69, Under the "Subir em modo headed
(browser visível)" heading, replace the incorrect command string './dev.sh logs'
with the correct startup command './dev.sh up' so the doc shows how to start the
environment in headed mode instead of tailing logs; update the line containing
'./dev.sh logs' to './dev.sh up'.

# Rebuild e subir produção
docker compose build && docker compose up -d

# Acompanhar logs filtrados
docker logs -f deepsproxy 2>&1 | grep -E "\[chat\]|GET |POST "

# Health check manual
curl http://localhost:9301/health
curl http://localhost:9300/health

# Limpar locks manualmente se necessário
find deepseek_profile -name 'Singleton*' -delete

# Testar API non-streaming com json_schema
curl -s http://localhost:9300/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-no-thinking","messages":[{"role":"user","content":"Say hello"}],"stream":false,"response_format":{"type":"json_object"}}' | jq

# Testar API streaming
curl -sS http://localhost:9300/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-thinking","messages":[{"role":"user","content":"Olá!"}],"stream":true}'
```

## Próximos passos recomendados
1. Execute os comandos de verificação acima e cole a saída aqui (ou permita que eu a verifique).
2. Se `/tmp/.X11-unix` do host estiver montado e `xhost` autorizar o usuário, iniciar `docker compose up -d deepsproxy-playwright` e executar `docker exec -d -u node -e DISPLAY=$DISPLAY deepsproxy-playwright npm run login` (sem `xvfb-run`) para abrir o Chromium visível.
3. Se isso falhar, podemos: (a) ajustar montagem/permissões de `/tmp/.X11-unix` e `xauth`, ou (b) manter `xvfb-run` e usar VNC/novnc para ver a tela virtual.

## Notas sobre validação com outros modelos/novo contexto
- Para validar o comportamento em outro ambiente ou modelo, exporte `deepseek_profile` e rode Playwright localmente fora do container, ou reproduza em uma VM com X disponível.
- Posso preparar um script curto que coleta logs, faz checagens e tenta ligar o browser no DISPLAY automaticamente (precisa de autorização para executar kills/changes).

---
Documento criado para iniciar um novo contexto de diagnóstico e validação.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ deepsproxy/
│ ├── index.test.ts # Testes unitários básicos
│ └── advanced.test.ts # Testes de integração avançados
├── docker-compose.yml # Orquestração multi-container
├── Dockerfile # Imagem Docker otimizada
├── Dockerfile.api # Dockerfile para a imagem da API
├── Dockerfile.playwright # Dockerfile para o serviço Playwright
Comment on lines +332 to +333

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Align Docker usage examples with the split-image architecture.

The project tree now documents Dockerfile.api and Dockerfile.playwright, but the Docker section still shows a single-service build: . flow. Please update that section to match the new two-service compose setup to avoid onboarding errors.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 332 - 333, Update the Docker usage section to reflect
the split-image architecture by replacing the single-service build example with
two services: an api service that builds from Dockerfile.api and a playwright
service that builds from Dockerfile.playwright; specifically, show service names
(e.g., "api" and "playwright") and for each include the correct build
context/filename (pointing to Dockerfile.api and Dockerfile.playwright), any
needed ports/volumes for the API and the Playwright service, and the correct
dependency relation (e.g., api depends_on playwright if applicable) so the docs
match the project tree entries Dockerfile.api and Dockerfile.playwright.

├── tsconfig.json # Configuração TypeScript strict
├── package.json # Dependências e scripts
├── .env.example # Template de variáveis de ambiente
Expand Down
48 changes: 48 additions & 0 deletions dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# dev.sh — Sobe o deepsproxy em modo dev (headed browser visível na tela).
# Usa network_mode: host para acessar o X11 abstract socket do host.
#
# Uso:
# ./dev.sh → sobe em background
# ./dev.sh rebuild → rebuilda ambas as imagens e sobe
# ./dev.sh logs → acompanha logs (api|browser|all)
# ./dev.sh down → para os containers

set -e

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Enable strict Bash mode for safer script execution.

set -e alone misses unset vars and pipeline failures; prefer strict mode.

Suggested patch
-set -e
+set -euo pipefail
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
set -e
set -euo pipefail
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dev.sh` at line 11, Replace the lone "set -e" usage at the top of dev.sh with
strict Bash mode: enable -euo pipefail and set a safe IFS (e.g., IFS=$'\n\t') so
the script fails on errors, undefined variables, and pipeline failures; locate
the existing "set -e" line and update it accordingly while keeping it near the
script header.


CMD="${1:-up}"
TYPE="${2:-all}"

case "$CMD" in
up)
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
echo "Para ver logs: ./dev.sh logs [api|browser|all]"
;;
rebuild)
echo "Rebuilding all containers..."
docker rm -f deepsproxy deepsproxy-playwright || true
docker compose -f docker-compose.yml -f docker-compose.dev.yml build
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
echo "Para ver logs: ./dev.sh logs [api|browser|all]"
;;
logs)
case "$TYPE" in
api)
docker logs -f deepsproxy
;;
browser)
docker logs -f deepsproxy-playwright
;;
Comment on lines +30 to +35

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use docker compose logs instead of hardcoded container names.

docker logs -f deepsproxy* is brittle and can fail when container names differ by compose project/context. Keep log routing inside the same compose files used by the script.

Suggested patch
   logs)
     case "$TYPE" in
       api)
-        docker logs -f deepsproxy
+        docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f deepsproxy
         ;;
       browser)
-        docker logs -f deepsproxy-playwright
+        docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f deepsproxy-playwright
         ;;
       *)
         docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f
         ;;
     esac
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
api)
docker logs -f deepsproxy
;;
browser)
docker logs -f deepsproxy-playwright
;;
api)
docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f deepsproxy
;;
browser)
docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f deepsproxy-playwright
;;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dev.sh` around lines 29 - 34, In the "api" and "browser" case branches
replace the brittle hardcoded container log commands ("docker logs -f
deepsproxy" and "docker logs -f deepsproxy-playwright") with docker compose logs
calls that target the services defined in the project's compose files (e.g., use
"docker compose -f <compose-file> logs -f <service-name>" or "docker compose
logs -f <service-name>") so the script follows the compose context instead of
fixed container names; update the "api" branch to follow the compose service for
the API and the "browser" branch to follow the Playwright/browser service,
ensuring you reference the same compose file(s) the script uses.

*)
docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f
;;
esac
;;
down)
docker compose -f docker-compose.yml -f docker-compose.dev.yml down
;;
*)
echo "Uso: ./dev.sh [up|rebuild|logs [api|browser|all]|down]"
exit 1
;;
esac
12 changes: 12 additions & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
services:
deepsproxy:
# network_mode: host
environment:
- PLAYWRIGHT_REMOTE_URL=http://playwright:9301
volumes:
- ./src:/app/src:rw
playwright:
# network_mode: host
volumes:
- ./src:/app/src:rw
- ./deepseek_profile:/app/deepseek_profile:rw
Loading