#!/usr/bin/env bash # Shared helpers, sourced by the other scripts in this directory. # Not meant to be executed directly, and not whitelisted on its own. CONFIG_FILE="$HOME/.agent-skills/obsidian-vault-kb/config.json" # Resolve a vault's absolute path by name from the config file. # If no name is given and the config has exactly one vault, use that one. # Never accepts a raw path from the caller — only a name looked up # server-side (in the config file) — so a whitelisted script can't be # pointed at an arbitrary directory outside the configured vault(s). resolve_vault_path() { local vault_name="${1:-}" if [ ! -f "$CONFIG_FILE" ]; then echo "Error: no configuration found at $CONFIG_FILE. Run /setup first." >&2 exit 1 fi if ! command -v python3 >/dev/null 2>&1; then echo "Error: python3 is required to parse the config file." >&2 exit 1 fi python3 - "$CONFIG_FILE" "$vault_name" << 'PYEOF' import json, sys config_file, vault_name = sys.argv[1], sys.argv[2] with open(config_file) as f: cfg = json.load(f) vaults = cfg.get("vaults", []) if not vaults: sys.stderr.write("Error: no vaults defined in config.\n") sys.exit(1) if vault_name: match = [v for v in vaults if v.get("name") == vault_name] if not match: sys.stderr.write(f"Error: no vault named '{vault_name}' in config.\n") sys.exit(1) print(match[0]["path"]) elif len(vaults) == 1: print(vaults[0]["path"]) else: names = ", ".join(v.get("name", "?") for v in vaults) sys.stderr.write(f"Error: multiple vaults configured ({names}); specify one by name.\n") sys.exit(1) PYEOF } # Validate that a resolved path is an existing, real directory and print # its canonical form (resolves symlinks, blocks '..' tricks). canonicalize_and_check_dir() { local path="$1" local real real=$(realpath -e "$path" 2>/dev/null) || { echo "Error: vault path '$path' does not exist." >&2 exit 1 } if [ ! -d "$real" ]; then echo "Error: vault path '$real' is not a directory." >&2 exit 1 fi echo "$real" }