--- name: cdp_set_file_input kind: function lang: py domain: browser version: "1.0.0" purity: impure signature: "def cdp_set_file_input(selector: str, file_paths, *, port: int = 9222, target_url_substr: str = '', timeout_s: float = 10.0) -> dict" description: "Asigna uno o varios archivos a un de una pestana de un Chrome con remote debugging, via CDP, SIN abrir el dialogo nativo del sistema operativo. Localiza el target por substring de URL, abre el WebSocket y ejecuta DOM.enable -> DOM.getDocument -> DOM.querySelector(selector) -> DOM.setFileInputFiles con las rutas ABSOLUTAS. Es el unico metodo robusto para subir archivos por CDP: el navegador no permite escribir el value de un file input desde JS (seguridad) y simular drag&drop es fragil; setFileInputFiles inyecta los File y dispara el evento change que la SPA escucha. Base de whatsapp_send_image y de cualquier flujo de subida de archivos sobre el navegador diario sin robar el foco al usuario." tags: [cdp, browser, automation, upload, file-input, python, navegator] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: ["json", "os", "urllib.request", "websocket"] params_schema: params: - name: selector desc: "Selector CSS del destino. Debe resolver a UN elemento (se usa el primer match). El input puede estar oculto (display:none); CDP lo localiza igual." - name: file_paths desc: "Ruta (str) o lista de rutas a asignar. Se expanden (~) y se convierten a rutas ABSOLUTAS; cada una debe existir en disco o se aborta con ok=False antes de tocar la red." - name: port desc: "Puerto de remote debugging de Chrome. Default 9222." - name: target_url_substr desc: "Substring que debe contener la URL del target (pestana). Si vacio, usa el primer target de tipo 'page'." - name: timeout_s desc: "Timeout en segundos para la conexion WebSocket. Default 10.0." output: "dict {ok: bool, error: str, node_id: int (nodeId CDP del input localizado, 0 si no se encontro), selector: str (eco), files: list[str] (rutas absolutas asignadas)}. ok=True solo si el input se localizo y setFileInputFiles no devolvio error. Nunca lanza: errores de archivo/red/conexion/transport se devuelven en 'error' con ok=False." tested: true tests: ["test_golden_asigna_archivos_al_input", "test_edge_archivo_inexistente_ok_false_sin_red", "test_edge_selector_no_encontrado_ok_false", "test_error_create_connection_lanza_ok_false"] test_file_path: "python/functions/browser/cdp_set_file_input_test.py" file_path: "python/functions/browser/cdp_set_file_input.py" --- ## Ejemplo ```python import sys, os sys.path.insert(0, os.path.join("python", "functions")) from browser.cdp_set_file_input import cdp_set_file_input # Requiere un Chrome lanzado con --remote-debugging-port=9222. # Adjuntar una imagen al input de subida de una pestana (WhatsApp Web, un formulario, etc). # El input "vivo" suele exponerse tras pulsar el boton "Adjuntar"/"Subir" (haz el click antes). res = cdp_set_file_input( 'input[type="file"][multiple]', "/home/enmanuel/ComfyUI/output/item_icon_potion_00001_.png", target_url_substr="whatsapp", ) print(res["ok"], res["node_id"], res["error"]) # -> True 120 ``` O directo por CLI: `python3 python/functions/browser/cdp_set_file_input.py 'input[type="file"]' /ruta/abs.png whatsapp`. ## Cuando usarla Cuando necesites **subir/adjuntar un archivo** a una pestana abierta sin que aparezca el dialogo nativo de archivos del sistema operativo (que CDP no puede operar). Es la primitiva de subida sobre la que se construye `whatsapp_send_image_py_browser` y cualquier automatizacion de formularios con ``. El patron tipico: primero un click real (`cdp_click_xy_py_browser`) en el boton que expone el input vivo, luego esta funcion con el selector del input y la ruta absoluta del archivo. ## Gotchas - **El input debe existir en el DOM al llamar.** Muchas SPAs (WhatsApp Web) solo crean/activan el `` "vivo" DESPUES de pulsar el boton de adjuntar. Haz el click real primero; si asignas sobre un input persistente/decoy, `setFileInputFiles` puede devolver ok pero la SPA no reacciona (no aparece el preview). - **Rutas ABSOLUTAS obligatorias.** `setFileInputFiles` exige rutas absolutas; la funcion ya convierte (`os.path.abspath` + expanduser), pero el archivo debe existir o aborta con ok=False antes de abrir la conexion. - **El selector debe resolver al input correcto.** Si hay varios `` (uno por tipo: fotos, documento...), afina el selector (`[multiple]`, `[accept*="image"]`). Si no matchea ninguno, devuelve `ok=False` con "no element matches selector". - **Dispara `change`, no `input`.** `DOM.setFileInputFiles` emite el evento `change` nativo (que la mayoria de uploads escuchan). Si una SPA solo escucha otro evento, no bastara. - Requiere un Chrome lanzado con `--remote-debugging-port=9222` (o el puerto que pases). Sin remote debugging, `GET /json` falla y devuelve `ok=False`. - Nunca lanza: errores de archivo/red/WS/transport se reportan en `error` con `ok=False`.