--- name: open_obsidian_vault kind: function lang: py domain: obsidian version: "1.0.0" purity: impure signature: "def open_obsidian_vault(vault: str, register_if_missing: bool = True, launch: bool = True, config_path: str = '') -> dict" description: "Abre un vault en la app de escritorio Obsidian construyendo el URI obsidian://open?vault= (name = basename del path o el propio nombre, URL-encodeado) y lanzandolo desacoplado via xdg-open. Si recibe una ruta existente no registrada y register_if_missing=True, la registra antes componiendo register_obsidian_vault (open=True). Con launch=False construye el URI sin lanzar nada (util en tests)." tags: [obsidian, vault, open, launch, uri, desktop-app, obsidian-json] uses_functions: ["register_obsidian_vault_py_obsidian"] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: ["os", "subprocess", "urllib.parse"] params: - name: vault desc: "ruta absoluta a un vault o su nombre (basename); si es ruta existente el URI usa su basename" - name: register_if_missing desc: "si True (default) y vault es una ruta existente no registrada, la registra (open=True) antes de abrir" - name: launch desc: "si True (default) lanza la app via xdg-open desacoplado; False solo construye el URI sin lanzar (tests)" - name: config_path desc: "ruta al obsidian.json de la app pasada a register_obsidian_vault; vacio usa ~/.config/obsidian/obsidian.json" output: "dict con vault (arg original), uri (obsidian://open?vault=), name (usado en el URI), launched (bool) y registered_now (bool, True si se registro en esta llamada)" tested: true tests: - "registra si falta y construye uri sin lanzar gui" - "por nombre construye uri sin registrar" test_file_path: "python/functions/obsidian/open_obsidian_vault_test.py" file_path: "python/functions/obsidian/open_obsidian_vault.py" --- ## Ejemplo ```python import sys, os sys.path.insert(0, os.path.join("python", "functions")) from obsidian import open_obsidian_vault # Abrir por ruta: registra si falta y lanza Obsidian res = open_obsidian_vault( vault="/home/enmanuel/vaults/osint", register_if_missing=True, launch=True, config_path="", ) print(res["uri"]) # obsidian://open?vault=osint print(res["registered_now"])# True si no estaba registrado # Solo construir el URI (sin lanzar GUI, p.ej. para inspeccion o tests) res = open_obsidian_vault("Mi Vault", launch=False) print(res["uri"]) # obsidian://open?vault=Mi%20Vault ``` ## Cuando usarla Cuando quieras abrir un vault en la app de escritorio Obsidian desde codigo o un agente: tras crear (`create_obsidian_vault`) y registrar (`register_obsidian_vault`) un vault, esta funcion lo abre en un solo paso (registra si hace falta + lanza el URI). Para construir el URI sin lanzar la GUI, usa `launch=False`. ## Gotchas - **Single-instance (lo importante)**: Obsidian es de instancia unica. Si ya hay una instancia corriendo con una config vieja en memoria, el URI `obsidian://open?vault=` puede responder **"unable to find a vault"** para un vault recien registrado, hasta reiniciar la app. Si registras y abres en caliente, reinicia Obsidian para que recargue `obsidian.json`. - **Lanza un proceso externo** (`xdg-open`, I/O impuro) de forma desacoplada (`start_new_session=True`, stdio a DEVNULL): no bloquea ni captura salida. `launch=False` evita lanzar nada. - El nombre del URI es el **basename** del path (Obsidian resuelve vaults por nombre, no por ruta completa). Dos vaults con el mismo basename en rutas distintas pueden colisionar en el URI; Obsidian abrira el que tenga ese nombre en su config. - Necesita un entorno grafico: hereda `DISPLAY`/`WAYLAND_DISPLAY` del entorno. En una sesion headless `xdg-open` puede fallar silenciosamente (el proceso se lanza pero no abre nada). - Si `register_if_missing=True` y el vault es una ruta existente nueva, **escribe la config de la app** (via `register_obsidian_vault`, con su backup `.bak`).