feat(dashboard): Plugins screen (Layout A) — Phase 2 complete 🎉#30
Closed
diegosouzapw wants to merge 78 commits into
Closed
feat(dashboard): Plugins screen (Layout A) — Phase 2 complete 🎉#30diegosouzapw wants to merge 78 commits into
diegosouzapw wants to merge 78 commits into
Conversation
…s major funding agencies
…G diagrams, and per-module metrics
…ython-TS Container registra 8 servicos core + 3 plugins TS. CommandRegistry bridge para 14 comandos. PluginManager com discover_ts_plugins, register_in_container, health_summary. 7 scripts Nexus com DI (from_container). 88/88 testes passando, 378/391 legado preservados. 100% backward compat. docs: README v4.1.0, OPENCODE_ECOSYSTEM.md atualizados, DI_MIGRATION.md criado.
…editais-br v7.1, cache versionado e correção KeyError
…, command interfaces, and project-specific documentation.
…ilidade universal
…ação para v4.2.1
…d refactor README - Create GETTING_STARTED.md in PT-BR with installation guide, prerequisites, 3 usage examples (/artigo, /reversa, /auto), and troubleshooting - Create CONTRIBUTING.md in PT-BR with project structure, code standards, guides for adding agents/skills/MCPs, and PR process - Create ROADMAP.md in PT-BR with version history, evolution cycles (evo-1 to evo-8), and short/medium/long-term goals - Refactor README.md: add Quick Start section after badges, add audience table, simplify Resumo with Detalhes Tecnicos subsection, move Diagramas section after Comandos Rapidos, add Documentacao links table Co-Authored-By: Prof. Marcelo Claro <marceloclaro@gmail.com>
- GETTING_STARTED.md: guia de instalação e primeiros passos - README.md: Quick Start, 'Para quem', diagramas movidos, resumo simplificado, tabela de docs - CONTRIBUTING.md: guia para contribuidores com padrões de código e estrutura do projeto - ROADMAP.md: histórico de versões e visão futura - GLOSSARY.md: glossário de termos técnicos (MCP, DI, RAG, MASWOS, SEEKER, etc.) - AGENTS_PTBR.md: tradução do AGENTS.md (chinês → PT-BR formal) - TUTORIALS.md: 4 tutoriais práticos (artigo, quantum, reversa, MCPs) - AGENTS.md: nota com link para versão em português Co-Authored-By: Prof. Marcelo Claro <marceloclaro@gmail.com>
… rule, MCP count, link annotations - Rename 'Quick Start' to 'Início Rápido' (PT-BR formal rule) - Add missing '## Arquitetura Geral' heading for broken index anchor - Remove duplicate horizontal rule between Arquitetura and Simulação sections - Clarify MCP count in GETTING_STARTED.md (40 registered, 17 active) - Mark TUTORIALS.md, GLOSSARY.md, AGENTS_PTBR.md links as '(em breve)' Co-Authored-By: Prof. Marcelo Claro <marceloclaro@gmail.com>
docs: add onboarding documentation (GETTING_STARTED, CONTRIBUTING, ROADMAP) and refactor README
Conflitos em CONTRIBUTING.md, GETTING_STARTED.md, ROADMAP.md e README.md resolvidos mantendo as versões criadas neste PR (conforme especificações do usuário), com adições do main: header Arquitetura Geral e link Documentação no índice. Co-Authored-By: Prof. Marcelo Claro <marceloclaro@gmail.com>
docs: adicionar documentação de onboarding completa em PT-BR
Correções aplicadas: - Corrigir '&' inválido em XML → '&' (causava xmlParseEntityRef error) - Adicionar markers coloridos por fase (arw-blue, arw-yellow, arw-red, arw-purple) - Corrigir setas do ciclo para conectar corretamente todas as 5 fases - Adicionar spokes tracejados do Health Monitor para cada fase - Reposicionar Health Monitor com score 96/100 - Adicionar badge 'Health Score: 96/100' - Ajustar layout para Phase 5 (VERIFICAR) ficar visível dentro do viewBox - Corrigir loop-back de VERIFICAR → MONITORAR Co-Authored-By: Prof. Marcelo Claro <marceloclaro@gmail.com>
…ling-svg fix: corrigir self-healing.svg — erro XML, layout e conexões
…idade Correções aplicadas em 6 SVGs: academic-pipeline.svg: - Corrigir atributo 'fontSize' → 'font-size' (XML inválido) - Corrigir typo 'Basearado' → 'Baseado' agent-orchestration.svg: - Adicionar 4ª conexão do Orquestrador para Agente Jurídico - Alinhar setas para centros reais dos boxes de agentes mcp-architecture.svg: - Adicionar zona de segurança para coluna Domain (3ª coluna) - Adicionar setas Client → Server entre camadas - Remover emojis (compatibilidade cross-browser) mirofish-phd-auditor.svg: - Remover emojis (compatibilidade cross-browser) rag-strategies.svg: - Substituir emoji circles por SVG <circle> com fill verde - Texto CONFIRMADO agora em verde (#3fb950) self-healing.svg: - Sincronizar com versão corrigida da main (PR #4) Co-Authored-By: Prof. Marcelo Claro <marceloclaro@gmail.com>
…detalhadas - Reestruturar em 4 partes progressivas (Fundamentos → Módulos → Infraestrutura → Referência) - Adicionar seção 'O que é o OpenCode Ecosystem?' com explicação acessível - Adicionar seção 'Conceitos Fundamentais' (Agentes, MCP, Skills, Nexus) - Adicionar seção 'Como Funciona — Fluxo de Trabalho' com diagrama ASCII - Mover Comandos Rápidos para início (uso prático primeiro) - Reordenar módulos: funcionalidades do usuário antes da infraestrutura técnica - Adicionar explicações contextuais em cada seção técnica - Consolidar AutoEvolve em seção própria 'Evolução Autônoma' - Mover diagramas SVG para seção colapsável (details/summary) - Mover comparativo para seção própria - Preservar 100% do conteúdo técnico original Co-Authored-By: Prof. Marcelo Claro <marceloclaro@gmail.com>
fix: melhorar fluxogramas SVG — corrigir erros, conexões e compatibilidade
…rificar MCPs (40 registrados, 17 ativos) Co-Authored-By: Prof. Marcelo Claro <marceloclaro@gmail.com>
…, AuditSearch, PipelineIntegration
…OSYSTEM, README, ROADMAP
…xogramas SVG + GLOSSARY+TUTORIALS
…a Branca, 10 Hooks, 30+ bibliotecas
… rounds, 15 citacoes + 2 novos SVGs
…ory) + bridge AuditSystem
…eis e fluxograma da evolucao R1-R13
…y e todos os fluxogramas
… protocolo reprodutibilidade, 20 citacoes DOI
…jeira, 3 niveis de profundidade, 25+ paginas, 20 citacoes DOI
* chore(config): add opencode.omniroute.json.example template
Opt-in config template for routing through OmniRoute AI Gateway as an
alternative to opencode/big-pickle. Users rename or merge this file into
opencode.json to activate. Original opencode.json is not touched.
* chore(scripts): add OmniRoute tenant health-check script
4-step validation (models, providers, combos, mcp/stream) with proper
exit codes (0 healthy, 1 threshold, 2 connectivity, 3 missing deps).
Used by GETTING_STARTED.md for users to verify their tenant before
applying the example config.
* docs: add optional OmniRoute section to GETTING_STARTED
New section 5 documents how to opt-in to OmniRoute. Preserves big-pickle
as the default and explicitly states no change happens for users who
don't apply the example config.
* docs(readme): mention OmniRoute as optional gateway
One-line addition under 'Modelo base' header pointing to the new section
in GETTING_STARTED.md. big-pickle remains the highlighted default.
* feat(scripts): add apply-omniroute-config.sh JSONC-aware merger
The previous "jq -s '.[0] * {mcp: .[1].mcp}'" command documented in
GETTING_STARTED.md failed because opencode.omniroute.json.example is
JSONC (has // comments) and jq only parses strict JSON.
This script does the merge correctly via Node, using a string-state-aware
JSONC stripper (URLs like https://... are preserved). Backup of the
original opencode.json is created with a UTC timestamp.
* fix(docs): use apply-omniroute-config.sh + default to localhost baseURL
- GETTING_STARTED step 3 now invokes the dedicated script instead of
inline node/jq (which was broken on JSONC).
- Step 2 uses <BASE_URL> placeholder instead of a hardcoded URL.
- Revert section uses dynamic backup detection.
- example baseURL default changed from a hardcoded tenant URL to
http://localhost:20128 (opt-in to external tenants instead of opt-out).
- inline reference to jq merge command removed from the example file.
* fix(scripts): consistent curl arg handling + truncated error output
- Check 4 (/api/mcp/stream) now uses an array for the optional auth
header, matching the style of the fetch() helper.
- Check 1 connectivity error is truncated to one line for terminal
readability (was printing full curl stderr).
* chore: ignore opencode.json.bak.* and merged.tmp artifacts
* fix(scripts): propagate node exit code from apply-omniroute-config
bash resets $? to 0 inside "if ! cmd; then" blocks. The previous
implementation captured EXIT_CODE=$? after the negated condition,
which always returned 0 even when node had failed with code 2 (invalid
JSONC) or 3 (invalid JSON). Callers checking the exit status would
proceed as if the merge succeeded.
Fix: capture $? on a separate line outside the if, with set +e/-e
bracketing to avoid set -e tripping before the exit code is read.
Verified: invalid example → exit 2, invalid target → exit 3, happy
path → exit 0.
* feat(agents): assign omniroute/claude-opus-4-7 to 5 reviewers + 4 architects Adds 'model: omniroute/claude-opus-4-7' frontmatter to nine quality-gate and decision agents. Original plan called for 'banca + orientadores' academic-review agents (5 reviewers + 4 PhD orientadores) but those exist only as textual descriptions in criador-artigo/banca/*.md, not as OpenCode agent files. Adjusted scope to the closest functional analogues in agents/: Reviewers (5): code-reviewer, reviewer, reversa-reviewer, ws-reviewer, security-auditor Architects/decisions (4): architect, architecture-analyzer, adr-manager, contract-manager Each file got a single line added immediately inside the frontmatter (after the opening --- for files without a 'name:' field, or after 'name:' when present). YAML frontmatter is preserved and parseable. Without OmniRoute configured (PR-1 not applied), OpenCode CLI falls back to the global default (opencode/big-pickle) — no crash. * docs: add omniroute-model-mapping reference + CONTRIBUTING section - references/omniroute-model-mapping.md: canonical table of agent categories -> recommended OmniRoute models, fallback ladder, free-tier preservation strategy, and explicit list of the 9 files specialized by this PR. - CONTRIBUTING.md: new section 'Especializando o modelo de um agente (opcional)' documenting the model: frontmatter convention, when to use it, fallback behavior, and PR checklist.
Extends ecosystem-sync to track OmniRoute provider/combo health when
the OMNIROUTE_BASE_URL env var is set. Without the env var, the plugin
behaves identically to v3.5 (zero regression).
New behavior (opt-in via env):
- session.created: fetches /api/providers and /api/combos with 3s
hard timeout, populates state.omniRoute.{providers, combos,
healthyProviderCount, degradedProviderCount, activeComboCount,
lastSync, lastError}. Soft-fail on any error.
- session.idle: log message appends OmniRoute summary.
- shell.env: exports 8 global + N per-provider env vars:
ECOSYSTEM_OMNIROUTE_{ENABLED, BASE_URL, HEALTHY, DEGRADED,
PROVIDER_COUNT, ACTIVE_COMBOS, LAST_SYNC, LAST_ERROR},
ECOSYSTEM_OMNIROUTE_COMBO_SLUGS (CSV — used by /route in PR-4),
ECOSYSTEM_OMNIROUTE_PROVIDER_<NAME>_{HEALTHY,TOTAL,CB}.
Implementation notes:
- 3 new interfaces (OmniRouteProviderHealth, OmniRouteComboInfo,
OmniRouteSnapshot) added before EcosystemState.
- state.omniRoute is OPTIONAL — v3.5 state files load without
migration.
- No new imports. fetch + AbortController are global in Bun 1.3
and Node 22+ (within engines.node range).
- version default bumped to '3.6.0' in loadState.
- service tag in client.app.log calls: 'ecosystem-sync-v3.6'.
- Banner string updated to 'EcosystemSync v3.6'.
Hooks NOT modified (preserved verbatim from v3.5):
- tool.execute.before
- tool.execute.after
- session.error
File: 528 -> 749 lines, +221 net.
#4) * feat(commands): add /route slash command for OmniRoute combo selection Adds the /route slash command which sets OMNIROUTE_COMBO for the current OpenCode session, allowing users to choose the routing strategy (combo) that pipelines like /artigo, /reversa, /quantum will use. Frontmatter declares 5 triggers (/route, /r, /combo, route, combo), arguments (combo_slug), env vars consumed (OMNIROUTE_BASE_URL) and exported (OMNIROUTE_COMBO). Documents 4 usage examples and 4 rules including env_required, slug_validation, session_scope, no_side_effects. The Python CommandRegistry is metadata-only; actual dispatch happens in command/dispatcher.ts (TypeScript) — handler implementation belongs there and is out of scope for this PR. * chore(registry): register /route in TRIGGER_MAP Single-line addition to the dict so CommandRegistry.find() can resolve the /route command from any of its 5 declared triggers. Verified with 'import ast' parse + CommandRegistry.load() discovery. * docs: document /route in README + TUTORIALS - README.md commands table: +1 row for /route. - TUTORIALS.md: new section 'Roteamento OmniRoute por sessão (/route)' with 5 usage examples (cost-optimized, claude-primary, auto-free, none, --list) and an error-handling reference table.
…dbox (#5) Adds a new system skill that teaches agents how to invoke OmniRoute's sandboxed Skills framework via MCP tools (skill_list, skill_run, skill_status, skill_cancel). Progressive disclosure: SKILL.md is 2217B (≤ 2500B budget), references/omniroute-skills-reference.md has full schemas (6169B). Rules enforced via 4 <rule> blocks: prefer_local, timeout_aware, audit_required, no_secrets. Use cases beyond local skills: - Isolation (untrusted code, eval suites) - Audit trail (mcp_audit table) - Public catalog skills (eval-factuality, pii-detect, etc.)
… skeleton (#6) * feat(dashboard): refactor dashboard_server.py to v3.0 with route dispatch Major refactor (849 -> 597 lines, -252 net) introducing the foundation for multi-page management screens in PR-7..PR-10: - PAGE_ROUTES + API_HANDLERS dispatch tables at module top - do_GET / do_PUT / do_POST / do_HEAD methods - _dispatch_api (longest-prefix match), _serve_page, _serve_asset (path-traversal guarded at 2 levels), _send_{json,text,bytes} helpers - _load_api_module() for dynamic handler registration from nexus/api/*.py - 1 MB body cap on POST/PUT to prevent payload DoS - ThreadingHTTPServer NOT yet — single-threaded for foundation; PR-8 will migrate when SSE is introduced Removed (v2.0 legacy): - Inline HTML_TEMPLATE string (~418 lines) — overview now served from nexus/dashboard/index.html on disk (the file that was already there as the public template). - gerar_html_estatico() simplified to read+write the on-disk template (no more inline generation). Preserved: - /dados.json legacy endpoint (external consumers may depend on it) - All overview rendering behavior — verified visually identical - All launcher scripts (nexus/dashboard/run_*.bat, start_dashboard.py) Adds /api/ping endpoint as foundation validation (see nexus/api/ping.py). * feat(api): add nexus/api/ping endpoint for foundation validation First handler registered via the new _load_api_module() pattern. Returns {ok, version: '3.0', omniroute_enabled, omniroute_base_url, timestamp}. Used by nav.js footer to display OmniRoute env status in the sidebar. * feat(dashboard): shared assets — nav.js, styles.css, api.js Three vanilla-JS/CSS assets used by all dashboard pages: - nav.js: window.renderNav(activeKey) renders the 5-item sidebar (overview + 4 pending PRs marked with 'PR-7' etc. badges) - styles.css: design tokens (dark theme), sidebar, table, button, panel styles. No external imports — no Google Fonts, no CDN. - api.js: window.api.{get,put,post,delete,stream} minimal fetch client with consistent error handling and SSE EventSource helper. Served via /assets/* (path-traversal guarded by dashboard_server.py). * feat(dashboard): wrap index.html in layout with sidebar nav - Body wrapped in <div class='layout'> > <div id='nav'> + <main> - All existing v2.0 content preserved verbatim inside <main class='main'> - Added <link rel='stylesheet' href='/assets/styles.css'> to head - Added api.js + nav.js scripts before </body> - Added renderNav('overview') call to highlight current page - Chart.js CDN tag enhanced with SRI integrity hash (CWE-353 mitigation) and crossorigin='anonymous' * docs(dashboard): document v3.0 architecture Architecture reference for contributors implementing PR-7..PR-10: - File layout (pages, assets, nexus/api/ handler modules) - Routing tables (PAGE_ROUTES, API_HANDLERS, assets, legacy) - Design principles (CLI is source of truth, loopback only, pending pattern, stdlib only, reversible) - Security model (loopback bind, path traversal, body cap, shell injection prevention, atomic writes, env scope) - How to add a new page (PR-N pattern) - Version history (v1.0 -> v2.0 -> v3.0 -> v3.1+ upcoming)
* feat(api): add Agents & Models REST endpoints (PR-7)
4 new handler modules registered via _load_api_module():
- nexus/api/agents.py — GET /api/agents with ?category/?model/?overridden/?q filters
- nexus/api/omniroute_proxy.py — GET /api/models, /api/combos (30s in-memory cache, soft-fail)
- nexus/api/session_combo.py — GET/PUT /api/session/combo persists to .evolve/session-env.json
- nexus/api/agent_changes.py — PUT/DELETE staging in .evolve/pending-agent-changes.json,
GET /api/agents/{pending,diff}, POST /api/agents/apply
with atomic per-file writes (tempfile + os.replace)
Soft-fail design: /api/models returns 503 with clear error when
OMNIROUTE_BASE_URL is unset. /api/agents works regardless (local-only).
Path-traversal protection: agent name validated against regex
^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$ before file access.
* feat(dashboard): register PR-7 handlers in dispatcher
Wires up /api/agents, /api/models, /api/combos, /api/session/combo,
/api/agents/{pending,diff,apply,<name>/{model,pending}}. Longest-prefix
match ensures /api/agents/{pending,diff,apply} resolve before the
/api/agents/ catchall for dynamic <agent_name> routes.
* feat(dashboard): Agents & Models screen frontend (Layout A)
- agents.html (149 lines): Layout A table with filters (category,
model, overridden, search), per-row model dropdown, pending counter,
bulk-assign select, diff modal, footer with apply/discard buttons
- agents.js (347 lines): fetch from /api/{agents,models,combos,session/combo,
agents/pending,agents/diff}; render table; handle staging via
/api/agents/<name>/model; preview diff in modal; apply via POST
- agents.css (50 lines): row-changed highlight, star icon for pending,
modal layout, cost tooltip
Layout A was selected by maintainer in the 3-mockup discussion
(see _tasks/pr-7-screen-agents-models/README.md).
* chore: ignore .evolve/session-env.json and pending-agent-changes.json
* feat(api): add Health screen REST + SSE endpoints (PR-8)
3 new handler modules registered via _load_api_module():
- nexus/api/health_providers.py — GET /api/health/providers, 5s cache,
proxies /api/providers from OmniRoute, normalizes to unified schema:
{type:'prov'|'mcp', name, status:'ok'|'warn'|'crit'|'off', score:0-100,
details, extra:{...}, last_check}
- nexus/api/health_mcp.py — GET /api/health/mcp, reads
.evolve/ecosystem-state.json (managed by ecosystem-sync), normalizes
to the same unified schema.
- nexus/api/health_stream.py — GET /api/health/stream Server-Sent
Events. Tick 5s, lifetime cap 10min. Factory pattern: receives
providers + mcp modules at registration time. Cleanly handles
BrokenPipeError/ConnectionResetError. Returns sentinel (-1, None, None)
to signal _dispatch_api that the response was already written.
* feat(dashboard): ThreadingHTTPServer + sentinel for SSE handlers
Two minimal changes enabling SSE in PR-8 without blocking concurrent
requests:
1. HTTPServer -> ThreadingHTTPServer: a single SSE connection no longer
blocks the rest of the API. Verified by running /api/health/stream
in parallel with /api/agents — both respond in <200ms.
2. _dispatch_api recognizes sentinel status=-1 from a handler as 'already
wrote response, do not double-write headers/body'. Required for SSE
handlers that take over the wfile stream.
Plus PR-8 handler registration block.
* feat(dashboard): Health screen frontend (Layout B + SSE)
Layout B (unified dense table) was selected by maintainer:
- health.html: filters (type, status, problems-only), sort dropdown,
table with 6 columns (STATUS, TYPE, NAME, SCORE, DETAILS, LAST CHECK),
alerts bar (CRITICAL/WARNING counts with row names), inline drawer
for selected item with extra fields.
- health.js: connects to /api/health/stream via EventSource, applies
filters/sort client-side, renders rows colored by status (row-ok,
row-warn, row-crit, row-off), live-updates the detail drawer.
- health.css: status-cell coloring, dot indicators, drawer + connection
row styles, pause indicator styling.
Layout B was selected by maintainer in the 3-mockup discussion
(see _tasks/pr-8-screen-health/README.md).
…ocess management) (#9) * feat(api): Pipelines screen REST + SSE endpoints (PR-9) 3 new SECURITY-CRITICAL handler modules: - nexus/api/pipelines_list.py (194 lines): GET /api/pipelines lists commands from command/*.md with frontmatter parser, GET /api/pipelines/runs lists runs from .evolve/pipeline-runs/*/meta.json with PID-liveness orphan detection. - nexus/api/pipelines_run.py (387 lines): POST /api/pipelines/run. Strict security: - Allow-list: command must exist in command/*.md - COMMAND_TOKEN_RE blocks shell metachars before dispatch - Args validated per-arg against schema in frontmatter (type, required, pattern, length cap 4096B per arg, 16KB total) - subprocess uses shell=False, list-form argv - start_new_session=True for killpg-based cancel - Hard timeout MAX_DURATION_S = 8*3600 (8h) - MAX_GLOBAL_CONCURRENT = 8 + per-command lock unless allow_concurrent: true in frontmatter - Args passed via PIPELINE_ARGS_JSON env var (no argv quoting) - cwd = workspace root, env inherited (no privilege escalation) - Append-only output.log - Atomic meta.json updates - nexus/api/pipelines_stream.py (156 lines): SSE tail of output.log + cancel. run_id regex r'run_\d{8}T\d{6}Z_[a-f0-9]{6}' strict. Cancel: SIGTERM → 5s grace → SIGKILL via os.killpg. Sentinel -1 for SSE handler. * feat(dashboard): register PR-9 handlers (pipelines) Adds dispatch routing for /api/pipelines, /api/pipelines/runs, /api/pipelines/run, /api/pipelines/runs/<id>/output/stream, /api/pipelines/runs/<id>/cancel. Uses unified _route_runs callable for dynamic <run_id> routing. * feat(dashboard): Pipelines screen frontend (Layout C) Layout C (tabs + drawer) selected by maintainer: - pipelines.html (134 lines): 2 tabs [Commands (14)] [Runs (N)], filters per tab, modal with auto-generated args form, inline drawer for terminal output of selected run. - pipelines.js (298 lines): tab switching, command list rendering with args-summary in cells, Run button opens modal with form generated from frontmatter arguments[], submit calls POST /api/pipelines/run, redirects to Runs tab, opens drawer with SSE consumer for stdout stream, polling 5s for run list refresh, cancel button. - pipelines.css (54 lines): tab styling, run row status colors, terminal monospace styling, modal form fields. Layout C was selected by maintainer in the 3-mockup discussion (see _tasks/pr-9-screen-pipelines/README.md). * chore: ignore .evolve/pipeline-runs/ (ephemeral run logs)
* feat(api): Plugins screen REST endpoints (PR-10)
2 new handler modules:
- nexus/api/plugins_list.py (227 lines): GET /api/plugins reads
opencode.json, strips JSONC comments via string-state machine
(preserves URLs like https://...), returns plugins with hardcoded
schemas for 5 known plugins (4 internal + @omniroute/opencode-plugin).
has_comments flag warns user that Apply will lose JSONC formatting.
- nexus/api/plugin_changes.py (316 lines): pending-changes machinery
+ atomic apply:
* PUT /api/plugins/<id> stages enabled/options in .evolve/
pending-plugin-changes.json
* DELETE /api/plugins/<id>/pending unstages
* GET /api/plugins/pending lists staged changes
* GET /api/plugins/diff renders unified diff
* POST /api/plugins/apply: pre-validate (schema + must exist in
current config) -> backup opencode.json.bak.<UTC-ts> -> atomic
write via tempfile + os.replace -> restore from backup on any
failure. Response includes restart_required + restart_hint.
Path-traversal protection: plugin id validated against regex
^[A-Za-z0-9@_./-]{1,200}$.
* feat(dashboard): register PR-10 handlers (plugins)
Adds dispatch routing for /api/plugins, /api/plugins/pending,
/api/plugins/diff, /api/plugins/apply, /api/plugins/<id>,
/api/plugins/<id>/pending. Longest-prefix match ensures specific
endpoints resolve before the /<id> catchall.
* feat(dashboard): Plugins screen frontend (Layout A)
Layout A (table + inline expansion) selected by maintainer:
- plugins.html (120 lines): table with ENABLED toggle, PLUGIN name,
VERSION, STATUS, OPTIONS (Configure button). Inline expansion
drawer shows configurable options with field-by-field form. Modal
for diff preview + Apply confirmation. Modal for 'How to restart'
instructions. Comments warning banner at top when applicable.
- plugins.js (321 lines): fetch plugins + pending; render table with
toggle/configure UI; stage changes via PUT /api/plugins/<id>;
preview diff in modal with colored +/- lines; Apply with backup
notice; Discard. Field rendering supports nested keys
(features.combos, etc.).
- plugins.css (72 lines): toggle switch styling, expanded row
highlight, options form grid layout, modal diff styling.
Layout A was selected by maintainer in the 3-mockup discussion
(see _tasks/pr-10-screen-plugins/README.md).
* chore: ignore PR-10 artifacts (backups + pending changes)
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
MarceloClaro
pushed a commit
that referenced
this pull request
May 30, 2026
…honesta - PE#26-#30 (5 problemas genuinamente cegos): 5/5 PASS - ROS-SPLC, LCSM, LIA (3 problemas genuinamente cegos): 3/3 PASS - Total acumulado: 42/42 (100%) — 30 PE + 12 Rosalind - 558K solvers cegos adicionais - Nota honesta: verificacao automatica, nao por revisores - Limitacao explicita: 8/10 dim CORA-Eval sem validacao externa - Pronto para o revisor senior
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
O que esta PR faz
Adiciona a quarta e última tela do Nexus Dashboard v3: Plugins. Configuração visual dos plugins declarados em
opencode.json— toggle enabled, edição de opções com form gerado a partir de schema conhecido, preview-diff antes de apply atômico com backup automático.Com esta PR, a fase Dashboard fica completa: 4 telas funcionais (Agents & Models, Health, Pipelines, Plugins) + Overview legado preservado.
Funcionalidades da tela
opencode.json(4 internos + opcionalmente@omniroute/opencode-pluginse ativo)plugin: [...])opencode.jsonque será gerado)opencode.json.bak.<UTC-ts>→ tempfile +os.replace→ restore automático se write falharJSONC-aware parser
opencode.jsoné JSONC (aceita// comments,/* block comments */, trailing commas). O parser usa state machine que respeita string literals — URLs comhttps://são preservadas (não cortadas como faria um regex naïve).Quando o arquivo tem comentários, a UI mostra banner de aviso explicando que Apply vai perder os comentários — mitigado por backup automático com timestamp.
Endpoints adicionados
/api/pluginshas_commentsflag/api/plugins/<id>/api/plugins/<id>/pending/api/plugins/pending/api/plugins/diff/api/plugins/applySchemas hardcoded (5 plugins conhecidos)
ecosystem-sync— sem opções configuráveismanus-evolve— sem opçõesbernstein-sync— sem opçõesantigravity-bridge— sem opções@omniroute/opencode-plugin— 12 opções (providerId, displayName, baseURL, modelCacheTtl, 8 features flags emfeatures.*)Plugin desconhecido (não no schema) mostra "no schema available — edit
opencode.jsonmanually". Continua podendo toggle enabled.Segurança
opencode.jsonaté Apply explícitoopencode.json.bak.YYYYMMDDTHHMMSSZ)Limitação conhecida (documentada na UI)
Apply destrói comentários JSONC do
opencode.json. Mitigação: banner explícito quandohas_comments=true+ backup com timestamp. Pode ser endereçado em PR futura (parser JSONC com preservação de comentários).Mudanças
nexus/api/plugins_list.pynexus/api/plugin_changes.pynexus/dashboard/plugins.htmlnexus/dashboard/assets/plugins.jsnexus/dashboard/assets/plugins.cssnexus/dashboard_server.py.gitignoreopencode.json.bak.*,merged.tmp,pending-plugin-changes.json)Reverter
git revert <commit-sha>— 4 commits. Backupsopencode.json.bak.*permanecem no disco como safety net mesmo após revert.Prints
🎉 Fase Dashboard completa
Com PR-6 a PR-10 mergeadas, o Nexus Dashboard v3.x ganha:
Próxima e última PR:
fix(audit): consolidated fixes from PRs 1-10 code review— fixes pós-review (do_DELETE missing, /api/dados regression, dispatch bug em rotas com trailing slash, e 7 outros itens menores).