--- name: cdp_perceive_outline kind: pipeline lang: py domain: pipelines version: "1.0.0" purity: impure signature: "def cdp_perceive_outline(debug_port: int, tab_id: str, max_chars: int = 20000) -> str" description: "Pipeline de percepción: conecta a Chrome via CDP, obtiene el AX tree completo, lo poda y lo convierte en un outline indentado legible para LLMs. Cada nodo accionable lleva #ref=nodeId. Reemplaza enviar 1k-50k nodos JSON crudos al modelo." tags: [browser, cdp, ax-tree, perception, navegator, llm] uses_functions: [cdp_get_ax_tree_py_pipelines, trim_ax_tree_py_core, render_ax_outline_py_core] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [argparse, sys, os] params: - name: debug_port desc: "Puerto de debug remoto de Chrome (ej. 9333). Chrome debe estar corriendo con --remote-debugging-port=PORT." - name: tab_id desc: "ID del tab CDP, campo 'id' de GET http://127.0.0.1:{port}/json/list. Usar cdp_list_tabs_go_browser para listarlo." - name: max_chars desc: "Límite de caracteres del outline resultante. Default 20000 (~5k tokens). 0 = sin límite. Si la página es muy densa, reducir a 10000 para no saturar el context window." output: "String multi-línea con el outline indentado de la página. Nodos accionables tienen ' #ref=nodeId' alineado. El LLM puede responder 'haz clic en #ref=44' para operar la página." tested: false tests: [] test_file_path: "" file_path: "python/functions/pipelines/cdp_perceive_outline.py" --- ## Ejemplo ```bash # Via fn run (patrón canónico para agentes) ./fn run cdp_perceive_outline --debug-port 9333 --tab-id # Obtener tab_id primero: curl -s http://127.0.0.1:9333/json/list | python3 -m json.tool | grep '"id"' ./fn run cdp_perceive_outline --debug-port 9333 --tab-id "A1B2C3D4..." --max-chars 15000 ``` ```python # Uso desde Python (heredoc o pipeline propio) import sys, os sys.path.insert(0, os.path.join("python", "functions")) from pipelines.cdp_perceive_outline import cdp_perceive_outline outline = cdp_perceive_outline(debug_port=9333, tab_id="A1B2C3D4...") print(outline) # RootWebArea "GitHub" # navigation "Site navigation" # link "Homepage" #ref=12 # button "Search" #ref=18 # main # heading "Repositories" # link "fn_registry" #ref=44 # textbox "Filter repositories" #ref=51 ``` ## Cuando usarla Cuando un agente LLM necesita "ver" una página Chrome ya abierta para decidir qué elemento accionar a continuación. Sustituye enviar el AX tree crudo (1k-50k nodos JSON) al modelo por un outline compacto de ~200-500 líneas. El `#ref=nodeId` hace que el LLM pueda responder con una referencia exacta sin ambigüedad. Flujo típico de un agente browser: 1. `cdp_list_tabs` → obtener `tab_id` 2. `cdp_perceive_outline` → outline compacto de la página 3. LLM decide acción (clic en #ref=44, texto en #ref=51, etc.) 4. `cdp_click_node` / `cdp_type_text` con el nodeId extraído del #ref ## Gotchas - Chrome debe estar corriendo con `--remote-debugging-port=`. En Linux nativo: `chromium --remote-debugging-port=9333 &`. Con CDP global activado en `/etc/chromium.d/cdp`, el puerto 9222 siempre está disponible. - El tab no puede tener DevTools abierto (toma el debugger exclusivo). Cerrar DevTools antes de llamar. - `Accessibility.getFullAXTree` puede tardar 2-10s en páginas muy pesadas (SPAs tipo Gmail con miles de nodos). El timeout total es 15s. - El outline resultante puede superar `max_chars` en ~100 chars si el último nodo visible es muy largo. Usar margen holgado (ej. 18000 en vez de 20000 si el context window es ajustado). - Si la página no tiene contenido accesible (ej. canvas puro, PDF embebido), el outline estará vacío o solo tendrá el RootWebArea. En ese caso usar CDP JS evaluation directamente. - `tab_id` es el campo `"id"` del JSON de `/json/list`, no `"targetId"`. Son diferentes.