Skip to content
Merged
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
18 changes: 9 additions & 9 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,36 @@ jobs:
- name: Check file sizes
run: |
echo "Checking file sizes (max 500 lines)..."
python scripts/check_file_size.py $(find vertice_cli vertice_tui vertice_core -name "*.py" -type f)
python scripts/check_file_size.py $(find packages/vertice-core/src/vertice_core -name "*.py" -type f)

# Nesting Depth Check - Max 4 levels
- name: Check nesting depth
run: |
echo "Checking nesting depth (max 4 levels)..."
python scripts/check_nesting.py $(find vertice_cli vertice_tui vertice_core -name "*.py" -type f)
python scripts/check_nesting.py $(find packages/vertice-core/src/vertice_core -name "*.py" -type f)

# Cyclomatic Complexity Check - Max D (10-15)
- name: Check cyclomatic complexity
run: |
echo "Checking cyclomatic complexity..."
radon cc vertice_cli/ vertice_tui/ vertice_core/ -a -nc --fail D
radon cc packages/vertice-core/src/vertice_core/ -a -nc --fail D

# Maintainability Index Check - Min A (20+)
- name: Check maintainability index
run: |
echo "Checking maintainability index..."
radon mi vertice_cli/ vertice_tui/ vertice_core/ -s
radon mi packages/vertice-core/src/vertice_core/ -s

# Ruff linting
- name: Run Ruff linter
run: |
ruff check vertice_cli/ vertice_tui/ vertice_core/
ruff check packages/vertice-core/src/vertice_core/

# Bare Exception Handler Check (Tech Debt Prevention)
- name: Check for bare exception handlers
run: |
echo "Checking for bare 'except Exception:' handlers..."
COUNT=$(grep -rn "except Exception:" vertice_cli/ providers/ --include="*.py" | wc -l)
COUNT=$(grep -rn "except Exception:" packages/vertice-core/src/vertice_core/ --include="*.py" | wc -l)
echo "Found $COUNT bare exception handlers"
if [ "$COUNT" -gt 30 ]; then
echo "::warning::Too many bare exception handlers ($COUNT). Target: <30"
Expand All @@ -65,10 +65,10 @@ jobs:
- name: Check for SessionManager duplication
run: |
echo "Checking for SessionManager class duplications..."
DUPS=$(grep -rn "class SessionManager" vertice_cli/ --include="*.py" | grep -v "core/session_manager" | grep -v "DEPRECATED" | wc -l)
DUPS=$(grep -rn "class SessionManager" packages/vertice-core/src/vertice_core/ --include="*.py" | grep -v "core/session_manager" | grep -v "DEPRECATED" | wc -l)
if [ "$DUPS" -gt 0 ]; then
echo "::error::Found $DUPS non-canonical SessionManager implementations"
grep -rn "class SessionManager" vertice_cli/ --include="*.py" | grep -v "core/session_manager" | grep -v "DEPRECATED"
grep -rn "class SessionManager" packages/vertice-core/src/vertice_core/ --include="*.py" | grep -v "core/session_manager" | grep -v "DEPRECATED"
exit 1
fi
echo "✅ No SessionManager duplication found"
Expand All @@ -92,7 +92,7 @@ jobs:

- name: Run tests with coverage
run: |
pytest tests/ -v --cov=vertice_cli --cov=vertice_tui --cov=vertice_core --cov-report=xml --cov-fail-under=60
pytest tests/ -v --cov=packages/vertice-core/src/vertice_core --cov-report=xml --cov-fail-under=60

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
Expand Down
36 changes: 36 additions & 0 deletions JULES_ISSUES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# JULES AGENT BACKLOG - VERTICE-CODE SINGULARITY

Este arquivo contém as issues iniciais para a atuação do agente **JULES**, focadas na transição para a Fase 7 (Cloud API Registry) e estabilização do padrão Google-Native 2026.

---

## [JULES-001] Infra: Inicializar ApiRegistry stub no VerticeAgent
**TAG:** `JULES`, `ADK`, `INFRA`
**DESCRIÇÃO:** Integrar a classe `ApiRegistry` da Vertex AI na classe base dos agentes para permitir a descoberta dinâmica de ferramentas, conforme o Blueprint 2026.
**TAREFAS:**
- [ ] Modificar `packages/vertice-core/src/vertice_core/adk/base.py`.
- [ ] Importar `vertexai.preview.api_registry.ApiRegistry` (dentro de um bloco try-except para manter compatibilidade local).
- [ ] Adicionar `self.registry = ApiRegistry(project=project)` no `__init__`.
- [ ] Criar um método placeholder `self.discover_tools(service_name: str)` que encapsule a busca no registry.

---

## [JULES-002] Deps: Alinhar requirements do Agent-Gateway com SDK 2026
**TAG:** `JULES`, `DEPS`, `COMPLIANCE`
**DESCRIÇÃO:** Atualizar as dependências do gateway de agentes para garantir compatibilidade com as versões especificadas no Blueprint da Singularidade.
**TAREFAS:**
- [ ] Modificar `apps/agent-gateway/requirements.txt`.
- [ ] Atualizar `google-cloud-aiplatform` para `1.115.0`.
- [ ] Atualizar `google-genai` para `1.2.0`.
- [ ] Garantir que o `vertice-core` seja instalado em modo editável (`-e`).

