import json
import os
import subprocess
from pathlib import Path
from typing import Any, Dict, List, Optional
from aimodelvault.core.config import VaultConfig
class Vault:
def __init__(
self,
vault_path: Optional[str] = None,
config: Optional[VaultConfig] = None,
) -> None:
self._config = config or VaultConfig()
self._vault_path = Path(vault_path) if vault_path else self._config.data_dir / "vault"
self._vault_path.mkdir(parents=True, exist_ok=True)
@property
def path(self) -> Path:
return self._vault_path
def _run_aim(self, args: List[str], passphrase: Optional[str] = None) -> subprocess.CompletedProcess:
env = os.environ.copy()
env["AIM_VAULT_PATH"] = str(self._vault_path)
if passphrase:
env["AIM_PASSPHRASE"] = passphrase
try:
result = subprocess.run(
["aim"] + args,
capture_output=True,
text=True,
env=env,
timeout=300,
)
except FileNotFoundError:
raise FileNotFoundError(
"The 'aim' binary was not found. Build with: cargo build --release"
)
if result.returncode != 0:
raise RuntimeError(f"aim command failed: {result.stderr.strip()}")
return result
def store(
self,
name: str,
model_path: str,
passphrase: Optional[str] = None,
description: Optional[str] = None,
) -> None:
args = ["store", name, model_path]
if description:
args.extend(["--description", description])
self._run_aim(args, passphrase=passphrase)
def retrieve(
self,
name: str,
output_path: str,
passphrase: Optional[str] = None,
version: Optional[int] = None,
) -> None:
args = ["retrieve", name, output_path]
if version is not None:
args.extend(["--version", str(version)])
self._run_aim(args, passphrase=passphrase)
def list_models(self) -> List[str]:
result = self._run_aim(["list"])
lines = result.stdout.strip().split("\n")
models = [line.strip() for line in lines if line.strip() and not line.startswith("─")]
return models
def delete(self, name: str) -> None:
self._run_aim(["delete", name])
def info(self, name: str) -> Dict[str, Any]:
result = self._run_aim(["info", name])
info: Dict[str, Any] = {}
for line in result.stdout.strip().split("\n"):
if ":" in line:
key, _, value = line.partition(":")
info[key.strip()] = value.strip()
return info
def verify(self, name: str, passphrase: Optional[str] = None) -> bool:
try:
self._run_aim(["verify", name], passphrase=passphrase)
return True
except RuntimeError:
return False