Além do TerminalUIProvider (diálogos prontos: MSDIALOG/FWGetText/
FWMenuSelect), o AdvPP agora expõe primitivas visuais de baixo nível para
um programa AdvPL compor a própria TUI — estilo opencode/Claude Code (caixas
com borda, markdown renderizado no terminal, tela alternativa, streaming de
LLM token a token). Ver pkg/vm/ui_render.go e seção 4.4.1 do
GUIA_DO_DESENVOLVEDOR_PARA_ADVPP.md.
- ✅
UiBox/UiStreamBox/UiStreamReset(lipgloss): caixa com borda arredondada e título; a varianteStreamapaga e redesenha por cima a cada chamada (altura rastreada emVM.lastBoxLines), dando o efeito de "cartão crescendo ao vivo" sem raw-mode de teclado - ✅
UiMarkdown(glamour): negrito/itálico/listas/código/títulos para ANSI, estilo "dark" fixo — mesma cautela contra auto-detecção de tema via OSC 11 (pode travar em terminal/multiplexer que não responde) já aplicada ao lipgloss empkg/ui/terminal.go - ✅
UiAltScreenEnter/UiAltScreenExit: tela alternativa (buffer do vim/less/htop) com handler de Ctrl+C que restaura antes de encerrar — sem isso um Ctrl+C durante o app travaria o terminal do usuário na tela alternativa - ✅
UiTermWidth: largura real do terminal, cai num default configurável quando stdout não é TTY - ✅
ConOutRaw: escreve sem newline — texto em streaming (deltas de LLM) na mesma linha - ✅
ConIndistingue EOF real de linha vazia: agora devolve Nil (não"") quando stdin fecha de verdade (Ctrl+D, pipe esgotado) — um REPL consegue sair do loop em vez de reimprimir o prompt pra sempre - ✅
ProcRun: executa um processo filho (sem shell) com callback síncrono por linha de stdout/stderr — consumo de NDJSON em streaming (ex.: CLI de um LLM) direto de dentro do AdvPL - ✅
JsonObject:FromJsoné um parser real (era stub que sempre devolvia Nil sem parsear nada): objetos aninhados viramJsonObject, arrays viramArray1-based,null→Nil;.F.(não erro) em JSON inválido - ✅ Paridade Windows: toda saída que pode conter ANSI passa por
stdoutW(go-colorableno Windows,os.Stdoutpuro no Linux/macOS) — sem issocmd.exe/PowerShell semENABLE_VIRTUAL_TERMINAL_PROCESSINGimprimiriam os escapes literalmente
pkg/vm/ui_render.go: as 7 natives de TUI (registerUiRenderNatives)pkg/vm/natives.go:stdoutW,CONOUTRAW,PROCRUN,CONIN(EOF→Nil)pkg/vm/vm.go:VM.lastBoxLines,jsonToAdvplValue,JsonObject:FromJsonreal- Nova dependência:
github.com/charmbracelet/glamour(+go-colorable) - Teste:
cmd/advplc/tui_natives_test.go+ fixturetests/tui_natives_test.prw— exercita as 7 natives de TUI,ConOutRaw,ProcRun(contra o próprio binário buildado, portátil entre SOs),FromJson(válido/inválido/aninhado) e o EOF deConIn
Até esta data, advplc build compilava e o binário resultante "rodava"
sem erro mesmo quando a interação real (login, menus, FWMBrowse) nunca
acontecia de fato — nenhum teste automatizado exercitava esse caminho, só
o smoke test 100%-console (TestBuildStandaloneSmoke, zero prompts). Os
dois problemas abaixo existiam desde a introdução do build e só foram
descobertos ao tentar usar um app de verdade (e-Gov) interativamente:
- ✅ Console interativo real (
pkg/ui/terminal.go,TerminalUIProvider):FWGetText/FWMenuSelect/Msg*leem/escrevem no terminal de verdade quando stdin é um TTY — antes, sem nenhumUIProvideranexado no modo headless, esses natives nunca tocavam stdin e devolviam o default silenciosamente (login "passava direto" sem pedir nada) - ✅ TUI real via
huh+lipgloss: formulários com borda, seleção por seta, tema escuro fixo (sem depender de query OSC 11 ao terminal, que pode travar em ambientes que não respondem) - ✅
FWMBrowsefunciona no console, não só emadvplc serve— listagem em tabela (largura adaptada ao terminal, com aviso de campos ocultos), Novo/Editar/Excluir com formulário multi-campo - ✅ Detecção console-vs-GUI corrigida: a heurística antiga checava
bc.Classes, que só registra classes declaradas (class X from Y) — nunca detectavaFWMBrowse():New()(toda instanciação real de classe builtin). Trocada por varredura real do bytecode (OP_CALL_NATIVEpara FWGetText/FWMenuSelect,OP_NEW_INSTANCEpara FWMBrowse/MSDIALOG/etc) - ✅
ADVPP_FORCE_GUI=1: força a janela Fyne mesmo rodando de um terminal — para um app cujo autor prefere GUI como padrão (ex.: e-Gov, GesCon), sem mudar o comportamento padrão (console-se-tem-TTY) de outros programas AdvPP - ✅ Correção de bug correlato em
FWMBrowse: o fallback de colunas sem entrada no SX3 expunhaR_E_C_N_O_/R_E_C_D_E_L_(chave interna) como campo editável — um Novo/Editar sobrescrevia o próprio rowid e o INSERT/UPDATE seguinte falhava com "datatype mismatch"
pkg/ui/terminal.go:TerminalUIProvider(implementavm.UIProviderevm.BrowseUI)pkg/compiler/stub_template.go: decisão console-vs-GUI,ADVPP_FORCE_GUIpkg/vm/browse.go: exclusão deR_E_C_N_O_/R_E_C_D_E_L_do fallback sem SX3- Teste de integração real (builda o binário, roda sob um pseudo-terminal
de verdade, digita/navega/confirma exatamente como um humano):
cmd/advplc/build_standalone_interactive_test.go(TestBuildStandaloneInteractive), fixturetests/standalone_interactive_test.prw— roda nos 3 SOs do CI (Linux/macOS viacreack/pty, Windows viagithub.com/UserExistsError/conpty, ConPty real em Go puro sobregolang.org/x/sys/windows, sem cgo), abstraído emptysession_posix_test.go/ptysession_windows_test.go— mesmo teste, mesmas asserções, cobertura real nas três plataformas que o release publica
Adendo (2026-08-01): advplc build --gui fixa a decisão console-vs-GUI
em tempo de compilação (a heurística acima descrita continua sendo o
comportamento padrão sem a flag). Diferença prática do ADVPP_FORCE_GUI
já documentado: --gui também linka o binário Windows no subsistema GUI
(-H=windowsgui, pkg/compiler/standalone.go:goBuildArgs), então nenhuma
janela de console aparece nem por um instante — ADVPP_FORCE_GUI sozinho
não muda o subsistema. Obrigatório para programas com MSDIALOG.
O compilador AdvPP agora inclui renderização completa de widgets Fyne para todos os componentes UI.
- ✅ Estruturas de dados de componentes (TButton, TGet, TComboBox, TCheckBox, etc.)
- ✅ Estruturas de diálogo (Dialog, MenuBar, ToolBar, StatusBar)
- ✅ Propriedades de componentes (X, Y, Width, Height, Label, Value, etc.)
- ✅ Framework de tratamento de eventos (onChange, onClick, onGotFocus, onLostFocus)
- ✅ Renderização de widgets Fyne para todos os componentes
- ✅ Renderização de TButton
- ✅ Renderização de TGet (entrada de texto)
- ✅ Renderização de TComboBox
- ✅ Renderização de TCheckBox
- ✅ Renderização de TLabel
- ✅ Renderização de MenuBar
- ✅ Renderização de ToolBar
- ✅ Renderização de StatusBar
- ✅ Renderização de view de formulário com conteúdo scrollable
- ✅ Diálogos Fyne básicos (MsgInfo, MsgStop, MsgAlert, MsgYesNo)
- ✅ Componentes UI da IDE (CodeEditor, OutputConsole, FileTree)
- ❌ Execução de eventos de componentes (manipuladores definidos mas não conectados)
- ❌ Atualizações dinâmicas de componentes (sem two-way binding)
- Componentes são definidos como structs Go em
pkg/mvc/view.go - Renderização Fyne implementada em
pkg/ui/renderer.go - Executável de teste visual:
./ui-test(emcmd/ui-test/) - Renderização completa de componentes agora funcional
O compilador AdvPP sobe um servidor HTTP REST real (pkg/rest + classe
nativa WSRestServer, mesmo padrão arquitetural do MCPServer) para o
estilo moderno TLPP de anotações (@Get/@Post/@Put/@Patch/@Delete
sobre User Function). O DSL clássico WSRESTFUL ... WSMETHOD ... ENDWSRESTFUL continua apenas parseado — ver limitação abaixo.
- ✅ Servidor HTTP real (
net/httppuro, sem CGO/dependências): classeWSRestServer—New(),AddRoute(verbo, path, funcao),Serve(porta) - ✅ Auto-discovery de rotas via anotação: toda
User Functionanotada com@Get("/path")/@Post(...)/@Put(...)/@Patch(...)/@Delete(...)vira rota automaticamente ao criar oWSRestServer - ✅ Path params (
/clientes/{id}) via roteador nativo do Go 1.22+ (http.ServeMux), populados no objeto de argumento da função AdvPL - ✅ Query string e corpo JSON decodificados e mesclados no objeto
de argumento (
oParam:CAMPO) — corpo tem precedência sobre path params, que tem precedência sobre query string - ✅ Dispatch real para a função AdvPL via VM isolada por requisição
(mesmo mecanismo do
MCPServer/StartJob:v.RunFunction), banco e bytecode compartilhados - ✅ Resposta JSON automática do retorno da função (200), erro vira 500, path inexistente vira 404, verbo não registrado num path existente vira 405
- ✅ Registro manual de rota via
AddRoute(cobre casos onde a anotação não é usada) - ✅ Sintaxe JSON inline, métodos JsonObject (toJson, hasProperty, getJsonText), serialização/deserialização JSON
- ❌ DSL clássico
WSRESTFUL <nome> ... WSMETHOD <verbo> ... PATH "..." ... ENDWSRESTFUL: o parser (parseWSClientempkg/parser/parser.go) reconhece a sintaxe e monta umast.ClassDecl, mas descarta o verbo HTTP e a cláusulaPATHao fazer isso — só o nome doWSMETHODsobrevive como protótipo. Além disso, a implementação real do método (WSMETHOD ... WSSERVICE <classe>) é um método de instância, ev.RunFunction(usado pelo dispatch HTTP) só chama funções top-level, não métodos de classe — precisaria criar a instância do serviço a cada requisição. Nenhuma das duas partes foi implementada: exigiria cirurgia de parser (capturar verbo+path como antes) e um caminho de dispatch novo (instanciar + chamar método) só para esse estilo, sem um caso de uso real nos corpora validados para justificar o esforço agora. Workaround: reescrever o serviço no estilo anotações (@Get/@PostsobreUser Function), que já é 100% funcional, ou registrar a rota manualmente viaAddRoute. - ❌ Geração de WSDL / cliente REST (
WSCLIENTconsumindo serviço externo) — fora de escopo, é consumo e não exposição de API - ❌ Controle fino de código HTTP de resposta pela função AdvPL (sempre
200 em sucesso / 500 em erro — sem equivalente a
SetLegacySuccess/GetHTTPCodedo lado servidor)
- Servidor:
pkg/rest/rest.go(stdlibnet/http, roteador nativo do Go 1.22+, sem dependências externas) - Ponte VM:
pkg/vm/rest_native.go(classe nativaWSRestServer, conversão JSON↔advplrt.Value, auto-discovery viaFunctionInfo.Annotationsdo bytecode) - Fixture de teste:
tests/rest_server_test.prw; teste de integração Go (builda o binário, sobe o servidor, faz requisições HTTP reais):cmd/advplc/rest_integration_test.go(TestRestServerFixture)
- ✅ Parsing de sintaxe WSCLIENT/WSSTRUCT/WSRESTFUL
- ✅ Definições de protótipo WSMETHOD
- ✅ Definições de campos WSDATA
- ✅ Metadados de serviço (DESCRIPTION, NAMESPACE)
- ✅ Criação e manipulação de objetos JSON
- ❌ Geração de código WSDL
- ❌ Geração de código de cliente REST
- ❌ Invocação de serviço
- ✅ Integração de cliente HTTP nativa:
FWHttpGet/FWHttpPost/FWHttpPut/FWHttpPatch/FWHttpDelete+FWHttpBody/FWHttpStatus/FWHttpErrorcom suporte a certificado PKCS#12 (.pfx/.p12), timeout 30s, TLS com verificação. Testes de integração com servidor HTTP local. Adicionado v2.0.1.
- ✅ Banco SQLite compartilhado: todas as ferramentas (advplc,
adveditor, advpp-ide) resolvem o mesmo banco via
shared.ResolveDatabasePath(flag →ADVPP_DB→ config real em disco →./advpp.dblocal do diretório de trabalho, criado automaticamente) - ✅ Driver 100% Go (modernc.org/sqlite, sem CGO) com WAL + busy_timeout
- ✅ Natives de banco conectados ao VM: DBSelectArea, DBSeek, DBSkip, RecCount, FieldGet/FieldPut etc. operam sobre o banco real
- ✅ StartJob(cFunc, cEnv, lWait, params...): execução em VM isolado (goroutine), síncrona ou assíncrona, com conexão própria ao banco
- ✅ FWGridProcess: pool de threads com backpressure (SetThreadGrid, CallExecute, StopExecute, IsFinished, meters, SaveLog)
- ✅ advplc check paralelo: N arquivos com 1 worker por CPU
- ✅ Renderer web (advplc serve): PO-UI embutido no binário; console, diálogos, FWMBrowse→po-table com dicionário SX3, po-dynamic-form, MSDIALOG legado por heurística de grade e hot reload (--watch)
- ✅ Motor de inferência LLM (classe
LLM): modelos GGUF I2_S (BitNet/Falcon3-1.58bit) viapkg/llm, 100% Go sem CGO, com kernel SIMD AVX2 em amd64 (fallback escalar em qualquer outra arquitetura), validado token a token contra ollama.cppde referência - ✅ Servidor MCP nativo (classe
MCPServer): JSON-RPC 2.0 real sobre stdio viapkg/mcp(initialize/tools.list/tools.call), expõe funções AdvPL como tools — execução real; validado com o SDK oficial em Python do MCP - ✅ Servidor REST nativo (classe
WSRestServer): HTTP real viapkg/rest(net/httppuro), auto-discovery de rotas por anotação (@Get/@Post/@Put/@Patch/@Delete) ou registro manual viaAddRoute, path params, dispatch para a função AdvPL viav.RunFunction— mesmo padrão doMCPServer; o DSL clássicoWSRESTFUL/WSMETHODcontinua só parseado (ver "Recursos REST 2.0") ⚠️ Locks de registro (RecLock/MsUnlock) são no-ops — sem controle de concorrência em escrita entre processos
| Recurso | Status | Notas |
|---|---|---|
| Componentes UI | ✅ Completo | Renderização Fyne completa implementada |
| Diálogos UI | ✅ Completo | MsgInfo, MsgStop, MsgAlert, MsgYesNo funcionam |
| Parsing REST | ✅ Completo | Sintaxe totalmente parseada |
| Execução REST (anotações @Get/@Post) | ✅ Funcional | Servidor HTTP real (WSRestServer), dispatch para a função AdvPL |
| Execução REST (DSL WSRESTFUL/WSMETHOD) | ❌ Nenhum | Apenas parsing — ver "Recursos REST 2.0" |
| Anotações @Get/@Post/@Put/@Patch/@Delete | ✅ Executadas | Viram rota HTTP automaticamente |
| Suporte JSON | ✅ Completo | Sintaxe inline e JsonObject funcionam |
| Construção de Serviços | Parseado, não gerado |
O compilador AdvPP e todos os componentes UI são totalmente compatíveis com a IDE AdvPP.
- ✅ Todos os 8 arquivos de teste existentes passam
- ✅ Componentes MVC funcionam no contexto da IDE
- ✅ Integração de provider UI funciona
- ✅ Saída do compilador com componentes UI funciona
- ✅ Execução da VM com renderização UI funciona
- ✅ Funções de diálogo (MsgInfo, MsgStop, MsgAlert, MsgYesNo) funcionam
- ✅ Suporte JSON funciona
- ✅ Funções nativas funcionam
- ✅ Estruturas de controle funcionam
- ✅ Arrays funcionam
- ✅ Funções de string funcionam
./advplc run tests/ide_integration_test.prwTodos os testes passaram - 100% de compatibilidade com IDE verificada.
Para testar a renderização UI:
go build -o ui-test ./cmd/ui-test
./ui-testIsso exibirá uma janela com:
- TLabel (título)
- TGet (entrada de texto)
- TComboBox (dropdown)
- TCheckBox (checkbox)
- TButton (botões)
- ToolBar (topo)
- StatusBar (fundo)
- Para Componentes UI: Implementar sistema de renderização de widgets Fyne ou documentar como apenas dados
- Para REST: DSL clássico
WSRESTFUL/WSMETHODainda precisa de captura de verbo+path no parser e dispatch via instância de classe (hojev.RunFunctionsó chama funções top-level) — sem caso de uso real nos corpora para priorizar agora - Para Serviços: Adicionar geração de código ou integração de cliente HTTP
- Documentação: Atualizar README para separar claramente recursos "parseados" de "executados"