---

## [JULES-003] Test: Validar conformidade de descoberta dinâmica no SDK
**TAG:** `JULES`, `TEST`, `ADK`
**DESCRIÇÃO:** Criar um teste unitário que valide se o `VerticeAgent` consegue instanciar o `ApiRegistry` sem quebrar o runtime caso o ambiente não seja GCP.
**TAREFAS:**
- [ ] Modificar `tests/unit/test_vertice_adk_sdk.py`.
- [ ] Adicionar um caso de teste `test_agent_registry_initialization`.
- [ ] Mockar a resposta do `ApiRegistry` para simular a descoberta de ferramentas do Prometheus.
- [ ] Verificar se o agente emite o evento de telemetria "registry_init" corretamente.
62 changes: 61 additions & 1 deletion docs/google/VERTICE_GOOGLE_SINGULARITY_BLUEPRINT_2026.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,64 @@ pytest tests/unit/test_alloydb_migration.py tests/unit/test_alloydb_cutover_beha
2. **Immersive Experience:** Landing page com input central direto para o agente e dashboard de streaming CoT (Chain of Thought).
3. **Artifact Gallery:** Interface visual para gestão de código, UI e ativos gerados pela malha de agentes.

### FASE 7: O NEXUS DE FERRAMENTAS (Cloud API Registry) — 🆕 NOVA (29/01/2026)
**Objetivo:** Centralizar a descoberta e execução de ferramentas MCP via infraestrutura gerenciada da Google, eliminando a configuração manual de endpoints e centralizando a governança.

#### 7.1 Registro e Ativação (Infrastructure)
O administrador deve habilitar os servidores MCP no projeto `vertice-ai`.

* **Habilitar Ferramentas Google:**
```bash
# Habilitar BigQuery como ferramenta MCP
gcloud beta api-registry mcp enable bigquery.googleapis.com --project=vertice-ai
```
* **Registrar Servidor Custom (Prometheus):**
Atualmente via **API Hub**, vinculando o endpoint do Cloud Run:
```bash
# Registrar o endpoint do vertice-mcp
gcloud apigee apis create vertice-mcp \
--display-name="Prometheus Tactical Tools" \
--description="58+ tactical tools for code, git, and shell" \
--project=vertice-ai
```

#### 7.2 Implementação no ADK (Python SDK)
Atualização do `VerticeAgent` para descoberta dinâmica de ferramentas. Em vez de hardcoding, usamos o `ApiRegistry`.

```python
from vertexai.preview.api_registry import ApiRegistry
from vertexai.preview.generative_models import GenerativeModel

class VerticeAgent(abc.ABC):
def __init__(self, project="vertice-ai", location="us-central1"):
# Inicializa o Registro de Ferramentas da Google
self.registry = ApiRegistry(project=project)

# Descoberta Dinâmica (O Nexus)
# Busca o toolset do Prometheus e do BigQuery
self.prometheus_tools = self.registry.get_toolset(
service_name="vertice-mcp.api.hub"
)
self.google_tools = self.registry.get_toolset(
service_name="bigquery.googleapis.com"
)

async def query(self, input_text):
# O modelo agora tem acesso às ferramentas via Registry
model = GenerativeModel(
"gemini-3-flash",
tools=[self.prometheus_tools, self.google_tools]
)
# ... execução do agente
```

#### 7.3 Governança IAM (Hardened)
A segurança não é mais por API Key, mas por identidade de serviço (Service Account).

* **Role de Visualização:** `roles/cloudapiregistry.viewer` (Permite ao agente ver o que existe).
* **Role de Execução:** `roles/mcp.toolUser` (Permite ao agente chamar `call_tool`).
* **Isolação:** Cada agente (Coder, Security) deve ter sua própria SA, com permissões específicas no Registry.

---

## 4. ESTRUTURA DE ARQUIVOS DEFINITIVA (2026)
Expand All @@ -124,14 +182,15 @@ pytest tests/unit/test_alloydb_migration.py tests/unit/test_alloydb_cutover_beha
├── packages/
│ ├── vertice-core/ # O "Espírito" (Python Library)
│ │ ├── adk/ # Core ADK 2026 (BaseAgent, ApiRegistry)
│ │ ├── agents/ # Definições Puras (ADK)
│ │ ├── tools/ # Ferramentas (Google Search, Code Interpreter)
│ │ └── memory/ # AlloyDB Connectors
│ └── vertice-ui/ # Design System (Radix/Tailwind)
└── infra/
├── terraform/ # IaC para AlloyDB, Vertex AI, Cloud Run
└── cloudbuild.yaml # Pipeline CI/CD Unificado
└── api-registry/ # Configurações de registro de ferramentas MCP
```

---
Expand All @@ -143,6 +202,7 @@ pytest tests/unit/test_alloydb_migration.py tests/unit/test_alloydb_cutover_beha
| **Escalabilidade** | Limitada pelo tamanho da VM | **Infinita** (Serverless) |
| **Latência** | Alta (Python processando tudo) | **Baixa** (Streaming via AG-UI) |
| **Manutenção** | Pesadelo (DevOps manual) | **Zero** (Managed Services) |
| **Discovery de Tools**| URLs fixas / .env | **Cloud API Registry** (Centralizado) |
| **Custo Ocioso** | 100% (VM sempre ligada) | **Perto de Zero** (Scale to Zero) |
| **Inteligência** | LLM legacy (pré‑Google‑native) | **Gemini 3 (Pro/Flash) via Vertex AI + Grounding** |

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions packages/vertice-core/src/vertice_core/adk/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from vertice_core.providers.vertex_ai import VertexAIProvider
from vertice_core.memory.cortex.cortex import MemoryCortex
from vertice_core.messaging.events import SystemEvent, get_event_bus
from vertice_core.adk.registry import ApiRegistry


class VerticeAgent(abc.ABC):
Expand All @@ -33,6 +34,9 @@ def __init__(
self._provider = VertexAIProvider(project=project, location=location, model_name=model)
self._cortex = MemoryCortex()

# Dynamic Discovery Registry
self.apis = ApiRegistry(project=project, location=location)

def emit_event(self, event_type: str, payload: Mapping[str, Any]) -> None:
"""
Emit an internal telemetry event (fire-and-forget).
Expand Down
107 changes: 107 additions & 0 deletions packages/vertice-core/src/vertice_core/adk/registry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
"""Vertice ADK - Dynamic API Registry for 2026 Google-Native ecosystem."""

from __future__ import annotations

import os
import logging
from typing import Any, Dict, List, Optional

logger = logging.getLogger(__name__)

# --- Google Gen AI SDK (Vertex AI) ---
HAS_GENAI_SDK = False
try:
from google import genai

HAS_GENAI_SDK = True
except ImportError:
pass


class ApiRegistry:
"""
Dynamic registry for discovering and managing available APIs and models.
Ensures runtime compatibility across different environments (GCP vs local).
"""

def __init__(self, project: Optional[str] = None, location: str = "global") -> None:
self.project = project or os.getenv("GOOGLE_CLOUD_PROJECT")
self.location = location
self._genai_client = None

# Check environment
self._is_gcp = self._check_gcp_environment()
logger.debug(f"ApiRegistry initialized. GCP detected: {self._is_gcp}")

def _check_gcp_environment(self) -> bool:
"""Heuristic to detect if running in a GCP environment."""
# Check for standard GCP environment variables
return any(
[
os.getenv("GOOGLE_CLOUD_PROJECT"),
os.getenv("K_SERVICE"), # Cloud Run
os.getenv("GAE_SERVICE"), # App Engine
os.path.exists("/var/run/secrets/google"), # GKE
]
)

def _get_genai_client(self) -> Optional[Any]:
"""Lazy initialization of the GenAI client."""
if self._genai_client is not None:
return self._genai_client

if not HAS_GENAI_SDK:
logger.debug("google-genai SDK not installed, discovery disabled.")
return None

try:
# We don't want this to raise during instantiation of the registry
self._genai_client = genai.Client(
vertexai=True,
project=self.project,
location=self.location,
)
return self._genai_client
except Exception as e:
logger.warning(f"Failed to initialize GenAI client for discovery: {e}")
return None

async def discover_models(self) -> List[Dict[str, Any]]:
"""
Dynamically discover available Gemini models on Vertex AI.

Returns a list of model metadata. Returns an empty list if discovery is
unavailable or fails.
"""
client = self._get_genai_client()
if client is None:
return []

try:
# Note: client.aio.models.list is the pattern for async discovery in 2026 SDK
response = await client.aio.models.list(config={"page_size": 50})

# Handle both Pager and direct list response
models = getattr(response, "models", response)

return [
{
"name": getattr(m, "name", str(m)),
"display_name": getattr(m, "display_name", ""),
"description": getattr(m, "description", ""),
"capabilities": getattr(m, "supported_generation_methods", []),
}
for m in models
]
except Exception as e:
logger.warning(f"Dynamic model discovery failed: {e}")
return []

def get_status(self) -> Dict[str, Any]:
"""Return the current status of the registry and environment."""
return {
"is_gcp": self._is_gcp,
"has_sdk": HAS_GENAI_SDK,
"project": self.project,
"location": self.location,
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ def __init__(
self._iteration_count = 0
self._start_time: Optional[float] = None

self._on_state_change: Optional[
Callable[[OrchestratorState, OrchestratorState], None]
] = None
self._on_state_change: Optional[Callable[[OrchestratorState, OrchestratorState], None]] = (
None
)
self._on_step_complete: Optional[Callable[[ExecutionStep, ExecutionResult], None]] = None

def _transition_to(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
Router Module - Semantic routing for agent selection.
"""


from .cache import RouterCacheMixin
from .router import SemanticRouter
from .similarity import SimilarityEngine
Expand Down
Loading
Loading